Annotation of Gnu-Mach/linux/pcmcia-cs/modules/rsrc_mgr.c, revision 1.1

1.1     ! root        1: /*======================================================================
        !             2: 
        !             3:     Resource management routines
        !             4: 
        !             5:     rsrc_mgr.c 1.94 2003/12/12 17:12:53
        !             6: 
        !             7:     The contents of this file are subject to the Mozilla Public
        !             8:     License Version 1.1 (the "License"); you may not use this file
        !             9:     except in compliance with the License. You may obtain a copy of
        !            10:     the License at http://www.mozilla.org/MPL/
        !            11: 
        !            12:     Software distributed under the License is distributed on an "AS
        !            13:     IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
        !            14:     implied. See the License for the specific language governing
        !            15:     rights and limitations under the License.
        !            16: 
        !            17:     The initial developer of the original code is David A. Hinds
        !            18:     <[email protected]>.  Portions created by David A. Hinds
        !            19:     are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
        !            20: 
        !            21:     Alternatively, the contents of this file may be used under the
        !            22:     terms of the GNU General Public License version 2 (the "GPL"), in
        !            23:     which case the provisions of the GPL are applicable instead of the
        !            24:     above.  If you wish to allow the use of your version of this file
        !            25:     only under the terms of the GPL and not to allow others to use
        !            26:     your version of this file under the MPL, indicate your decision
        !            27:     by deleting the provisions above and replace them with the notice
        !            28:     and other provisions required by the GPL.  If you do not delete
        !            29:     the provisions above, a recipient may use your version of this
        !            30:     file under either the MPL or the GPL.
        !            31:     
        !            32: ======================================================================*/
        !            33: 
        !            34: #define __NO_VERSION__
        !            35: 
        !            36: #include <linux/config.h>
        !            37: #include <linux/module.h>
        !            38: #include <linux/init.h>
        !            39: #include <linux/sched.h>
        !            40: #include <linux/kernel.h>
        !            41: #include <linux/errno.h>
        !            42: #include <linux/types.h>
        !            43: #include <linux/slab.h>
        !            44: #include <linux/ioport.h>
        !            45: #include <linux/timer.h>
        !            46: #include <linux/spinlock.h>
        !            47: #include <asm/irq.h>
        !            48: #include <asm/io.h>
        !            49: 
        !            50: #include <pcmcia/cs_types.h>
        !            51: #include <pcmcia/ss.h>
        !            52: #include <pcmcia/cs.h>
        !            53: #include <pcmcia/bulkmem.h>
        !            54: #include <pcmcia/cistpl.h>
        !            55: #include "cs_internal.h"
        !            56: 
        !            57: /*====================================================================*/
        !            58: 
        !            59: /* Parameters that can be set with 'insmod' */
        !            60: 
        !            61: #define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i")
        !            62: 
        !            63: INT_MODULE_PARM(probe_mem,     1);             /* memory probe? */
        !            64: #ifdef CONFIG_ISA
        !            65: INT_MODULE_PARM(probe_io,      1);             /* IO port probe? */
        !            66: INT_MODULE_PARM(mem_limit,     0x10000);
        !            67: #endif
        !            68: 
        !            69: /*======================================================================
        !            70: 
        !            71:     The resource_map_t structures are used to track what resources are
        !            72:     available for allocation for PC Card devices.
        !            73: 
        !            74: ======================================================================*/
        !            75: 
        !            76: typedef struct resource_map_t {
        !            77:     u_long                     base, num;
        !            78:     struct resource_map_t      *next;
        !            79: } resource_map_t;
        !            80: 
        !            81: /* Memory resource database */
        !            82: static resource_map_t mem_db = { 0, 0, &mem_db };
        !            83: 
        !            84: /* IO port resource database */
        !            85: static resource_map_t io_db = { 0, 0, &io_db };
        !            86: 
        !            87: #ifdef CONFIG_ISA
        !            88: 
        !            89: typedef struct irq_info_t {
        !            90:     u_int                      Attributes;
        !            91:     int                                time_share, dyn_share;
        !            92:     struct socket_info_t       *Socket;
        !            93: } irq_info_t;
        !            94: 
        !            95: /* Table of ISA IRQ assignments */
        !            96: static irq_info_t irq_table[16] = { { 0, 0, 0 }, /* etc */ };
        !            97: 
        !            98: #endif
        !            99: 
        !           100: /*======================================================================
        !           101: 
        !           102:     Linux resource management extensions
        !           103:     
        !           104: ======================================================================*/
        !           105: 
        !           106: #ifndef CONFIG_PNP_BIOS
        !           107: #define check_io_region(b,n) (0)
        !           108: #endif
        !           109: 
        !           110: #if defined(CONFIG_PNP_BIOS) || !defined(HAVE_MEMRESERVE)
        !           111: 
        !           112: #ifdef __SMP__
        !           113: static spinlock_t rsrc_lock = SPIN_LOCK_UNLOCKED;
        !           114: #endif
        !           115: 
        !           116: typedef struct resource_entry_t {
        !           117:     u_long                     base, num;
        !           118:     char                       *name;
        !           119:     struct resource_entry_t    *next;
        !           120: } resource_entry_t;
        !           121: 
        !           122: /* Ordered linked lists of allocated IO and memory blocks */
        !           123: #ifdef CONFIG_PNP_BIOS
        !           124: static resource_entry_t io_list = { 0, 0, NULL, NULL };
        !           125: #endif
        !           126: #ifndef HAVE_MEMRESERVE
        !           127: static resource_entry_t mem_list = { 0, 0, NULL, NULL };
        !           128: #endif
        !           129: 
        !           130: static resource_entry_t *find_gap(resource_entry_t *root,
        !           131:                                  resource_entry_t *entry)
        !           132: {
        !           133:     resource_entry_t *p;
        !           134:     
        !           135:     if (entry->base > entry->base+entry->num-1)
        !           136:        return NULL;
        !           137:     for (p = root; ; p = p->next) {
        !           138:        if ((p != root) && (p->base+p->num-1 >= entry->base)) {
        !           139:            p = NULL;
        !           140:            break;
        !           141:        }
        !           142:        if ((p->next == NULL) ||
        !           143:            (p->next->base > entry->base+entry->num-1))
        !           144:            break;
        !           145:     }
        !           146:     return p;
        !           147: }
        !           148: 
        !           149: static int register_my_resource(resource_entry_t *list,
        !           150:                                u_long base, u_long num, char *name)
        !           151: {
        !           152:     u_long flags;
        !           153:     resource_entry_t *p, *entry;
        !           154: 
        !           155:     entry = kmalloc(sizeof(resource_entry_t), GFP_ATOMIC);
        !           156:     if (!entry) return -ENOMEM;
        !           157:     entry->base = base;
        !           158:     entry->num = num;
        !           159:     entry->name = name;
        !           160: 
        !           161:     spin_lock_irqsave(&rsrc_lock, flags);
        !           162:     p = find_gap(list, entry);
        !           163:     if (p == NULL) {
        !           164:        spin_unlock_irqrestore(&rsrc_lock, flags);
        !           165:        kfree(entry);
        !           166:        return -EBUSY;
        !           167:     }
        !           168:     entry->next = p->next;
        !           169:     p->next = entry;
        !           170:     spin_unlock_irqrestore(&rsrc_lock, flags);
        !           171:     return 0;
        !           172: }
        !           173: 
        !           174: static void release_my_resource(resource_entry_t *list,
        !           175:                                u_long base, u_long num)
        !           176: {
        !           177:     u_long flags;
        !           178:     resource_entry_t *p, *q;
        !           179: 
        !           180:     spin_lock_irqsave(&rsrc_lock, flags);
        !           181:     for (p = list; ; p = q) {
        !           182:        q = p->next;
        !           183:        if (q == NULL) break;
        !           184:        if ((q->base == base) && (q->num == num)) {
        !           185:            p->next = q->next;
        !           186:            kfree(q);
        !           187:            spin_unlock_irqrestore(&rsrc_lock, flags);
        !           188:            return;
        !           189:        }
        !           190:     }
        !           191:     spin_unlock_irqrestore(&rsrc_lock, flags);
        !           192:     return;
        !           193: }
        !           194: 
        !           195: static int check_my_resource(resource_entry_t *list,
        !           196:                             u_long base, u_long num)
        !           197: {
        !           198:     if (register_my_resource(list, base, num, NULL) != 0)
        !           199:        return -EBUSY;
        !           200:     release_my_resource(list, base, num);
        !           201:     return 0;
        !           202: }
        !           203: 
        !           204: #ifdef CONFIG_PNP_BIOS
        !           205: int check_io_region(u_long base, u_long num)
        !           206: {
        !           207:     return check_my_resource(&io_list, base, num);
        !           208: }
        !           209: void request_io_region(u_long base, u_long num, char *name)
        !           210: {
        !           211:     register_my_resource(&io_list, base, num, name);
        !           212: }
        !           213: void release_io_region(u_long base, u_long num)
        !           214: {
        !           215:     release_my_resource(&io_list, base, num);
        !           216: }
        !           217: #ifdef HAS_PROC_BUS
        !           218: int proc_read_io(char *buf, char **start, off_t pos,
        !           219:                 int count, int *eof, void *data)
        !           220: {
        !           221:     resource_entry_t *r;
        !           222:     u_long flags;
        !           223:     char *p = buf;
        !           224:     
        !           225:     spin_lock_irqsave(&rsrc_lock, flags);
        !           226:     for (r = io_list.next; r; r = r->next)
        !           227:        p += sprintf(p, "%04lx-%04lx : %s\n", r->base,
        !           228:                     r->base+r->num-1, r->name);
        !           229:     spin_unlock_irqrestore(&rsrc_lock, flags);
        !           230:     return (p - buf);
        !           231: }
        !           232: #endif
        !           233: #endif
        !           234: 
        !           235: #ifndef HAVE_MEMRESERVE
        !           236: int check_mem_region(u_long base, u_long num)
        !           237: {
        !           238:     return check_my_resource(&mem_list, base, num);
        !           239: }
        !           240: void request_mem_region(u_long base, u_long num, char *name)
        !           241: {
        !           242:     register_my_resource(&mem_list, base, num, name);
        !           243: }
        !           244: void release_mem_region(u_long base, u_long num)
        !           245: {
        !           246:     release_my_resource(&mem_list, base, num);
        !           247: }
        !           248: #ifdef HAS_PROC_BUS
        !           249: int proc_read_mem(char *buf, char **start, off_t pos,
        !           250:                  int count, int *eof, void *data)
        !           251: {
        !           252:     resource_entry_t *r;
        !           253:     u_long flags;
        !           254:     char *p = buf;
        !           255:     
        !           256:     spin_lock_irqsave(&rsrc_lock, flags);
        !           257:     for (r = mem_list.next; r; r = r->next)
        !           258:        p += sprintf(p, "%08lx-%08lx : %s\n", r->base,
        !           259:                     r->base+r->num-1, r->name);
        !           260:     spin_unlock_irqrestore(&rsrc_lock, flags);
        !           261:     return (p - buf);
        !           262: }
        !           263: #endif
        !           264: #endif
        !           265: 
        !           266: #endif /* defined(CONFIG_PNP_BIOS) || !defined(HAVE_MEMRESERVE) */
        !           267: 
        !           268: /*======================================================================
        !           269: 
        !           270:     These manage the internal databases of available resources.
        !           271:     
        !           272: ======================================================================*/
        !           273: 
        !           274: static int add_interval(resource_map_t *map, u_long base, u_long num)
        !           275: {
        !           276:     resource_map_t *p, *q;
        !           277: 
        !           278:     for (p = map; ; p = p->next) {
        !           279:        if ((p != map) && (p->base+p->num-1 >= base))
        !           280:            return -1;
        !           281:        if ((p->next == map) || (p->next->base > base+num-1))
        !           282:            break;
        !           283:     }
        !           284:     q = kmalloc(sizeof(resource_map_t), GFP_KERNEL);
        !           285:     if (!q) return CS_OUT_OF_RESOURCE;
        !           286:     q->base = base; q->num = num;
        !           287:     q->next = p->next; p->next = q;
        !           288:     return CS_SUCCESS;
        !           289: }
        !           290: 
        !           291: /*====================================================================*/
        !           292: 
        !           293: static int sub_interval(resource_map_t *map, u_long base, u_long num)
        !           294: {
        !           295:     resource_map_t *p, *q;
        !           296: 
        !           297:     for (p = map; ; p = q) {
        !           298:        q = p->next;
        !           299:        if (q == map)
        !           300:            break;
        !           301:        if ((q->base+q->num > base) && (base+num > q->base)) {
        !           302:            if (q->base >= base) {
        !           303:                if (q->base+q->num <= base+num) {
        !           304:                    /* Delete whole block */
        !           305:                    p->next = q->next;
        !           306:                    kfree(q);
        !           307:                    /* don't advance the pointer yet */
        !           308:                    q = p;
        !           309:                } else {
        !           310:                    /* Cut off bit from the front */
        !           311:                    q->num = q->base + q->num - base - num;
        !           312:                    q->base = base + num;
        !           313:                }
        !           314:            } else if (q->base+q->num <= base+num) {
        !           315:                /* Cut off bit from the end */
        !           316:                q->num = base - q->base;
        !           317:            } else {
        !           318:                /* Split the block into two pieces */
        !           319:                p = kmalloc(sizeof(resource_map_t), GFP_KERNEL);
        !           320:                if (!p) return CS_OUT_OF_RESOURCE;
        !           321:                p->base = base+num;
        !           322:                p->num = q->base+q->num - p->base;
        !           323:                q->num = base - q->base;
        !           324:                p->next = q->next ; q->next = p;
        !           325:            }
        !           326:        }
        !           327:     }
        !           328:     return CS_SUCCESS;
        !           329: }
        !           330: 
        !           331: /*======================================================================
        !           332: 
        !           333:     These routines examine a region of IO or memory addresses to
        !           334:     determine what ranges might be genuinely available.
        !           335:     
        !           336: ======================================================================*/
        !           337: 
        !           338: #ifdef CONFIG_ISA
        !           339: static void do_io_probe(ioaddr_t base, ioaddr_t num)
        !           340: {
        !           341:     
        !           342:     ioaddr_t i, j, bad, any;
        !           343:     u_char *b, hole, most;
        !           344:     
        !           345:     printk(KERN_INFO "cs: IO port probe 0x%04x-0x%04x:",
        !           346:           base, base+num-1);
        !           347:     
        !           348:     /* First, what does a floating port look like? */
        !           349:     b = kmalloc(256, GFP_KERNEL);
        !           350:     if (!b) {
        !           351:        printk(KERN_INFO " kmalloc failed!\n");
        !           352:        return;
        !           353:     }
        !           354:     memset(b, 0, 256);
        !           355:     for (i = base, most = 0; i < base+num; i += 8) {
        !           356:        if (check_region(i, 8) || check_io_region(i, 8))
        !           357:            continue;
        !           358:        hole = inb(i);
        !           359:        for (j = 1; j < 8; j++)
        !           360:            if (inb(i+j) != hole) break;
        !           361:        if ((j == 8) && (++b[hole] > b[most]))
        !           362:            most = hole;
        !           363:        if (b[most] == 127) break;
        !           364:     }
        !           365:     kfree(b);
        !           366: 
        !           367:     bad = any = 0;
        !           368:     for (i = base; i < base+num; i += 8) {
        !           369:        if (check_region(i, 8) || check_io_region(i, 8))
        !           370:            continue;
        !           371:        for (j = 0; j < 8; j++)
        !           372:            if (inb(i+j) != most) break;
        !           373:        if (j < 8) {
        !           374:            if (!any)
        !           375:                printk(" excluding");
        !           376:            if (!bad)
        !           377:                bad = any = i;
        !           378:        } else {
        !           379:            if (bad) {
        !           380:                sub_interval(&io_db, bad, i-bad);
        !           381:                printk(" %#04x-%#04x", bad, i-1);
        !           382:                bad = 0;
        !           383:            }
        !           384:        }
        !           385:     }
        !           386:     if (bad) {
        !           387:        if ((num > 16) && (bad == base) && (i == base+num)) {
        !           388:            printk(" nothing: probe failed.\n");
        !           389:            return;
        !           390:        } else {
        !           391:            sub_interval(&io_db, bad, i-bad);
        !           392:            printk(" %#04x-%#04x", bad, i-1);
        !           393:        }
        !           394:     }
        !           395:     
        !           396:     printk(any ? "\n" : " clean.\n");
        !           397: }
        !           398: 
        !           399: static int io_scan; /* = 0 */
        !           400: 
        !           401: static void invalidate_io(void)
        !           402: {
        !           403:     io_scan = 0;
        !           404: }
        !           405: 
        !           406: static void validate_io(void)
        !           407: {
        !           408:     resource_map_t *m, *n;
        !           409:     if (!probe_io || io_scan++)
        !           410:        return;
        !           411:     for (m = io_db.next; m != &io_db; m = n) {
        !           412:        n = m->next;
        !           413:        do_io_probe(m->base, m->num);
        !           414:     }
        !           415: }
        !           416: 
        !           417: #else /* CONFIG_ISA */
        !           418: 
        !           419: #define validate_io() do { } while (0)
        !           420: #define invalidate_io() do { } while (0)
        !           421: 
        !           422: #endif /* CONFIG_ISA */
        !           423: 
        !           424: /*======================================================================
        !           425: 
        !           426:     The memory probe.  If the memory list includes a 64K-aligned block
        !           427:     below 1MB, we probe in 64K chunks, and as soon as we accumulate at
        !           428:     least mem_limit free space, we quit.
        !           429:     
        !           430: ======================================================================*/
        !           431: 
        !           432: static int do_mem_probe(u_long base, u_long num,
        !           433:                        int (*is_valid)(u_long), int (*do_cksum)(u_long))
        !           434: {
        !           435:     u_long i, j, bad, fail, step;
        !           436: 
        !           437:     printk(KERN_INFO "cs: memory probe 0x%06lx-0x%06lx:",
        !           438:           base, base+num-1);
        !           439:     bad = fail = 0;
        !           440:     step = (num < 0x20000) ? 0x2000 : ((num>>4) & ~0x1fff);
        !           441:     for (i = j = base; i < base+num; i = j + step) {
        !           442:        if (!fail) {    
        !           443:            for (j = i; j < base+num; j += step)
        !           444:                if ((check_mem_region(j, step) == 0) && is_valid(j))
        !           445:                    break;
        !           446:            fail = ((i == base) && (j == base+num));
        !           447:        }
        !           448:        if (fail) {
        !           449:            for (j = i; j < base+num; j += 2*step)
        !           450:                if ((check_mem_region(j, 2*step) == 0) &&
        !           451:                    do_cksum(j) && do_cksum(j+step))
        !           452:                    break;
        !           453:        }
        !           454:        if (i != j) {
        !           455:            if (!bad) printk(" excluding");
        !           456:            printk(" %#05lx-%#05lx", i, j-1);
        !           457:            sub_interval(&mem_db, i, j-i);
        !           458:            bad += j-i;
        !           459:        }
        !           460:     }
        !           461:     printk(bad ? "\n" : " clean.\n");
        !           462:     return (num - bad);
        !           463: }
        !           464: 
        !           465: #ifdef CONFIG_ISA
        !           466: 
        !           467: static u_long inv_probe(int (*is_valid)(u_long),
        !           468:                        int (*do_cksum)(u_long),
        !           469:                        resource_map_t *m)
        !           470: {
        !           471:     u_long ok;
        !           472:     if (m == &mem_db)
        !           473:        return 0;
        !           474:     ok = inv_probe(is_valid, do_cksum, m->next);
        !           475:     if (ok) {
        !           476:        if (m->base >= 0x100000)
        !           477:            sub_interval(&mem_db, m->base, m->num);
        !           478:        return ok;
        !           479:     }
        !           480:     if (m->base < 0x100000)
        !           481:        return 0;
        !           482:     return do_mem_probe(m->base, m->num, is_valid, do_cksum);
        !           483: }
        !           484: 
        !           485: static int hi_scan, lo_scan; /* = 0 */
        !           486: 
        !           487: static void invalidate_mem(void)
        !           488: {
        !           489:     hi_scan = lo_scan = 0;
        !           490: }
        !           491: 
        !           492: void validate_mem(int (*is_valid)(u_long), int (*do_cksum)(u_long),
        !           493:                  int force_low)
        !           494: {
        !           495:     resource_map_t *m, mm;
        !           496:     static u_char order[] = { 0xd0, 0xe0, 0xc0, 0xf0 };
        !           497:     u_long b, i, ok = 0;
        !           498:     
        !           499:     if (!probe_mem) return;
        !           500:     /* We do up to four passes through the list */
        !           501:     if (!force_low) {
        !           502:        if (hi_scan++ || (inv_probe(is_valid, do_cksum, mem_db.next) > 0))
        !           503:            return;
        !           504:        printk(KERN_NOTICE "cs: warning: no high memory space "
        !           505:               "available!\n");
        !           506:     }
        !           507:     if (lo_scan++) return;
        !           508:     for (m = mem_db.next; m != &mem_db; m = mm.next) {
        !           509:        mm = *m;
        !           510:        /* Only probe < 1 MB */
        !           511:        if (mm.base >= 0x100000) continue;
        !           512:        if ((mm.base | mm.num) & 0xffff) {
        !           513:            ok += do_mem_probe(mm.base, mm.num, is_valid, do_cksum);
        !           514:            continue;
        !           515:        }
        !           516:        /* Special probe for 64K-aligned block */
        !           517:        for (i = 0; i < 4; i++) {
        !           518:            b = order[i] << 12;
        !           519:            if ((b >= mm.base) && (b+0x10000 <= mm.base+mm.num)) {
        !           520:                if (ok >= mem_limit)
        !           521:                    sub_interval(&mem_db, b, 0x10000);
        !           522:                else
        !           523:                    ok += do_mem_probe(b, 0x10000, is_valid, do_cksum);
        !           524:            }
        !           525:        }
        !           526:     }
        !           527: }
        !           528: 
        !           529: #else /* CONFIG_ISA */
        !           530: 
        !           531: #define invalidate_mem() do { } while (0)
        !           532: 
        !           533: void validate_mem(int (*is_valid)(u_long), int (*do_cksum)(u_long),
        !           534:                  int force_low)
        !           535: {
        !           536:     resource_map_t *m, *n;
        !           537:     static int done = 0;
        !           538:     
        !           539:     if (!probe_mem || done++)
        !           540:        return;
        !           541:     for (m = mem_db.next; m != &mem_db; m = n)
        !           542:        n = m->next;
        !           543:        if (do_mem_probe(m->base, m->num, is_valid, do_cksum))
        !           544:            return;
        !           545: }
        !           546: 
        !           547: #endif /* CONFIG_ISA */
        !           548: 
        !           549: /*======================================================================
        !           550: 
        !           551:     These find ranges of I/O ports or memory addresses that are not
        !           552:     currently allocated by other devices.
        !           553: 
        !           554:     The 'align' field should reflect the number of bits of address
        !           555:     that need to be preserved from the initial value of *base.  It
        !           556:     should be a power of two, greater than or equal to 'num'.  A value
        !           557:     of 0 means that all bits of *base are significant.  *base should
        !           558:     also be strictly less than 'align'.
        !           559:     
        !           560: ======================================================================*/
        !           561: 
        !           562: int find_io_region(ioaddr_t *base, ioaddr_t num, ioaddr_t align,
        !           563:                   char *name)
        !           564: {
        !           565:     ioaddr_t try;
        !           566:     resource_map_t *m;
        !           567: 
        !           568:     validate_io();
        !           569:     for (m = io_db.next; m != &io_db; m = m->next) {
        !           570:        try = (m->base & ~(align-1)) + *base;
        !           571:        for (try = (try >= m->base) ? try : try+align;
        !           572:             (try >= m->base) && (try+num <= m->base+m->num);
        !           573:             try += align) {
        !           574:            if ((check_region(try, num) == 0) &&
        !           575:                (check_io_region(try, num) == 0)) {
        !           576:                *base = try;
        !           577:                if (name) request_region(try, num, name);
        !           578:                return 0;
        !           579:            }
        !           580:            if (!align) break;
        !           581:        }
        !           582:     }
        !           583:     return -1;
        !           584: }
        !           585: 
        !           586: int find_mem_region(u_long *base, u_long num, u_long align,
        !           587:                    int force_low, char *name)
        !           588: {
        !           589:     u_long try;
        !           590:     resource_map_t *m;
        !           591: 
        !           592:     while (1) {
        !           593:        for (m = mem_db.next; m != &mem_db; m = m->next) {
        !           594:            /* first pass >1MB, second pass <1MB */
        !           595:            if ((force_low != 0) ^ (m->base < 0x100000)) continue;
        !           596:            try = (m->base & ~(align-1)) + *base;
        !           597:            for (try = (try >= m->base) ? try : try+align;
        !           598:                 (try >= m->base) && (try+num <= m->base+m->num);
        !           599:                 try += align) {
        !           600:                if (check_mem_region(try, num) == 0) {
        !           601:                    if (name) request_mem_region(try, num, name);
        !           602:                    *base = try;
        !           603:                    return 0;
        !           604:                }
        !           605:                if (!align) break;
        !           606:            }
        !           607:        }
        !           608:        if (force_low) break;
        !           609:        force_low++;
        !           610:     }
        !           611:     return -1;
        !           612: }
        !           613: 
        !           614: /*======================================================================
        !           615: 
        !           616:     This checks to see if an interrupt is available, with support
        !           617:     for interrupt sharing.  We don't support reserving interrupts
        !           618:     yet.  If the interrupt is available, we allocate it.
        !           619:     
        !           620: ======================================================================*/
        !           621: 
        !           622: #ifdef CONFIG_ISA
        !           623: 
        !           624: static void fake_irq(int i, void *d, struct pt_regs *r) { }
        !           625: static inline int check_irq(int irq)
        !           626: {
        !           627:     if (request_irq(irq, fake_irq, 0, "bogus", NULL) != 0)
        !           628:        return -1;
        !           629:     free_irq(irq, NULL);
        !           630:     return 0;
        !           631: }
        !           632: 
        !           633: int try_irq(u_int Attributes, int irq, int specific)
        !           634: {
        !           635:     irq_info_t *info = &irq_table[irq];
        !           636:     if (info->Attributes & RES_ALLOCATED) {
        !           637:        switch (Attributes & IRQ_TYPE) {
        !           638:        case IRQ_TYPE_EXCLUSIVE:
        !           639:            return CS_IN_USE;
        !           640:        case IRQ_TYPE_TIME:
        !           641:            if ((info->Attributes & RES_IRQ_TYPE)
        !           642:                != RES_IRQ_TYPE_TIME)
        !           643:                return CS_IN_USE;
        !           644:            if (Attributes & IRQ_FIRST_SHARED)
        !           645:                return CS_BAD_ATTRIBUTE;
        !           646:            info->Attributes |= RES_IRQ_TYPE_TIME | RES_ALLOCATED;
        !           647:            info->time_share++;
        !           648:            break;
        !           649:        case IRQ_TYPE_DYNAMIC_SHARING:
        !           650:            if ((info->Attributes & RES_IRQ_TYPE)
        !           651:                != RES_IRQ_TYPE_DYNAMIC)
        !           652:                return CS_IN_USE;
        !           653:            if (Attributes & IRQ_FIRST_SHARED)
        !           654:                return CS_BAD_ATTRIBUTE;
        !           655:            info->Attributes |= RES_IRQ_TYPE_DYNAMIC | RES_ALLOCATED;
        !           656:            info->dyn_share++;
        !           657:            break;
        !           658:        }
        !           659:     } else {
        !           660:        if ((info->Attributes & RES_RESERVED) && !specific)
        !           661:            return CS_IN_USE;
        !           662:        if (check_irq(irq) != 0)
        !           663:            return CS_IN_USE;
        !           664:        switch (Attributes & IRQ_TYPE) {
        !           665:        case IRQ_TYPE_EXCLUSIVE:
        !           666:            info->Attributes |= RES_ALLOCATED;
        !           667:            break;
        !           668:        case IRQ_TYPE_TIME:
        !           669:            if (!(Attributes & IRQ_FIRST_SHARED))
        !           670:                return CS_BAD_ATTRIBUTE;
        !           671:            info->Attributes |= RES_IRQ_TYPE_TIME | RES_ALLOCATED;
        !           672:            info->time_share = 1;
        !           673:            break;
        !           674:        case IRQ_TYPE_DYNAMIC_SHARING:
        !           675:            if (!(Attributes & IRQ_FIRST_SHARED))
        !           676:                return CS_BAD_ATTRIBUTE;
        !           677:            info->Attributes |= RES_IRQ_TYPE_DYNAMIC | RES_ALLOCATED;
        !           678:            info->dyn_share = 1;
        !           679:            break;
        !           680:        }
        !           681:     }
        !           682:     return 0;
        !           683: }
        !           684: 
        !           685: #endif
        !           686: 
        !           687: /*====================================================================*/
        !           688: 
        !           689: #ifdef CONFIG_ISA
        !           690: 
        !           691: void undo_irq(u_int Attributes, int irq)
        !           692: {
        !           693:     irq_info_t *info;
        !           694: 
        !           695:     info = &irq_table[irq];
        !           696:     switch (Attributes & IRQ_TYPE) {
        !           697:     case IRQ_TYPE_EXCLUSIVE:
        !           698:        info->Attributes &= RES_RESERVED;
        !           699:        break;
        !           700:     case IRQ_TYPE_TIME:
        !           701:        info->time_share--;
        !           702:        if (info->time_share == 0)
        !           703:            info->Attributes &= RES_RESERVED;
        !           704:        break;
        !           705:     case IRQ_TYPE_DYNAMIC_SHARING:
        !           706:        info->dyn_share--;
        !           707:        if (info->dyn_share == 0)
        !           708:            info->Attributes &= RES_RESERVED;
        !           709:        break;
        !           710:     }
        !           711: }
        !           712: 
        !           713: #endif
        !           714: 
        !           715: /*======================================================================
        !           716: 
        !           717:     The various adjust_* calls form the external interface to the
        !           718:     resource database.
        !           719:     
        !           720: ======================================================================*/
        !           721: 
        !           722: static int adjust_memory(adjust_t *adj)
        !           723: {
        !           724:     u_long base, num;
        !           725:     int i, ret;
        !           726: 
        !           727:     base = adj->resource.memory.Base;
        !           728:     num = adj->resource.memory.Size;
        !           729:     if ((num == 0) || (base+num-1 < base))
        !           730:        return CS_BAD_SIZE;
        !           731: 
        !           732:     ret = CS_SUCCESS;
        !           733:     switch (adj->Action) {
        !           734:     case ADD_MANAGED_RESOURCE:
        !           735:        ret = add_interval(&mem_db, base, num);
        !           736:        break;
        !           737:     case REMOVE_MANAGED_RESOURCE:
        !           738:        ret = sub_interval(&mem_db, base, num);
        !           739:        if (ret == CS_SUCCESS) {
        !           740:            invalidate_mem();
        !           741:            for (i = 0; i < sockets; i++) {
        !           742:                release_cis_mem(socket_table[i]);
        !           743: #ifdef CONFIG_CARDBUS
        !           744:                cb_release_cis_mem(socket_table[i]);
        !           745: #endif
        !           746:            }
        !           747:        }
        !           748:        break;
        !           749:     default:
        !           750:        ret = CS_UNSUPPORTED_FUNCTION;
        !           751:     }
        !           752:     
        !           753:     return ret;
        !           754: }
        !           755: 
        !           756: /*====================================================================*/
        !           757: 
        !           758: static int adjust_io(adjust_t *adj)
        !           759: {
        !           760:     int base, num;
        !           761:     
        !           762:     base = adj->resource.io.BasePort;
        !           763:     num = adj->resource.io.NumPorts;
        !           764:     if ((base < 0) || (base > 0xffff))
        !           765:        return CS_BAD_BASE;
        !           766:     if ((num <= 0) || (base+num > 0x10000) || (base+num <= base))
        !           767:        return CS_BAD_SIZE;
        !           768: 
        !           769:     switch (adj->Action) {
        !           770:     case ADD_MANAGED_RESOURCE:
        !           771:        if (add_interval(&io_db, base, num) != 0)
        !           772:            return CS_IN_USE;
        !           773:        break;
        !           774:     case REMOVE_MANAGED_RESOURCE:
        !           775:        sub_interval(&io_db, base, num);
        !           776:        invalidate_io();
        !           777:        break;
        !           778:     default:
        !           779:        return CS_UNSUPPORTED_FUNCTION;
        !           780:        break;
        !           781:     }
        !           782: 
        !           783:     return CS_SUCCESS;
        !           784: }
        !           785: 
        !           786: /*====================================================================*/
        !           787: 
        !           788: static int adjust_irq(adjust_t *adj)
        !           789: {
        !           790: #ifdef CONFIG_ISA
        !           791:     int irq;
        !           792:     irq_info_t *info;
        !           793:     
        !           794:     irq = adj->resource.irq.IRQ;
        !           795:     if ((irq < 0) || (irq > 15))
        !           796:        return CS_BAD_IRQ;
        !           797:     info = &irq_table[irq];
        !           798:     
        !           799:     switch (adj->Action) {
        !           800:     case ADD_MANAGED_RESOURCE:
        !           801:        if (info->Attributes & RES_REMOVED)
        !           802:            info->Attributes &= ~(RES_REMOVED|RES_ALLOCATED);
        !           803:        else
        !           804:            if (adj->Attributes & RES_ALLOCATED)
        !           805:                return CS_IN_USE;
        !           806:        if (adj->Attributes & RES_RESERVED)
        !           807:            info->Attributes |= RES_RESERVED;
        !           808:        else
        !           809:            info->Attributes &= ~RES_RESERVED;
        !           810:        break;
        !           811:     case REMOVE_MANAGED_RESOURCE:
        !           812:        if (info->Attributes & RES_REMOVED)
        !           813:            return 0;
        !           814:        if (info->Attributes & RES_ALLOCATED)
        !           815:            return CS_IN_USE;
        !           816:        info->Attributes |= RES_ALLOCATED|RES_REMOVED;
        !           817:        info->Attributes &= ~RES_RESERVED;
        !           818:        break;
        !           819:     default:
        !           820:        return CS_UNSUPPORTED_FUNCTION;
        !           821:        break;
        !           822:     }
        !           823: #endif
        !           824:     return CS_SUCCESS;
        !           825: }
        !           826: 
        !           827: /*====================================================================*/
        !           828: 
        !           829: int adjust_resource_info(client_handle_t handle, adjust_t *adj)
        !           830: {
        !           831:     if (CHECK_HANDLE(handle))
        !           832:        return CS_BAD_HANDLE;
        !           833:     
        !           834:     switch (adj->Resource) {
        !           835:     case RES_MEMORY_RANGE:
        !           836:        return adjust_memory(adj);
        !           837:        break;
        !           838:     case RES_IO_RANGE:
        !           839:        return adjust_io(adj);
        !           840:        break;
        !           841:     case RES_IRQ:
        !           842:        return adjust_irq(adj);
        !           843:        break;
        !           844:     }
        !           845:     return CS_UNSUPPORTED_FUNCTION;
        !           846: }
        !           847: 
        !           848: /*====================================================================*/
        !           849: 
        !           850: void release_resource_db(void)
        !           851: {
        !           852:     resource_map_t *p, *q;
        !           853: #if defined(CONFIG_PNP_BIOS) || !defined(HAVE_MEMRESERVE)
        !           854:     resource_entry_t *u, *v;
        !           855: #endif
        !           856:     
        !           857:     for (p = mem_db.next; p != &mem_db; p = q) {
        !           858:        q = p->next;
        !           859:        kfree(p);
        !           860:     }
        !           861:     for (p = io_db.next; p != &io_db; p = q) {
        !           862:        q = p->next;
        !           863:        kfree(p);
        !           864:     }
        !           865: #ifdef CONFIG_PNP_BIOS
        !           866:     for (u = io_list.next; u; u = v) {
        !           867:        v = u->next;
        !           868:        kfree(u);
        !           869:     }
        !           870: #endif
        !           871: #ifndef HAVE_MEMRESERVE
        !           872:     for (u = mem_list.next; u; u = v) {
        !           873:        v = u->next;
        !           874:        kfree(u);
        !           875:     }
        !           876: #endif
        !           877: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.