4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
30 * 1394 Services Layer Asynchronous Communications Routines
31 * These routines handle all of the tasks relating to asynch commands
36 #include <sys/sunddi.h>
37 #include <sys/cmn_err.h>
38 #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>
47 #include <sys/1394/ieee1212.h>
49 static void s1394_handle_lock(cmd1394_cmd_t
*cmd
);
51 static cmd1394_cmd_t
*s1394_pending_q_remove(s1394_hal_t
*hal
);
53 static boolean_t
s1394_process_pending_q(s1394_hal_t
*hal
);
55 static boolean_t
s1394_pending_q_helper(s1394_hal_t
*hal
, cmd1394_cmd_t
*cmd
);
57 static int s1394_process_split_lock(cmd1394_cmd_t
*cmd
,
58 cmd1394_cmd_t
*target_cmd
);
60 static int s1394_finish_split_lock(cmd1394_cmd_t
*cmd
,
61 cmd1394_cmd_t
*target_cmd
);
65 * is used to allocate a command for a target or for a HAL.
68 s1394_alloc_cmd(s1394_hal_t
*hal
, uint_t flags
, cmd1394_cmd_t
**cmdp
)
70 s1394_cmd_priv_t
*s_priv
;
75 alloc_sleep
= (flags
& T1394_ALLOC_CMD_NOSLEEP
) ? KM_NOSLEEP
: KM_SLEEP
;
77 if ((alloc_sleep
== KM_SLEEP
) &&
78 (servicing_interrupt())) {
79 ASSERT(alloc_sleep
!= KM_SLEEP
); /* fail */
83 /* either FCP command or response, but not both */
85 (T1394_ALLOC_CMD_FCP_COMMAND
| T1394_ALLOC_CMD_FCP_RESPONSE
)) ==
86 (T1394_ALLOC_CMD_FCP_COMMAND
| T1394_ALLOC_CMD_FCP_RESPONSE
)) {
90 *cmdp
= kmem_cache_alloc(hal
->hal_kmem_cachep
, alloc_sleep
);
94 cmd_size
= sizeof (cmd1394_cmd_t
) +
95 sizeof (s1394_cmd_priv_t
) + hal
->halinfo
.hal_overhead
;
96 bzero((void *)*cmdp
, cmd_size
);
98 (*cmdp
)->cmd_version
= T1394_VERSION_V1
;
99 (*cmdp
)->cmd_result
= CMD1394_NOSTATUS
;
101 /* Get the Services Layer private area */
102 s_priv
= S1394_GET_CMD_PRIV(*cmdp
);
104 /* Set extension type */
105 if (flags
& T1394_ALLOC_CMD_FCP_COMMAND
) {
106 s1394_fa_init_cmd(s_priv
, S1394_FA_TYPE_FCP_CTL
);
107 } else if (flags
& T1394_ALLOC_CMD_FCP_RESPONSE
) {
108 s1394_fa_init_cmd(s_priv
, S1394_FA_TYPE_FCP_TGT
);
111 /* Set up the hal_overhead ptr in the hal_cmd_private */
112 hal_overhead
= (uchar_t
*)s_priv
+ sizeof (s1394_cmd_priv_t
);
113 s_priv
->hal_cmd_private
.hal_overhead
= (void *)hal_overhead
;
115 /* kstats - number of cmd allocs */
116 hal
->hal_kstats
->cmd_alloc
++;
118 return (DDI_SUCCESS
);
123 * is used to free a command that had been previously allocated by
127 s1394_free_cmd(s1394_hal_t
*hal
, cmd1394_cmd_t
**cmdp
)
129 s1394_cmd_priv_t
*s_priv
;
131 /* Get the Services Layer private area */
132 s_priv
= S1394_GET_CMD_PRIV(*cmdp
);
134 /* Check that command isn't in use */
135 if (s_priv
->cmd_in_use
== B_TRUE
) {
136 ASSERT(s_priv
->cmd_in_use
== B_FALSE
);
137 return (DDI_FAILURE
);
140 /* kstats - number of cmd allocs */
141 kmem_cache_free(hal
->hal_kmem_cachep
, *cmdp
);
143 /* Command pointer is set to NULL before returning */
146 /* kstats - number of cmd frees */
147 hal
->hal_kstats
->cmd_free
++;
149 return (DDI_SUCCESS
);
153 * s1394_xfer_asynch_command()
154 * is used to send an asynch command down to the HAL. Based upon the type
155 * of command that is being sent, the appropriate HAL function is called.
156 * Command failures are handled be returning an error and/or shutting down
157 * the HAL, depending on the severity of the error.
160 s1394_xfer_asynch_command(s1394_hal_t
*hal
, cmd1394_cmd_t
*cmd
, int *err
)
162 s1394_cmd_priv_t
*s_priv
;
163 h1394_cmd_priv_t
*h_priv
;
164 s1394_hal_state_t state
;
169 ASSERT(MUTEX_NOT_HELD(&hal
->topology_tree_mutex
));
171 mutex_enter(&hal
->topology_tree_mutex
);
172 state
= hal
->hal_state
;
173 if (((state
!= S1394_HAL_NORMAL
) && (state
!= S1394_HAL_RESET
)) ||
174 (hal
->disable_requests_bit
== 1)) {
175 *err
= s1394_HAL_asynch_error(hal
, cmd
, state
);
176 mutex_exit(&hal
->topology_tree_mutex
);
177 return (DDI_FAILURE
);
179 mutex_exit(&hal
->topology_tree_mutex
);
181 /* Get the Services Layer private area */
182 s_priv
= S1394_GET_CMD_PRIV(cmd
);
184 /* Get a pointer to the HAL private struct */
185 h_priv
= (h1394_cmd_priv_t
*)&s_priv
->hal_cmd_private
;
187 /* kstats - number of AT requests sent */
188 switch (cmd
->cmd_type
) {
189 case CMD1394_ASYNCH_RD_QUAD
:
190 hal
->hal_kstats
->atreq_quad_rd
++;
193 case CMD1394_ASYNCH_RD_BLOCK
:
194 hal
->hal_kstats
->atreq_blk_rd
++;
197 case CMD1394_ASYNCH_WR_QUAD
:
198 hal
->hal_kstats
->atreq_quad_wr
++;
201 case CMD1394_ASYNCH_WR_BLOCK
:
202 hal
->hal_kstats
->atreq_blk_wr
++;
203 hal
->hal_kstats
->atreq_blk_wr_size
+= h_priv
->mblk
.length
;
206 case CMD1394_ASYNCH_LOCK_32
:
207 hal
->hal_kstats
->atreq_lock32
++;
210 case CMD1394_ASYNCH_LOCK_64
:
211 hal
->hal_kstats
->atreq_lock64
++;
215 switch (s_priv
->cmd_priv_xfer_type
) {
216 /* Call the HAL's read entry point */
218 ret
= HAL_CALL(hal
).read(hal
->halinfo
.hal_private
,
219 (cmd1394_cmd_t
*)cmd
,
220 (h1394_cmd_priv_t
*)&s_priv
->hal_cmd_private
,
224 /* Call the HAL's write entry point */
225 case S1394_CMD_WRITE
:
226 ret
= HAL_CALL(hal
).write(hal
->halinfo
.hal_private
,
227 (cmd1394_cmd_t
*)cmd
,
228 (h1394_cmd_priv_t
*)&s_priv
->hal_cmd_private
,
232 /* Call the HAL's lock entry point */
234 ret
= HAL_CALL(hal
).lock(hal
->halinfo
.hal_private
,
235 (cmd1394_cmd_t
*)cmd
,
236 (h1394_cmd_priv_t
*)&s_priv
->hal_cmd_private
,
241 *err
= CMD1394_EUNKNOWN_ERROR
;
243 return (DDI_FAILURE
);
246 if (ret
== DDI_FAILURE
) {
247 switch (result_from_hal
) {
248 case H1394_STATUS_EMPTY_TLABEL
:
249 /* Out of TLABELs - Unable to send AT req */
250 *err
= CMD1394_ENO_ATREQ
;
253 case H1394_STATUS_INVALID_BUSGEN
:
254 /* Out of TLABELs - Unable to send AT req */
255 *err
= CMD1394_ESTALE_GENERATION
;
258 case H1394_STATUS_NOMORE_SPACE
:
259 /* No more space on HAL's HW queue */
260 *err
= CMD1394_ENO_ATREQ
;
263 case H1394_STATUS_INTERNAL_ERROR
:
264 dip
= hal
->halinfo
.dip
;
266 /* An unexpected error in the HAL */
267 cmn_err(CE_WARN
, HALT_ERROR_MESSAGE
,
268 ddi_node_name(dip
), ddi_get_instance(dip
));
270 /* Disable the HAL */
271 s1394_hal_shutdown(hal
, B_TRUE
);
273 *err
= CMD1394_EFATAL_ERROR
;
277 dip
= hal
->halinfo
.dip
;
279 /* An unexpected error in the HAL */
280 cmn_err(CE_WARN
, HALT_ERROR_MESSAGE
,
281 ddi_node_name(dip
), ddi_get_instance(dip
));
283 /* Disable the HAL */
284 s1394_hal_shutdown(hal
, B_TRUE
);
286 *err
= CMD1394_EFATAL_ERROR
;
290 return (DDI_FAILURE
);
293 /* No errors, return success */
294 *err
= CMD1394_NOSTATUS
;
296 return (DDI_SUCCESS
);
300 * s1394_setup_asynch_command()
301 * is used to setup an asynch command to be sent down to the HAL and out
302 * onto the bus. This function handles setting up the destination address
303 * (if necessary), speed, max_payload, putting the command onto the
304 * outstanding Q list, and any other things that must be done prior to
308 s1394_setup_asynch_command(s1394_hal_t
*hal
, s1394_target_t
*target
,
309 cmd1394_cmd_t
*cmd
, uint32_t xfer_type
, int *err
)
311 s1394_cmd_priv_t
*s_priv
;
312 h1394_cmd_priv_t
*h_priv
;
316 uint32_t bus_capabilities
;
317 uint_t current_max_payload
;
321 ASSERT(MUTEX_HELD(&hal
->topology_tree_mutex
));
323 switch (cmd
->cmd_type
) {
324 case CMD1394_ASYNCH_RD_QUAD
:
325 case CMD1394_ASYNCH_WR_QUAD
:
326 case CMD1394_ASYNCH_RD_BLOCK
:
327 case CMD1394_ASYNCH_WR_BLOCK
:
328 case CMD1394_ASYNCH_LOCK_32
:
329 case CMD1394_ASYNCH_LOCK_64
:
333 *err
= CMD1394_EINVALID_COMMAND
;
334 return (DDI_FAILURE
);
337 /* Check for potential address roll-over */
338 if (s1394_address_rollover(cmd
) != B_FALSE
) {
339 *err
= CMD1394_EADDRESS_ERROR
;
340 return (DDI_FAILURE
);
343 /* Get the Services Layer private area */
344 s_priv
= S1394_GET_CMD_PRIV(cmd
);
346 /* Set up who sent command on which hal */
347 s_priv
->sent_by_target
= (s1394_target_t
*)target
;
348 s_priv
->sent_on_hal
= (s1394_hal_t
*)hal
;
350 /* Set up command transfer type */
351 s_priv
->cmd_priv_xfer_type
= xfer_type
;
353 if (cmd
->cmd_options
& CMD1394_OVERRIDE_ADDR
) {
354 /* Compare the current generation from the HAL struct */
355 /* to the one given by the target */
357 /* Speed is to be filled in from speed map */
358 from_node
= IEEE1394_NODE_NUM(hal
->node_id
);
359 to_node
= IEEE1394_ADDR_PHY_ID(cmd
->cmd_addr
);
361 if (cmd
->bus_generation
!= hal
->generation_count
) {
362 *err
= CMD1394_ESTALE_GENERATION
;
363 return (DDI_FAILURE
);
367 /* Set the generation */
368 cmd
->bus_generation
= hal
->generation_count
;
370 /* If not OVERRIDE_ADDR, then target may not be NULL */
371 ASSERT(target
!= NULL
);
373 rw_enter(&hal
->target_list_rwlock
, RW_READER
);
375 if ((target
->target_state
& S1394_TARG_GONE
) != 0 ||
376 target
->on_node
== NULL
) {
377 rw_exit(&hal
->target_list_rwlock
);
378 *err
= CMD1394_EDEVICE_REMOVED
;
379 return (DDI_FAILURE
);
382 ASSERT((target
->target_state
& S1394_TARG_GONE
) == 0);
383 node
= target
->on_node
->node_num
;
384 rw_exit(&hal
->target_list_rwlock
);
386 /* Mask in the top 16-bits */
387 cmd
->cmd_addr
= (cmd
->cmd_addr
& IEEE1394_ADDR_OFFSET_MASK
);
388 cmd
->cmd_addr
= (cmd
->cmd_addr
|
389 (node
<< IEEE1394_ADDR_PHY_ID_SHIFT
));
390 cmd
->cmd_addr
= (cmd
->cmd_addr
| IEEE1394_ADDR_BUS_ID_MASK
);
392 /* Speed is to be filled in from speed map */
393 from_node
= IEEE1394_NODE_NUM(hal
->node_id
);
394 to_node
= (uint32_t)node
;
397 /* Get a pointer to the HAL private struct */
398 h_priv
= (h1394_cmd_priv_t
*)&s_priv
->hal_cmd_private
;
400 /* Copy the generation into the HAL's private field */
401 h_priv
->bus_generation
= cmd
->bus_generation
;
403 /* Fill in the nodeID */
404 cmd
->nodeID
= (cmd
->cmd_addr
& IEEE1394_ADDR_NODE_ID_MASK
) >>
405 IEEE1394_ADDR_NODE_ID_SHIFT
;
407 if (cmd
->cmd_options
& CMD1394_OVERRIDE_SPEED
) {
408 if (cmd
->cmd_speed
> IEEE1394_S400
) {
409 *err
= CMD1394_EINVALID_COMMAND
;
410 return (DDI_FAILURE
);
413 s_priv
->hal_cmd_private
.speed
= (int)cmd
->cmd_speed
;
417 /* Speed is to be filled in from speed map */
418 s_priv
->hal_cmd_private
.speed
= (int)s1394_speed_map_get(hal
,
422 /* Is it a block request? */
423 if ((cmd
->cmd_type
== CMD1394_ASYNCH_RD_BLOCK
) ||
424 (cmd
->cmd_type
== CMD1394_ASYNCH_WR_BLOCK
)) {
426 if (cmd
->cmd_u
.b
.data_block
== NULL
) {
427 *err
= CMD1394_ENULL_MBLK
;
428 return (DDI_FAILURE
);
431 /* Also need to check for MBLK_TOO_SMALL */
432 if (s1394_mblk_too_small(cmd
) != B_FALSE
) {
433 *err
= CMD1394_EMBLK_TOO_SMALL
;
434 return (DDI_FAILURE
);
437 /* Initialize bytes_transferred to zero */
438 cmd
->cmd_u
.b
.bytes_transferred
= 0;
440 /* Handle the MAX_PAYLOAD size */
441 if (cmd
->cmd_options
& CMD1394_OVERRIDE_ADDR
) {
443 current_max_payload
= 512 <<
444 (s_priv
->hal_cmd_private
.speed
);
445 if (hal
->topology_tree
[to_node
].cfgrom
) {
447 hal
->topology_tree
[to_node
].cfgrom
[
448 IEEE1212_NODE_CAP_QUAD
];
449 max_rec
= (bus_capabilities
&
450 IEEE1394_BIB_MAXREC_MASK
) >>
451 IEEE1394_BIB_MAXREC_SHIFT
;
456 if ((max_rec
> 0) && (max_rec
< 14)) {
457 max_blk
= 1 << (max_rec
+ 1);
460 /* These are either unspecified or reserved */
463 if (max_blk
< current_max_payload
)
464 current_max_payload
= max_blk
;
467 rw_enter(&hal
->target_list_rwlock
, RW_READER
);
468 current_max_payload
= target
->current_max_payload
;
469 rw_exit(&hal
->target_list_rwlock
);
472 if (cmd
->cmd_options
& CMD1394_OVERRIDE_MAX_PAYLOAD
) {
473 if (current_max_payload
> cmd
->cmd_u
.b
.max_payload
)
474 current_max_payload
= cmd
->cmd_u
.b
.max_payload
;
477 h_priv
->mblk
.curr_mblk
= cmd
->cmd_u
.b
.data_block
;
479 if (cmd
->cmd_type
== CMD1394_ASYNCH_WR_BLOCK
) {
480 h_priv
->mblk
.curr_offset
=
481 cmd
->cmd_u
.b
.data_block
->b_rptr
;
483 h_priv
->mblk
.curr_offset
=
484 cmd
->cmd_u
.b
.data_block
->b_wptr
;
487 if (cmd
->cmd_u
.b
.blk_length
> current_max_payload
) {
488 h_priv
->mblk
.length
= current_max_payload
;
489 s_priv
->data_remaining
= cmd
->cmd_u
.b
.blk_length
;
492 h_priv
->mblk
.length
= cmd
->cmd_u
.b
.blk_length
;
493 s_priv
->data_remaining
= cmd
->cmd_u
.b
.blk_length
;
497 /* Mark command as being used */
498 s_priv
->cmd_in_use
= B_TRUE
;
500 /* Put command on the HAL's outstanding request Q */
501 s1394_insert_q_asynch_cmd(hal
, cmd
);
503 return (DDI_SUCCESS
);
507 * s1394_insert_q_asynch_cmd()
508 * is used to insert a given command structure onto a HAL's outstanding
512 s1394_insert_q_asynch_cmd(s1394_hal_t
*hal
, cmd1394_cmd_t
*cmd
)
514 s1394_cmd_priv_t
*s_priv
;
515 s1394_cmd_priv_t
*c_priv
;
516 cmd1394_cmd_t
*temp_cmd
;
518 mutex_enter(&hal
->outstanding_q_mutex
);
520 /* Get the Services Layer private area */
521 s_priv
= S1394_GET_CMD_PRIV(cmd
);
523 /* Is the outstanding request queue empty? */
524 if ((hal
->outstanding_q_head
== NULL
) &&
525 (hal
->outstanding_q_tail
== NULL
)) {
527 hal
->outstanding_q_head
= (cmd1394_cmd_t
*)cmd
;
528 hal
->outstanding_q_tail
= (cmd1394_cmd_t
*)cmd
;
529 s_priv
->cmd_priv_next
= (cmd1394_cmd_t
*)NULL
;
530 s_priv
->cmd_priv_prev
= (cmd1394_cmd_t
*)NULL
;
533 s_priv
->cmd_priv_next
= hal
->outstanding_q_head
;
534 s_priv
->cmd_priv_prev
= (cmd1394_cmd_t
*)NULL
;
536 temp_cmd
= (cmd1394_cmd_t
*)hal
->outstanding_q_head
;
537 c_priv
= (s1394_cmd_priv_t
*)((uchar_t
*)temp_cmd
+
538 sizeof (cmd1394_cmd_t
));
539 c_priv
->cmd_priv_prev
= (cmd1394_cmd_t
*)cmd
;
541 hal
->outstanding_q_head
= (cmd1394_cmd_t
*)cmd
;
544 mutex_exit(&hal
->outstanding_q_mutex
);
548 * s1394_remove_q_asynch_cmd()
549 * is used to remove a given command structure from a HAL's outstanding
553 s1394_remove_q_asynch_cmd(s1394_hal_t
*hal
, cmd1394_cmd_t
*cmd
)
555 s1394_cmd_priv_t
*s_priv
;
556 s1394_cmd_priv_t
*c_priv
;
557 cmd1394_cmd_t
*prev_cmd
;
558 cmd1394_cmd_t
*next_cmd
;
560 mutex_enter(&hal
->outstanding_q_mutex
);
562 /* Get the Services Layer private area */
563 s_priv
= S1394_GET_CMD_PRIV(cmd
);
565 prev_cmd
= (cmd1394_cmd_t
*)s_priv
->cmd_priv_prev
;
566 next_cmd
= (cmd1394_cmd_t
*)s_priv
->cmd_priv_next
;
568 s_priv
->cmd_priv_prev
= (cmd1394_cmd_t
*)NULL
;
569 s_priv
->cmd_priv_next
= (cmd1394_cmd_t
*)NULL
;
571 if (prev_cmd
!= NULL
) {
572 c_priv
= (s1394_cmd_priv_t
*)((uchar_t
*)prev_cmd
+
573 sizeof (cmd1394_cmd_t
));
574 c_priv
->cmd_priv_next
= (cmd1394_cmd_t
*)next_cmd
;
577 if (hal
->outstanding_q_head
== (cmd1394_cmd_t
*)cmd
)
578 hal
->outstanding_q_head
= (cmd1394_cmd_t
*)next_cmd
;
581 if (next_cmd
!= NULL
) {
582 c_priv
= (s1394_cmd_priv_t
*)((uchar_t
*)next_cmd
+
583 sizeof (cmd1394_cmd_t
));
584 c_priv
->cmd_priv_prev
= (cmd1394_cmd_t
*)prev_cmd
;
587 if (hal
->outstanding_q_tail
== (cmd1394_cmd_t
*)cmd
)
588 hal
->outstanding_q_tail
= (cmd1394_cmd_t
*)prev_cmd
;
591 mutex_exit(&hal
->outstanding_q_mutex
);
595 * s1394_atreq_cmd_complete()
596 * is called by h1394_cmd_is_complete() when an AT request has completed.
597 * Based upon a command's completion status, s1394_atreq_cmd_complete()
598 * determines whether to call the target (or unblock), put the command onto
599 * the pending Q to be sent out later, or to resend the command
600 * (multi-part command).
603 s1394_atreq_cmd_complete(s1394_hal_t
*hal
, cmd1394_cmd_t
*req
, int status
)
605 s1394_cmd_priv_t
*s_priv
;
606 h1394_cmd_priv_t
*h_priv
;
612 /* Get the Services Layer private area */
613 s_priv
= S1394_GET_CMD_PRIV(req
);
615 /* If not an ack_complete... */
616 if (status
!= H1394_CMD_SUCCESS
) {
617 /* kstats - number of failure AT responses */
618 switch (req
->cmd_type
) {
619 case CMD1394_ASYNCH_RD_QUAD
:
620 hal
->hal_kstats
->atresp_quad_rd_fail
++;
623 case CMD1394_ASYNCH_RD_BLOCK
:
624 hal
->hal_kstats
->atresp_blk_rd_fail
++;
627 case CMD1394_ASYNCH_WR_QUAD
:
628 hal
->hal_kstats
->atresp_quad_wr_fail
++;
631 case CMD1394_ASYNCH_WR_BLOCK
:
632 hal
->hal_kstats
->atresp_blk_wr_fail
++;
635 case CMD1394_ASYNCH_LOCK_32
:
636 hal
->hal_kstats
->atresp_lock32_fail
++;
639 case CMD1394_ASYNCH_LOCK_64
:
640 hal
->hal_kstats
->atresp_lock64_fail
++;
646 /* evt_missing_ack */
647 case H1394_CMD_ETIMEOUT
:
648 cmd_result
= CMD1394_ETIMEOUT
;
652 case H1394_CMD_EBUSRESET
:
653 /* Move request to pending Q if cancel on */
654 /* reset is not set */
655 if (req
->cmd_options
& CMD1394_CANCEL_ON_BUS_RESET
) {
656 cmd_result
= CMD1394_EBUSRESET
;
659 s1394_remove_q_asynch_cmd(hal
, req
);
660 s1394_pending_q_insert(hal
, req
, S1394_PENDING_Q_REAR
);
666 case H1394_CMD_EDEVICE_BUSY
:
667 cmd_result
= CMD1394_EDEVICE_BUSY
;
671 case H1394_CMD_EDATA_ERROR
:
672 cmd_result
= CMD1394_EDATA_ERROR
;
676 case H1394_CMD_ETYPE_ERROR
:
677 cmd_result
= CMD1394_ETYPE_ERROR
;
680 /* resp_address_error */
681 /* ack_address_error */
682 case H1394_CMD_EADDR_ERROR
:
683 cmd_result
= CMD1394_EADDRESS_ERROR
;
686 /* resp_conflict_error */
687 /* ack_conflict_error */
688 case H1394_CMD_ERSRC_CONFLICT
:
689 cmd_result
= CMD1394_ERSRC_CONFLICT
;
693 case H1394_CMD_EDEVICE_POWERUP
:
694 cmd_result
= CMD1394_EDEVICE_BUSY
;
697 /* device errors (bad tcodes, ACKs, etc...) */
698 case H1394_CMD_EDEVICE_ERROR
:
699 cmd_result
= CMD1394_EDEVICE_ERROR
;
702 /* Unknown error type */
703 case H1394_CMD_EUNKNOWN_ERROR
:
704 cmd_result
= CMD1394_EUNKNOWN_ERROR
;
707 /* Unrecognized error */
709 dip
= hal
->halinfo
.dip
;
711 /* An unexpected error in the HAL */
712 cmn_err(CE_WARN
, HALT_ERROR_MESSAGE
,
713 ddi_node_name(dip
), ddi_get_instance(dip
));
715 /* Disable the HAL */
716 s1394_hal_shutdown(hal
, B_TRUE
);
721 /* Remove command from the HAL's outstanding request Q */
722 s1394_remove_q_asynch_cmd(hal
, req
);
724 s_priv
->cmd_in_use
= B_FALSE
;
726 req
->cmd_result
= cmd_result
;
728 /* Is this a blocking command? */
729 if (req
->cmd_options
& CMD1394_BLOCKING
) {
730 /* Unblock the waiting command */
731 mutex_enter(&s_priv
->blocking_mutex
);
732 s_priv
->blocking_flag
= B_TRUE
;
733 cv_signal(&s_priv
->blocking_cv
);
734 mutex_exit(&s_priv
->blocking_mutex
);
739 /* Call the target's completion_callback() */
740 if (req
->completion_callback
!= NULL
) {
741 req
->completion_callback(req
);
747 /* Successful unless otherwise modified */
748 err
= CMD1394_CMDSUCCESS
;
750 if ((req
->cmd_type
== CMD1394_ASYNCH_RD_BLOCK
) ||
751 (req
->cmd_type
== CMD1394_ASYNCH_WR_BLOCK
)) {
753 /* Get a pointer to the HAL private struct */
754 h_priv
= (h1394_cmd_priv_t
*)&s_priv
->hal_cmd_private
;
756 /* Update data_remaining */
757 s_priv
->data_remaining
-= h_priv
->mblk
.length
;
759 /* Increment bytes_transferred */
760 req
->cmd_u
.b
.bytes_transferred
+= h_priv
->mblk
.length
;
762 if (req
->cmd_type
== CMD1394_ASYNCH_RD_BLOCK
)
763 hal
->hal_kstats
->atreq_blk_rd_size
+=
766 /* Is there still more to send? */
767 if (s_priv
->data_remaining
> 0) {
769 /* Setup the new mblk and offset */
770 h_priv
->mblk
.curr_mblk
= h_priv
->mblk
.next_mblk
;
771 h_priv
->mblk
.curr_offset
= h_priv
->mblk
.next_offset
;
773 /* Update destination address */
774 if (!(req
->cmd_options
&
775 CMD1394_DISABLE_ADDR_INCREMENT
)) {
776 req
->cmd_addr
+= h_priv
->mblk
.length
;
780 * Use the current MAX_PAYLOAD size. This value
781 * doesn't need to be recalculated because we must
782 * be in the same generation on the bus, else we
783 * would have seen a bus reset error.
785 if (s_priv
->data_remaining
< h_priv
->mblk
.length
) {
786 h_priv
->mblk
.length
= s_priv
->data_remaining
;
789 /* Send command out again */
790 ret
= s1394_xfer_asynch_command(hal
, req
, &err
);
792 if (ret
== DDI_SUCCESS
) {
795 } else if (err
== CMD1394_ESTALE_GENERATION
) {
796 /* Remove cmd from outstanding request Q */
797 s1394_remove_q_asynch_cmd(hal
, req
);
798 s1394_pending_q_insert(hal
, req
,
799 S1394_PENDING_Q_REAR
);
806 /* Remove command from the HAL's outstanding request Q */
807 s1394_remove_q_asynch_cmd(hal
, req
);
809 s_priv
->cmd_in_use
= B_FALSE
;
812 req
->cmd_result
= err
;
814 /* Is this a blocking command? */
815 if (req
->cmd_options
& CMD1394_BLOCKING
) {
816 /* Unblock the waiting command */
817 mutex_enter(&s_priv
->blocking_mutex
);
818 s_priv
->blocking_flag
= B_TRUE
;
819 cv_signal(&s_priv
->blocking_cv
);
820 mutex_exit(&s_priv
->blocking_mutex
);
825 /* Set status and call completion_callback() */
826 if (req
->completion_callback
!= NULL
) {
828 req
->completion_callback(req
);
835 * s1394_atresp_cmd_complete()
836 * is similar to s1394_atreq_cmd_complete(). It is also called by
837 * h1394_cmd_is_complete(), but when an AT response has completed.
838 * Again, based upon the command's completion status,
839 * s1394_atresp_cmd_complete() determines whether to call the target or
840 * to simply cleanup the command and return.
843 s1394_atresp_cmd_complete(s1394_hal_t
*hal
, cmd1394_cmd_t
*resp
, int status
)
845 s1394_cmd_priv_t
*s_priv
;
846 h1394_cmd_priv_t
*h_priv
;
848 boolean_t valid_addr_blk
;
851 target_status
= CMD1394_CMDSUCCESS
;
853 /* If not an ack_complete */
854 if (status
!= H1394_CMD_SUCCESS
) {
856 /* evt_missing_ack */
857 case H1394_CMD_ETIMEOUT
:
858 target_status
= CMD1394_ETIMEOUT
;
862 case H1394_CMD_EBUSRESET
:
863 target_status
= CMD1394_EBUSRESET
;
869 case H1394_CMD_EDEVICE_BUSY
:
870 target_status
= CMD1394_EDEVICE_BUSY
;
874 case H1394_CMD_EDATA_ERROR
:
875 target_status
= CMD1394_EDATA_ERROR
;
879 case H1394_CMD_ETYPE_ERROR
:
880 target_status
= CMD1394_ETYPE_ERROR
;
883 /* ack_address_error */
884 case H1394_CMD_EADDR_ERROR
:
885 target_status
= CMD1394_EADDRESS_ERROR
;
888 /* ack_conflict_error */
889 case H1394_CMD_ERSRC_CONFLICT
:
890 target_status
= CMD1394_ERSRC_CONFLICT
;
894 case H1394_CMD_EDEVICE_POWERUP
:
895 target_status
= CMD1394_EDEVICE_BUSY
;
898 /* device errors (bad tcodes, ACKs, etc...) */
899 case H1394_CMD_EDEVICE_ERROR
:
900 target_status
= CMD1394_EDEVICE_ERROR
;
903 /* Unknown error type */
904 case H1394_CMD_EUNKNOWN_ERROR
:
905 target_status
= CMD1394_EUNKNOWN_ERROR
;
908 /* Unrecognized error */
910 dip
= hal
->halinfo
.dip
;
912 /* An unexpected error in the HAL */
913 cmn_err(CE_WARN
, HALT_ERROR_MESSAGE
,
914 ddi_node_name(dip
), ddi_get_instance(dip
));
916 /* Disable the HAL */
917 s1394_hal_shutdown(hal
, B_TRUE
);
923 /* Get the Services Layer private area */
924 s_priv
= S1394_GET_CMD_PRIV(resp
);
926 /* Get a pointer to the HAL private struct */
927 h_priv
= (h1394_cmd_priv_t
*)&s_priv
->hal_cmd_private
;
929 valid_addr_blk
= s_priv
->arreq_valid_addr
;
931 if (valid_addr_blk
== B_TRUE
) {
932 /* Set the command status */
933 resp
->cmd_result
= target_status
;
935 switch (s_priv
->cmd_priv_xfer_type
) {
937 case S1394_CMD_WRITE
:
939 if (resp
->completion_callback
!= NULL
) {
940 resp
->completion_callback(resp
);
945 dip
= hal
->halinfo
.dip
;
947 /* An unexpected error in the HAL */
948 cmn_err(CE_WARN
, HALT_ERROR_MESSAGE
,
949 ddi_node_name(dip
), ddi_get_instance(dip
));
951 /* Disable the HAL */
952 s1394_hal_shutdown(hal
, B_TRUE
);
958 /* Free the command - Pass it back to the HAL */
959 HAL_CALL(hal
).response_complete(hal
->halinfo
.hal_private
, resp
, h_priv
);
963 * s1394_send_response()
964 * is used to send a response to an AR request. Depending on whether the
965 * request was a broadcast request, a write to posted write address space,
966 * or some other request, either a response packet is sent, or the command
967 * is returned to the HAL. A return value of DDI_SUCCESS means that the
968 * command has been handled correctly. It was either successfully sent to
969 * the HAL, or, if it was posted_write of broadcast, it was freed up. A
970 * return value of DDI_FAILURE indicates either a serious error, in which
971 * case the HAL is shutdown, or a failure returned by the HAL, in which
972 * case the command is freed up and notice of the failure is returned.
975 s1394_send_response(s1394_hal_t
*hal
, cmd1394_cmd_t
*resp
)
977 s1394_cmd_priv_t
*s_priv
;
978 h1394_cmd_priv_t
*h_priv
;
983 /* Get the Services Layer private area */
984 s_priv
= S1394_GET_CMD_PRIV(resp
);
986 /* Get a pointer to the HAL private struct */
987 h_priv
= (h1394_cmd_priv_t
*)&s_priv
->hal_cmd_private
;
990 * If request was broadcast or a write request to a posted write
991 * address, don't send a response
993 if ((resp
->broadcast
== 1) || ((s_priv
->posted_write
== B_TRUE
) &&
994 ((resp
->cmd_result
== CMD1394_ASYNCH_WR_QUAD
) ||
995 (resp
->cmd_result
== CMD1394_ASYNCH_WR_BLOCK
)))) {
997 /* Free the command - Pass it back to the HAL */
998 HAL_CALL(hal
).response_complete(hal
->halinfo
.hal_private
,
1001 return (DDI_SUCCESS
);
1004 /* kstats - number of failure responses sent */
1005 if (resp
->cmd_result
!= IEEE1394_RESP_COMPLETE
) {
1006 switch (resp
->cmd_type
) {
1007 case CMD1394_ASYNCH_RD_QUAD
:
1008 hal
->hal_kstats
->arresp_quad_rd_fail
++;
1011 case CMD1394_ASYNCH_RD_BLOCK
:
1012 hal
->hal_kstats
->arresp_blk_rd_fail
++;
1015 case CMD1394_ASYNCH_WR_QUAD
:
1016 hal
->hal_kstats
->arresp_quad_wr_fail
++;
1019 case CMD1394_ASYNCH_WR_BLOCK
:
1020 hal
->hal_kstats
->arresp_blk_wr_fail
++;
1023 case CMD1394_ASYNCH_LOCK_32
:
1024 hal
->hal_kstats
->arresp_lock32_fail
++;
1027 case CMD1394_ASYNCH_LOCK_64
:
1028 hal
->hal_kstats
->arresp_lock64_fail
++;
1032 if (resp
->cmd_type
== CMD1394_ASYNCH_RD_BLOCK
)
1033 hal
->hal_kstats
->arreq_blk_rd_size
+=
1034 resp
->cmd_u
.b
.blk_length
;
1037 if (resp
->cmd_type
== CMD1394_ASYNCH_RD_BLOCK
) {
1038 h_priv
->mblk
.curr_mblk
= resp
->cmd_u
.b
.data_block
;
1039 h_priv
->mblk
.curr_offset
= resp
->cmd_u
.b
.data_block
->b_rptr
;
1040 h_priv
->mblk
.length
= resp
->cmd_u
.b
.blk_length
;
1043 switch (s_priv
->cmd_priv_xfer_type
) {
1044 case S1394_CMD_READ
:
1045 ret
= HAL_CALL(hal
).read_response(hal
->halinfo
.hal_private
,
1046 resp
, h_priv
, &result
);
1049 case S1394_CMD_WRITE
:
1050 ret
= HAL_CALL(hal
).write_response(hal
->halinfo
.hal_private
,
1051 resp
, h_priv
, &result
);
1054 case S1394_CMD_LOCK
:
1055 ret
= HAL_CALL(hal
).lock_response(hal
->halinfo
.hal_private
,
1056 resp
, h_priv
, &result
);
1060 dip
= hal
->halinfo
.dip
;
1062 /* An unexpected error in the HAL */
1063 cmn_err(CE_WARN
, HALT_ERROR_MESSAGE
,
1064 ddi_node_name(dip
), ddi_get_instance(dip
));
1066 /* Disable the HAL */
1067 s1394_hal_shutdown(hal
, B_TRUE
);
1069 return (DDI_FAILURE
);
1072 /* Unable to send a response */
1073 if (ret
!= DDI_SUCCESS
) {
1074 /* Free the command - Pass it back to the HAL */
1075 HAL_CALL(hal
).response_complete(hal
->halinfo
.hal_private
,
1078 return (DDI_FAILURE
);
1081 return (DDI_SUCCESS
);
1085 * s1394_compare_swap()
1086 * is used by t1394_lock() to send a lock request. Any of the lock
1087 * requests specified explicitly by the 1394 spec will pass thru here,
1088 * i.e compare-swap, mask-swap, etc.
1091 s1394_compare_swap(s1394_hal_t
*hal
, s1394_target_t
*target
, cmd1394_cmd_t
*cmd
)
1093 s1394_cmd_priv_t
*s_priv
;
1094 s1394_hal_state_t state
;
1098 ASSERT(MUTEX_NOT_HELD(&hal
->topology_tree_mutex
));
1100 /* Lock the topology tree - protect from bus reset */
1101 mutex_enter(&hal
->topology_tree_mutex
);
1103 ret
= s1394_setup_asynch_command(hal
, target
, cmd
, S1394_CMD_LOCK
,
1106 /* Unlock the topology tree */
1107 mutex_exit(&hal
->topology_tree_mutex
);
1109 /* Get the Services Layer private area */
1110 s_priv
= S1394_GET_CMD_PRIV(cmd
);
1112 /* Command has now been put onto the queue! */
1113 if (ret
!= DDI_SUCCESS
) {
1114 /* Copy error code into result */
1115 cmd
->cmd_result
= err
;
1117 return (DDI_FAILURE
);
1120 mutex_enter(&hal
->topology_tree_mutex
);
1121 state
= hal
->hal_state
;
1122 /* If this command was sent during a bus reset, */
1123 /* then put it onto the pending Q. */
1124 if (state
== S1394_HAL_RESET
) {
1125 /* Remove cmd from outstanding request Q */
1126 s1394_remove_q_asynch_cmd(hal
, cmd
);
1128 /* Are we on the bus reset event stack? */
1129 if (s1394_on_br_thread(hal
) == B_TRUE
) {
1130 /* Blocking commands are not allowed */
1131 if (cmd
->cmd_options
& CMD1394_BLOCKING
) {
1132 mutex_exit(&hal
->topology_tree_mutex
);
1134 s_priv
->cmd_in_use
= B_FALSE
;
1136 cmd
->cmd_result
= CMD1394_EINVALID_CONTEXT
;
1138 return (DDI_FAILURE
);
1142 s1394_pending_q_insert(hal
, cmd
, S1394_PENDING_Q_FRONT
);
1143 mutex_exit(&hal
->topology_tree_mutex
);
1145 /* Block (if necessary) */
1146 s1394_block_on_asynch_cmd(cmd
);
1148 return (DDI_SUCCESS
);
1150 mutex_exit(&hal
->topology_tree_mutex
);
1152 /* Send the command out */
1153 ret
= s1394_xfer_asynch_command(hal
, cmd
, &err
);
1155 if (ret
!= DDI_SUCCESS
) {
1156 if (err
== CMD1394_ESTALE_GENERATION
) {
1157 /* Remove cmd from outstanding request Q */
1158 s1394_remove_q_asynch_cmd(hal
, cmd
);
1159 s1394_pending_q_insert(hal
, cmd
, S1394_PENDING_Q_FRONT
);
1161 /* Block (if necessary) */
1162 s1394_block_on_asynch_cmd(cmd
);
1164 return (DDI_SUCCESS
);
1167 /* Remove cmd from outstanding request Q */
1168 s1394_remove_q_asynch_cmd(hal
, cmd
);
1170 s_priv
->cmd_in_use
= B_FALSE
;
1172 /* Copy error code into result */
1173 cmd
->cmd_result
= err
;
1175 return (DDI_FAILURE
);
1178 /* Block (if necessary) */
1179 s1394_block_on_asynch_cmd(cmd
);
1181 return (DDI_SUCCESS
);
1186 * s1394_split_lock_req()
1187 * is also used by t1394_lock() to send a lock request. The difference
1188 * is that s1394_split_lock_req() is used to send the software supported
1189 * lock types, i.e. bit_and, bit_or, etc. These lock requests require
1190 * more than one transaction, typically compare-swap's.
1193 s1394_split_lock_req(s1394_hal_t
*hal
, s1394_target_t
*target
,
1196 s1394_cmd_priv_t
*s_priv
;
1197 cmd1394_cmd_t
*tmp_cmd
;
1199 /* Allocate a temporary command */
1200 if (s1394_alloc_cmd(hal
, T1394_ALLOC_CMD_NOSLEEP
, &tmp_cmd
) !=
1202 cmd
->cmd_result
= CMD1394_EUNKNOWN_ERROR
;
1204 return (DDI_FAILURE
);
1207 /* Get the Services Layer private area */
1208 s_priv
= S1394_GET_CMD_PRIV(tmp_cmd
);
1210 tmp_cmd
->completion_callback
= s1394_handle_lock
;
1211 tmp_cmd
->cmd_callback_arg
= (opaque_t
)cmd
;
1212 tmp_cmd
->cmd_type
= cmd
->cmd_type
;
1213 tmp_cmd
->cmd_addr
= cmd
->cmd_addr
;
1214 tmp_cmd
->cmd_options
= cmd
->cmd_options
;
1215 tmp_cmd
->bus_generation
= cmd
->bus_generation
;
1217 /* The temporary command can not block */
1218 tmp_cmd
->cmd_options
= tmp_cmd
->cmd_options
& ~CMD1394_BLOCKING
;
1220 /* Setup compare-swap with data_value == arg_value (read) */
1221 if (tmp_cmd
->cmd_type
== CMD1394_ASYNCH_LOCK_32
) {
1222 tmp_cmd
->cmd_u
.l32
.data_value
= 0;
1223 tmp_cmd
->cmd_u
.l32
.arg_value
= 0;
1224 tmp_cmd
->cmd_u
.l32
.lock_type
= CMD1394_LOCK_COMPARE_SWAP
;
1225 s_priv
->temp_num_retries
= cmd
->cmd_u
.l32
.num_retries
;
1227 tmp_cmd
->cmd_u
.l64
.data_value
= 0;
1228 tmp_cmd
->cmd_u
.l64
.arg_value
= 0;
1229 tmp_cmd
->cmd_u
.l64
.lock_type
= CMD1394_LOCK_COMPARE_SWAP
;
1230 s_priv
->temp_num_retries
= cmd
->cmd_u
.l64
.num_retries
;
1233 /* Initialize lock_req_step */
1234 s_priv
->lock_req_step
= 0;
1236 /* Get the Services Layer private area for the target cmd */
1237 s_priv
= S1394_GET_CMD_PRIV(cmd
);
1239 s_priv
->cmd_in_use
= B_TRUE
;
1241 /* Send the request */
1242 if (s1394_compare_swap(hal
, target
, tmp_cmd
) != DDI_SUCCESS
) {
1243 s_priv
->cmd_in_use
= B_FALSE
;
1245 /* Free the temporary command */
1246 if (s1394_free_cmd(hal
, &tmp_cmd
) != DDI_SUCCESS
)
1247 cmd
->cmd_result
= CMD1394_EUNKNOWN_ERROR
;
1249 return (DDI_FAILURE
);
1252 /* Block (if necessary) */
1253 s1394_block_on_asynch_cmd(cmd
);
1255 return (DDI_SUCCESS
);
1259 * s1394_handle_lock()
1260 * is the callback for s1394_split_lock_req(). It does all of the real
1261 * work. Based on the specific lock type all necessary manipulation is
1262 * performed and another compare swap is sent out. If the transaction
1263 * is unsuccessful, it is retried.
1266 s1394_handle_lock(cmd1394_cmd_t
*cmd
)
1268 s1394_hal_t
*to_hal
;
1269 s1394_target_t
*target
;
1270 s1394_cmd_priv_t
*s_priv
;
1271 cmd1394_cmd_t
*target_cmd
;
1272 uint32_t lock_req_step
;
1276 /* Get the Services Layer private area */
1277 s_priv
= S1394_GET_CMD_PRIV(cmd
);
1279 lock_req_step
= s_priv
->lock_req_step
;
1281 /* Get the target's command */
1282 target_cmd
= (cmd1394_cmd_t
*)cmd
->cmd_callback_arg
;
1284 /* Get the destination of the command */
1285 to_hal
= s_priv
->sent_on_hal
;
1288 /* Is this step 0 completing? */
1289 if (lock_req_step
== 0) {
1290 /* Was the request successful? */
1291 if (cmd
->cmd_result
== CMD1394_CMDSUCCESS
) {
1292 /* Do any math, bit ops, or byte-swapping necessary */
1293 ret
= s1394_process_split_lock(cmd
, target_cmd
);
1295 if (ret
!= DDI_SUCCESS
) {
1296 tcmd_result
= target_cmd
->cmd_result
;
1300 s_priv
->lock_req_step
= 1;
1302 target
= s_priv
->sent_by_target
;
1304 if (s1394_compare_swap(to_hal
, target
, cmd
) !=
1306 tcmd_result
= cmd
->cmd_result
;
1312 /* Command failed for some reason */
1313 tcmd_result
= cmd
->cmd_result
;
1316 } else { /* lock_req_step == 1 */
1317 /* Was the request successful? */
1318 if (cmd
->cmd_result
== CMD1394_CMDSUCCESS
) {
1319 /* Do whatever's necessary to finish up the lock */
1320 ret
= s1394_finish_split_lock(cmd
, target_cmd
);
1322 if (ret
!= DDI_SUCCESS
) {
1324 goto lock_req_step_0
;
1326 tcmd_result
= cmd
->cmd_result
;
1330 /* Command failed for some reason */
1331 tcmd_result
= cmd
->cmd_result
;
1337 if (s1394_free_cmd(to_hal
, &cmd
) != DDI_SUCCESS
) {
1340 /* Get the Services Layer private area */
1341 s_priv
= S1394_GET_CMD_PRIV(target_cmd
);
1343 s_priv
->cmd_in_use
= B_FALSE
;
1345 target_cmd
->cmd_result
= tcmd_result
;
1347 /* Is this a blocking command? */
1348 if (target_cmd
->cmd_options
& CMD1394_BLOCKING
) {
1349 /* Unblock the waiting command */
1350 mutex_enter(&s_priv
->blocking_mutex
);
1351 s_priv
->blocking_flag
= B_TRUE
;
1352 cv_signal(&s_priv
->blocking_cv
);
1353 mutex_exit(&s_priv
->blocking_mutex
);
1358 /* Call the target's completion_callback() */
1359 if (target_cmd
->completion_callback
!= NULL
)
1360 target_cmd
->completion_callback(target_cmd
);
1364 * s1394_pending_q_insert()
1365 * is used to insert a given command structure onto a HAL's pending queue
1366 * for later processing (after the bus reset). All commands returned by
1367 * the HAL, are inserted onto the rear of the list (first priority), and
1368 * all other commands (from targets during bus reset) are put onto the front.
1371 s1394_pending_q_insert(s1394_hal_t
*hal
, cmd1394_cmd_t
*cmd
, uint_t flags
)
1373 cmd1394_cmd_t
*temp_cmd
;
1374 s1394_cmd_priv_t
*s_priv
;
1375 s1394_cmd_priv_t
*c_priv
;
1377 mutex_enter(&hal
->pending_q_mutex
);
1379 /* Get the Services Layer private area */
1380 s_priv
= S1394_GET_CMD_PRIV(cmd
);
1382 /* Is the outstanding request queue empty? */
1383 if ((hal
->pending_q_head
== NULL
) && (hal
->pending_q_tail
== NULL
)) {
1385 hal
->pending_q_head
= (cmd1394_cmd_t
*)cmd
;
1386 hal
->pending_q_tail
= (cmd1394_cmd_t
*)cmd
;
1387 s_priv
->cmd_priv_next
= (cmd1394_cmd_t
*)NULL
;
1388 s_priv
->cmd_priv_prev
= (cmd1394_cmd_t
*)NULL
;
1390 } else if (flags
== S1394_PENDING_Q_FRONT
) {
1391 s_priv
->cmd_priv_next
= hal
->pending_q_head
;
1392 s_priv
->cmd_priv_prev
= (cmd1394_cmd_t
*)NULL
;
1394 temp_cmd
= (cmd1394_cmd_t
*)hal
->pending_q_head
;
1395 c_priv
= (s1394_cmd_priv_t
*)((uchar_t
*)temp_cmd
+
1396 sizeof (cmd1394_cmd_t
));
1397 c_priv
->cmd_priv_prev
= (cmd1394_cmd_t
*)cmd
;
1399 hal
->pending_q_head
= (cmd1394_cmd_t
*)cmd
;
1402 s_priv
->cmd_priv_prev
= hal
->pending_q_tail
;
1403 s_priv
->cmd_priv_next
= (cmd1394_cmd_t
*)NULL
;
1405 temp_cmd
= (cmd1394_cmd_t
*)hal
->pending_q_tail
;
1406 c_priv
= (s1394_cmd_priv_t
*)((uchar_t
*)temp_cmd
+
1407 sizeof (cmd1394_cmd_t
));
1408 c_priv
->cmd_priv_next
= (cmd1394_cmd_t
*)cmd
;
1410 hal
->pending_q_tail
= (cmd1394_cmd_t
*)cmd
;
1413 mutex_exit(&hal
->pending_q_mutex
);
1415 /* kstats - number of pending Q insertions */
1416 hal
->hal_kstats
->pending_q_insert
++;
1420 * s1394_pending_q_remove()
1421 * is used to remove a command structure from a HAL's pending queue for
1424 static cmd1394_cmd_t
*
1425 s1394_pending_q_remove(s1394_hal_t
*hal
)
1427 s1394_cmd_priv_t
*s_priv
;
1428 s1394_cmd_priv_t
*c_priv
;
1430 cmd1394_cmd_t
*prev_cmd
;
1432 mutex_enter(&hal
->pending_q_mutex
);
1434 cmd
= (cmd1394_cmd_t
*)hal
->pending_q_tail
;
1436 mutex_exit(&hal
->pending_q_mutex
);
1440 /* Get the Services Layer private area */
1441 s_priv
= S1394_GET_CMD_PRIV(cmd
);
1443 prev_cmd
= (cmd1394_cmd_t
*)s_priv
->cmd_priv_prev
;
1445 s_priv
->cmd_priv_prev
= (cmd1394_cmd_t
*)NULL
;
1446 s_priv
->cmd_priv_next
= (cmd1394_cmd_t
*)NULL
;
1448 if (prev_cmd
!= NULL
) {
1449 c_priv
= (s1394_cmd_priv_t
*)((uchar_t
*)prev_cmd
+
1450 sizeof (cmd1394_cmd_t
));
1451 c_priv
->cmd_priv_next
= (cmd1394_cmd_t
*)NULL
;
1454 hal
->pending_q_head
= (cmd1394_cmd_t
*)NULL
;
1456 hal
->pending_q_tail
= (cmd1394_cmd_t
*)prev_cmd
;
1458 mutex_exit(&hal
->pending_q_mutex
);
1464 * s1394_resend_pending_cmds()
1465 * is called when the pending queue is to be flushed. After most of the
1466 * bus reset processing is completed, the pending commands are sent/resent.
1469 s1394_resend_pending_cmds(s1394_hal_t
*hal
)
1473 ASSERT(MUTEX_NOT_HELD(&hal
->topology_tree_mutex
));
1476 done
= s1394_process_pending_q(hal
);
1477 } while (done
== B_FALSE
);
1479 ASSERT(MUTEX_NOT_HELD(&hal
->topology_tree_mutex
));
1483 * s1394_process_pending_q()
1484 * is called to send/resend the commands on the pending queue. All command
1485 * handling can be done here, including notifying the target of failed
1486 * commands, etc. If it is necessary to recompute the address, speed,
1487 * or max_payload for a command, that can be done here too. And if there
1488 * is no reason not to continue sending commands from the pending queue,
1489 * then a B_FALSE is returned, else B_TRUE is returned.
1492 s1394_process_pending_q(s1394_hal_t
*hal
)
1494 s1394_cmd_priv_t
*s_priv
;
1495 h1394_cmd_priv_t
*h_priv
;
1496 s1394_target_t
*target
;
1501 uint_t current_max_payload
;
1504 ASSERT(MUTEX_NOT_HELD(&hal
->topology_tree_mutex
));
1506 /* Pull a command from the Pending Q */
1507 cmd
= s1394_pending_q_remove(hal
);
1513 /* Get the Services Layer private area */
1514 s_priv
= S1394_GET_CMD_PRIV(cmd
);
1516 /* Get a pointer to the HAL private struct */
1517 h_priv
= (h1394_cmd_priv_t
*)&s_priv
->hal_cmd_private
;
1519 if ((cmd
->cmd_options
& CMD1394_OVERRIDE_ADDR
) ||
1520 (cmd
->cmd_options
& CMD1394_CANCEL_ON_BUS_RESET
)) {
1521 if (h_priv
->bus_generation
== hal
->generation_count
) {
1522 ret
= s1394_pending_q_helper(hal
, cmd
);
1526 s_priv
->cmd_in_use
= B_FALSE
;
1528 cmd
->cmd_result
= CMD1394_EBUSRESET
;
1530 /* Is this a blocking command? */
1531 if (cmd
->cmd_options
& CMD1394_BLOCKING
) {
1532 /* Unblock the waiting command */
1533 mutex_enter(&s_priv
->blocking_mutex
);
1534 s_priv
->blocking_flag
= B_TRUE
;
1535 cv_signal(&s_priv
->blocking_cv
);
1536 mutex_exit(&s_priv
->blocking_mutex
);
1541 /* Call the target's completion_callback() */
1542 if (cmd
->completion_callback
!= NULL
) {
1543 cmd
->completion_callback(cmd
);
1549 if (h_priv
->bus_generation
== hal
->generation_count
) {
1550 ret
= s1394_pending_q_helper(hal
, cmd
);
1553 /* Make sure we can get the topology_tree_mutex */
1554 if (s1394_lock_tree(hal
) != DDI_SUCCESS
)
1557 /* Set the generation */
1558 cmd
->bus_generation
= hal
->generation_count
;
1560 /* Copy the generation into the HAL's private field */
1561 h_priv
->bus_generation
= cmd
->bus_generation
;
1563 target
= s_priv
->sent_by_target
;
1565 /* If not OVERRIDE_ADDR, then target may not be NULL */
1566 ASSERT(target
!= NULL
);
1568 rw_enter(&hal
->target_list_rwlock
, RW_READER
);
1570 if (((target
->target_state
& S1394_TARG_GONE
) == 0) &&
1571 (target
->on_node
!= NULL
)) {
1572 node
= target
->on_node
->node_num
;
1573 rw_exit(&hal
->target_list_rwlock
);
1575 rw_exit(&hal
->target_list_rwlock
);
1577 s_priv
->cmd_in_use
= B_FALSE
;
1579 cmd
->cmd_result
= CMD1394_EDEVICE_REMOVED
;
1581 /* Is this a blocking command? */
1582 if (cmd
->cmd_options
& CMD1394_BLOCKING
) {
1583 s1394_unlock_tree(hal
);
1585 /* Unblock the waiting command */
1586 mutex_enter(&s_priv
->blocking_mutex
);
1587 s_priv
->blocking_flag
= B_TRUE
;
1588 cv_signal(&s_priv
->blocking_cv
);
1589 mutex_exit(&s_priv
->blocking_mutex
);
1594 /* Call the target's completion_callback() */
1595 if (cmd
->completion_callback
!= NULL
) {
1596 s1394_unlock_tree(hal
);
1597 cmd
->completion_callback(cmd
);
1600 s1394_unlock_tree(hal
);
1605 /* Mask in the top 16-bits */
1606 cmd
->cmd_addr
= cmd
->cmd_addr
&
1607 IEEE1394_ADDR_OFFSET_MASK
;
1608 cmd
->cmd_addr
= cmd
->cmd_addr
|
1609 (node
<< IEEE1394_ADDR_PHY_ID_SHIFT
);
1610 cmd
->cmd_addr
= cmd
->cmd_addr
|
1611 IEEE1394_ADDR_BUS_ID_MASK
;
1613 /* Speed is to be filled in from speed map */
1614 from_node
= IEEE1394_NODE_NUM(hal
->node_id
);
1615 to_node
= (uint32_t)node
;
1617 /* Fill in the nodeID */
1619 (cmd
->cmd_addr
& IEEE1394_ADDR_NODE_ID_MASK
) >>
1620 IEEE1394_ADDR_NODE_ID_SHIFT
;
1622 if (cmd
->cmd_options
& CMD1394_OVERRIDE_SPEED
) {
1623 s_priv
->hal_cmd_private
.speed
=
1624 (int)cmd
->cmd_speed
;
1626 /* Speed is to be filled in from speed map */
1627 s_priv
->hal_cmd_private
.speed
=
1628 (int)s1394_speed_map_get(hal
, from_node
,
1632 /* Is it a block request? */
1633 if ((cmd
->cmd_type
== CMD1394_ASYNCH_RD_BLOCK
) ||
1634 (cmd
->cmd_type
== CMD1394_ASYNCH_WR_BLOCK
)) {
1636 /* Get a pointer to the HAL private struct */
1637 h_priv
= (h1394_cmd_priv_t
*)&s_priv
->
1640 /* Handle the MAX_PAYLOAD size */
1641 if (s_priv
->sent_by_target
!= NULL
) {
1642 current_max_payload
=
1643 s_priv
->sent_by_target
->
1644 current_max_payload
;
1646 current_max_payload
= 4;
1648 if (cmd
->cmd_options
&
1649 CMD1394_OVERRIDE_MAX_PAYLOAD
) {
1650 if (current_max_payload
>
1651 cmd
->cmd_u
.b
.max_payload
)
1652 current_max_payload
=
1653 cmd
->cmd_u
.b
.max_payload
;
1655 if (s_priv
->data_remaining
<
1656 current_max_payload
) {
1657 h_priv
->mblk
.length
=
1658 s_priv
->data_remaining
;
1660 h_priv
->mblk
.length
=
1661 current_max_payload
;
1664 s1394_unlock_tree(hal
);
1665 ret
= s1394_pending_q_helper(hal
, cmd
);
1672 * s1394_pending_q_helper()
1673 * is a "helper" function for s1394_process_pending_q(). It attempts to
1674 * resend commands, handling error conditions whenever necessary.
1677 s1394_pending_q_helper(s1394_hal_t
*hal
, cmd1394_cmd_t
*cmd
)
1679 s1394_cmd_priv_t
*s_priv
;
1683 ASSERT(MUTEX_NOT_HELD(&hal
->topology_tree_mutex
));
1685 /* Get the Services Layer private area */
1686 s_priv
= S1394_GET_CMD_PRIV(cmd
);
1688 /* Put cmd on outstanding request Q */
1689 s1394_insert_q_asynch_cmd(hal
, cmd
);
1691 /* Send command out again */
1692 ret
= s1394_xfer_asynch_command(hal
, cmd
, &err
);
1694 if (ret
!= DDI_SUCCESS
) {
1695 if (err
== CMD1394_ESTALE_GENERATION
) {
1696 /* Remove cmd outstanding req Q */
1697 s1394_remove_q_asynch_cmd(hal
, cmd
);
1698 s1394_pending_q_insert(hal
, cmd
, S1394_PENDING_Q_FRONT
);
1702 /* Remove cmd from outstanding request Q */
1703 s1394_remove_q_asynch_cmd(hal
, cmd
);
1705 s_priv
->cmd_in_use
= B_FALSE
;
1707 cmd
->cmd_result
= err
;
1709 /* Is this a blocking command? */
1710 if (cmd
->cmd_options
& CMD1394_BLOCKING
) {
1711 /* Unblock waiting command */
1712 mutex_enter(&s_priv
->blocking_mutex
);
1713 s_priv
->blocking_flag
= B_TRUE
;
1714 cv_signal(&s_priv
->blocking_cv
);
1715 mutex_exit(&s_priv
->blocking_mutex
);
1720 /* Call target completion_callback() */
1721 if (cmd
->completion_callback
!= NULL
) {
1722 cmd
->completion_callback(cmd
);
1734 * s1394_process_split_lock()
1735 * is a "helper" function for the s1394_handle_lock() callback. Its
1736 * job is to perform whatever manipulation is required for the given
1740 s1394_process_split_lock(cmd1394_cmd_t
*cmd
, cmd1394_cmd_t
*target_cmd
)
1742 uint64_t new_value64
;
1743 uint64_t data_value64
;
1744 uint64_t arg_value64
;
1745 uint64_t old_value64
;
1746 uint64_t temp_value64
;
1747 uint32_t new_value32
;
1748 uint32_t data_value32
;
1749 uint32_t arg_value32
;
1750 uint32_t old_value32
;
1751 uint32_t temp_value32
;
1753 if (cmd
->cmd_type
== CMD1394_ASYNCH_LOCK_32
) {
1754 old_value32
= cmd
->cmd_u
.l32
.old_value
;
1755 data_value32
= target_cmd
->cmd_u
.l32
.data_value
;
1756 arg_value32
= target_cmd
->cmd_u
.l32
.arg_value
;
1758 /* Lock type specific */
1759 switch (target_cmd
->cmd_u
.l32
.lock_type
) {
1760 case CMD1394_LOCK_BIT_AND
:
1761 new_value32
= old_value32
& data_value32
;
1764 case CMD1394_LOCK_BIT_OR
:
1765 new_value32
= old_value32
| data_value32
;
1768 case CMD1394_LOCK_BIT_XOR
:
1769 new_value32
= old_value32
^ data_value32
;
1772 case CMD1394_LOCK_INCREMENT
:
1773 old_value32
= T1394_DATA32(old_value32
);
1774 new_value32
= old_value32
+ 1;
1775 new_value32
= T1394_DATA32(new_value32
);
1776 old_value32
= T1394_DATA32(old_value32
);
1779 case CMD1394_LOCK_DECREMENT
:
1780 old_value32
= T1394_DATA32(old_value32
);
1781 new_value32
= old_value32
- 1;
1782 new_value32
= T1394_DATA32(new_value32
);
1783 old_value32
= T1394_DATA32(old_value32
);
1786 case CMD1394_LOCK_ADD
:
1787 old_value32
= T1394_DATA32(old_value32
);
1788 new_value32
= old_value32
+ data_value32
;
1789 new_value32
= T1394_DATA32(new_value32
);
1790 old_value32
= T1394_DATA32(old_value32
);
1793 case CMD1394_LOCK_SUBTRACT
:
1794 old_value32
= T1394_DATA32(old_value32
);
1795 new_value32
= old_value32
- data_value32
;
1796 new_value32
= T1394_DATA32(new_value32
);
1797 old_value32
= T1394_DATA32(old_value32
);
1800 case CMD1394_LOCK_THRESH_ADD
:
1801 old_value32
= T1394_DATA32(old_value32
);
1802 temp_value32
= (old_value32
+ data_value32
);
1803 if ((temp_value32
>= old_value32
) &&
1804 (temp_value32
<= arg_value32
)) {
1805 new_value32
= T1394_DATA32(temp_value32
);
1806 old_value32
= T1394_DATA32(old_value32
);
1808 /* Failed threshold add */
1809 target_cmd
->cmd_u
.l32
.old_value
=
1810 T1394_DATA32(cmd
->cmd_u
.l32
.old_value
);
1811 target_cmd
->cmd_result
= CMD1394_CMDSUCCESS
;
1812 return (DDI_FAILURE
);
1816 case CMD1394_LOCK_THRESH_SUBTRACT
:
1817 old_value32
= T1394_DATA32(old_value32
);
1818 temp_value32
= (old_value32
- data_value32
);
1819 if ((old_value32
>= data_value32
) &&
1820 (temp_value32
>= arg_value32
)) {
1821 new_value32
= T1394_DATA32(temp_value32
);
1822 old_value32
= T1394_DATA32(old_value32
);
1824 /* Failed threshold subtract */
1825 target_cmd
->cmd_u
.l32
.old_value
=
1826 T1394_DATA32(cmd
->cmd_u
.l32
.old_value
);
1827 target_cmd
->cmd_result
= CMD1394_CMDSUCCESS
;
1828 return (DDI_FAILURE
);
1832 case CMD1394_LOCK_CLIP_ADD
:
1833 old_value32
= T1394_DATA32(old_value32
);
1834 temp_value32
= (old_value32
+ data_value32
);
1835 if ((temp_value32
< old_value32
) ||
1836 (temp_value32
> arg_value32
))
1837 new_value32
= T1394_DATA32(arg_value32
);
1839 new_value32
= T1394_DATA32(temp_value32
);
1840 old_value32
= T1394_DATA32(old_value32
);
1843 case CMD1394_LOCK_CLIP_SUBTRACT
:
1844 old_value32
= T1394_DATA32(old_value32
);
1845 temp_value32
= (old_value32
- data_value32
);
1846 if ((data_value32
> old_value32
) ||
1847 (temp_value32
< arg_value32
))
1848 new_value32
= T1394_DATA32(arg_value32
);
1850 new_value32
= T1394_DATA32(temp_value32
);
1851 old_value32
= T1394_DATA32(old_value32
);
1855 /* Send compare-swap lock request */
1856 cmd
->cmd_u
.l32
.arg_value
= old_value32
;
1857 cmd
->cmd_u
.l32
.data_value
= new_value32
;
1859 old_value64
= cmd
->cmd_u
.l64
.old_value
;
1860 data_value64
= target_cmd
->cmd_u
.l64
.data_value
;
1861 arg_value64
= target_cmd
->cmd_u
.l64
.arg_value
;
1863 /* Lock type specific */
1864 switch (target_cmd
->cmd_u
.l64
.lock_type
) {
1865 case CMD1394_LOCK_BIT_AND
:
1866 new_value64
= old_value64
& data_value64
;
1869 case CMD1394_LOCK_BIT_OR
:
1870 new_value64
= old_value64
| data_value64
;
1873 case CMD1394_LOCK_BIT_XOR
:
1874 new_value64
= old_value64
^ data_value64
;
1877 case CMD1394_LOCK_INCREMENT
:
1878 old_value64
= T1394_DATA64(old_value64
);
1879 new_value64
= old_value64
+ 1;
1880 new_value64
= T1394_DATA64(new_value64
);
1881 old_value64
= T1394_DATA64(old_value64
);
1884 case CMD1394_LOCK_DECREMENT
:
1885 old_value64
= T1394_DATA64(old_value64
);
1886 new_value64
= old_value64
- 1;
1887 new_value64
= T1394_DATA64(new_value64
);
1888 old_value64
= T1394_DATA64(old_value64
);
1891 case CMD1394_LOCK_ADD
:
1892 old_value64
= T1394_DATA64(old_value64
);
1893 new_value64
= old_value64
+ data_value64
;
1894 new_value64
= T1394_DATA64(new_value64
);
1895 old_value64
= T1394_DATA64(old_value64
);
1898 case CMD1394_LOCK_SUBTRACT
:
1899 old_value64
= T1394_DATA64(old_value64
);
1900 new_value64
= old_value64
- data_value64
;
1901 new_value64
= T1394_DATA64(new_value64
);
1902 old_value64
= T1394_DATA64(old_value64
);
1905 case CMD1394_LOCK_THRESH_ADD
:
1906 old_value64
= T1394_DATA64(old_value64
);
1907 temp_value64
= (old_value64
+ data_value64
);
1908 if ((temp_value64
>= old_value64
) &&
1909 (temp_value64
<= arg_value64
)) {
1910 new_value64
= T1394_DATA64(temp_value64
);
1911 old_value64
= T1394_DATA64(old_value64
);
1913 /* Failed threshold add */
1914 target_cmd
->cmd_u
.l64
.old_value
=
1915 T1394_DATA64(cmd
->cmd_u
.l64
.old_value
);
1916 target_cmd
->cmd_result
= CMD1394_CMDSUCCESS
;
1917 return (DDI_FAILURE
);
1921 case CMD1394_LOCK_THRESH_SUBTRACT
:
1922 old_value64
= T1394_DATA64(old_value64
);
1923 temp_value64
= (old_value64
- data_value64
);
1924 if ((old_value64
>= data_value64
) &&
1925 (temp_value64
>= arg_value64
)) {
1926 new_value64
= T1394_DATA64(temp_value64
);
1927 old_value64
= T1394_DATA64(old_value64
);
1929 /* Failed threshold subtract */
1930 target_cmd
->cmd_u
.l64
.old_value
=
1931 T1394_DATA64(cmd
->cmd_u
.l64
.old_value
);
1932 target_cmd
->cmd_result
= CMD1394_CMDSUCCESS
;
1933 return (DDI_FAILURE
);
1937 case CMD1394_LOCK_CLIP_ADD
:
1938 old_value64
= T1394_DATA64(old_value64
);
1939 temp_value64
= (old_value64
+ data_value64
);
1940 if ((temp_value64
< old_value64
) ||
1941 (temp_value64
> arg_value64
))
1942 new_value64
= T1394_DATA64(arg_value64
);
1944 new_value64
= T1394_DATA64(temp_value64
);
1945 old_value64
= T1394_DATA64(old_value64
);
1948 case CMD1394_LOCK_CLIP_SUBTRACT
:
1949 old_value64
= T1394_DATA64(old_value64
);
1950 temp_value64
= (old_value64
- data_value64
);
1951 if ((data_value64
> old_value64
) ||
1952 (temp_value64
< arg_value64
))
1953 new_value64
= T1394_DATA64(arg_value64
);
1955 new_value64
= T1394_DATA64(temp_value64
);
1956 old_value64
= T1394_DATA64(old_value64
);
1960 /* Send compare-swap lock request */
1961 cmd
->cmd_u
.l64
.arg_value
= old_value64
;
1962 cmd
->cmd_u
.l64
.data_value
= new_value64
;
1965 return (DDI_SUCCESS
);
1969 * s1394_finish_split_lock()
1970 * is another "helper" function for the s1394_handle_lock() callback.
1971 * Its job is to finish up whatever lock request procesing is necessary.
1974 s1394_finish_split_lock(cmd1394_cmd_t
*cmd
, cmd1394_cmd_t
*target_cmd
)
1976 s1394_cmd_priv_t
*s_priv
;
1977 uint64_t tmp_value64
;
1978 uint32_t tmp_value32
;
1980 /* Get the Services Layer private area */
1981 s_priv
= S1394_GET_CMD_PRIV(cmd
);
1983 if (((cmd
->cmd_type
== CMD1394_ASYNCH_LOCK_32
) &&
1984 (cmd
->cmd_u
.l32
.old_value
== cmd
->cmd_u
.l32
.arg_value
)) ||
1985 ((cmd
->cmd_type
== CMD1394_ASYNCH_LOCK_64
) &&
1986 (cmd
->cmd_u
.l64
.old_value
== cmd
->cmd_u
.l64
.arg_value
))) {
1988 if (cmd
->cmd_type
== CMD1394_ASYNCH_LOCK_32
) {
1989 switch (cmd
->cmd_u
.l32
.lock_type
) {
1990 case CMD1394_LOCK_INCREMENT
:
1991 case CMD1394_LOCK_DECREMENT
:
1992 case CMD1394_LOCK_ADD
:
1993 case CMD1394_LOCK_SUBTRACT
:
1994 case CMD1394_LOCK_THRESH_ADD
:
1995 case CMD1394_LOCK_THRESH_SUBTRACT
:
1996 case CMD1394_LOCK_CLIP_ADD
:
1997 case CMD1394_LOCK_CLIP_SUBTRACT
:
1998 tmp_value32
= cmd
->cmd_u
.l32
.old_value
;
1999 tmp_value32
= T1394_DATA32(tmp_value32
);
2000 target_cmd
->cmd_u
.l32
.old_value
= tmp_value32
;
2003 tmp_value32
= cmd
->cmd_u
.l32
.old_value
;
2004 target_cmd
->cmd_u
.l32
.old_value
= tmp_value32
;
2008 switch (cmd
->cmd_u
.l64
.lock_type
) {
2009 case CMD1394_LOCK_INCREMENT
:
2010 case CMD1394_LOCK_DECREMENT
:
2011 case CMD1394_LOCK_ADD
:
2012 case CMD1394_LOCK_SUBTRACT
:
2013 case CMD1394_LOCK_THRESH_ADD
:
2014 case CMD1394_LOCK_THRESH_SUBTRACT
:
2015 case CMD1394_LOCK_CLIP_ADD
:
2016 case CMD1394_LOCK_CLIP_SUBTRACT
:
2017 tmp_value64
= cmd
->cmd_u
.l64
.old_value
;
2018 tmp_value64
= T1394_DATA64(tmp_value64
);
2019 target_cmd
->cmd_u
.l64
.old_value
= tmp_value64
;
2022 tmp_value64
= cmd
->cmd_u
.l64
.old_value
;
2023 target_cmd
->cmd_u
.l64
.old_value
= tmp_value64
;
2028 target_cmd
->cmd_result
= CMD1394_CMDSUCCESS
;
2029 return (DDI_SUCCESS
);
2031 if (s_priv
->temp_num_retries
> 0) {
2032 /* Decrement retry count */
2033 s_priv
->temp_num_retries
--;
2035 /* Reset lock_req_step */
2036 s_priv
->lock_req_step
= 0;
2038 /* Resend... start at step 0 again */
2040 return (DDI_FAILURE
);
2042 /* Failed... RETRIES_EXCEEDED */
2043 target_cmd
->cmd_result
= CMD1394_ERETRIES_EXCEEDED
;
2044 return (DDI_SUCCESS
);