4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
31 * 1394 Address Space Routines
32 * Implements all the routines necessary for alloc/free and lookup
33 * of the 1394 address space
38 #include <sys/sunddi.h>
39 #include <sys/types.h>
41 #include <sys/tnf_probe.h>
43 #include <sys/1394/t1394.h>
44 #include <sys/1394/s1394.h>
45 #include <sys/1394/h1394.h>
46 #include <sys/1394/ieee1394.h>
48 static s1394_addr_space_blk_t
*s1394_free_list_search(s1394_hal_t
*hal
,
51 static s1394_addr_space_blk_t
*s1394_free_list_find(s1394_hal_t
*hal
,
52 uint32_t type
, uint32_t length
);
54 static s1394_addr_space_blk_t
*s1394_free_list_delete(s1394_hal_t
*hal
,
55 s1394_addr_space_blk_t
*del_blk
);
57 static void s1394_used_tree_insert(s1394_hal_t
*hal
, s1394_addr_space_blk_t
*x
);
59 static void s1394_tree_insert(s1394_addr_space_blk_t
**root
,
60 s1394_addr_space_blk_t
*z
);
62 static s1394_addr_space_blk_t
*s1394_tree_search(s1394_addr_space_blk_t
*x
,
65 static void s1394_used_tree_delete_fixup(s1394_addr_space_blk_t
**root
,
66 s1394_addr_space_blk_t
*p
, s1394_addr_space_blk_t
*x
,
67 s1394_addr_space_blk_t
*w
, int side_of_x
);
69 static void s1394_left_rotate(s1394_addr_space_blk_t
**root
,
70 s1394_addr_space_blk_t
*x
);
72 static void s1394_right_rotate(s1394_addr_space_blk_t
**root
,
73 s1394_addr_space_blk_t
*x
);
75 static s1394_addr_space_blk_t
*s1394_tree_minimum(s1394_addr_space_blk_t
*x
);
77 static s1394_addr_space_blk_t
*s1394_tree_successor(s1394_addr_space_blk_t
*x
);
80 * s1394_request_addr_blk()
81 * is called when a target driver is requesting a block of 1394 Address
82 * Space of a particular type without regard for its exact location. It
83 * searches the free list for a block that's big enough and of the specified
84 * type, and it inserts it into the used tree.
87 s1394_request_addr_blk(s1394_hal_t
*hal
, t1394_alloc_addr_t
*addr_allocp
)
89 s1394_addr_space_blk_t
*curr_blk
;
90 s1394_addr_space_blk_t
*new_blk
;
93 TNF_PROBE_0_DEBUG(s1394_request_addr_blk_enter
,
94 S1394_TNF_SL_ARREQ_STACK
, "");
98 /* Lock the address space "free" list */
99 mutex_enter(&hal
->addr_space_free_mutex
);
101 curr_blk
= s1394_free_list_find(hal
, addr_allocp
->aa_type
,
102 addr_allocp
->aa_length
);
103 if (curr_blk
== NULL
) {
104 /* Unlock the address space "free" list */
105 mutex_exit(&hal
->addr_space_free_mutex
);
107 TNF_PROBE_1(s1394_request_addr_blk_error
,
108 S1394_TNF_SL_ARREQ_ERROR
, "", tnf_string
, msg
,
109 "1394 address space - no more memory");
110 TNF_PROBE_0_DEBUG(s1394_request_addr_blk_exit
,
111 S1394_TNF_SL_ARREQ_STACK
, "");
112 return (DDI_FAILURE
);
115 amount_free
= (curr_blk
->addr_hi
- curr_blk
->addr_lo
) + 1;
116 /* Does it fit exact? */
117 if (amount_free
== addr_allocp
->aa_length
) {
118 /* Take it out of the "free" list */
119 curr_blk
= s1394_free_list_delete(hal
, curr_blk
);
121 /* Unlock the address space "free" list */
122 mutex_exit(&hal
->addr_space_free_mutex
);
124 curr_blk
->addr_enable
= addr_allocp
->aa_enable
;
125 curr_blk
->kmem_bufp
= addr_allocp
->aa_kmem_bufp
;
126 curr_blk
->addr_arg
= addr_allocp
->aa_arg
;
127 curr_blk
->addr_events
= addr_allocp
->aa_evts
;
129 addr_allocp
->aa_address
= curr_blk
->addr_lo
;
130 addr_allocp
->aa_hdl
= (t1394_addr_handle_t
)curr_blk
;
132 /* Put it into the "used" tree */
133 s1394_used_tree_insert(hal
, curr_blk
);
135 s1394_addr_alloc_kstat(hal
, addr_allocp
->aa_address
);
137 TNF_PROBE_0_DEBUG(s1394_request_addr_blk_exit
,
138 S1394_TNF_SL_ARREQ_STACK
, "");
139 return (DDI_SUCCESS
);
142 /* Needs to be broken up */
143 new_blk
= (s1394_addr_space_blk_t
*)
144 kmem_zalloc(sizeof (s1394_addr_space_blk_t
), KM_NOSLEEP
);
145 if (new_blk
== NULL
) {
146 /* Unlock the address space "free" list */
147 mutex_exit(&hal
->addr_space_free_mutex
);
148 TNF_PROBE_0(s1394_request_addr_blk_error
,
149 S1394_TNF_SL_ARREQ_ERROR
, "");
150 TNF_PROBE_0_DEBUG(s1394_request_addr_blk_exit
,
151 S1394_TNF_SL_ARREQ_STACK
, "");
152 return (DDI_FAILURE
);
155 new_blk
->addr_lo
= curr_blk
->addr_lo
;
156 new_blk
->addr_hi
= curr_blk
->addr_lo
+
157 (addr_allocp
->aa_length
- 1);
158 new_blk
->addr_type
= curr_blk
->addr_type
;
159 new_blk
->addr_enable
= addr_allocp
->aa_enable
;
160 new_blk
->kmem_bufp
= addr_allocp
->aa_kmem_bufp
;
161 new_blk
->addr_arg
= addr_allocp
->aa_arg
;
162 new_blk
->addr_events
= addr_allocp
->aa_evts
;
164 curr_blk
->addr_lo
= new_blk
->addr_hi
+ 1;
166 addr_allocp
->aa_address
= new_blk
->addr_lo
;
167 addr_allocp
->aa_hdl
= (t1394_addr_handle_t
)new_blk
;
169 /* Unlock the address space "free" list */
170 mutex_exit(&hal
->addr_space_free_mutex
);
172 /* Put it into the "used" tree */
173 s1394_used_tree_insert(hal
, new_blk
);
175 s1394_addr_alloc_kstat(hal
, addr_allocp
->aa_address
);
177 TNF_PROBE_0_DEBUG(s1394_request_addr_blk_exit
,
178 S1394_TNF_SL_ARREQ_STACK
, "");
179 return (DDI_SUCCESS
);
184 * s1394_claim_addr_blk()
185 * is called when a target driver is requesting a block of 1394 Address
186 * Space with a specific address. If the block containing that address
187 * is not in the free list, or if the block is too small, then
188 * s1394_claim_addr_blk() returns failure. If the block is found,
189 * however, it is inserted into the used tree.
192 s1394_claim_addr_blk(s1394_hal_t
*hal
, t1394_alloc_addr_t
*addr_allocp
)
194 s1394_addr_space_blk_t
*curr_blk
;
195 s1394_addr_space_blk_t
*new_blk
;
196 s1394_addr_space_blk_t
*middle_blk
;
197 uint64_t upper_bound
;
199 TNF_PROBE_0_DEBUG(s1394_claim_addr_blk_enter
,
200 S1394_TNF_SL_ARREQ_STACK
, "");
204 /* Lock the address space "free" list */
205 mutex_enter(&hal
->addr_space_free_mutex
);
207 /* Find the block in the "free" list */
208 curr_blk
= s1394_free_list_search(hal
, addr_allocp
->aa_address
);
210 /* If it wasn't found, it isn't free... */
211 if (curr_blk
== NULL
) {
212 /* Unlock the address space free list */
213 mutex_exit(&hal
->addr_space_free_mutex
);
215 TNF_PROBE_1(s1394_claim_addr_blk_error
,
216 S1394_TNF_SL_ARREQ_ERROR
, "", tnf_string
, msg
,
217 "1394 address space - address unavailable");
218 TNF_PROBE_0_DEBUG(s1394_claim_addr_blk_exit
,
219 S1394_TNF_SL_ARREQ_STACK
, "");
220 return (DDI_FAILURE
);
223 /* Does the request fit in the block? */
224 upper_bound
= (addr_allocp
->aa_address
+ addr_allocp
->aa_length
) - 1;
225 if ((upper_bound
>= curr_blk
->addr_lo
) &&
226 (upper_bound
<= curr_blk
->addr_hi
)) {
228 /* How does the requested range fit in the current range? */
229 if (addr_allocp
->aa_address
== curr_blk
->addr_lo
) {
230 if (upper_bound
== curr_blk
->addr_hi
) {
233 /* Take it out of the "free" list */
234 curr_blk
= s1394_free_list_delete(hal
,
237 /* Unlock the address space "free" list */
238 mutex_exit(&hal
->addr_space_free_mutex
);
240 curr_blk
->addr_enable
= addr_allocp
->aa_enable
;
241 curr_blk
->kmem_bufp
= addr_allocp
->aa_kmem_bufp
;
242 curr_blk
->addr_arg
= addr_allocp
->aa_arg
;
243 curr_blk
->addr_events
= addr_allocp
->aa_evts
;
245 addr_allocp
->aa_hdl
=
246 (t1394_addr_handle_t
)curr_blk
;
248 /* Put it into the "used" tree */
249 s1394_used_tree_insert(hal
, curr_blk
);
251 s1394_addr_alloc_kstat(hal
,
252 addr_allocp
->aa_address
);
254 TNF_PROBE_0_DEBUG(s1394_claim_addr_blk_exit
,
255 S1394_TNF_SL_ARREQ_STACK
, "");
256 return (DDI_SUCCESS
);
259 /* If space is reserved, must claim it all */
260 if (curr_blk
->addr_reserved
== ADDR_RESERVED
) {
264 /* Front part of range */
265 new_blk
= (s1394_addr_space_blk_t
*)
266 kmem_zalloc(sizeof (s1394_addr_space_blk_t
),
268 if (new_blk
== NULL
) {
269 /* Unlock the addr space "free" list */
270 mutex_exit(&hal
->addr_space_free_mutex
);
271 TNF_PROBE_0(s1394_claim_addr_blk_error
,
272 S1394_TNF_SL_ARREQ_ERROR
, "");
274 s1394_claim_addr_blk_exit
,
275 S1394_TNF_SL_ARREQ_STACK
, "");
276 return (DDI_FAILURE
);
279 new_blk
->addr_lo
= curr_blk
->addr_lo
;
280 new_blk
->addr_hi
= upper_bound
;
281 new_blk
->addr_type
= curr_blk
->addr_type
;
282 new_blk
->addr_enable
= addr_allocp
->aa_enable
;
283 new_blk
->kmem_bufp
= addr_allocp
->aa_kmem_bufp
;
284 new_blk
->addr_arg
= addr_allocp
->aa_arg
;
285 new_blk
->addr_events
= addr_allocp
->aa_evts
;
287 curr_blk
->addr_lo
= new_blk
->addr_hi
+ 1;
289 addr_allocp
->aa_hdl
=
290 (t1394_addr_handle_t
)new_blk
;
292 /* Unlock the address space free list */
293 mutex_exit(&hal
->addr_space_free_mutex
);
295 /* Put it into the "used" tree */
296 s1394_used_tree_insert(hal
, new_blk
);
298 s1394_addr_alloc_kstat(hal
,
299 addr_allocp
->aa_address
);
301 TNF_PROBE_0_DEBUG(s1394_claim_addr_blk_exit
,
302 S1394_TNF_SL_ARREQ_STACK
, "");
303 return (DDI_SUCCESS
);
307 if (upper_bound
== curr_blk
->addr_hi
) {
308 /* If space is reserved, must claim it all */
309 if (curr_blk
->addr_reserved
== ADDR_RESERVED
) {
313 /* End part of range */
314 new_blk
= (s1394_addr_space_blk_t
*)
315 kmem_zalloc(sizeof (s1394_addr_space_blk_t
),
317 if (new_blk
== NULL
) {
318 /* Unlock the addr space "free" list */
319 mutex_exit(&hal
->addr_space_free_mutex
);
320 TNF_PROBE_0(s1394_claim_addr_blk_error
,
321 S1394_TNF_SL_ARREQ_ERROR
, "");
323 (s1394_claim_addr_blk_exit
,
324 S1394_TNF_SL_ARREQ_STACK
, "");
325 return (DDI_FAILURE
);
328 new_blk
->addr_lo
= addr_allocp
->aa_address
;
329 new_blk
->addr_hi
= upper_bound
;
330 new_blk
->addr_type
= curr_blk
->addr_type
;
331 new_blk
->addr_enable
= addr_allocp
->aa_enable
;
332 new_blk
->kmem_bufp
= addr_allocp
->aa_kmem_bufp
;
333 new_blk
->addr_arg
= addr_allocp
->aa_arg
;
334 new_blk
->addr_events
= addr_allocp
->aa_evts
;
336 curr_blk
->addr_hi
= addr_allocp
->aa_address
- 1;
338 addr_allocp
->aa_hdl
=
339 (t1394_addr_handle_t
)new_blk
;
341 /* Unlock the address space free list */
342 mutex_exit(&hal
->addr_space_free_mutex
);
344 /* Put it into the "used" tree */
345 s1394_used_tree_insert(hal
, new_blk
);
347 s1394_addr_alloc_kstat(hal
,
348 addr_allocp
->aa_address
);
350 TNF_PROBE_0_DEBUG(s1394_claim_addr_blk_exit
,
351 S1394_TNF_SL_ARREQ_STACK
, "");
352 return (DDI_SUCCESS
);
355 /* If space is reserved, must claim it all */
356 if (curr_blk
->addr_reserved
== ADDR_RESERVED
) {
360 /* Middle part of range */
361 new_blk
= (s1394_addr_space_blk_t
*)
362 kmem_zalloc(sizeof (s1394_addr_space_blk_t
),
364 if (new_blk
== NULL
) {
365 /* Unlock the addr space "free" list */
366 mutex_exit(&hal
->addr_space_free_mutex
);
367 TNF_PROBE_0(s1394_claim_addr_blk_error
,
368 S1394_TNF_SL_ARREQ_ERROR
, "");
370 s1394_claim_addr_blk_exit
,
371 S1394_TNF_SL_ARREQ_STACK
, "");
372 return (DDI_FAILURE
);
375 middle_blk
= (s1394_addr_space_blk_t
*)
376 kmem_zalloc(sizeof (s1394_addr_space_blk_t
),
378 if (middle_blk
== NULL
) {
379 /* Unlock the addr space "free" list */
380 mutex_exit(&hal
->addr_space_free_mutex
);
382 sizeof (s1394_addr_space_blk_t
));
383 TNF_PROBE_0(s1394_claim_addr_blk_error
,
384 S1394_TNF_SL_ARREQ_ERROR
, "");
386 (s1394_claim_addr_blk_exit
,
387 S1394_TNF_SL_ARREQ_STACK
, "");
388 return (DDI_FAILURE
);
391 middle_blk
->addr_lo
= addr_allocp
->aa_address
;
392 middle_blk
->addr_hi
= upper_bound
;
393 new_blk
->addr_lo
= upper_bound
+ 1;
394 new_blk
->addr_hi
= curr_blk
->addr_hi
;
396 new_blk
->addr_type
= curr_blk
->addr_type
;
398 middle_blk
->addr_type
= curr_blk
->addr_type
;
399 middle_blk
->addr_enable
=
400 addr_allocp
->aa_enable
;
401 middle_blk
->kmem_bufp
=
402 addr_allocp
->aa_kmem_bufp
;
403 middle_blk
->addr_arg
= addr_allocp
->aa_arg
;
404 middle_blk
->addr_events
= addr_allocp
->aa_evts
;
406 curr_blk
->addr_hi
= addr_allocp
->aa_address
- 1;
408 addr_allocp
->aa_hdl
=
409 (t1394_addr_handle_t
)middle_blk
;
411 /* Put part back into the "free" tree */
412 s1394_free_list_insert(hal
, new_blk
);
414 /* Unlock the address space free list */
415 mutex_exit(&hal
->addr_space_free_mutex
);
417 /* Put it into the "used" tree */
418 s1394_used_tree_insert(hal
, middle_blk
);
420 s1394_addr_alloc_kstat(hal
,
421 addr_allocp
->aa_address
);
423 TNF_PROBE_0_DEBUG(s1394_claim_addr_blk_exit
,
424 S1394_TNF_SL_ARREQ_STACK
, "");
425 return (DDI_SUCCESS
);
431 /* Unlock the address space free list */
432 mutex_exit(&hal
->addr_space_free_mutex
);
434 TNF_PROBE_0_DEBUG(s1394_claim_addr_blk_exit
,
435 S1394_TNF_SL_ARREQ_STACK
, "");
436 return (DDI_FAILURE
);
440 * s1394_free_addr_blk()
441 * An opposite of s1394_claim_addr_blk(): takes the address block
442 * out of the "used" tree and puts it into the "free" tree.
445 s1394_free_addr_blk(s1394_hal_t
*hal
, s1394_addr_space_blk_t
*blk
)
447 TNF_PROBE_0_DEBUG(s1394_free_addr_blk_enter
, S1394_TNF_SL_ARREQ_STACK
,
450 /* Lock the address space "free" list */
451 mutex_enter(&hal
->addr_space_free_mutex
);
453 /* Take it out of the "used" tree */
454 blk
= s1394_used_tree_delete(hal
, blk
);
457 /* Unlock the address space "free" list */
458 mutex_exit(&hal
->addr_space_free_mutex
);
459 TNF_PROBE_1(s1394_free_addr_blk_error
,
460 S1394_TNF_SL_ARREQ_ERROR
, "", tnf_string
, msg
,
461 "Can't free block not found in used list");
462 TNF_PROBE_0_DEBUG(s1394_free_addr_blk_exit
,
463 S1394_TNF_SL_ARREQ_STACK
, "");
464 return (DDI_FAILURE
);
467 /* Put it into the "free" tree */
468 s1394_free_list_insert(hal
, blk
);
470 /* Unlock the address space "free" list */
471 mutex_exit(&hal
->addr_space_free_mutex
);
473 TNF_PROBE_0_DEBUG(s1394_free_addr_blk_exit
, S1394_TNF_SL_ARREQ_STACK
,
475 return (DDI_SUCCESS
);
479 * s1394_reserve_addr_blk()
480 * is similar to s1394_claim_addr_blk(), with the difference being that
481 * after the address block is found, it is marked as "reserved" rather
482 * than inserted into the used tree. Blocks of data that are marked
483 * "reserved" cannot be unintentionally allocated by a target, they must
484 * be specifically requested by specifying the exact address and size of
485 * the "reserved" block.
488 s1394_reserve_addr_blk(s1394_hal_t
*hal
, t1394_alloc_addr_t
*addr_allocp
)
490 s1394_addr_space_blk_t
*curr_blk
;
491 s1394_addr_space_blk_t
*new_blk
;
492 s1394_addr_space_blk_t
*middle_blk
;
493 uint64_t upper_bound
;
495 TNF_PROBE_0_DEBUG(s1394_reserve_addr_blk_enter
,
496 S1394_TNF_SL_ARREQ_STACK
, "");
500 /* Lock the address space "free" list */
501 mutex_enter(&hal
->addr_space_free_mutex
);
503 /* Find the block in the "free" list */
504 curr_blk
= s1394_free_list_search(hal
, addr_allocp
->aa_address
);
505 /* If it wasn't found, it isn't free... */
506 if (curr_blk
== NULL
) {
507 /* Unlock the address space free list */
508 mutex_exit(&hal
->addr_space_free_mutex
);
510 TNF_PROBE_1(s1394_reserve_addr_blk_error
,
511 S1394_TNF_SL_ARREQ_ERROR
, "", tnf_string
, msg
,
512 "1394 address space - address unavailable");
513 TNF_PROBE_0_DEBUG(s1394_reserve_addr_blk_exit
,
514 S1394_TNF_SL_ARREQ_STACK
, "");
515 return (DDI_FAILURE
);
518 /* Is this block already reserved? */
519 if (curr_blk
->addr_reserved
== ADDR_RESERVED
) {
520 /* Unlock the address space free list */
521 mutex_exit(&hal
->addr_space_free_mutex
);
523 TNF_PROBE_0_DEBUG(s1394_reserve_addr_blk_exit
,
524 S1394_TNF_SL_ARREQ_STACK
, "");
525 return (DDI_FAILURE
);
528 /* Does the request fit in the block? */
529 upper_bound
= (addr_allocp
->aa_address
+ addr_allocp
->aa_length
) - 1;
530 if ((upper_bound
>= curr_blk
->addr_lo
) &&
531 (upper_bound
<= curr_blk
->addr_hi
)) {
533 /* How does the requested range fit in the current range? */
534 if (addr_allocp
->aa_address
== curr_blk
->addr_lo
) {
535 if (upper_bound
== curr_blk
->addr_hi
) {
537 curr_blk
->addr_reserved
= ADDR_RESERVED
;
539 /* Unlock the address space "free" list */
540 mutex_exit(&hal
->addr_space_free_mutex
);
542 TNF_PROBE_0_DEBUG(s1394_reserve_addr_blk_exit
,
543 S1394_TNF_SL_ARREQ_STACK
, "");
544 return (DDI_SUCCESS
);
547 /* Front part of range */
548 new_blk
= (s1394_addr_space_blk_t
*)
549 kmem_zalloc(sizeof (s1394_addr_space_blk_t
),
551 if (new_blk
== NULL
) {
552 /* Unlock the addr space "free" list */
553 mutex_exit(&hal
->addr_space_free_mutex
);
555 s1394_reserve_addr_blk_error
,
556 S1394_TNF_SL_ARREQ_ERROR
, "");
558 s1394_reserve_addr_blk_exit
,
559 S1394_TNF_SL_ARREQ_STACK
, "");
560 return (DDI_FAILURE
);
563 new_blk
->addr_lo
= curr_blk
->addr_lo
;
564 new_blk
->addr_hi
= upper_bound
;
565 new_blk
->addr_type
= curr_blk
->addr_type
;
566 new_blk
->addr_reserved
= ADDR_RESERVED
;
568 curr_blk
->addr_lo
= new_blk
->addr_hi
+ 1;
570 /* Put it back into the "free" list */
571 s1394_free_list_insert(hal
, new_blk
);
573 /* Unlock the address space free list */
574 mutex_exit(&hal
->addr_space_free_mutex
);
576 TNF_PROBE_0_DEBUG(s1394_reserve_addr_blk_exit
,
577 "stacktrace 1394 s1394 arreq", "");
578 return (DDI_SUCCESS
);
582 if (upper_bound
== curr_blk
->addr_hi
) {
583 /* End part of range */
584 new_blk
= (s1394_addr_space_blk_t
*)
585 kmem_zalloc(sizeof (s1394_addr_space_blk_t
),
587 if (new_blk
== NULL
) {
588 /* Unlock the addr space "free" list */
589 mutex_exit(&hal
->addr_space_free_mutex
);
591 s1394_reserve_addr_blk_error
,
592 S1394_TNF_SL_ARREQ_ERROR
, "");
594 s1394_reserve_addr_blk_exit
,
595 S1394_TNF_SL_ARREQ_STACK
, "");
596 return (DDI_FAILURE
);
599 new_blk
->addr_lo
= addr_allocp
->aa_address
;
600 new_blk
->addr_hi
= upper_bound
;
601 new_blk
->addr_type
= curr_blk
->addr_type
;
602 new_blk
->addr_reserved
= ADDR_RESERVED
;
604 curr_blk
->addr_hi
= addr_allocp
->aa_address
- 1;
606 /* Put it back into the "free" list */
607 s1394_free_list_insert(hal
, new_blk
);
609 /* Unlock the address space free list */
610 mutex_exit(&hal
->addr_space_free_mutex
);
612 TNF_PROBE_0_DEBUG(s1394_reserve_addr_blk_exit
,
613 S1394_TNF_SL_ARREQ_STACK
, "");
614 return (DDI_SUCCESS
);
617 /* Middle part of range */
618 new_blk
= (s1394_addr_space_blk_t
*)
619 kmem_zalloc(sizeof (s1394_addr_space_blk_t
),
621 if (new_blk
== NULL
) {
622 /* Unlock the addr space "free" list */
623 mutex_exit(&hal
->addr_space_free_mutex
);
625 s1394_reserve_addr_blk_error
,
626 S1394_TNF_SL_ARREQ_ERROR
, "");
628 s1394_reserve_addr_blk_exit
,
629 S1394_TNF_SL_ARREQ_STACK
, "");
630 return (DDI_FAILURE
);
633 middle_blk
= (s1394_addr_space_blk_t
*)
634 kmem_zalloc(sizeof (s1394_addr_space_blk_t
),
636 if (middle_blk
== NULL
) {
637 /* Unlock the addr space "free" list */
638 mutex_exit(&hal
->addr_space_free_mutex
);
640 sizeof (s1394_addr_space_blk_t
));
642 s1394_reserve_addr_blk_error
,
643 S1394_TNF_SL_ARREQ_ERROR
, "");
645 s1394_reserve_addr_blk_exit
,
646 S1394_TNF_SL_ARREQ_STACK
, "");
647 return (DDI_FAILURE
);
650 middle_blk
->addr_lo
= addr_allocp
->aa_address
;
651 middle_blk
->addr_hi
= upper_bound
;
652 new_blk
->addr_lo
= upper_bound
+ 1;
653 new_blk
->addr_hi
= curr_blk
->addr_hi
;
655 new_blk
->addr_type
= curr_blk
->addr_type
;
657 middle_blk
->addr_type
= curr_blk
->addr_type
;
658 middle_blk
->addr_reserved
= ADDR_RESERVED
;
660 curr_blk
->addr_hi
= addr_allocp
->aa_address
- 1;
662 /* Put pieces back into the "free" list */
663 s1394_free_list_insert(hal
, middle_blk
);
664 s1394_free_list_insert(hal
, new_blk
);
666 /* Unlock the address space free list */
667 mutex_exit(&hal
->addr_space_free_mutex
);
669 TNF_PROBE_0_DEBUG(s1394_reserve_addr_blk_exit
,
670 S1394_TNF_SL_ARREQ_STACK
, "");
671 return (DDI_SUCCESS
);
676 /* Unlock the address space free list */
677 mutex_exit(&hal
->addr_space_free_mutex
);
679 TNF_PROBE_0_DEBUG(s1394_reserve_addr_blk_exit
,
680 S1394_TNF_SL_ARREQ_STACK
, "");
681 return (DDI_FAILURE
);
685 * s1394_init_addr_space()
686 * is called in the HAL attach routine - h1394_attach() - to setup the
687 * initial address space with the appropriate ranges, etc. At attach,
688 * the HAL specifies not only the type and bounds for each kind of 1394
689 * address space, but also a list of the blocks that are to be marked
690 * ¨reserved". Prior to marking the "reserved" ranges the local hosts
691 * CSR registers are allocated/setup in s1394_setup_CSR_space().
694 s1394_init_addr_space(s1394_hal_t
*hal
)
696 s1394_addr_space_blk_t
*addr_blk
;
697 t1394_alloc_addr_t addr_alloc
;
698 h1394_addr_map_t
*addr_map
;
699 h1394_addr_map_t
*resv_map
;
706 TNF_PROBE_0_DEBUG(s1394_init_addr_space_enter
,
707 S1394_TNF_SL_ARREQ_STACK
, "");
709 /* Setup Address Space */
710 mutex_init(&hal
->addr_space_free_mutex
,
711 NULL
, MUTEX_DRIVER
, NULL
);
712 mutex_init(&hal
->addr_space_used_mutex
,
713 NULL
, MUTEX_DRIVER
, hal
->halinfo
.hw_interrupt
);
715 /* Set address space to NULL (empty) */
716 hal
->addr_space_free_list
= NULL
;
717 hal
->addr_space_used_tree
= NULL
;
719 /* Initialize the 1394 Address Space from HAL's description */
720 num_blks
= hal
->halinfo
.addr_map_num_entries
;
721 addr_map
= hal
->halinfo
.addr_map
;
723 /* Lock the address space free list */
724 mutex_enter(&hal
->addr_space_free_mutex
);
726 /* Default to NO posted write space */
727 hal
->posted_write_addr_lo
= ADDR_LO_INVALID
;
728 hal
->posted_write_addr_hi
= ADDR_HI_INVALID
;
730 /* Default to NO physical space */
731 hal
->physical_addr_lo
= ADDR_LO_INVALID
;
732 hal
->physical_addr_hi
= ADDR_HI_INVALID
;
734 /* Default to NO CSR space */
735 hal
->csr_addr_lo
= ADDR_LO_INVALID
;
736 hal
->csr_addr_hi
= ADDR_HI_INVALID
;
738 /* Default to NO normal space */
739 hal
->normal_addr_lo
= ADDR_LO_INVALID
;
740 hal
->normal_addr_hi
= ADDR_HI_INVALID
;
742 for (i
= 0; i
< num_blks
; i
++) {
743 if (addr_map
[i
].length
== 0)
745 addr_blk
= kmem_zalloc(sizeof (s1394_addr_space_blk_t
),
747 addr_blk
->addr_lo
= addr_map
[i
].address
;
749 (addr_blk
->addr_lo
+ addr_map
[i
].length
) - 1;
751 switch (addr_map
[i
].addr_type
) {
752 case H1394_ADDR_POSTED_WRITE
:
753 addr_blk
->addr_type
= T1394_ADDR_POSTED_WRITE
;
754 hal
->posted_write_addr_lo
= addr_blk
->addr_lo
;
755 hal
->posted_write_addr_hi
= addr_blk
->addr_hi
;
758 case H1394_ADDR_NORMAL
:
759 addr_blk
->addr_type
= T1394_ADDR_NORMAL
;
760 hal
->normal_addr_lo
= addr_blk
->addr_lo
;
761 hal
->normal_addr_hi
= addr_blk
->addr_hi
;
765 addr_blk
->addr_type
= T1394_ADDR_CSR
;
766 hal
->csr_addr_lo
= addr_blk
->addr_lo
;
767 hal
->csr_addr_hi
= addr_blk
->addr_hi
;
770 case H1394_ADDR_PHYSICAL
:
771 addr_blk
->addr_type
= T1394_ADDR_FIXED
;
772 hal
->physical_addr_lo
= addr_blk
->addr_lo
;
773 hal
->physical_addr_hi
= addr_blk
->addr_hi
;
777 /* Unlock the address space free list */
778 mutex_exit(&hal
->addr_space_free_mutex
);
779 s1394_destroy_addr_space(hal
);
780 TNF_PROBE_1(s1394_init_addr_space_error
,
781 S1394_TNF_SL_ARREQ_ERROR
, "", tnf_string
, msg
,
782 "Invalid addr_type specified");
783 TNF_PROBE_0_DEBUG(s1394_init_addr_space_exit
,
784 S1394_TNF_SL_ARREQ_STACK
, "");
785 return (DDI_FAILURE
);
787 s1394_free_list_insert(hal
, addr_blk
);
790 /* Unlock the address space free list */
791 mutex_exit(&hal
->addr_space_free_mutex
);
793 /* Setup the necessary CSR space */
794 if (s1394_setup_CSR_space(hal
) != DDI_SUCCESS
) {
795 s1394_destroy_addr_space(hal
);
796 TNF_PROBE_1(s1394_init_addr_space_error
,
797 S1394_TNF_SL_ARREQ_ERROR
, "", tnf_string
, msg
,
798 "Failed in s1394_setup_CSR_space()");
799 TNF_PROBE_0_DEBUG(s1394_init_addr_space_exit
,
800 S1394_TNF_SL_ARREQ_STACK
, "");
801 return (DDI_FAILURE
);
805 /* Handle all the HAL's reserved spaces */
806 num_blks
= hal
->halinfo
.resv_map_num_entries
;
807 resv_map
= hal
->halinfo
.resv_map
;
809 for (i
= 0; i
< num_blks
; i
++) {
810 /* Can't reserve physical addresses */
811 lo
= resv_map
[i
].address
;
812 hi
= (lo
+ resv_map
[i
].length
) - 1;
813 if ((lo
>= hal
->physical_addr_lo
) &&
814 (hi
<= hal
->physical_addr_hi
)) {
815 s1394_destroy_addr_space(hal
);
816 TNF_PROBE_1(s1394_init_addr_space_error
,
817 S1394_TNF_SL_ARREQ_ERROR
, "", tnf_string
, msg
,
818 "Attempted to reserve physical memory");
819 TNF_PROBE_0_DEBUG(s1394_init_addr_space_exit
,
820 S1394_TNF_SL_ARREQ_STACK
, "");
821 return (DDI_FAILURE
);
824 addr_alloc
.aa_address
= resv_map
[i
].address
;
825 addr_alloc
.aa_length
= resv_map
[i
].length
;
826 ret
= s1394_reserve_addr_blk(hal
, &addr_alloc
);
827 if (ret
!= DDI_SUCCESS
) {
828 s1394_destroy_addr_space(hal
);
829 TNF_PROBE_1(s1394_init_addr_space_error
,
830 S1394_TNF_SL_ARREQ_ERROR
, "", tnf_string
, msg
,
831 "Unable to reserve 1394 address");
832 TNF_PROBE_0_DEBUG(s1394_init_addr_space_exit
,
833 S1394_TNF_SL_ARREQ_STACK
, "");
834 return (DDI_FAILURE
);
838 TNF_PROBE_0_DEBUG(s1394_init_addr_space_exit
, S1394_TNF_SL_ARREQ_STACK
,
840 return (DDI_SUCCESS
);
844 * s1394_destroy_addr_space()
845 * is necessary for h1394_detach(). It undoes all the work that
846 * s1394_init_addr_space() had setup and more. By pulling everything out
847 * of the used tree and free list and then freeing the structures,
848 * mutexes, and (if necessary) any backing store memory, the 1394 address
849 * space is completely dismantled.
852 s1394_destroy_addr_space(s1394_hal_t
*hal
)
854 s1394_addr_space_blk_t
*addr_blk
;
855 s1394_addr_space_blk_t
*next_blk
;
860 TNF_PROBE_0_DEBUG(s1394_destroy_addr_space_enter
,
861 S1394_TNF_SL_ARREQ_STACK
, "");
863 /* Lock the address space "used" tree */
864 mutex_enter(&hal
->addr_space_used_mutex
);
866 addr_blk
= hal
->addr_space_used_tree
;
868 while (addr_blk
!= NULL
) {
869 if (addr_blk
->asb_left
!= NULL
) {
870 addr_blk
= addr_blk
->asb_left
;
871 } else if (addr_blk
->asb_right
!= NULL
) {
872 addr_blk
= addr_blk
->asb_right
;
874 /* Free any of our own backing store (if necessary) */
875 if ((addr_blk
->free_kmem_bufp
== B_TRUE
) &&
876 (addr_blk
->kmem_bufp
!= NULL
)) {
877 lo
= addr_blk
->addr_lo
;
878 hi
= addr_blk
->addr_hi
;
879 length
= (uint_t
)((hi
- lo
) + 1);
880 kmem_free((void *)addr_blk
->kmem_bufp
, length
);
883 next_blk
= addr_blk
->asb_parent
;
885 /* Free the s1394_addr_space_blk_t structure */
886 kmem_free((void *)addr_blk
,
887 sizeof (s1394_addr_space_blk_t
));
889 if (next_blk
!= NULL
) {
890 if (next_blk
->asb_left
!= NULL
)
891 next_blk
->asb_left
= NULL
;
893 next_blk
->asb_right
= NULL
;
900 /* Unlock and destroy the address space "used" tree */
901 mutex_exit(&hal
->addr_space_used_mutex
);
902 mutex_destroy(&hal
->addr_space_used_mutex
);
904 /* Lock the address space "free" list */
905 mutex_enter(&hal
->addr_space_free_mutex
);
907 addr_blk
= hal
->addr_space_free_list
;
909 while (addr_blk
!= NULL
) {
910 next_blk
= addr_blk
->asb_right
;
912 /* Free the s1394_addr_space_blk_t structure */
913 kmem_free((void *)addr_blk
, sizeof (s1394_addr_space_blk_t
));
917 /* Unlock & destroy the address space "free" list */
918 mutex_exit(&hal
->addr_space_free_mutex
);
919 mutex_destroy(&hal
->addr_space_free_mutex
);
921 TNF_PROBE_0_DEBUG(s1394_destroy_addr_space_exit
,
922 S1394_TNF_SL_ARREQ_STACK
, "");
926 * s1394_free_list_insert()
927 * takes an s1394_addr_space_blk_t and inserts it into the free list in the
928 * appropriate place. It will concatenate into a single structure on the
929 * list any two neighboring blocks that can be joined (same type,
930 * consecutive addresses, neither is "reserved", etc.)
933 s1394_free_list_insert(s1394_hal_t
*hal
, s1394_addr_space_blk_t
*new_blk
)
935 s1394_addr_space_blk_t
*curr_blk
;
936 s1394_addr_space_blk_t
*left_blk
;
937 s1394_addr_space_blk_t
*right_blk
;
939 TNF_PROBE_0_DEBUG(s1394_free_list_insert_enter
,
940 S1394_TNF_SL_ARREQ_STACK
, "");
942 ASSERT(MUTEX_HELD(&hal
->addr_space_free_mutex
));
944 /* Start at the head of the "free" list */
945 curr_blk
= hal
->addr_space_free_list
;
947 if (curr_blk
!= NULL
)
948 left_blk
= curr_blk
->asb_left
;
952 while (curr_blk
!= NULL
) {
953 if (new_blk
->addr_lo
< curr_blk
->addr_lo
)
955 /* Go to the next element in the list */
957 curr_blk
= curr_blk
->asb_right
;
960 new_blk
->asb_left
= left_blk
;
961 new_blk
->asb_right
= curr_blk
;
963 if (left_blk
!= NULL
)
964 left_blk
->asb_right
= new_blk
;
966 hal
->addr_space_free_list
= new_blk
;
968 if (curr_blk
!= NULL
)
969 curr_blk
->asb_left
= new_blk
;
971 right_blk
= new_blk
->asb_right
;
972 left_blk
= new_blk
->asb_left
;
974 /* Can we merge with block to the left? */
975 if ((left_blk
!= NULL
) &&
976 (new_blk
->addr_type
== left_blk
->addr_type
) &&
977 (new_blk
->addr_reserved
!= ADDR_RESERVED
) &&
978 (left_blk
->addr_reserved
!= ADDR_RESERVED
) &&
979 (new_blk
->addr_lo
== left_blk
->addr_hi
+ 1)) {
981 new_blk
->addr_lo
= left_blk
->addr_lo
;
982 new_blk
->asb_left
= left_blk
->asb_left
;
984 if (left_blk
->asb_left
!= NULL
)
985 left_blk
->asb_left
->asb_right
= new_blk
;
986 if (hal
->addr_space_free_list
== left_blk
)
987 hal
->addr_space_free_list
= new_blk
;
988 kmem_free((void *)left_blk
, sizeof (s1394_addr_space_blk_t
));
991 /* Can we merge with block to the right? */
992 if ((right_blk
!= NULL
) &&
993 (new_blk
->addr_type
== right_blk
->addr_type
) &&
994 (new_blk
->addr_reserved
!= ADDR_RESERVED
) &&
995 (right_blk
->addr_reserved
!= ADDR_RESERVED
) &&
996 (new_blk
->addr_hi
+ 1 == right_blk
->addr_lo
)) {
998 new_blk
->addr_hi
= right_blk
->addr_hi
;
999 new_blk
->asb_right
= right_blk
->asb_right
;
1001 if (right_blk
->asb_right
!= NULL
)
1002 right_blk
->asb_right
->asb_left
= new_blk
;
1003 kmem_free((void *)right_blk
, sizeof (s1394_addr_space_blk_t
));
1006 new_blk
->addr_enable
= 0;
1007 new_blk
->kmem_bufp
= NULL
;
1008 new_blk
->addr_arg
= NULL
;
1010 TNF_PROBE_0_DEBUG(s1394_free_list_insert_exit
,
1011 S1394_TNF_SL_ARREQ_STACK
, "");
1015 * s1394_free_list_search()
1016 * attempts to find a block in the free list that contains the address
1017 * specified. If none is found, it returns NULL.
1019 static s1394_addr_space_blk_t
*
1020 s1394_free_list_search(s1394_hal_t
*hal
, uint64_t addr
)
1022 s1394_addr_space_blk_t
*curr_blk
;
1024 TNF_PROBE_0_DEBUG(s1394_free_list_search_enter
,
1025 S1394_TNF_SL_ARREQ_STACK
, "");
1027 ASSERT(MUTEX_HELD(&hal
->addr_space_free_mutex
));
1029 /* Start at the head of the list */
1030 curr_blk
= hal
->addr_space_free_list
;
1031 while (curr_blk
!= NULL
) {
1032 if ((addr
>= curr_blk
->addr_lo
) && (addr
<= curr_blk
->addr_hi
))
1035 curr_blk
= curr_blk
->asb_right
;
1038 TNF_PROBE_0_DEBUG(s1394_free_list_search_exit
,
1039 S1394_TNF_SL_ARREQ_STACK
, "");
1044 * s1394_free_list_find()
1045 * attempts to find a block in the free list that is of the specified
1046 * type and size. It will ignore any blocks marked "reserved".
1048 static s1394_addr_space_blk_t
*
1049 s1394_free_list_find(s1394_hal_t
*hal
, uint32_t type
, uint32_t length
)
1051 s1394_addr_space_blk_t
*curr_blk
;
1054 TNF_PROBE_0_DEBUG(s1394_free_list_find_enter
, S1394_TNF_SL_ARREQ_STACK
,
1057 ASSERT(MUTEX_HELD(&hal
->addr_space_free_mutex
));
1059 /* Start at the head of the list */
1060 curr_blk
= hal
->addr_space_free_list
;
1062 while (curr_blk
!= NULL
) {
1063 /* Find block of right "type" - that isn't "reserved" */
1064 if ((curr_blk
->addr_type
== type
) &&
1065 (curr_blk
->addr_reserved
!= ADDR_RESERVED
)) {
1067 /* CSR allocs above IEEE1394_UCSR_RESERVED_BOUNDARY */
1068 if ((type
== T1394_ADDR_CSR
) &&
1069 (curr_blk
->addr_lo
<
1070 IEEE1394_UCSR_RESERVED_BOUNDARY
)) {
1071 curr_blk
= curr_blk
->asb_right
;
1075 size
= (curr_blk
->addr_hi
- curr_blk
->addr_lo
) + 1;
1076 if (size
>= (uint64_t)length
)
1079 curr_blk
= curr_blk
->asb_right
;
1082 TNF_PROBE_0_DEBUG(s1394_free_list_find_exit
, S1394_TNF_SL_ARREQ_STACK
,
1088 * s1394_free_list_delete()
1089 * will remove the block pointed to by del_blk from the free list.
1090 * Typically, this is done so that it may be inserted into the used tree.
1092 static s1394_addr_space_blk_t
*
1093 s1394_free_list_delete(s1394_hal_t
*hal
, s1394_addr_space_blk_t
*del_blk
)
1095 s1394_addr_space_blk_t
*left_blk
;
1096 s1394_addr_space_blk_t
*right_blk
;
1098 TNF_PROBE_0_DEBUG(s1394_free_list_delete_enter
,
1099 S1394_TNF_SL_ARREQ_STACK
, "");
1101 ASSERT(MUTEX_HELD(&hal
->addr_space_free_mutex
));
1103 left_blk
= del_blk
->asb_left
;
1104 right_blk
= del_blk
->asb_right
;
1106 del_blk
->asb_left
= NULL
;
1107 del_blk
->asb_right
= NULL
;
1109 if (left_blk
!= NULL
)
1110 left_blk
->asb_right
= right_blk
;
1112 hal
->addr_space_free_list
= right_blk
;
1114 if (right_blk
!= NULL
)
1115 right_blk
->asb_left
= left_blk
;
1117 TNF_PROBE_0_DEBUG(s1394_free_list_delete_exit
,
1118 S1394_TNF_SL_ARREQ_STACK
, "");
1123 * s1394_used_tree_insert()
1124 * is used to insert a 1394 address block that has been removed from the
1125 * free list into the used tree. In the used tree it will be possible
1126 * to search for a given address when an AR request arrives. Since the
1127 * used tree is implemented as a red-black tree, the insertion is done
1128 * with s1394_tree_insert() which does a simple binary tree insertion.
1129 * It is then followed by cleanup of links and red-black coloring. This
1130 * particulat implementation of the red-black tree is modified from code
1131 * included in "Introduction to Algorithms" - Cormen, Leiserson, and Rivest,
1135 s1394_used_tree_insert(s1394_hal_t
*hal
, s1394_addr_space_blk_t
*x
)
1137 s1394_addr_space_blk_t
*y
;
1138 s1394_addr_space_blk_t
**root
;
1140 TNF_PROBE_0_DEBUG(s1394_used_tree_insert_enter
,
1141 S1394_TNF_SL_ARREQ_STACK
, "");
1143 /* Lock the "used" tree */
1144 mutex_enter(&hal
->addr_space_used_mutex
);
1146 /* Get the head of the "used" tree */
1147 root
= &hal
->addr_space_used_tree
;
1149 s1394_tree_insert(root
, x
);
1152 while ((x
!= *root
) && (x
->asb_parent
->asb_color
== RED
)) {
1153 /* Is x's parent the "left-child" or the "right-child"? */
1154 if (x
->asb_parent
== x
->asb_parent
->asb_parent
->asb_left
) {
1155 /* Left-child, set y to the sibling */
1156 y
= x
->asb_parent
->asb_parent
->asb_right
;
1157 if ((y
!= NULL
) && (y
->asb_color
== RED
)) {
1158 x
->asb_parent
->asb_color
= BLACK
;
1159 y
->asb_color
= BLACK
;
1160 x
->asb_parent
->asb_parent
->asb_color
= RED
;
1161 x
= x
->asb_parent
->asb_parent
;
1164 if (x
== x
->asb_parent
->asb_right
) {
1166 s1394_left_rotate(root
, x
);
1168 x
->asb_parent
->asb_color
= BLACK
;
1169 x
->asb_parent
->asb_parent
->asb_color
= RED
;
1170 s1394_right_rotate(root
,
1171 x
->asb_parent
->asb_parent
);
1175 /* Right-child, set y to the sibling */
1176 y
= x
->asb_parent
->asb_parent
->asb_left
;
1177 if ((y
!= NULL
) && (y
->asb_color
== RED
)) {
1178 x
->asb_parent
->asb_color
= BLACK
;
1179 y
->asb_color
= BLACK
;
1180 x
->asb_parent
->asb_parent
->asb_color
= RED
;
1181 x
= x
->asb_parent
->asb_parent
;
1184 if (x
== x
->asb_parent
->asb_left
) {
1186 s1394_right_rotate(root
, x
);
1188 x
->asb_parent
->asb_color
= BLACK
;
1189 x
->asb_parent
->asb_parent
->asb_color
= RED
;
1190 s1394_left_rotate(root
,
1191 x
->asb_parent
->asb_parent
);
1196 (*root
)->asb_color
= BLACK
;
1198 /* Unlock the "used" tree */
1199 mutex_exit(&hal
->addr_space_used_mutex
);
1201 TNF_PROBE_0_DEBUG(s1394_used_tree_insert_exit
,
1202 S1394_TNF_SL_ARREQ_STACK
, "");
1206 * s1394_tree_insert()
1207 * is a "helper" function for s1394_used_tree_insert(). It inserts an
1208 * address block into a binary tree (red-black tree), and
1209 * s1394_used_tree_insert() then cleans up the links and colorings, etc.
1212 s1394_tree_insert(s1394_addr_space_blk_t
**root
, s1394_addr_space_blk_t
*z
)
1214 s1394_addr_space_blk_t
*y
= NULL
;
1215 s1394_addr_space_blk_t
*x
= *root
;
1217 TNF_PROBE_0_DEBUG(s1394_tree_insert_enter
, S1394_TNF_SL_ARREQ_STACK
,
1222 if (z
->addr_lo
< x
->addr_lo
)
1229 z
->asb_right
= NULL
;
1234 else if (z
->addr_lo
< y
->addr_lo
)
1239 TNF_PROBE_0_DEBUG(s1394_tree_insert_exit
, S1394_TNF_SL_ARREQ_STACK
,
1244 * s1394_used_tree_search()
1245 * is called when an AR request arrives. By calling s1394_tree_search()
1246 * with the destination address, it can quickly find a block for that
1247 * address (if one exists in the used tree) and return a pointer to it.
1249 s1394_addr_space_blk_t
*
1250 s1394_used_tree_search(s1394_hal_t
*hal
, uint64_t addr
)
1252 s1394_addr_space_blk_t
*curr_blk
;
1254 TNF_PROBE_0_DEBUG(s1394_used_tree_search_enter
,
1255 S1394_TNF_SL_ARREQ_STACK
, "");
1257 ASSERT(MUTEX_HELD(&hal
->addr_space_used_mutex
));
1259 /* Search the HAL's "used" tree for this address */
1260 curr_blk
= s1394_tree_search(hal
->addr_space_used_tree
, addr
);
1262 TNF_PROBE_0_DEBUG(s1394_used_tree_search_exit
,
1263 S1394_TNF_SL_ARREQ_STACK
, "");
1268 * s1394_tree_search()
1269 * is a "helper" function for s1394_used_tree_search(). It implements a
1270 * typical binary tree search with the address as the search key.
1272 static s1394_addr_space_blk_t
*
1273 s1394_tree_search(s1394_addr_space_blk_t
*x
, uint64_t address
)
1275 TNF_PROBE_0_DEBUG(s1394_tree_search_enter
, S1394_TNF_SL_ARREQ_STACK
,
1279 if (x
->addr_lo
> address
)
1281 else if (x
->addr_hi
< address
)
1287 TNF_PROBE_0_DEBUG(s1394_tree_search_exit
, S1394_TNF_SL_ARREQ_STACK
,
1293 * s1394_used_tree_delete()
1294 * is used to remove an address block from the used tree. This is
1295 * necessary when address spaces are freed. The removal is accomplished
1296 * in two steps, the removal done by this function and the cleanup done
1297 * by s1394_used_tree_delete_fixup().
1299 s1394_addr_space_blk_t
*
1300 s1394_used_tree_delete(s1394_hal_t
*hal
, s1394_addr_space_blk_t
*z
)
1302 s1394_addr_space_blk_t
*y
;
1303 s1394_addr_space_blk_t
*x
;
1304 s1394_addr_space_blk_t
*w
;
1305 s1394_addr_space_blk_t
*p
;
1306 s1394_addr_space_blk_t
**root
;
1310 TNF_PROBE_0_DEBUG(s1394_used_tree_delete_enter
,
1311 S1394_TNF_SL_ARREQ_STACK
, "");
1313 /* Lock the "used" tree */
1314 mutex_enter(&hal
->addr_space_used_mutex
);
1316 /* Get the head of the "used" tree */
1317 root
= &hal
->addr_space_used_tree
;
1319 if ((z
->asb_left
== NULL
) || (z
->asb_right
== NULL
))
1322 y
= s1394_tree_successor(z
);
1324 if (y
->asb_parent
== z
)
1329 if (y
->asb_left
!= NULL
) {
1331 if ((y
!= *root
) && (y
== y
->asb_parent
->asb_left
)) {
1332 w
= y
->asb_parent
->asb_right
;
1336 if ((y
!= *root
) && (y
== y
->asb_parent
->asb_right
)) {
1337 w
= y
->asb_parent
->asb_left
;
1343 if ((y
!= *root
) && (y
== y
->asb_parent
->asb_left
)) {
1344 w
= y
->asb_parent
->asb_right
;
1348 if ((y
!= *root
) && (y
== y
->asb_parent
->asb_right
)) {
1349 w
= y
->asb_parent
->asb_left
;
1356 x
->asb_parent
= y
->asb_parent
;
1358 if (y
->asb_parent
== NULL
)
1360 else if (y
== y
->asb_parent
->asb_left
)
1361 y
->asb_parent
->asb_left
= x
;
1363 y
->asb_parent
->asb_right
= x
;
1365 old_color
= y
->asb_color
;
1367 /* Substitute the y-node for the z-node (deleted) */
1369 y
->asb_color
= z
->asb_color
;
1370 y
->asb_parent
= z
->asb_parent
;
1371 if (z
->asb_parent
!= NULL
) {
1372 if (z
->asb_parent
->asb_left
== z
)
1373 z
->asb_parent
->asb_left
= y
;
1374 if (z
->asb_parent
->asb_right
== z
)
1375 z
->asb_parent
->asb_right
= y
;
1378 y
->asb_left
= z
->asb_left
;
1379 if (z
->asb_left
!= NULL
)
1380 z
->asb_left
->asb_parent
= y
;
1381 y
->asb_right
= z
->asb_right
;
1382 if (z
->asb_right
!= NULL
)
1383 z
->asb_right
->asb_parent
= y
;
1389 z
->asb_parent
= NULL
;
1390 z
->asb_right
= NULL
;
1393 if (old_color
== BLACK
)
1394 s1394_used_tree_delete_fixup(root
, p
, x
, w
, side_of_x
);
1396 /* Unlock the "used" tree */
1397 mutex_exit(&hal
->addr_space_used_mutex
);
1399 TNF_PROBE_0_DEBUG(s1394_used_tree_delete_exit
,
1400 S1394_TNF_SL_ARREQ_STACK
, "");
1405 * s1394_used_tree_delete_fixup()
1406 * is the "helper" function for s1394_used_tree_delete(). It is used to
1407 * cleanup/enforce the red-black coloring in the tree.
1410 s1394_used_tree_delete_fixup(s1394_addr_space_blk_t
**root
,
1411 s1394_addr_space_blk_t
*p
, s1394_addr_space_blk_t
*x
,
1412 s1394_addr_space_blk_t
*w
, int side_of_x
)
1414 boolean_t first_time
;
1416 TNF_PROBE_0_DEBUG(s1394_used_tree_delete_fixup_enter
,
1417 S1394_TNF_SL_ARREQ_STACK
, "");
1419 first_time
= B_TRUE
;
1420 while ((x
!= *root
) && ((x
== NULL
) || (x
->asb_color
== BLACK
))) {
1421 if (((first_time
== B_TRUE
) && (side_of_x
== LEFT
)) ||
1422 ((first_time
== B_FALSE
) && (x
== p
->asb_left
))) {
1424 if (first_time
!= B_TRUE
)
1427 if ((w
!= NULL
) && (w
->asb_color
== RED
)) {
1428 w
->asb_color
= BLACK
;
1430 s1394_left_rotate(root
, p
);
1437 first_time
= B_FALSE
;
1439 } else if (((w
->asb_left
== NULL
) ||
1440 (w
->asb_left
->asb_color
== BLACK
)) &&
1441 ((w
->asb_right
== NULL
) ||
1442 (w
->asb_right
->asb_color
== BLACK
))) {
1446 first_time
= B_FALSE
;
1449 if ((w
->asb_right
== NULL
) ||
1450 (w
->asb_right
->asb_color
== BLACK
)) {
1451 w
->asb_left
->asb_color
= BLACK
;
1453 s1394_right_rotate(root
, w
);
1457 w
->asb_color
= p
->asb_color
;
1458 p
->asb_color
= BLACK
;
1459 if (w
->asb_right
!= NULL
)
1460 w
->asb_right
->asb_color
= BLACK
;
1461 s1394_left_rotate(root
, p
);
1463 first_time
= B_FALSE
;
1467 if (first_time
== B_FALSE
)
1470 if ((w
!= NULL
) && (w
->asb_color
== RED
)) {
1471 w
->asb_color
= BLACK
;
1473 s1394_right_rotate(root
, p
);
1480 first_time
= B_FALSE
;
1482 } else if (((w
->asb_left
== NULL
) ||
1483 (w
->asb_left
->asb_color
== BLACK
)) &&
1484 ((w
->asb_right
== NULL
) ||
1485 (w
->asb_right
->asb_color
== BLACK
))) {
1489 first_time
= B_FALSE
;
1492 if ((w
->asb_left
== NULL
) ||
1493 (w
->asb_left
->asb_color
== BLACK
)) {
1495 w
->asb_right
->asb_color
= BLACK
;
1497 s1394_left_rotate(root
, w
);
1501 w
->asb_color
= p
->asb_color
;
1502 p
->asb_color
= BLACK
;
1503 if (w
->asb_left
!= NULL
)
1504 w
->asb_left
->asb_color
= BLACK
;
1505 s1394_right_rotate(root
, p
);
1507 first_time
= B_FALSE
;
1512 x
->asb_color
= BLACK
;
1514 TNF_PROBE_0_DEBUG(s1394_used_tree_delete_fixup_exit
,
1515 S1394_TNF_SL_ARREQ_STACK
, "");
1519 * s1394_left_rotate()
1520 * is necessary with a red-black tree to help maintain the coloring in the
1521 * tree as items are inserted and removed. Its operation, the opposite of
1522 * s1394_right_rotate(), is a fundamental operation on the red-black tree.
1525 s1394_left_rotate(s1394_addr_space_blk_t
**root
, s1394_addr_space_blk_t
*x
)
1527 s1394_addr_space_blk_t
*y
;
1529 TNF_PROBE_0_DEBUG(s1394_left_rotate_enter
, S1394_TNF_SL_ARREQ_STACK
,
1533 x
->asb_right
= y
->asb_left
;
1535 if (y
->asb_left
!= NULL
)
1536 y
->asb_left
->asb_parent
= x
;
1538 y
->asb_parent
= x
->asb_parent
;
1539 if (x
->asb_parent
== NULL
)
1541 else if (x
== x
->asb_parent
->asb_left
)
1542 x
->asb_parent
->asb_left
= y
;
1544 x
->asb_parent
->asb_right
= y
;
1549 TNF_PROBE_0_DEBUG(s1394_left_rotate_exit
, S1394_TNF_SL_ARREQ_STACK
,
1554 * s1394_right_rotate()
1555 * is necessary with a red-black tree to help maintain the coloring in the
1556 * tree as items are inserted and removed. Its operation, the opposite of
1557 * s1394_left_rotate(), is a fundamental operation on the red-black tree.
1560 s1394_right_rotate(s1394_addr_space_blk_t
**root
, s1394_addr_space_blk_t
*x
)
1562 s1394_addr_space_blk_t
*y
;
1564 TNF_PROBE_0_DEBUG(s1394_right_rotate_enter
, S1394_TNF_SL_ARREQ_STACK
,
1568 x
->asb_left
= y
->asb_right
;
1570 if (y
->asb_right
!= NULL
)
1571 y
->asb_right
->asb_parent
= x
;
1573 y
->asb_parent
= x
->asb_parent
;
1574 if (x
->asb_parent
== NULL
)
1576 else if (x
== x
->asb_parent
->asb_right
)
1577 x
->asb_parent
->asb_right
= y
;
1579 x
->asb_parent
->asb_left
= y
;
1584 TNF_PROBE_0_DEBUG(s1394_right_rotate_exit
, S1394_TNF_SL_ARREQ_STACK
,
1589 * s1394_tree_minimum()
1590 * is used to find the smallest key in a binary tree.
1592 static s1394_addr_space_blk_t
*
1593 s1394_tree_minimum(s1394_addr_space_blk_t
*x
)
1595 TNF_PROBE_0_DEBUG(s1394_tree_minimum_enter
, S1394_TNF_SL_ARREQ_STACK
,
1598 while (x
->asb_left
!= NULL
)
1601 TNF_PROBE_0_DEBUG(s1394_tree_minimum_exit
, S1394_TNF_SL_ARREQ_STACK
,
1607 * s1394_tree_successor()
1608 * is used to find the next largest key is a binary tree, given a starting
1611 static s1394_addr_space_blk_t
*
1612 s1394_tree_successor(s1394_addr_space_blk_t
*x
)
1614 s1394_addr_space_blk_t
*y
;
1616 TNF_PROBE_0_DEBUG(s1394_tree_successor_enter
, S1394_TNF_SL_ARREQ_STACK
,
1619 if (x
->asb_right
!= NULL
) {
1620 y
= s1394_tree_minimum(x
->asb_right
);
1622 TNF_PROBE_0_DEBUG(s1394_tree_successor_exit
,
1623 S1394_TNF_SL_ARREQ_STACK
, "");
1628 while ((y
!= NULL
) && (x
== y
->asb_right
)) {
1633 TNF_PROBE_0_DEBUG(s1394_tree_successor_exit
, S1394_TNF_SL_ARREQ_STACK
,
1639 * s1394_is_posted_write()
1640 * returns a B_TRUE if the given address is in the "posted write" range
1641 * of the given HAL's 1394 address space and B_FALSE if it isn't.
1644 s1394_is_posted_write(s1394_hal_t
*hal
, uint64_t addr
)
1646 addr
= addr
& IEEE1394_ADDR_OFFSET_MASK
;
1648 if ((addr
>= hal
->posted_write_addr_lo
) &&
1649 (addr
<= hal
->posted_write_addr_hi
))
1656 * s1394_is_physical_addr()
1657 * returns a B_TRUE if the given address is in the "physical" range of
1658 * the given HAL's 1394 address space and B_FALSE if it isn't.
1661 s1394_is_physical_addr(s1394_hal_t
*hal
, uint64_t addr
)
1663 addr
= addr
& IEEE1394_ADDR_OFFSET_MASK
;
1665 if ((addr
>= hal
->physical_addr_lo
) &&
1666 (addr
<= hal
->physical_addr_hi
))
1673 * s1394_is_csr_addr()
1674 * returns a B_TRUE if the given address is in the "CSR" range of the
1675 * given HAL's 1394 address space and B_FALSE if it isn't.
1678 s1394_is_csr_addr(s1394_hal_t
*hal
, uint64_t addr
)
1680 addr
= addr
& IEEE1394_ADDR_OFFSET_MASK
;
1682 if ((addr
>= hal
->csr_addr_lo
) &&
1683 (addr
<= hal
->csr_addr_hi
))
1690 * s1394_is_normal_addr()
1691 * returns a B_TRUE if the given address is in the "normal" range of
1692 * the given HAL's 1394 address space and B_FALSE if it isn't.
1695 s1394_is_normal_addr(s1394_hal_t
*hal
, uint64_t addr
)
1697 addr
= addr
& IEEE1394_ADDR_OFFSET_MASK
;
1699 if ((addr
>= hal
->normal_addr_lo
) &&
1700 (addr
<= hal
->normal_addr_hi
))