Annotation of Gnu-Mach/linux/pcmcia-cs/modules/rsrc_mgr.c, revision 1.1.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.