5255 uts shouldn't open-code ISP2
[illumos-gate.git] / usr / src / uts / common / io / 1394 / s1394_isoch.c
blob2df89157cacbca6706fc53e1fb0530fbe4f1926d
1 /*
2 * CDDL HEADER START
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
7 * with the License.
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]
20 * CDDL HEADER END
23 * Copyright (c) 1999-2000 by Sun Microsystems, Inc.
24 * All rights reserved.
27 #pragma ident "%Z%%M% %I% %E% SMI"
30 * s1394_isoch.c
31 * 1394 Services Layer Isochronous Communication Routines
32 * This file contains routines for managing isochronous bandwidth
33 * and channel needs for registered targets (through the target
34 * isoch interfaces).
37 #include <sys/conf.h>
38 #include <sys/ddi.h>
39 #include <sys/sunddi.h>
40 #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>
49 * s1394_isoch_rsrc_realloc()
50 * is called during bus reset processing to reallocate any isochronous
51 * resources that were previously allocated.
53 void
54 s1394_isoch_rsrc_realloc(s1394_hal_t *hal)
56 s1394_isoch_cec_t *cec_curr;
57 uint32_t chnl_mask;
58 uint32_t old_chnl_mask;
59 uint_t bw_alloc_units;
60 uint_t generation;
61 uint_t chnl_num;
62 int err;
63 int ret;
65 TNF_PROBE_0_DEBUG(s1394_isoch_rsrc_realloc_enter,
66 S1394_TNF_SL_ISOCH_STACK, "");
69 * Get the current generation number - don't need the
70 * topology tree mutex here because it is read-only, and
71 * there is a race condition with or without it.
73 generation = hal->generation_count;
75 /* Lock the Isoch CEC list */
76 mutex_enter(&hal->isoch_cec_list_mutex);
78 cec_curr = hal->isoch_cec_list_head;
79 while (cec_curr != NULL) {
80 /* Lock the Isoch CEC member list */
81 mutex_enter(&cec_curr->isoch_cec_mutex);
83 /* Are we supposed to reallocate resources? */
84 if (!(cec_curr->cec_options & T1394_NO_IRM_ALLOC) &&
85 (cec_curr->realloc_valid == B_TRUE) &&
86 (cec_curr->realloc_failed == B_FALSE)) {
88 /* Reallocate some bandwidth */
89 bw_alloc_units = s1394_compute_bw_alloc_units(hal,
90 cec_curr->bandwidth, cec_curr->realloc_speed);
92 /* Check that the generation has not changed */
93 if (generation != hal->generation_count) {
94 /* Try the next Isoch CEC */
95 goto next_isoch_cec;
98 /* Unlock the Isoch CEC member list */
99 mutex_exit(&cec_curr->isoch_cec_mutex);
101 * We can unlock the Isoch CEC list here
102 * because we know this Isoch CEC can not
103 * go away (we are trying to realloc its
104 * resources so it can't be in a state that
105 * will allow a free).
107 mutex_exit(&hal->isoch_cec_list_mutex);
109 /* Try to reallocate bandwidth */
110 ret = s1394_bandwidth_alloc(hal, bw_alloc_units,
111 generation, &err);
113 /* Lock the Isoch CEC list */
114 mutex_enter(&hal->isoch_cec_list_mutex);
115 /* Lock the Isoch CEC member list */
116 mutex_enter(&cec_curr->isoch_cec_mutex);
118 /* If we failed because we couldn't get bandwidth */
119 if (ret == DDI_FAILURE) {
120 cec_curr->realloc_failed = B_TRUE;
121 cec_curr->realloc_fail_reason =
122 T1394_RSRC_BANDWIDTH;
126 /* Are we supposed to reallocate resources? */
127 if (!(cec_curr->cec_options & T1394_NO_IRM_ALLOC) &&
128 (cec_curr->realloc_valid == B_TRUE) &&
129 (cec_curr->realloc_failed == B_FALSE)) {
131 /* Reallocate the channel */
132 chnl_num = cec_curr->realloc_chnl_num;
133 chnl_mask = (1 << ((63 - chnl_num) % 32));
135 /* Unlock the Isoch CEC member list */
136 mutex_exit(&cec_curr->isoch_cec_mutex);
138 * We can unlock the Isoch CEC list here
139 * because we know this Isoch CEC can not
140 * go away (we are trying to realloc its
141 * resources so it can't be in a state that
142 * will allow a free).
144 mutex_exit(&hal->isoch_cec_list_mutex);
146 if (chnl_num < 32) {
147 ret = s1394_channel_alloc(hal, chnl_mask,
148 generation, S1394_CHANNEL_ALLOC_HI,
149 &old_chnl_mask, &err);
150 } else {
151 ret = s1394_channel_alloc(hal, chnl_mask,
152 generation, S1394_CHANNEL_ALLOC_LO,
153 &old_chnl_mask, &err);
156 /* Lock the Isoch CEC list */
157 mutex_enter(&hal->isoch_cec_list_mutex);
158 /* Lock the Isoch CEC member list */
159 mutex_enter(&cec_curr->isoch_cec_mutex);
161 if (ret == DDI_FAILURE) {
162 if (err != CMD1394_EBUSRESET) {
164 * If we successfully reallocate
165 * bandwidth, and then fail getting
166 * the channel, we need to free up
167 * the bandwidth
170 /* Try to free up the bandwidth */
171 ret = s1394_bandwidth_free(hal,
172 bw_alloc_units, generation, &err);
173 if ((ret == DDI_FAILURE) &&
174 (err != CMD1394_EBUSRESET)) {
175 TNF_PROBE_1(
176 s1394_isoch_rsrc_realloc_error,
177 S1394_TNF_SL_ISOCH_ERROR,
178 "", tnf_string, msg,
179 "Unable to free bandwidth");
181 /* Try the next Isoch CEC */
182 goto next_isoch_cec;
184 cec_curr->realloc_failed = B_TRUE;
185 cec_curr->realloc_fail_reason =
186 T1394_RSRC_CHANNEL;
189 next_isoch_cec:
190 /* Unlock the Isoch CEC member list */
191 mutex_exit(&cec_curr->isoch_cec_mutex);
192 cec_curr = cec_curr->cec_next;
195 /* Unlock the Isoch CEC list */
196 mutex_exit(&hal->isoch_cec_list_mutex);
197 TNF_PROBE_0_DEBUG(s1394_isoch_rsrc_realloc_exit,
198 S1394_TNF_SL_ISOCH_STACK, "");
202 * s1394_isoch_rsrc_realloc_notify()
203 * is called during bus reset processing to notify all targets for
204 * which isochronous resources were not able to be reallocated.
206 void
207 s1394_isoch_rsrc_realloc_notify(s1394_hal_t *hal)
209 s1394_isoch_cec_t *cec_curr;
210 s1394_isoch_cec_member_t *member_curr;
211 t1394_isoch_rsrc_error_t fail_arg;
212 opaque_t evts_arg;
213 s1394_isoch_cec_type_t type;
214 void (*rsrc_fail_callback)(t1394_isoch_cec_handle_t, opaque_t,
215 t1394_isoch_rsrc_error_t);
217 TNF_PROBE_0_DEBUG(s1394_isoch_rsrc_realloc_notify_enter,
218 S1394_TNF_SL_ISOCH_STACK, "");
220 /* Lock the Isoch CEC list */
221 mutex_enter(&hal->isoch_cec_list_mutex);
223 /* Notify all targets that failed realloc */
224 cec_curr = hal->isoch_cec_list_head;
225 while (cec_curr != NULL) {
226 /* Lock the Isoch CEC member list */
227 mutex_enter(&cec_curr->isoch_cec_mutex);
229 /* Do we notify of realloc failure? */
230 if (!(cec_curr->cec_options & T1394_NO_IRM_ALLOC) &&
231 (cec_curr->realloc_valid == B_TRUE) &&
232 (cec_curr->realloc_failed == B_TRUE)) {
234 /* Reason for realloc failure */
235 fail_arg = cec_curr->realloc_fail_reason;
237 /* Now we are going into the callbacks */
238 cec_curr->in_fail_callbacks = B_TRUE;
240 type = cec_curr->cec_type;
242 /* Unlock the Isoch CEC member list */
243 mutex_exit(&cec_curr->isoch_cec_mutex);
245 * We can unlock the Isoch CEC list here
246 * because we have the in_fail_callbacks
247 * field set to B_TRUE. And free will fail
248 * if we are in fail callbacks.
250 mutex_exit(&hal->isoch_cec_list_mutex);
252 /* Call all of the rsrc_fail_target() callbacks */
253 /* Start at the head (talker first) and */
254 /* go toward the tail (listeners last) */
255 member_curr = cec_curr->cec_member_list_head;
256 while (member_curr != NULL) {
257 rsrc_fail_callback = member_curr->
258 isoch_cec_evts.rsrc_fail_target;
259 evts_arg = member_curr->isoch_cec_evts_arg;
260 if (rsrc_fail_callback != NULL) {
262 if (type == S1394_PEER_TO_PEER) {
263 rsrc_fail_callback(
264 (t1394_isoch_cec_handle_t)
265 cec_curr, evts_arg,
266 fail_arg);
267 } else {
268 rsrc_fail_callback(
269 (t1394_isoch_cec_handle_t)
270 cec_curr, evts_arg,
271 fail_arg);
274 member_curr = member_curr->cec_mem_next;
277 /* Lock the Isoch CEC list */
278 mutex_enter(&hal->isoch_cec_list_mutex);
279 /* Lock the Isoch CEC member list */
280 mutex_enter(&cec_curr->isoch_cec_mutex);
282 /* We are finished with the callbacks */
283 cec_curr->in_fail_callbacks = B_FALSE;
284 if (cec_curr->cec_want_wakeup == B_TRUE) {
285 cec_curr->cec_want_wakeup = B_FALSE;
286 cv_broadcast(&cec_curr->in_callbacks_cv);
289 /* Set flags back to original state */
290 cec_curr->realloc_valid = B_FALSE;
291 cec_curr->realloc_failed = B_FALSE;
293 /* Unlock the Isoch CEC member list */
294 mutex_exit(&cec_curr->isoch_cec_mutex);
295 cec_curr = cec_curr->cec_next;
298 /* Unlock the Isoch CEC list */
299 mutex_exit(&hal->isoch_cec_list_mutex);
300 TNF_PROBE_0_DEBUG(s1394_isoch_rsrc_realloc_notify_exit,
301 S1394_TNF_SL_ISOCH_STACK, "");
305 * s1394_channel_alloc()
306 * is used to allocate an isochronous channel. A channel mask and
307 * generation are passed. A request is sent to whichever node is the
308 * IRM for the appropriate channels. If it fails because of a bus
309 * reset it can be retried. If it fails for another reason the
310 * channel(s) may not be availble or there may be no IRM.
313 s1394_channel_alloc(s1394_hal_t *hal, uint32_t channel_mask, uint_t generation,
314 uint_t flags, uint32_t *old_channels, int *result)
316 cmd1394_cmd_t *cmd;
317 uint64_t IRM_ID_addr;
318 uint32_t compare;
319 uint32_t swap;
320 uint32_t old_value;
321 uint_t hal_node_num;
322 uint_t IRM_node;
323 uint_t offset;
324 int ret;
325 int i;
326 int num_retries = S1394_ISOCH_ALLOC_RETRIES;
328 TNF_PROBE_0_DEBUG(s1394_channel_alloc_enter,
329 S1394_TNF_SL_ISOCH_STACK, "");
331 /* Lock the topology tree */
332 mutex_enter(&hal->topology_tree_mutex);
334 hal_node_num = IEEE1394_NODE_NUM(hal->node_id);
335 IRM_node = hal->IRM_node;
337 /* Unlock the topology tree */
338 mutex_exit(&hal->topology_tree_mutex);
340 /* Make sure there is a valid IRM on the bus */
341 if (IRM_node == -1) {
342 *result = CMD1394_ERETRIES_EXCEEDED;
343 TNF_PROBE_1(s1394_channel_alloc_error,
344 S1394_TNF_SL_ISOCH_ERROR, "", tnf_string, msg,
345 "No IRM on the 1394 bus");
346 TNF_PROBE_0_DEBUG(s1394_channel_alloc_exit,
347 S1394_TNF_SL_ISOCH_STACK, "");
348 return (DDI_FAILURE);
351 if (flags & S1394_CHANNEL_ALLOC_HI) {
352 offset =
353 (IEEE1394_SCSR_CHANS_AVAIL_HI & IEEE1394_CSR_OFFSET_MASK);
354 } else {
355 offset =
356 (IEEE1394_SCSR_CHANS_AVAIL_LO & IEEE1394_CSR_OFFSET_MASK);
359 /* Send compare-swap to CHANNELS_AVAILABLE */
360 /* register on the Isoch Rsrc Mgr */
361 if (IRM_node == hal_node_num) {
362 /* Local */
363 i = num_retries;
364 do {
365 (void) HAL_CALL(hal).csr_read(hal->halinfo.hal_private,
366 offset, &old_value);
368 /* Check that the generation has not changed */
369 if (generation != hal->generation_count) {
370 *result = CMD1394_EBUSRESET;
371 TNF_PROBE_0_DEBUG(s1394_channel_alloc_exit,
372 S1394_TNF_SL_ISOCH_STACK, "");
373 return (DDI_FAILURE);
376 compare = old_value;
377 swap = old_value & (~channel_mask);
379 ret = HAL_CALL(hal).csr_cswap32(
380 hal->halinfo.hal_private, generation,
381 offset, compare, swap, &old_value);
382 if (ret != DDI_SUCCESS) {
383 *result = CMD1394_EBUSRESET;
384 TNF_PROBE_1(s1394_channel_alloc_error,
385 S1394_TNF_SL_ISOCH_ERROR, "", tnf_string,
386 msg, "Error in cswap32");
387 TNF_PROBE_0_DEBUG(s1394_channel_alloc_exit,
388 "stacktrace 1394 s1394", "");
389 return (DDI_FAILURE);
392 if ((~old_value & channel_mask) != 0) {
393 *result = CMD1394_ERETRIES_EXCEEDED;
394 TNF_PROBE_1(s1394_channel_alloc_error,
395 S1394_TNF_SL_ISOCH_ERROR, "", tnf_string,
396 msg, "Channels already taken");
397 TNF_PROBE_0_DEBUG(s1394_channel_alloc_exit,
398 S1394_TNF_SL_ISOCH_STACK, "");
399 return (DDI_FAILURE);
402 if (old_value == compare) {
403 *result = CMD1394_CMDSUCCESS;
404 *old_channels = old_value;
406 TNF_PROBE_0_DEBUG(s1394_channel_alloc_exit,
407 S1394_TNF_SL_ISOCH_STACK, "");
408 return (DDI_SUCCESS);
410 } while (i--);
412 *result = CMD1394_ERETRIES_EXCEEDED;
413 TNF_PROBE_1(s1394_channel_alloc_error,
414 S1394_TNF_SL_ISOCH_ERROR, "", tnf_string, msg,
415 "Retries exceeded");
416 TNF_PROBE_0_DEBUG(s1394_channel_alloc_exit,
417 S1394_TNF_SL_ISOCH_STACK, "");
418 return (DDI_FAILURE);
420 } else {
421 /* Remote */
422 if (s1394_alloc_cmd(hal, 0, &cmd) != DDI_SUCCESS) {
423 *result = CMD1394_EUNKNOWN_ERROR;
424 TNF_PROBE_1(s1394_channel_alloc_error,
425 S1394_TNF_SL_ISOCH_ERROR, "", tnf_string, msg,
426 "Unable to allocate command");
427 TNF_PROBE_0_DEBUG(s1394_channel_alloc_exit,
428 S1394_TNF_SL_ISOCH_STACK, "");
429 return (DDI_FAILURE);
432 cmd->cmd_options = (CMD1394_CANCEL_ON_BUS_RESET |
433 CMD1394_OVERRIDE_ADDR | CMD1394_BLOCKING);
434 cmd->cmd_type = CMD1394_ASYNCH_LOCK_32;
436 if (flags & S1394_CHANNEL_ALLOC_HI) {
437 IRM_ID_addr = (IEEE1394_ADDR_BUS_ID_MASK |
438 IEEE1394_SCSR_CHANS_AVAIL_HI) |
439 (((uint64_t)IRM_node) <<
440 IEEE1394_ADDR_PHY_ID_SHIFT);
441 } else {
442 IRM_ID_addr = (IEEE1394_ADDR_BUS_ID_MASK |
443 IEEE1394_SCSR_CHANS_AVAIL_LO) |
444 (((uint64_t)IRM_node) <<
445 IEEE1394_ADDR_PHY_ID_SHIFT);
448 cmd->cmd_addr = IRM_ID_addr;
449 cmd->bus_generation = generation;
450 cmd->cmd_u.l32.data_value = T1394_DATA32(~channel_mask);
451 cmd->cmd_u.l32.num_retries = num_retries;
452 cmd->cmd_u.l32.lock_type = CMD1394_LOCK_BIT_AND;
454 ret = s1394_split_lock_req(hal, NULL, cmd);
456 if (ret == DDI_SUCCESS) {
457 if (cmd->cmd_result == CMD1394_CMDSUCCESS) {
458 *old_channels = T1394_DATA32(
459 cmd->cmd_u.l32.old_value);
461 if ((~(*old_channels) & channel_mask) != 0) {
462 *result = CMD1394_ERETRIES_EXCEEDED;
463 TNF_PROBE_1(s1394_channel_alloc_error,
464 S1394_TNF_SL_ISOCH_ERROR, "",
465 tnf_string, msg,
466 "Channels already taken");
467 TNF_PROBE_0_DEBUG(
468 s1394_channel_alloc_exit,
469 S1394_TNF_SL_ISOCH_STACK, "");
470 ret = DDI_FAILURE;
471 } else {
472 *result = cmd->cmd_result;
475 /* Need to free the command */
476 (void) s1394_free_cmd(hal, &cmd);
478 TNF_PROBE_0_DEBUG(s1394_channel_alloc_exit,
479 S1394_TNF_SL_ISOCH_STACK, "");
480 return (ret);
482 } else {
483 *result = cmd->cmd_result;
484 /* Need to free the command */
485 (void) s1394_free_cmd(hal, &cmd);
487 TNF_PROBE_1(s1394_channel_alloc_error,
488 S1394_TNF_SL_ISOCH_ERROR, "", tnf_string,
489 msg, "Error allocating isoch channel");
490 TNF_PROBE_0_DEBUG(s1394_channel_alloc_exit,
491 S1394_TNF_SL_ISOCH_STACK, "");
492 return (DDI_FAILURE);
494 } else {
495 *result = cmd->cmd_result;
497 /* Need to free the command */
498 (void) s1394_free_cmd(hal, &cmd);
500 TNF_PROBE_1(s1394_channel_alloc_error,
501 S1394_TNF_SL_ISOCH_ERROR, "", tnf_string, msg,
502 "Error allocating isoch channel");
503 TNF_PROBE_0_DEBUG(s1394_channel_alloc_exit,
504 S1394_TNF_SL_ISOCH_STACK, "");
505 return (DDI_FAILURE);
511 * s1394_channel_free()
512 * is used to free up an isochronous channel. A channel mask and
513 * generation are passed. A request is sent to whichever node is the
514 * IRM for the appropriate channels. If it fails because of a bus
515 * reset it can be retried. If it fails for another reason the
516 * channel(s) may already be free or there may be no IRM.
519 s1394_channel_free(s1394_hal_t *hal, uint32_t channel_mask, uint_t generation,
520 uint_t flags, uint32_t *old_channels, int *result)
522 cmd1394_cmd_t *cmd;
523 uint64_t IRM_ID_addr;
524 uint32_t compare;
525 uint32_t swap;
526 uint32_t old_value;
527 uint_t hal_node_num;
528 uint_t IRM_node;
529 uint_t offset;
530 int ret;
531 int i;
532 int num_retries = S1394_ISOCH_ALLOC_RETRIES;
534 TNF_PROBE_0_DEBUG(s1394_channel_free_enter,
535 S1394_TNF_SL_ISOCH_STACK, "");
537 /* Lock the topology tree */
538 mutex_enter(&hal->topology_tree_mutex);
540 hal_node_num = IEEE1394_NODE_NUM(hal->node_id);
541 IRM_node = hal->IRM_node;
543 /* Unlock the topology tree */
544 mutex_exit(&hal->topology_tree_mutex);
546 /* Make sure there is a valid IRM on the bus */
547 if (IRM_node == -1) {
548 *result = CMD1394_ERETRIES_EXCEEDED;
549 TNF_PROBE_1(s1394_channel_free_error,
550 S1394_TNF_SL_ISOCH_ERROR, "", tnf_string, msg,
551 "No IRM on the 1394 bus");
552 TNF_PROBE_0_DEBUG(s1394_channel_free_exit,
553 S1394_TNF_SL_ISOCH_STACK, "");
554 return (DDI_FAILURE);
557 if (flags & S1394_CHANNEL_ALLOC_HI) {
558 offset =
559 (IEEE1394_SCSR_CHANS_AVAIL_HI & IEEE1394_CSR_OFFSET_MASK);
560 } else {
561 offset =
562 (IEEE1394_SCSR_CHANS_AVAIL_LO & IEEE1394_CSR_OFFSET_MASK);
565 /* Send compare-swap to CHANNELS_AVAILABLE */
566 /* register on the Isoch Rsrc Mgr */
567 if (hal->IRM_node == hal_node_num) {
568 /* Local */
569 i = num_retries;
570 do {
571 (void) HAL_CALL(hal).csr_read(hal->halinfo.hal_private,
572 offset, &old_value);
574 /* Check that the generation has not changed */
575 if (generation != hal->generation_count) {
576 *result = CMD1394_EBUSRESET;
577 TNF_PROBE_0_DEBUG(s1394_channel_free_exit,
578 S1394_TNF_SL_ISOCH_STACK, "");
579 return (DDI_FAILURE);
582 compare = old_value;
583 swap = old_value | channel_mask;
585 ret = HAL_CALL(hal).csr_cswap32(
586 hal->halinfo.hal_private, hal->generation_count,
587 offset, compare, swap, &old_value);
588 if (ret != DDI_SUCCESS) {
589 *result = CMD1394_EBUSRESET;
590 TNF_PROBE_1(s1394_channel_free_error,
591 S1394_TNF_SL_ISOCH_ERROR, "", tnf_string,
592 msg, "Error in cswap32");
593 TNF_PROBE_0_DEBUG(s1394_channel_free_exit,
594 "stacktrace 1394 s1394", "");
595 return (DDI_FAILURE);
598 if (old_value == compare) {
599 *result = CMD1394_CMDSUCCESS;
600 *old_channels = old_value;
601 TNF_PROBE_0_DEBUG(s1394_channel_free_exit,
602 S1394_TNF_SL_ISOCH_STACK, "");
603 return (DDI_SUCCESS);
605 } while (i--);
607 *result = CMD1394_ERETRIES_EXCEEDED;
608 TNF_PROBE_1(s1394_channel_free_error,
609 S1394_TNF_SL_ISOCH_ERROR, "", tnf_string, msg,
610 "Retries exceeded");
611 TNF_PROBE_0_DEBUG(s1394_channel_free_exit,
612 S1394_TNF_SL_ISOCH_STACK, "");
613 return (DDI_FAILURE);
615 } else {
616 /* Remote */
617 if (s1394_alloc_cmd(hal, 0, &cmd) != DDI_SUCCESS) {
618 *result = CMD1394_EUNKNOWN_ERROR;
619 TNF_PROBE_1(s1394_channel_free_error,
620 S1394_TNF_SL_ISOCH_ERROR, "", tnf_string, msg,
621 "Unable to allocate command");
622 TNF_PROBE_0_DEBUG(s1394_channel_free_exit,
623 S1394_TNF_SL_ISOCH_STACK, "");
624 return (DDI_FAILURE);
627 cmd->cmd_options = (CMD1394_CANCEL_ON_BUS_RESET |
628 CMD1394_OVERRIDE_ADDR | CMD1394_BLOCKING);
629 cmd->cmd_type = CMD1394_ASYNCH_LOCK_32;
631 if (flags & S1394_CHANNEL_ALLOC_HI) {
632 IRM_ID_addr = (IEEE1394_ADDR_BUS_ID_MASK |
633 IEEE1394_SCSR_CHANS_AVAIL_HI) |
634 (((uint64_t)IRM_node) <<
635 IEEE1394_ADDR_PHY_ID_SHIFT);
636 } else {
637 IRM_ID_addr = (IEEE1394_ADDR_BUS_ID_MASK |
638 IEEE1394_SCSR_CHANS_AVAIL_LO) |
639 (((uint64_t)IRM_node) <<
640 IEEE1394_ADDR_PHY_ID_SHIFT);
643 cmd->cmd_addr = IRM_ID_addr;
644 cmd->bus_generation = generation;
645 cmd->cmd_u.l32.data_value = T1394_DATA32(channel_mask);
646 cmd->cmd_u.l32.num_retries = num_retries;
647 cmd->cmd_u.l32.lock_type = CMD1394_LOCK_BIT_OR;
649 ret = s1394_split_lock_req(hal, NULL, cmd);
651 if (ret == DDI_SUCCESS) {
652 if (cmd->cmd_result == CMD1394_CMDSUCCESS) {
654 *old_channels = T1394_DATA32(
655 cmd->cmd_u.l32.old_value);
656 *result = cmd->cmd_result;
658 /* Need to free the command */
659 (void) s1394_free_cmd(hal, &cmd);
661 TNF_PROBE_0_DEBUG(s1394_channel_free_exit,
662 S1394_TNF_SL_ISOCH_STACK, "");
663 return (DDI_SUCCESS);
665 } else {
666 *result = cmd->cmd_result;
668 /* Need to free the command */
669 (void) s1394_free_cmd(hal, &cmd);
671 TNF_PROBE_1(s1394_channel_free_error,
672 S1394_TNF_SL_ISOCH_ERROR, "", tnf_string,
673 msg, "Error freeing isoch channel");
674 TNF_PROBE_0_DEBUG(s1394_channel_free_exit,
675 S1394_TNF_SL_ISOCH_STACK, "");
676 return (DDI_FAILURE);
678 } else {
679 *result = cmd->cmd_result;
680 /* Need to free the command */
681 (void) s1394_free_cmd(hal, &cmd);
683 TNF_PROBE_1(s1394_channel_free_error,
684 S1394_TNF_SL_ISOCH_ERROR, "", tnf_string, msg,
685 "Error freeing isoch channel");
686 TNF_PROBE_0_DEBUG(s1394_channel_free_exit,
687 S1394_TNF_SL_ISOCH_STACK, "");
688 return (DDI_FAILURE);
694 * s1394_bandwidth_alloc()
695 * is used to allocate isochronous bandwidth. A number of bandwidth
696 * allocation units and a generation are passed. The request is sent
697 * to whichever node is the IRM for this amount of bandwidth. If it
698 * fails because of a bus reset it can be retried. If it fails for
699 * another reason the bandwidth may not be available or there may be
700 * no IRM.
703 s1394_bandwidth_alloc(s1394_hal_t *hal, uint32_t bw_alloc_units,
704 uint_t generation, int *result)
706 cmd1394_cmd_t *cmd;
707 uint64_t IRM_ID_addr;
708 uint32_t compare;
709 uint32_t swap;
710 uint32_t old_value;
711 uint_t hal_node_num;
712 uint_t IRM_node;
713 int temp_value;
714 int ret;
715 int i;
716 int num_retries = S1394_ISOCH_ALLOC_RETRIES;
718 TNF_PROBE_0_DEBUG(s1394_bandwidth_alloc_enter,
719 S1394_TNF_SL_ISOCH_STACK, "");
721 /* Lock the topology tree */
722 mutex_enter(&hal->topology_tree_mutex);
724 hal_node_num = IEEE1394_NODE_NUM(hal->node_id);
725 IRM_node = hal->IRM_node;
727 /* Unlock the topology tree */
728 mutex_exit(&hal->topology_tree_mutex);
730 /* Make sure there is a valid IRM on the bus */
731 if (IRM_node == -1) {
732 *result = CMD1394_ERETRIES_EXCEEDED;
733 TNF_PROBE_1(s1394_bandwidth_alloc_error,
734 S1394_TNF_SL_ISOCH_ERROR, "", tnf_string, msg,
735 "No IRM on the 1394 bus");
736 TNF_PROBE_0_DEBUG(s1394_bandwidth_alloc_exit,
737 S1394_TNF_SL_ISOCH_STACK, "");
738 return (DDI_FAILURE);
741 /* Send compare-swap to BANDWIDTH_AVAILABLE */
742 /* register on the Isoch Rsrc Mgr */
743 if (IRM_node == hal_node_num) {
744 /* Local */
745 i = num_retries;
746 do {
747 (void) HAL_CALL(hal).csr_read(hal->halinfo.hal_private,
748 (IEEE1394_SCSR_BANDWIDTH_AVAIL &
749 IEEE1394_CSR_OFFSET_MASK), &old_value);
751 * Check that the generation has not changed -
752 * don't need the lock (read-only)
754 if (generation != hal->generation_count) {
755 *result = CMD1394_EBUSRESET;
756 TNF_PROBE_0_DEBUG(s1394_bandwidth_alloc_exit,
757 S1394_TNF_SL_ISOCH_STACK, "");
758 return (DDI_FAILURE);
761 temp_value = (old_value - bw_alloc_units);
762 if ((old_value >= bw_alloc_units) &&
763 (temp_value >= IEEE1394_BANDWIDTH_MIN)) {
764 compare = old_value;
765 swap = (uint32_t)temp_value;
766 } else {
767 *result = CMD1394_ERETRIES_EXCEEDED;
768 TNF_PROBE_1(s1394_bandwidth_alloc_error,
769 S1394_TNF_SL_ISOCH_ERROR, "", tnf_string,
770 msg, "Retries exceeded");
771 TNF_PROBE_0_DEBUG(s1394_bandwidth_alloc_exit,
772 S1394_TNF_SL_ISOCH_STACK, "");
773 return (DDI_FAILURE);
776 ret = HAL_CALL(hal).csr_cswap32(
777 hal->halinfo.hal_private, generation,
778 (IEEE1394_SCSR_BANDWIDTH_AVAIL &
779 IEEE1394_CSR_OFFSET_MASK), compare, swap,
780 &old_value);
781 if (ret != DDI_SUCCESS) {
782 *result = CMD1394_EBUSRESET;
783 TNF_PROBE_1(s1394_bandwidth_alloc_error,
784 S1394_TNF_SL_ISOCH_ERROR, "", tnf_string,
785 msg, "Error in cswap32");
786 TNF_PROBE_0_DEBUG(s1394_bandwidth_alloc_exit,
787 S1394_TNF_SL_ISOCH_STACK, "");
788 return (DDI_FAILURE);
791 if (old_value == compare) {
792 *result = CMD1394_CMDSUCCESS;
793 TNF_PROBE_0_DEBUG(s1394_bandwidth_alloc_exit,
794 S1394_TNF_SL_ISOCH_STACK, "");
795 return (DDI_SUCCESS);
797 } while (i--);
799 *result = CMD1394_ERETRIES_EXCEEDED;
800 TNF_PROBE_1(s1394_bandwidth_alloc_error,
801 S1394_TNF_SL_ISOCH_ERROR, "", tnf_string, msg,
802 "Too many retries");
803 TNF_PROBE_0_DEBUG(s1394_bandwidth_alloc_exit,
804 S1394_TNF_SL_ISOCH_STACK, "");
805 return (DDI_FAILURE);
807 } else {
808 /* Remote */
809 if (s1394_alloc_cmd(hal, 0, &cmd) != DDI_SUCCESS) {
810 *result = CMD1394_EUNKNOWN_ERROR;
811 TNF_PROBE_1(s1394_bandwidth_alloc_error,
812 S1394_TNF_SL_ISOCH_ERROR, "", tnf_string, msg,
813 "Unable to allocate command");
814 TNF_PROBE_0_DEBUG(s1394_bandwidth_alloc_exit,
815 S1394_TNF_SL_ISOCH_STACK, "");
816 return (DDI_FAILURE);
819 cmd->cmd_options = (CMD1394_CANCEL_ON_BUS_RESET |
820 CMD1394_OVERRIDE_ADDR | CMD1394_BLOCKING);
821 cmd->cmd_type = CMD1394_ASYNCH_LOCK_32;
822 IRM_ID_addr = (IEEE1394_ADDR_BUS_ID_MASK |
823 IEEE1394_SCSR_BANDWIDTH_AVAIL) | (((uint64_t)IRM_node) <<
824 IEEE1394_ADDR_PHY_ID_SHIFT);
825 cmd->cmd_addr = IRM_ID_addr;
826 cmd->bus_generation = generation;
827 cmd->cmd_u.l32.arg_value = 0;
828 cmd->cmd_u.l32.data_value = bw_alloc_units;
829 cmd->cmd_u.l32.num_retries = num_retries;
830 cmd->cmd_u.l32.lock_type = CMD1394_LOCK_THRESH_SUBTRACT;
832 ret = s1394_split_lock_req(hal, NULL, cmd);
834 if (ret == DDI_SUCCESS) {
835 if (cmd->cmd_result == CMD1394_CMDSUCCESS) {
836 *result = cmd->cmd_result;
837 /* Need to free the command */
838 (void) s1394_free_cmd(hal, &cmd);
840 TNF_PROBE_0_DEBUG(s1394_bandwidth_alloc_exit,
841 S1394_TNF_SL_ISOCH_STACK, "");
842 return (DDI_SUCCESS);
844 } else {
845 *result = cmd->cmd_result;
846 /* Need to free the command */
847 (void) s1394_free_cmd(hal, &cmd);
849 TNF_PROBE_1(s1394_bandwidth_alloc_error,
850 S1394_TNF_SL_ISOCH_ERROR, "", tnf_string,
851 msg, "Error allocating isoch bandwidth");
852 TNF_PROBE_0_DEBUG(s1394_bandwidth_alloc_exit,
853 S1394_TNF_SL_ISOCH_STACK, "");
854 return (DDI_FAILURE);
856 } else {
857 *result = cmd->cmd_result;
858 /* Need to free the command */
859 (void) s1394_free_cmd(hal, &cmd);
861 TNF_PROBE_1(s1394_bandwidth_alloc_error,
862 S1394_TNF_SL_ISOCH_ERROR, "", tnf_string, msg,
863 "Error allocating isoch bandwidth");
864 TNF_PROBE_0_DEBUG(s1394_bandwidth_alloc_exit,
865 S1394_TNF_SL_ISOCH_STACK, "");
866 return (DDI_FAILURE);
872 * s1394_compute_bw_alloc_units()
873 * is used to compute the number of "bandwidth allocation units" that
874 * are necessary for a given bit rate. It calculates the overhead
875 * necessary for isoch packet headers, bus arbitration, etc. (See
876 * IEEE 1394-1995 Section 8.3.2.3.7 for an explanation of what a
877 * "bandwidth allocation unit" is.
879 uint_t
880 s1394_compute_bw_alloc_units(s1394_hal_t *hal, uint_t bandwidth, uint_t speed)
882 uint_t total_quads;
883 uint_t speed_factor;
884 uint_t bau;
885 int max_hops;
887 /* Lock the topology tree */
888 mutex_enter(&hal->topology_tree_mutex);
890 /* Calculate the 1394 bus diameter */
891 max_hops = s1394_topology_tree_calculate_diameter(hal);
893 /* Unlock the topology tree */
894 mutex_exit(&hal->topology_tree_mutex);
896 /* Calculate the total bandwidth (including overhead) */
897 total_quads = (bandwidth >> 2) + IEEE1394_ISOCH_HDR_QUAD_SZ;
898 switch (speed) {
899 case IEEE1394_S400:
900 speed_factor = ISOCH_SPEED_FACTOR_S400;
901 break;
902 case IEEE1394_S200:
903 speed_factor = ISOCH_SPEED_FACTOR_S200;
904 break;
905 case IEEE1394_S100:
906 speed_factor = ISOCH_SPEED_FACTOR_S100;
907 break;
909 /* See IEC 61883-1 pp. 26-29 for this formula */
910 bau = (32 * max_hops) + (total_quads * speed_factor);
912 return (bau);
916 * s1394_bandwidth_free()
917 * is used to free up isochronous bandwidth. A number of bandwidth
918 * allocation units and a generation are passed. The request is sent
919 * to whichever node is the IRM for this amount of bandwidth. If it
920 * fails because of a bus reset it can be retried. If it fails for
921 * another reason the bandwidth may already be freed or there may
922 * be no IRM.
925 s1394_bandwidth_free(s1394_hal_t *hal, uint32_t bw_alloc_units,
926 uint_t generation, int *result)
928 cmd1394_cmd_t *cmd;
929 uint64_t IRM_ID_addr;
930 uint32_t compare;
931 uint32_t swap;
932 uint32_t old_value;
933 uint32_t temp_value;
934 uint_t hal_node_num;
935 uint_t IRM_node;
936 int ret;
937 int i;
938 int num_retries = S1394_ISOCH_ALLOC_RETRIES;
940 TNF_PROBE_0_DEBUG(s1394_bandwidth_free_enter,
941 S1394_TNF_SL_ISOCH_STACK, "");
943 /* Lock the topology tree */
944 mutex_enter(&hal->topology_tree_mutex);
946 hal_node_num = IEEE1394_NODE_NUM(hal->node_id);
947 IRM_node = hal->IRM_node;
949 /* Unlock the topology tree */
950 mutex_exit(&hal->topology_tree_mutex);
952 /* Make sure there is a valid IRM on the bus */
953 if (IRM_node == -1) {
954 *result = CMD1394_ERETRIES_EXCEEDED;
955 TNF_PROBE_1(s1394_bandwidth_free_error,
956 S1394_TNF_SL_ISOCH_ERROR, "", tnf_string, msg,
957 "No IRM on the 1394 bus");
958 TNF_PROBE_0_DEBUG(s1394_bandwidth_free_exit,
959 S1394_TNF_SL_ISOCH_STACK, "");
960 return (DDI_FAILURE);
963 /* Send compare-swap to BANDWIDTH_AVAILABLE */
964 /* register on the Isoch Rsrc Mgr */
965 if (IRM_node == hal_node_num) {
966 i = num_retries;
967 do {
968 (void) HAL_CALL(hal).csr_read(hal->halinfo.hal_private,
969 (IEEE1394_SCSR_BANDWIDTH_AVAIL &
970 IEEE1394_CSR_OFFSET_MASK), &old_value);
972 /* Check that the generation has not changed */
973 if (generation != hal->generation_count) {
974 *result = CMD1394_EBUSRESET;
975 TNF_PROBE_0_DEBUG(s1394_bandwidth_free_exit,
976 S1394_TNF_SL_ISOCH_STACK, "");
977 return (DDI_FAILURE);
980 temp_value = (old_value + bw_alloc_units);
981 if ((temp_value >= old_value) &&
982 (temp_value <= IEEE1394_BANDWIDTH_MAX)) {
983 compare = old_value;
984 swap = temp_value;
985 } else {
986 *result = CMD1394_ERETRIES_EXCEEDED;
987 TNF_PROBE_1(s1394_bandwidth_free_error,
988 S1394_TNF_SL_ISOCH_ERROR, "", tnf_string,
989 msg, "Too many retries");
990 TNF_PROBE_0_DEBUG(s1394_bandwidth_free_exit,
991 S1394_TNF_SL_ISOCH_STACK, "");
992 return (DDI_FAILURE);
995 ret = HAL_CALL(hal).csr_cswap32(
996 hal->halinfo.hal_private, generation,
997 (IEEE1394_SCSR_BANDWIDTH_AVAIL &
998 IEEE1394_CSR_OFFSET_MASK), compare, swap,
999 &old_value);
1000 if (ret != DDI_SUCCESS) {
1001 *result = CMD1394_EBUSRESET;
1002 TNF_PROBE_1(s1394_bandwidth_free_error,
1003 S1394_TNF_SL_ISOCH_ERROR, "", tnf_string,
1004 msg, "Error in cswap32");
1005 TNF_PROBE_0_DEBUG(s1394_bandwidth_free_exit,
1006 S1394_TNF_SL_ISOCH_STACK, "");
1007 return (DDI_FAILURE);
1010 if (old_value == compare) {
1011 *result = CMD1394_CMDSUCCESS;
1012 TNF_PROBE_0_DEBUG(s1394_bandwidth_free_exit,
1013 S1394_TNF_SL_ISOCH_STACK, "");
1014 return (DDI_SUCCESS);
1016 } while (i--);
1018 *result = CMD1394_ERETRIES_EXCEEDED;
1019 TNF_PROBE_1(s1394_bandwidth_free_error,
1020 S1394_TNF_SL_ISOCH_ERROR, "", tnf_string, msg,
1021 "Retries exceeded");
1022 TNF_PROBE_0_DEBUG(s1394_bandwidth_free_exit,
1023 S1394_TNF_SL_ISOCH_STACK, "");
1024 return (DDI_FAILURE);
1026 } else {
1027 /* Remote */
1028 if (s1394_alloc_cmd(hal, 0, &cmd) != DDI_SUCCESS) {
1029 *result = CMD1394_EUNKNOWN_ERROR;
1030 TNF_PROBE_1(s1394_bandwidth_free_error,
1031 S1394_TNF_SL_ISOCH_ERROR, "", tnf_string, msg,
1032 "Unable to allocate command");
1033 TNF_PROBE_0_DEBUG(s1394_bandwidth_free_exit,
1034 S1394_TNF_SL_ISOCH_STACK, "");
1035 return (DDI_FAILURE);
1038 cmd->cmd_options = (CMD1394_CANCEL_ON_BUS_RESET |
1039 CMD1394_OVERRIDE_ADDR | CMD1394_BLOCKING);
1040 cmd->cmd_type = CMD1394_ASYNCH_LOCK_32;
1041 IRM_ID_addr = (IEEE1394_ADDR_BUS_ID_MASK |
1042 IEEE1394_SCSR_BANDWIDTH_AVAIL) |
1043 (((uint64_t)hal->IRM_node) << IEEE1394_ADDR_PHY_ID_SHIFT);
1044 cmd->cmd_addr = IRM_ID_addr;
1045 cmd->bus_generation = generation;
1046 cmd->cmd_u.l32.arg_value = IEEE1394_BANDWIDTH_MAX;
1047 cmd->cmd_u.l32.data_value = bw_alloc_units;
1048 cmd->cmd_u.l32.num_retries = num_retries;
1049 cmd->cmd_u.l32.lock_type = CMD1394_LOCK_THRESH_ADD;
1051 ret = s1394_split_lock_req(hal, NULL, cmd);
1053 if (ret == DDI_SUCCESS) {
1054 if (cmd->cmd_result == CMD1394_CMDSUCCESS) {
1055 *result = cmd->cmd_result;
1057 /* Need to free the command */
1058 (void) s1394_free_cmd(hal, &cmd);
1060 TNF_PROBE_0_DEBUG(s1394_bandwidth_free_exit,
1061 S1394_TNF_SL_ISOCH_STACK, "");
1062 return (DDI_SUCCESS);
1064 } else {
1065 *result = cmd->cmd_result;
1066 /* Need to free the command */
1067 (void) s1394_free_cmd(hal, &cmd);
1069 TNF_PROBE_1(s1394_bandwidth_free_error,
1070 S1394_TNF_SL_ISOCH_ERROR, "", tnf_string,
1071 msg, "Error freeing isoch bandwidth");
1072 TNF_PROBE_0_DEBUG(s1394_bandwidth_free_exit,
1073 S1394_TNF_SL_ISOCH_STACK, "");
1074 return (DDI_FAILURE);
1076 } else {
1077 *result = cmd->cmd_result;
1078 /* Need to free the command */
1079 (void) s1394_free_cmd(hal, &cmd);
1081 TNF_PROBE_1(s1394_bandwidth_free_error,
1082 S1394_TNF_SL_ISOCH_ERROR, "", tnf_string, msg,
1083 "Error freeing isoch bandwidth");
1084 TNF_PROBE_0_DEBUG(s1394_bandwidth_free_exit,
1085 S1394_TNF_SL_ISOCH_STACK, "");
1086 return (DDI_FAILURE);
1092 * s1394_isoch_cec_list_insert()
1093 * is used to insert an Isoch CEC into a given HAL's list of Isoch CECs.
1095 void
1096 s1394_isoch_cec_list_insert(s1394_hal_t *hal, s1394_isoch_cec_t *cec)
1098 s1394_isoch_cec_t *cec_temp;
1100 TNF_PROBE_0_DEBUG(s1394_isoch_cec_list_insert_enter,
1101 S1394_TNF_SL_ISOCH_STACK, "");
1103 ASSERT(MUTEX_HELD(&hal->isoch_cec_list_mutex));
1105 /* Is the Isoch CEC list empty? */
1106 if ((hal->isoch_cec_list_head == NULL) &&
1107 (hal->isoch_cec_list_tail == NULL)) {
1109 hal->isoch_cec_list_head = cec;
1110 hal->isoch_cec_list_tail = cec;
1112 cec->cec_next = NULL;
1113 cec->cec_prev = NULL;
1115 } else {
1116 cec->cec_next = hal->isoch_cec_list_head;
1117 cec->cec_prev = NULL;
1118 cec_temp = hal->isoch_cec_list_head;
1119 cec_temp->cec_prev = cec;
1121 hal->isoch_cec_list_head = cec;
1124 TNF_PROBE_0_DEBUG(s1394_isoch_cec_list_insert_exit,
1125 S1394_TNF_SL_ISOCH_STACK, "");
1129 * s1394_isoch_cec_list_remove()
1130 * is used to remove an Isoch CEC from a given HAL's list of Isoch CECs.
1132 void
1133 s1394_isoch_cec_list_remove(s1394_hal_t *hal, s1394_isoch_cec_t *cec)
1135 s1394_isoch_cec_t *prev_cec;
1136 s1394_isoch_cec_t *next_cec;
1138 TNF_PROBE_0_DEBUG(s1394_isoch_cec_list_remove_enter,
1139 S1394_TNF_SL_ISOCH_STACK, "");
1141 ASSERT(MUTEX_HELD(&hal->isoch_cec_list_mutex));
1143 prev_cec = cec->cec_prev;
1144 next_cec = cec->cec_next;
1145 cec->cec_prev = NULL;
1146 cec->cec_next = NULL;
1148 if (prev_cec != NULL) {
1149 prev_cec->cec_next = next_cec;
1151 } else {
1152 if (hal->isoch_cec_list_head == cec)
1153 hal->isoch_cec_list_head = next_cec;
1156 if (next_cec != NULL) {
1157 next_cec->cec_prev = prev_cec;
1159 } else {
1160 if (hal->isoch_cec_list_tail == cec)
1161 hal->isoch_cec_list_tail = prev_cec;
1164 TNF_PROBE_0_DEBUG(s1394_isoch_cec_list_remove_exit,
1165 S1394_TNF_SL_ISOCH_STACK, "");
1169 * s1394_isoch_cec_member_list_insert()
1170 * is used to insert a new member (target) into the list of members for
1171 * a given Isoch CEC.
1173 /* ARGSUSED */
1174 void
1175 s1394_isoch_cec_member_list_insert(s1394_hal_t *hal, s1394_isoch_cec_t *cec,
1176 s1394_isoch_cec_member_t *member)
1178 s1394_isoch_cec_member_t *member_temp;
1180 TNF_PROBE_0_DEBUG(s1394_isoch_cec_member_list_insert_enter,
1181 S1394_TNF_SL_ISOCH_STACK, "");
1183 ASSERT(MUTEX_HELD(&cec->isoch_cec_mutex));
1185 /* Is the Isoch CEC member list empty? */
1186 if ((cec->cec_member_list_head == NULL) &&
1187 (cec->cec_member_list_tail == NULL)) {
1189 cec->cec_member_list_head = member;
1190 cec->cec_member_list_tail = member;
1191 member->cec_mem_next = NULL;
1192 member->cec_mem_prev = NULL;
1194 } else if (member->cec_mem_options & T1394_TALKER) {
1195 /* Put talker at the head of the list */
1196 member->cec_mem_next = cec->cec_member_list_head;
1197 member->cec_mem_prev = NULL;
1198 member_temp = cec->cec_member_list_head;
1199 member_temp->cec_mem_prev = member;
1200 cec->cec_member_list_head = member;
1202 } else {
1203 /* Put listeners at the tail of the list */
1204 member->cec_mem_prev = cec->cec_member_list_tail;
1205 member->cec_mem_next = NULL;
1206 member_temp = cec->cec_member_list_tail;
1207 member_temp->cec_mem_next = member;
1208 cec->cec_member_list_tail = member;
1211 TNF_PROBE_0_DEBUG(s1394_isoch_cec_member_list_insert_exit,
1212 S1394_TNF_SL_ISOCH_STACK, "");
1216 * s1394_isoch_cec_member_list_remove()
1217 * is used to remove a member (target) from the list of members for
1218 * a given Isoch CEC.
1220 /* ARGSUSED */
1221 void
1222 s1394_isoch_cec_member_list_remove(s1394_hal_t *hal, s1394_isoch_cec_t *cec,
1223 s1394_isoch_cec_member_t *member)
1225 s1394_isoch_cec_member_t *prev_member;
1226 s1394_isoch_cec_member_t *next_member;
1228 TNF_PROBE_0_DEBUG(s1394_isoch_cec_member_list_remove_enter,
1229 S1394_TNF_SL_ISOCH_STACK, "");
1231 ASSERT(MUTEX_HELD(&cec->isoch_cec_mutex));
1233 prev_member = member->cec_mem_prev;
1234 next_member = member->cec_mem_next;
1236 member->cec_mem_prev = NULL;
1237 member->cec_mem_next = NULL;
1239 if (prev_member != NULL) {
1240 prev_member->cec_mem_next = next_member;
1242 } else {
1243 if (cec->cec_member_list_head == member)
1244 cec->cec_member_list_head = next_member;
1247 if (next_member != NULL) {
1248 next_member->cec_mem_prev = prev_member;
1250 } else {
1251 if (cec->cec_member_list_tail == member)
1252 cec->cec_member_list_tail = prev_member;
1255 TNF_PROBE_0_DEBUG(s1394_isoch_cec_member_list_remove_exit,
1256 S1394_TNF_SL_ISOCH_STACK, "");