2 * linux/kernel/resource.c
4 * Copyright (C) 1995 Linus Torvalds
7 * Kernel io-region resource management
10 #include <linux/sched.h>
11 #include <linux/errno.h>
12 #include <linux/ioport.h>
13 #include <linux/init.h>
15 #define IOTABLE_SIZE 128
17 typedef struct resource_entry_t
{
20 struct resource_entry_t
*next
;
23 static resource_entry_t iolist
= { 0, 0, "", NULL
};
25 static resource_entry_t iotable
[IOTABLE_SIZE
];
28 * This generates the report for /proc/ioports
30 int get_ioport_list(char *buf
)
35 for (p
= iolist
.next
; (p
) && (len
< 4000); p
= p
->next
)
36 len
+= sprintf(buf
+len
, "%04lx-%04lx : %s\n",
37 p
->from
, p
->from
+p
->num
-1, p
->name
);
39 len
+= sprintf(buf
+len
, "4K limit reached!\n");
44 * The workhorse function: find where to put a new entry
46 static resource_entry_t
*find_gap(resource_entry_t
*root
,
47 u_long from
, u_long num
)
52 if (from
> from
+num
-1)
56 for (p
= root
; ; p
= p
->next
) {
57 if ((p
!= root
) && (p
->from
+p
->num
-1 >= from
)) {
61 if ((p
->next
== NULL
) || (p
->next
->from
> from
+num
-1))
69 * Call this from the device driver to register the ioport region.
71 void request_region(unsigned long from
, unsigned long num
, const char *name
)
76 for (i
= 0; i
< IOTABLE_SIZE
; i
++)
77 if (iotable
[i
].num
== 0)
79 if (i
== IOTABLE_SIZE
)
80 printk("warning: ioport table is full\n");
82 p
= find_gap(&iolist
, from
, num
);
85 iotable
[i
].name
= name
;
86 iotable
[i
].from
= from
;
88 iotable
[i
].next
= p
->next
;
89 p
->next
= &iotable
[i
];
95 * Call this when the device driver is unloaded
97 void release_region(unsigned long from
, unsigned long num
)
99 resource_entry_t
*p
, *q
;
101 for (p
= &iolist
; ; p
= q
) {
105 if ((q
->from
== from
) && (q
->num
== num
)) {
114 * Call this to check the ioport region before probing
116 int check_region(unsigned long from
, unsigned long num
)
118 return (find_gap(&iolist
, from
, num
) == NULL
) ? -EBUSY
: 0;
121 #ifdef __sparc__ /* Why to carry unused code on other architectures? */
123 * This is for architectures with MMU-managed ports (sparc).
125 unsigned long occupy_region(unsigned long base
, unsigned long end
,
126 unsigned long num
, unsigned int align
, const char *name
)
128 unsigned long from
= 0, till
;
131 resource_entry_t
*p
; /* Scanning ptr */
132 resource_entry_t
*p1
; /* === p->next */
133 resource_entry_t
*s
; /* Found slot */
137 if (num
> end
- base
)
140 for (i
= 0; i
< IOTABLE_SIZE
; i
++)
141 if (iotable
[i
].num
== 0)
143 if (i
== IOTABLE_SIZE
) {
144 /* Driver prints a warning typically. */
150 /* printk("occupy: search in %08lx[%08lx] ", base, end - base); */
152 for (p
= &iolist
; p
!= NULL
; p
= p1
) {
154 /* Find window in list */
155 from
= (p
->from
+p
->num
+ align
-1) & ~((unsigned long)align
-1);
156 till
= (p1
== NULL
)? (unsigned long) (0 - (unsigned long)align
): p1
->from
;
157 /* printk(" %08lx:%08lx", from, till); */
158 /* Clip window with base and end */
159 if (from
< base
) from
= base
;
160 if (till
> end
) till
= end
;
161 /* See if result is large enougth */
162 if (from
< till
&& from
+ num
< till
) {
167 /* printk("\r\n"); */
168 restore_flags(flags
);
173 iotable
[i
].name
= name
;
174 iotable
[i
].from
= from
;
175 iotable
[i
].num
= num
;
176 iotable
[i
].next
= s
->next
;
177 s
->next
= &iotable
[i
];
182 /* Called from init/main.c to reserve IO ports. */
183 void __init
reserve_setup(char *str
, int *ints
)
187 for (i
= 1; i
< ints
[0]; i
+= 2)
188 request_region(ints
[i
], ints
[i
+1], "reserved");