OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [pcmcia/] [rsrc_mgr.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*======================================================================
2
 
3
    Resource management routines
4
 
5
    rsrc_mgr.c 1.79 2000/08/30 20:23:58
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
    <dahinds@users.sourceforge.net>.  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 which
23
    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/proc_fs.h>
47
#include <linux/pci.h>
48
#include <asm/irq.h>
49
#include <asm/io.h>
50
 
51
#include <pcmcia/cs_types.h>
52
#include <pcmcia/ss.h>
53
#include <pcmcia/cs.h>
54
#include <pcmcia/bulkmem.h>
55
#include <pcmcia/cistpl.h>
56
#include "cs_internal.h"
57
 
58
/*====================================================================*/
59
 
60
/* Parameters that can be set with 'insmod' */
61
 
62
#define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i")
63
 
64
INT_MODULE_PARM(probe_mem,      1);             /* memory probe? */
65
#ifdef CONFIG_ISA
66
INT_MODULE_PARM(probe_io,       1);             /* IO port probe? */
67
INT_MODULE_PARM(mem_limit,      0x10000);
68
#endif
69
 
70
/*======================================================================
71
 
72
    The resource_map_t structures are used to track what resources are
73
    available for allocation for PC Card devices.
74
 
75
======================================================================*/
76
 
77
typedef struct resource_map_t {
78
    u_long                      base, num;
79
    struct resource_map_t       *next;
80
} resource_map_t;
81
 
82
/* Memory resource database */
83
static resource_map_t mem_db = { 0, 0, &mem_db };
84
 
85
/* IO port resource database */
86
static resource_map_t io_db = { 0, 0, &io_db };
87
 
88
#ifdef CONFIG_ISA
89
 
90
typedef struct irq_info_t {
91
    u_int                       Attributes;
92
    int                         time_share, dyn_share;
93
    struct socket_info_t        *Socket;
94
} irq_info_t;
95
 
96
/* Table of IRQ assignments */
97
static irq_info_t irq_table[NR_IRQS] = { { 0, 0, 0 }, /* etc */ };
98
 
99
#endif
100
 
101
/*======================================================================
102
 
103
    Linux resource management extensions
104
 
105
======================================================================*/
106
 
107
static struct resource *resource_parent(unsigned long b, unsigned long n,
108
                                        int flags, struct pci_dev *dev)
109
{
110
#ifdef CONFIG_PCI
111
        struct resource res, *pr;
112
 
113
        if (dev != NULL) {
114
                res.start = b;
115
                res.end = b + n - 1;
116
                res.flags = flags;
117
                pr = pci_find_parent_resource(dev, &res);
118
                if (pr)
119
                        return pr;
120
        }
121
#endif /* CONFIG_PCI */
122
        if (flags & IORESOURCE_MEM)
123
                return &iomem_resource;
124
        return &ioport_resource;
125
}
126
 
127
static inline int check_io_resource(unsigned long b, unsigned long n,
128
                                    struct pci_dev *dev)
129
{
130
        return check_resource(resource_parent(b, n, IORESOURCE_IO, dev), b, n);
131
}
132
 
133
static inline int check_mem_resource(unsigned long b, unsigned long n,
134
                                     struct pci_dev *dev)
135
{
136
        return check_resource(resource_parent(b, n, IORESOURCE_MEM, dev), b, n);
137
}
138
 
139
static struct resource *make_resource(unsigned long b, unsigned long n,
140
                                      int flags, char *name)
141
{
142
        struct resource *res = kmalloc(sizeof(*res), GFP_KERNEL);
143
 
144
        if (res) {
145
                memset(res, 0, sizeof(*res));
146
                res->name = name;
147
                res->start = b;
148
                res->end = b + n - 1;
149
                res->flags = flags | IORESOURCE_BUSY;
150
        }
151
        return res;
152
}
153
 
154
static int request_io_resource(unsigned long b, unsigned long n,
155
                               char *name, struct pci_dev *dev)
156
{
157
        struct resource *res = make_resource(b, n, IORESOURCE_IO, name);
158
        struct resource *pr = resource_parent(b, n, IORESOURCE_IO, dev);
159
        int err = -ENOMEM;
160
 
161
        if (res) {
162
                err = request_resource(pr, res);
163
                if (err)
164
                        kfree(res);
165
        }
166
        return err;
167
}
168
 
169
static int request_mem_resource(unsigned long b, unsigned long n,
170
                                char *name, struct pci_dev *dev)
171
{
172
        struct resource *res = make_resource(b, n, IORESOURCE_MEM, name);
173
        struct resource *pr = resource_parent(b, n, IORESOURCE_MEM, dev);
174
        int err = -ENOMEM;
175
 
176
        if (res) {
177
                err = request_resource(pr, res);
178
                if (err)
179
                        kfree(res);
180
        }
181
        return err;
182
}
183
 
184
/*======================================================================
185
 
186
    These manage the internal databases of available resources.
187
 
188
======================================================================*/
189
 
190
static int add_interval(resource_map_t *map, u_long base, u_long num)
191
{
192
    resource_map_t *p, *q;
193
 
194
    for (p = map; ; p = p->next) {
195
        if ((p != map) && (p->base+p->num-1 >= base))
196
            return -1;
197
        if ((p->next == map) || (p->next->base > base+num-1))
198
            break;
199
    }
200
    q = kmalloc(sizeof(resource_map_t), GFP_KERNEL);
201
    if (!q) return CS_OUT_OF_RESOURCE;
202
    q->base = base; q->num = num;
203
    q->next = p->next; p->next = q;
204
    return CS_SUCCESS;
205
}
206
 
207
/*====================================================================*/
208
 
209
static int sub_interval(resource_map_t *map, u_long base, u_long num)
210
{
211
    resource_map_t *p, *q;
212
 
213
    for (p = map; ; p = q) {
214
        q = p->next;
215
        if (q == map)
216
            break;
217
        if ((q->base+q->num > base) && (base+num > q->base)) {
218
            if (q->base >= base) {
219
                if (q->base+q->num <= base+num) {
220
                    /* Delete whole block */
221
                    p->next = q->next;
222
                    kfree(q);
223
                    /* don't advance the pointer yet */
224
                    q = p;
225
                } else {
226
                    /* Cut off bit from the front */
227
                    q->num = q->base + q->num - base - num;
228
                    q->base = base + num;
229
                }
230
            } else if (q->base+q->num <= base+num) {
231
                /* Cut off bit from the end */
232
                q->num = base - q->base;
233
            } else {
234
                /* Split the block into two pieces */
235
                p = kmalloc(sizeof(resource_map_t), GFP_KERNEL);
236
                if (!p) return CS_OUT_OF_RESOURCE;
237
                p->base = base+num;
238
                p->num = q->base+q->num - p->base;
239
                q->num = base - q->base;
240
                p->next = q->next ; q->next = p;
241
            }
242
        }
243
    }
244
    return CS_SUCCESS;
245
}
246
 
247
/*======================================================================
248
 
249
    These routines examine a region of IO or memory addresses to
250
    determine what ranges might be genuinely available.
251
 
252
======================================================================*/
253
 
254
#ifdef CONFIG_ISA
255
static void do_io_probe(ioaddr_t base, ioaddr_t num)
256
{
257
 
258
    ioaddr_t i, j, bad, any;
259
    u_char *b, hole, most;
260
 
261
    printk(KERN_INFO "cs: IO port probe 0x%04x-0x%04x:",
262
           base, base+num-1);
263
 
264
    /* First, what does a floating port look like? */
265
    b = kmalloc(256, GFP_KERNEL);
266
    if (!b) {
267
            printk(KERN_ERR "do_io_probe: unable to kmalloc 256 bytes");
268
            return;
269
    }
270
    memset(b, 0, 256);
271
    for (i = base, most = 0; i < base+num; i += 8) {
272
        if (check_io_resource(i, 8, NULL))
273
            continue;
274
        hole = inb(i);
275
        for (j = 1; j < 8; j++)
276
            if (inb(i+j) != hole) break;
277
        if ((j == 8) && (++b[hole] > b[most]))
278
            most = hole;
279
        if (b[most] == 127) break;
280
    }
281
    kfree(b);
282
 
283
    bad = any = 0;
284
    for (i = base; i < base+num; i += 8) {
285
        if (check_io_resource(i, 8, NULL))
286
            continue;
287
        for (j = 0; j < 8; j++)
288
            if (inb(i+j) != most) break;
289
        if (j < 8) {
290
            if (!any)
291
                printk(" excluding");
292
            if (!bad)
293
                bad = any = i;
294
        } else {
295
            if (bad) {
296
                sub_interval(&io_db, bad, i-bad);
297
                printk(" %#04x-%#04x", bad, i-1);
298
                bad = 0;
299
            }
300
        }
301
    }
302
    if (bad) {
303
        if ((num > 16) && (bad == base) && (i == base+num)) {
304
            printk(" nothing: probe failed.\n");
305
            return;
306
        } else {
307
            sub_interval(&io_db, bad, i-bad);
308
            printk(" %#04x-%#04x", bad, i-1);
309
        }
310
    }
311
 
312
    printk(any ? "\n" : " clean.\n");
313
}
314
#endif
315
 
316
/*======================================================================
317
 
318
    The memory probe.  If the memory list includes a 64K-aligned block
319
    below 1MB, we probe in 64K chunks, and as soon as we accumulate at
320
    least mem_limit free space, we quit.
321
 
322
======================================================================*/
323
 
324
static int do_mem_probe(u_long base, u_long num,
325
                        int (*is_valid)(u_long), int (*do_cksum)(u_long),
326
                        socket_info_t *s)
327
{
328
    u_long i, j, bad, fail, step;
329
 
330
    printk(KERN_INFO "cs: memory probe 0x%06lx-0x%06lx:",
331
           base, base+num-1);
332
    bad = fail = 0;
333
    step = (num < 0x20000) ? 0x2000 : ((num>>4) & ~0x1fff);
334
    for (i = j = base; i < base+num; i = j + step) {
335
        if (!fail) {
336
            for (j = i; j < base+num; j += step)
337
                if ((check_mem_resource(j, step, s->cap.cb_dev) == 0) &&
338
                    is_valid(j))
339
                    break;
340
            fail = ((i == base) && (j == base+num));
341
        }
342
        if (fail) {
343
            for (j = i; j < base+num; j += 2*step)
344
                if ((check_mem_resource(j, 2*step, s->cap.cb_dev) == 0) &&
345
                    do_cksum(j) && do_cksum(j+step))
346
                    break;
347
        }
348
        if (i != j) {
349
            if (!bad) printk(" excluding");
350
            printk(" %#05lx-%#05lx", i, j-1);
351
            sub_interval(&mem_db, i, j-i);
352
            bad += j-i;
353
        }
354
    }
355
    printk(bad ? "\n" : " clean.\n");
356
    return (num - bad);
357
}
358
 
359
#ifdef CONFIG_ISA
360
 
361
static u_long inv_probe(int (*is_valid)(u_long),
362
                        int (*do_cksum)(u_long),
363
                        resource_map_t *m, socket_info_t *s)
364
{
365
    u_long ok;
366
    if (m == &mem_db)
367
        return 0;
368
    ok = inv_probe(is_valid, do_cksum, m->next, s);
369
    if (ok) {
370
        if (m->base >= 0x100000)
371
            sub_interval(&mem_db, m->base, m->num);
372
        return ok;
373
    }
374
    if (m->base < 0x100000)
375
        return 0;
376
    return do_mem_probe(m->base, m->num, is_valid, do_cksum, s);
377
}
378
 
379
void validate_mem(int (*is_valid)(u_long), int (*do_cksum)(u_long),
380
                  int force_low, socket_info_t *s)
381
{
382
    resource_map_t *m, mm;
383
    static u_char order[] = { 0xd0, 0xe0, 0xc0, 0xf0 };
384
    static int hi = 0, lo = 0;
385
    u_long b, i, ok = 0;
386
 
387
    if (!probe_mem) return;
388
    /* We do up to four passes through the list */
389
    if (!force_low) {
390
        if (hi++ || (inv_probe(is_valid, do_cksum, mem_db.next, s) > 0))
391
            return;
392
        printk(KERN_NOTICE "cs: warning: no high memory space "
393
               "available!\n");
394
    }
395
    if (lo++) return;
396
    for (m = mem_db.next; m != &mem_db; m = mm.next) {
397
        mm = *m;
398
        /* Only probe < 1 MB */
399
        if (mm.base >= 0x100000) continue;
400
        if ((mm.base | mm.num) & 0xffff) {
401
            ok += do_mem_probe(mm.base, mm.num, is_valid, do_cksum, s);
402
            continue;
403
        }
404
        /* Special probe for 64K-aligned block */
405
        for (i = 0; i < 4; i++) {
406
            b = order[i] << 12;
407
            if ((b >= mm.base) && (b+0x10000 <= mm.base+mm.num)) {
408
                if (ok >= mem_limit)
409
                    sub_interval(&mem_db, b, 0x10000);
410
                else
411
                    ok += do_mem_probe(b, 0x10000, is_valid, do_cksum, s);
412
            }
413
        }
414
    }
415
}
416
 
417
#else /* CONFIG_ISA */
418
 
419
void validate_mem(int (*is_valid)(u_long), int (*do_cksum)(u_long),
420
                  int force_low, socket_info_t *s)
421
{
422
    resource_map_t *m, *n;
423
    static int done = 0;
424
 
425
    if (!probe_mem || done++)
426
        return;
427
 
428
    for (m = mem_db.next; m != &mem_db; m = n) {
429
        n = m->next;
430
        if (do_mem_probe(m->base, m->num, is_valid, do_cksum, s))
431
            return;
432
    }
433
}
434
 
435
#endif /* CONFIG_ISA */
436
 
437
/*======================================================================
438
 
439
    These find ranges of I/O ports or memory addresses that are not
440
    currently allocated by other devices.
441
 
442
    The 'align' field should reflect the number of bits of address
443
    that need to be preserved from the initial value of *base.  It
444
    should be a power of two, greater than or equal to 'num'.  A value
445
    of 0 means that all bits of *base are significant.  *base should
446
    also be strictly less than 'align'.
447
 
448
======================================================================*/
449
 
450
int find_io_region(ioaddr_t *base, ioaddr_t num, ioaddr_t align,
451
                   char *name, socket_info_t *s)
452
{
453
    ioaddr_t try;
454
    resource_map_t *m;
455
 
456
    for (m = io_db.next; m != &io_db; m = m->next) {
457
        try = (m->base & ~(align-1)) + *base;
458
        for (try = (try >= m->base) ? try : try+align;
459
             (try >= m->base) && (try+num <= m->base+m->num);
460
             try += align) {
461
            if (request_io_resource(try, num, name, s->cap.cb_dev) == 0) {
462
                *base = try;
463
                return 0;
464
            }
465
            if (!align) break;
466
        }
467
    }
468
    return -1;
469
}
470
 
471
int find_mem_region(u_long *base, u_long num, u_long align,
472
                    int force_low, char *name, socket_info_t *s)
473
{
474
    u_long try;
475
    resource_map_t *m;
476
 
477
    while (1) {
478
        for (m = mem_db.next; m != &mem_db; m = m->next) {
479
            /* first pass >1MB, second pass <1MB */
480
            if ((force_low != 0) ^ (m->base < 0x100000)) continue;
481
            try = (m->base & ~(align-1)) + *base;
482
            for (try = (try >= m->base) ? try : try+align;
483
                 (try >= m->base) && (try+num <= m->base+m->num);
484
                 try += align) {
485
                if (request_mem_resource(try, num, name, s->cap.cb_dev) == 0) {
486
                    *base = try;
487
                    return 0;
488
                }
489
                if (!align) break;
490
            }
491
        }
492
        if (force_low) break;
493
        force_low++;
494
    }
495
    return -1;
496
}
497
 
498
/*======================================================================
499
 
500
    This checks to see if an interrupt is available, with support
501
    for interrupt sharing.  We don't support reserving interrupts
502
    yet.  If the interrupt is available, we allocate it.
503
 
504
======================================================================*/
505
 
506
#ifdef CONFIG_ISA
507
 
508
static void fake_irq(int i, void *d, struct pt_regs *r) { }
509
static inline int check_irq(int irq)
510
{
511
    if (request_irq(irq, fake_irq, 0, "bogus", NULL) != 0)
512
        return -1;
513
    free_irq(irq, NULL);
514
    return 0;
515
}
516
 
517
int try_irq(u_int Attributes, int irq, int specific)
518
{
519
    irq_info_t *info = &irq_table[irq];
520
    if (info->Attributes & RES_ALLOCATED) {
521
        switch (Attributes & IRQ_TYPE) {
522
        case IRQ_TYPE_EXCLUSIVE:
523
            return CS_IN_USE;
524
        case IRQ_TYPE_TIME:
525
            if ((info->Attributes & RES_IRQ_TYPE)
526
                != RES_IRQ_TYPE_TIME)
527
                return CS_IN_USE;
528
            if (Attributes & IRQ_FIRST_SHARED)
529
                return CS_BAD_ATTRIBUTE;
530
            info->Attributes |= RES_IRQ_TYPE_TIME | RES_ALLOCATED;
531
            info->time_share++;
532
            break;
533
        case IRQ_TYPE_DYNAMIC_SHARING:
534
            if ((info->Attributes & RES_IRQ_TYPE)
535
                != RES_IRQ_TYPE_DYNAMIC)
536
                return CS_IN_USE;
537
            if (Attributes & IRQ_FIRST_SHARED)
538
                return CS_BAD_ATTRIBUTE;
539
            info->Attributes |= RES_IRQ_TYPE_DYNAMIC | RES_ALLOCATED;
540
            info->dyn_share++;
541
            break;
542
        }
543
    } else {
544
        if ((info->Attributes & RES_RESERVED) && !specific)
545
            return CS_IN_USE;
546
        if (check_irq(irq) != 0)
547
            return CS_IN_USE;
548
        switch (Attributes & IRQ_TYPE) {
549
        case IRQ_TYPE_EXCLUSIVE:
550
            info->Attributes |= RES_ALLOCATED;
551
            break;
552
        case IRQ_TYPE_TIME:
553
            if (!(Attributes & IRQ_FIRST_SHARED))
554
                return CS_BAD_ATTRIBUTE;
555
            info->Attributes |= RES_IRQ_TYPE_TIME | RES_ALLOCATED;
556
            info->time_share = 1;
557
            break;
558
        case IRQ_TYPE_DYNAMIC_SHARING:
559
            if (!(Attributes & IRQ_FIRST_SHARED))
560
                return CS_BAD_ATTRIBUTE;
561
            info->Attributes |= RES_IRQ_TYPE_DYNAMIC | RES_ALLOCATED;
562
            info->dyn_share = 1;
563
            break;
564
        }
565
    }
566
    return 0;
567
}
568
 
569
#endif
570
 
571
/*====================================================================*/
572
 
573
#ifdef CONFIG_ISA
574
 
575
void undo_irq(u_int Attributes, int irq)
576
{
577
    irq_info_t *info;
578
 
579
    info = &irq_table[irq];
580
    switch (Attributes & IRQ_TYPE) {
581
    case IRQ_TYPE_EXCLUSIVE:
582
        info->Attributes &= RES_RESERVED;
583
        break;
584
    case IRQ_TYPE_TIME:
585
        info->time_share--;
586
        if (info->time_share == 0)
587
            info->Attributes &= RES_RESERVED;
588
        break;
589
    case IRQ_TYPE_DYNAMIC_SHARING:
590
        info->dyn_share--;
591
        if (info->dyn_share == 0)
592
            info->Attributes &= RES_RESERVED;
593
        break;
594
    }
595
}
596
 
597
#endif
598
 
599
/*======================================================================
600
 
601
    The various adjust_* calls form the external interface to the
602
    resource database.
603
 
604
======================================================================*/
605
 
606
static int adjust_memory(adjust_t *adj)
607
{
608
    u_long base, num;
609
    int i, ret;
610
 
611
    base = adj->resource.memory.Base;
612
    num = adj->resource.memory.Size;
613
    if ((num == 0) || (base+num-1 < base))
614
        return CS_BAD_SIZE;
615
 
616
    ret = CS_SUCCESS;
617
    switch (adj->Action) {
618
    case ADD_MANAGED_RESOURCE:
619
        ret = add_interval(&mem_db, base, num);
620
        break;
621
    case REMOVE_MANAGED_RESOURCE:
622
        ret = sub_interval(&mem_db, base, num);
623
        if (ret == CS_SUCCESS) {
624
            for (i = 0; i < sockets; i++) {
625
                release_cis_mem(socket_table[i]);
626
#ifdef CONFIG_CARDBUS
627
                cb_release_cis_mem(socket_table[i]);
628
#endif
629
            }
630
        }
631
        break;
632
    default:
633
        ret = CS_UNSUPPORTED_FUNCTION;
634
    }
635
 
636
    return ret;
637
}
638
 
639
/*====================================================================*/
640
 
641
static int adjust_io(adjust_t *adj)
642
{
643
    int base, num;
644
 
645
    base = adj->resource.io.BasePort;
646
    num = adj->resource.io.NumPorts;
647
    if ((base < 0) || (base > 0xffff))
648
        return CS_BAD_BASE;
649
    if ((num <= 0) || (base+num > 0x10000) || (base+num <= base))
650
        return CS_BAD_SIZE;
651
 
652
    switch (adj->Action) {
653
    case ADD_MANAGED_RESOURCE:
654
        if (add_interval(&io_db, base, num) != 0)
655
            return CS_IN_USE;
656
#ifdef CONFIG_ISA
657
        if (probe_io)
658
            do_io_probe(base, num);
659
#endif
660
        break;
661
    case REMOVE_MANAGED_RESOURCE:
662
        sub_interval(&io_db, base, num);
663
        break;
664
    default:
665
        return CS_UNSUPPORTED_FUNCTION;
666
        break;
667
    }
668
 
669
    return CS_SUCCESS;
670
}
671
 
672
/*====================================================================*/
673
 
674
static int adjust_irq(adjust_t *adj)
675
{
676
#ifdef CONFIG_ISA
677
    int irq;
678
    irq_info_t *info;
679
 
680
    irq = adj->resource.irq.IRQ;
681
    if ((irq < 0) || (irq > 15))
682
        return CS_BAD_IRQ;
683
    info = &irq_table[irq];
684
 
685
    switch (adj->Action) {
686
    case ADD_MANAGED_RESOURCE:
687
        if (info->Attributes & RES_REMOVED)
688
            info->Attributes &= ~(RES_REMOVED|RES_ALLOCATED);
689
        else
690
            if (adj->Attributes & RES_ALLOCATED)
691
                return CS_IN_USE;
692
        if (adj->Attributes & RES_RESERVED)
693
            info->Attributes |= RES_RESERVED;
694
        else
695
            info->Attributes &= ~RES_RESERVED;
696
        break;
697
    case REMOVE_MANAGED_RESOURCE:
698
        if (info->Attributes & RES_REMOVED)
699
            return 0;
700
        if (info->Attributes & RES_ALLOCATED)
701
            return CS_IN_USE;
702
        info->Attributes |= RES_ALLOCATED|RES_REMOVED;
703
        info->Attributes &= ~RES_RESERVED;
704
        break;
705
    default:
706
        return CS_UNSUPPORTED_FUNCTION;
707
        break;
708
    }
709
#endif
710
    return CS_SUCCESS;
711
}
712
 
713
/*====================================================================*/
714
 
715
int pcmcia_adjust_resource_info(client_handle_t handle, adjust_t *adj)
716
{
717
    if (CHECK_HANDLE(handle))
718
        return CS_BAD_HANDLE;
719
 
720
    switch (adj->Resource) {
721
    case RES_MEMORY_RANGE:
722
        return adjust_memory(adj);
723
        break;
724
    case RES_IO_RANGE:
725
        return adjust_io(adj);
726
        break;
727
    case RES_IRQ:
728
        return adjust_irq(adj);
729
        break;
730
    }
731
    return CS_UNSUPPORTED_FUNCTION;
732
}
733
 
734
/*====================================================================*/
735
 
736
void release_resource_db(void)
737
{
738
    resource_map_t *p, *q;
739
 
740
    for (p = mem_db.next; p != &mem_db; p = q) {
741
        q = p->next;
742
        kfree(p);
743
    }
744
    for (p = io_db.next; p != &io_db; p = q) {
745
        q = p->next;
746
        kfree(p);
747
    }
748
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.