This source file includes following definitions.
- rbus_space_alloc
- rbus_space_alloc_subregion
- rbus_space_free
- rbus_new_body
- rbus_new
- rbus_new_root_delegate
- rbus_new_root_share
- rbus_delete
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 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/device.h>
36 #include <sys/malloc.h>
37 #include <sys/extent.h>
38
39 #include <machine/bus.h>
40
41 #include <dev/cardbus/rbus.h>
42
43
44
45 #if defined RBUS_DEBUG
46 #define STATIC
47 #define DPRINTF(a) printf a
48 #define DDELAY(x) delay((x)*1000*1000)
49 #else
50 #define STATIC static
51 #define DPRINTF(a)
52 #endif
53
54
55 static rbus_tag_t rbus_new_body(bus_space_tag_t, rbus_tag_t, struct extent *,
56 bus_addr_t, bus_addr_t, bus_addr_t, int);
57
58 int
59 rbus_space_alloc(rbus_tag_t rbt, bus_addr_t addr, bus_size_t size,
60 bus_addr_t mask, bus_addr_t align, int flags, bus_addr_t *addrp,
61 bus_space_handle_t *bshp)
62 {
63 return (rbus_space_alloc_subregion(rbt, rbt->rb_start, rbt->rb_end,
64 addr, size, mask, align, flags, addrp, bshp));
65 }
66
67 int
68 rbus_space_alloc_subregion(rbus_tag_t rbt, bus_addr_t substart,
69 bus_addr_t subend, bus_addr_t addr, bus_size_t size,
70 bus_addr_t mask, bus_addr_t align, int flags, bus_addr_t *addrp,
71 bus_space_handle_t *bshp)
72 {
73 bus_addr_t decodesize = mask + 1;
74 bus_addr_t boundary, search_addr;
75 int val;
76 u_long result;
77 int exflags = EX_FAST | EX_NOWAIT | EX_MALLOCOK;
78
79 DPRINTF(("rbus_space_alloc: addr %lx, size %lx, mask %lx, align %lx\n",
80 (u_long)addr, (u_long)size, (u_long)mask, (u_long)align));
81
82 addr += rbt->rb_offset;
83
84 if (mask == 0) {
85
86 decodesize = 0;
87 }
88
89 if (rbt->rb_flags == RBUS_SPACE_ASK_PARENT) {
90 return (rbus_space_alloc(rbt->rb_parent, addr, size, mask,
91 align, flags, addrp, bshp));
92 } else if (rbt->rb_flags == RBUS_SPACE_SHARE ||
93 rbt->rb_flags == RBUS_SPACE_DEDICATE) {
94
95
96
97
98 if (substart < rbt->rb_ext->ex_start ||
99 subend > rbt->rb_ext->ex_end) {
100 DPRINTF(("rbus: out of range\n"));
101 return (1);
102 }
103
104 if (decodesize == align) {
105 if (extent_alloc_subregion(rbt->rb_ext, substart,
106 subend, size, align, 0, 0, exflags, &result))
107 return (1);
108 } else if (decodesize == 0) {
109
110
111 if (extent_alloc_subregion(rbt->rb_ext, addr,
112 addr + size, size, 1, 0, 0, exflags, &result))
113 return (1);
114 } else {
115 boundary = decodesize > align ? decodesize : align;
116
117 search_addr = (substart & ~(boundary - 1)) + addr;
118
119 if (search_addr < substart)
120 search_addr += boundary;
121
122 val = 1;
123 for (; search_addr + size <= subend;
124 search_addr += boundary) {
125 val = extent_alloc_subregion(
126 rbt->rb_ext,search_addr,
127 search_addr + size, size, align, 0, 0,
128 exflags, &result);
129 DPRINTF(("rbus: trying [%lx:%lx] %lx\n",
130 (u_long)search_addr,
131 (u_long)search_addr + size,
132 (u_long)align));
133 if (val == 0)
134 break;
135 }
136
137 if (val != 0) {
138
139 DPRINTF(("rbus: no space found\n"));
140 return (1);
141 }
142 }
143
144 if (md_space_map(rbt->rb_bt, result, size, flags, bshp)) {
145
146 extent_free(rbt->rb_ext, result, size, exflags);
147 return (1);
148 }
149
150 if (addrp != NULL)
151 *addrp = result + rbt->rb_offset;
152 return (0);
153 } else {
154
155 DPRINTF(("rbus: no rbus type\n"));
156 return (1);
157 }
158 }
159
160 int
161 rbus_space_free(rbus_tag_t rbt, bus_space_handle_t bsh, bus_size_t size,
162 bus_addr_t *addrp)
163 {
164 int exflags = EX_FAST | EX_NOWAIT;
165 bus_addr_t addr;
166 int status = 1;
167
168 if (rbt->rb_flags == RBUS_SPACE_ASK_PARENT) {
169 status = rbus_space_free(rbt->rb_parent, bsh, size, &addr);
170 } else if (rbt->rb_flags == RBUS_SPACE_SHARE ||
171 rbt->rb_flags == RBUS_SPACE_DEDICATE) {
172 md_space_unmap(rbt->rb_bt, bsh, size, &addr);
173
174 extent_free(rbt->rb_ext, addr, size, exflags);
175
176 status = 0;
177 } else {
178
179 status = 1;
180 }
181
182 if (addrp != NULL)
183 *addrp = addr;
184
185 return (status);
186 }
187
188
189
190
191
192
193
194
195 static rbus_tag_t
196 rbus_new_body(bus_space_tag_t bt, rbus_tag_t parent, struct extent *ex,
197 bus_addr_t start, bus_addr_t end, bus_addr_t offset, int flags)
198 {
199 rbus_tag_t rb;
200
201
202 if (parent != NULL) {
203 if (start < parent->rb_start || end > parent->rb_end) {
204
205
206
207 return (0);
208
209 }
210 }
211
212 if ((rb = (rbus_tag_t)malloc(sizeof(struct rbustag), M_DEVBUF,
213 M_NOWAIT)) == NULL) {
214 panic("no memory for rbus instance");
215 }
216
217 rb->rb_bt = bt;
218 rb->rb_parent = parent;
219 rb->rb_start = start;
220 rb->rb_end = end;
221 rb->rb_offset = offset;
222 rb->rb_flags = flags;
223 rb->rb_ext = ex;
224
225 DPRINTF(("rbus_new_body: [%lx, %lx] type %s name [%s]\n",
226 (u_long)start, (u_long)end,
227 flags == RBUS_SPACE_SHARE ? "share" :
228 flags == RBUS_SPACE_DEDICATE ? "dedicated" :
229 flags == RBUS_SPACE_ASK_PARENT ? "parent" : "invalid",
230 ex != NULL ? ex->ex_name : "noname"));
231
232 return (rb);
233 }
234
235
236
237
238
239
240
241 rbus_tag_t
242 rbus_new(rbus_tag_t parent, bus_addr_t start, bus_size_t size,
243 bus_addr_t offset, int flags)
244 {
245 rbus_tag_t rb;
246 struct extent *ex = NULL;
247 bus_addr_t end = start + size;
248
249 if (flags == RBUS_SPACE_SHARE) {
250 ex = parent->rb_ext;
251 } else if (flags == RBUS_SPACE_DEDICATE) {
252 if ((ex = extent_create("rbus", start, end, M_DEVBUF, NULL, 0,
253 EX_NOCOALESCE|EX_NOWAIT)) == NULL)
254 return (NULL);
255 } else if (flags == RBUS_SPACE_ASK_PARENT) {
256 ex = NULL;
257 } else {
258
259 return (0);
260 }
261
262 rb = rbus_new_body(parent->rb_bt, parent, ex, start, start + size,
263 offset, flags);
264
265 if ((rb == NULL) && (flags == RBUS_SPACE_DEDICATE))
266 extent_destroy(ex);
267
268 return (rb);
269 }
270
271
272
273
274
275
276
277 rbus_tag_t
278 rbus_new_root_delegate(bus_space_tag_t bt, bus_addr_t start, bus_size_t size,
279 bus_addr_t offset)
280 {
281 rbus_tag_t rb;
282 struct extent *ex;
283
284 if ((ex = extent_create("rbus root", start, start + size, M_DEVBUF,
285 NULL, 0, EX_NOCOALESCE|EX_NOWAIT)) == NULL)
286 return (NULL);
287
288 rb = rbus_new_body(bt, NULL, ex, start, start + size, offset,
289 RBUS_SPACE_DEDICATE);
290
291 if (rb == NULL)
292 extent_destroy(ex);
293
294 return (rb);
295 }
296
297
298
299
300
301
302
303 rbus_tag_t
304 rbus_new_root_share(bus_space_tag_t bt, struct extent *ex, bus_addr_t start,
305 bus_size_t size, bus_addr_t offset)
306 {
307
308 if (start < ex->ex_start || start + size > ex->ex_end) {
309
310
311
312 return (0);
313
314 }
315
316 return (rbus_new_body(bt, NULL, ex, start, start + size, offset,
317 RBUS_SPACE_SHARE));
318 }
319
320
321
322
323
324
325 int
326 rbus_delete(rbus_tag_t rb)
327 {
328 DPRINTF(("rbus_delete called [%s]\n", rb->rb_ext != NULL ?
329 rb->rb_ext->ex_name : "noname"));
330
331 if (rb->rb_flags == RBUS_SPACE_DEDICATE)
332 extent_destroy(rb->rb_ext);
333
334 free(rb, M_DEVBUF);
335
336 return (0);
337 }