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