Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 | /* * linux/kernel/resource.c * * Copyright (C) 1995 Linus Torvalds * David Hinds * * Kernel io-region resource management */ #include <linux/sched.h> #include <linux/kernel.h> #include <linux/errno.h> #include <linux/types.h> #include <linux/ioport.h> #define IOTABLE_SIZE 64 typedef struct resource_entry_t { u_long from, num; const char *name; struct resource_entry_t *next; } resource_entry_t; static resource_entry_t iolist = { 0, 0, "", NULL }; static resource_entry_t iotable[IOTABLE_SIZE]; /* * This generates the report for /proc/ioports */ int get_ioport_list(char *buf) { resource_entry_t *p; int len = 0; for (p = iolist.next; (p) && (len < 4000); p = p->next) len += sprintf(buf+len, "%04lx-%04lx : %s\n", p->from, p->from+p->num-1, p->name); if (p) len += sprintf(buf+len, "4K limit reached!\n"); return len; } /* * The workhorse function: find where to put a new entry */ static resource_entry_t *find_gap(resource_entry_t *root, u_long from, u_long num) { unsigned long flags; resource_entry_t *p; if (from > from+num-1) return NULL; save_flags(flags); cli(); for (p = root; ; p = p->next) { if ((p != root) && (p->from+p->num-1 >= from)) { p = NULL; break; } if ((p->next == NULL) || (p->next->from > from+num-1)) break; } restore_flags(flags); return p; } /* * Call this from the device driver to register the ioport region. */ void request_region(unsigned int from, unsigned int num, const char *name) { resource_entry_t *p; int i; for (i = 0; i < IOTABLE_SIZE; i++) if (iotable[i].num == 0) break; if (i == IOTABLE_SIZE) printk("warning: ioport table is full\n"); else { p = find_gap(&iolist, from, num); if (p == NULL) return; iotable[i].name = name; iotable[i].from = from; iotable[i].num = num; iotable[i].next = p->next; p->next = &iotable[i]; return; } } /* * Call this when the device driver is unloaded */ void release_region(unsigned int from, unsigned int num) { resource_entry_t *p, *q; for (p = &iolist; ; p = q) { q = p->next; if (q == NULL) break; if ((q->from == from) && (q->num == num)) { q->num = 0; p->next = q->next; return; } } } /* * Call this to check the ioport region before probing */ int check_region(unsigned int from, unsigned int num) { return (find_gap(&iolist, from, num) == NULL) ? -EBUSY : 0; } /* Called from init/main.c to reserve IO ports. */ void reserve_setup(char *str, int *ints) { int i; for (i = 1; i < ints[0]; i += 2) request_region(ints[i], ints[i+1], "reserved"); } |