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/kernel.h>
12 #include <linux/errno.h>
13 #include <linux/types.h>
14 #include <linux/ioport.h>
15 #include <linux/init.h>
17 #define IOTABLE_SIZE 128
19 typedef struct resource_entry_t
{
22 struct resource_entry_t
*next
;
25 static resource_entry_t iolist
= { 0, 0, "", NULL
};
27 static resource_entry_t iotable
[IOTABLE_SIZE
];
30 * This generates the report for /proc/ioports
32 int get_ioport_list(char *buf
)
37 for (p
= iolist
.next
; (p
) && (len
< 4000); p
= p
->next
)
38 len
+= sprintf(buf
+len
, "%04lx-%04lx : %s\n",
39 p
->from
, p
->from
+p
->num
-1, p
->name
);
41 len
+= sprintf(buf
+len
, "4K limit reached!\n");
46 * The workhorse function: find where to put a new entry
48 static resource_entry_t
*find_gap(resource_entry_t
*root
,
49 u_long from
, u_long num
)
54 if (from
> from
+num
-1)
58 for (p
= root
; ; p
= p
->next
) {
59 if ((p
!= root
) && (p
->from
+p
->num
-1 >= from
)) {
63 if ((p
->next
== NULL
) || (p
->next
->from
> from
+num
-1))
71 * Call this from the device driver to register the ioport region.
73 void request_region(unsigned long from
, unsigned long num
, const char *name
)
78 for (i
= 0; i
< IOTABLE_SIZE
; i
++)
79 if (iotable
[i
].num
== 0)
81 if (i
== IOTABLE_SIZE
)
82 printk("warning: ioport table is full\n");
84 p
= find_gap(&iolist
, from
, num
);
87 iotable
[i
].name
= name
;
88 iotable
[i
].from
= from
;
90 iotable
[i
].next
= p
->next
;
91 p
->next
= &iotable
[i
];
97 * Call this when the device driver is unloaded
99 void release_region(unsigned long from
, unsigned long num
)
101 resource_entry_t
*p
, *q
;
103 for (p
= &iolist
; ; p
= q
) {
107 if ((q
->from
== from
) && (q
->num
== num
)) {
116 * Call this to check the ioport region before probing
118 int check_region(unsigned long from
, unsigned long num
)
120 return (find_gap(&iolist
, from
, num
) == NULL
) ? -EBUSY
: 0;
123 #ifdef __sparc__ /* Why to carry unused code on other architectures? */
125 * This is for architectures with MMU-managed ports (sparc).
127 unsigned long occupy_region(unsigned long base
, unsigned long end
,
128 unsigned long num
, unsigned int align
, const char *name
)
130 unsigned long from
= 0, till
;
133 resource_entry_t
*p
; /* Scanning ptr */
134 resource_entry_t
*p1
; /* === p->next */
135 resource_entry_t
*s
; /* Found slot */
139 if (num
> end
- base
)
142 for (i
= 0; i
< IOTABLE_SIZE
; i
++)
143 if (iotable
[i
].num
== 0)
145 if (i
== IOTABLE_SIZE
) {
146 /* Driver prints a warning typically. */
152 /* printk("occupy: search in %08lx[%08lx] ", base, end - base); */
154 for (p
= &iolist
; p
!= NULL
; p
= p1
) {
156 /* Find window in list */
157 from
= (p
->from
+p
->num
+ align
-1) & ~((unsigned long)align
-1);
158 till
= (p1
== NULL
)? (unsigned long) (0 - (unsigned long)align
): p1
->from
;
159 /* printk(" %08lx:%08lx", from, till); */
160 /* Clip window with base and end */
161 if (from
< base
) from
= base
;
162 if (till
> end
) till
= end
;
163 /* See if result is large enougth */
164 if (from
< till
&& from
+ num
< till
) {
169 /* printk("\r\n"); */
170 restore_flags(flags
);
175 iotable
[i
].name
= name
;
176 iotable
[i
].from
= from
;
177 iotable
[i
].num
= num
;
178 iotable
[i
].next
= s
->next
;
179 s
->next
= &iotable
[i
];
184 /* Called from init/main.c to reserve IO ports. */
185 void __init
reserve_setup(char *str
, int *ints
)
189 for (i
= 1; i
< ints
[0]; i
+= 2)
190 request_region(ints
[i
], ints
[i
+1], "reserved");