|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.