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 TNF_PROBE_0_DEBUG(s1394_alloc_cmd_enter
, S1394_TNF_SL_STACK
, "");
77 alloc_sleep
= (flags
& T1394_ALLOC_CMD_NOSLEEP
) ? KM_NOSLEEP
: KM_SLEEP
;
79 if ((alloc_sleep
== KM_SLEEP
) &&
80 (servicing_interrupt())) {
81 TNF_PROBE_1(s1394_alloc_cmd_error
, S1394_TNF_SL_ATREQ_ERROR
,
82 "", tnf_string
, msg
, "Tried to sleep in intr context");
83 TNF_PROBE_0_DEBUG(s1394_alloc_cmd_exit
,
84 S1394_TNF_SL_ATREQ_STACK
, "");
85 ASSERT(alloc_sleep
!= KM_SLEEP
); /* fail */
89 /* either FCP command or response, but not both */
91 (T1394_ALLOC_CMD_FCP_COMMAND
| T1394_ALLOC_CMD_FCP_RESPONSE
)) ==
92 (T1394_ALLOC_CMD_FCP_COMMAND
| T1394_ALLOC_CMD_FCP_RESPONSE
)) {
93 TNF_PROBE_1(s1394_alloc_cmd_error
, S1394_TNF_SL_ATREQ_ERROR
,
94 "", tnf_string
, msg
, "Both FCP cmd and resp flags");
95 TNF_PROBE_0_DEBUG(s1394_alloc_cmd_exit
,
96 S1394_TNF_SL_ATREQ_STACK
, "");
100 *cmdp
= kmem_cache_alloc(hal
->hal_kmem_cachep
, alloc_sleep
);
102 TNF_PROBE_0_DEBUG(s1394_alloc_cmd_exit
,
103 S1394_TNF_SL_STACK
, "");
104 return (DDI_FAILURE
);
106 cmd_size
= sizeof (cmd1394_cmd_t
) +
107 sizeof (s1394_cmd_priv_t
) + hal
->halinfo
.hal_overhead
;
108 bzero((void *)*cmdp
, cmd_size
);
110 (*cmdp
)->cmd_version
= T1394_VERSION_V1
;
111 (*cmdp
)->cmd_result
= CMD1394_NOSTATUS
;
113 /* Get the Services Layer private area */
114 s_priv
= S1394_GET_CMD_PRIV(*cmdp
);
116 /* Set extension type */
117 if (flags
& T1394_ALLOC_CMD_FCP_COMMAND
) {
118 s1394_fa_init_cmd(s_priv
, S1394_FA_TYPE_FCP_CTL
);
119 } else if (flags
& T1394_ALLOC_CMD_FCP_RESPONSE
) {
120 s1394_fa_init_cmd(s_priv
, S1394_FA_TYPE_FCP_TGT
);
123 /* Set up the hal_overhead ptr in the hal_cmd_private */
124 hal_overhead
= (uchar_t
*)s_priv
+ sizeof (s1394_cmd_priv_t
);
125 s_priv
->hal_cmd_private
.hal_overhead
= (void *)hal_overhead
;
127 TNF_PROBE_1_DEBUG(s1394_alloc_cmd
, S1394_TNF_SL_STACK
, "",
128 tnf_opaque
, cmd
, *cmdp
);
130 /* kstats - number of cmd allocs */
131 hal
->hal_kstats
->cmd_alloc
++;
133 TNF_PROBE_0_DEBUG(s1394_alloc_cmd_exit
, S1394_TNF_SL_STACK
, "");
134 return (DDI_SUCCESS
);
139 * is used to free a command that had been previously allocated by
143 s1394_free_cmd(s1394_hal_t
*hal
, cmd1394_cmd_t
**cmdp
)
145 s1394_cmd_priv_t
*s_priv
;
147 TNF_PROBE_0_DEBUG(s1394_free_cmd_enter
, S1394_TNF_SL_STACK
, "");
149 /* Get the Services Layer private area */
150 s_priv
= S1394_GET_CMD_PRIV(*cmdp
);
152 /* Check that command isn't in use */
153 if (s_priv
->cmd_in_use
== B_TRUE
) {
154 TNF_PROBE_1(s1394_free_cmd_error
, S1394_TNF_SL_ERROR
, "",
155 tnf_string
, msg
, "Attempted to free an in-use command");
156 TNF_PROBE_0_DEBUG(s1394_free_cmd_exit
, S1394_TNF_SL_STACK
, "");
157 ASSERT(s_priv
->cmd_in_use
== B_FALSE
);
158 return (DDI_FAILURE
);
160 TNF_PROBE_1_DEBUG(s1394_free_cmd
, S1394_TNF_SL_STACK
, "",
161 tnf_opaque
, cmd
, *cmdp
);
163 /* kstats - number of cmd allocs */
164 kmem_cache_free(hal
->hal_kmem_cachep
, *cmdp
);
166 /* Command pointer is set to NULL before returning */
169 /* kstats - number of cmd frees */
170 hal
->hal_kstats
->cmd_free
++;
172 TNF_PROBE_0_DEBUG(s1394_free_cmd_exit
, S1394_TNF_SL_STACK
, "");
173 return (DDI_SUCCESS
);
177 * s1394_xfer_asynch_command()
178 * is used to send an asynch command down to the HAL. Based upon the type
179 * of command that is being sent, the appropriate HAL function is called.
180 * Command failures are handled be returning an error and/or shutting down
181 * the HAL, depending on the severity of the error.
184 s1394_xfer_asynch_command(s1394_hal_t
*hal
, cmd1394_cmd_t
*cmd
, int *err
)
186 s1394_cmd_priv_t
*s_priv
;
187 h1394_cmd_priv_t
*h_priv
;
188 s1394_hal_state_t state
;
193 TNF_PROBE_0_DEBUG(s1394_xfer_asynch_command_enter
,
194 S1394_TNF_SL_ATREQ_STACK
, "");
196 ASSERT(MUTEX_NOT_HELD(&hal
->topology_tree_mutex
));
198 mutex_enter(&hal
->topology_tree_mutex
);
199 state
= hal
->hal_state
;
200 if (((state
!= S1394_HAL_NORMAL
) && (state
!= S1394_HAL_RESET
)) ||
201 (hal
->disable_requests_bit
== 1)) {
202 *err
= s1394_HAL_asynch_error(hal
, cmd
, state
);
203 mutex_exit(&hal
->topology_tree_mutex
);
204 TNF_PROBE_0_DEBUG(s1394_xfer_asynch_command_exit
,
205 S1394_TNF_SL_ATREQ_STACK
, "");
206 return (DDI_FAILURE
);
208 mutex_exit(&hal
->topology_tree_mutex
);
210 /* Get the Services Layer private area */
211 s_priv
= S1394_GET_CMD_PRIV(cmd
);
213 /* Get a pointer to the HAL private struct */
214 h_priv
= (h1394_cmd_priv_t
*)&s_priv
->hal_cmd_private
;
216 /* kstats - number of AT requests sent */
217 switch (cmd
->cmd_type
) {
218 case CMD1394_ASYNCH_RD_QUAD
:
219 hal
->hal_kstats
->atreq_quad_rd
++;
222 case CMD1394_ASYNCH_RD_BLOCK
:
223 hal
->hal_kstats
->atreq_blk_rd
++;
226 case CMD1394_ASYNCH_WR_QUAD
:
227 hal
->hal_kstats
->atreq_quad_wr
++;
230 case CMD1394_ASYNCH_WR_BLOCK
:
231 hal
->hal_kstats
->atreq_blk_wr
++;
232 hal
->hal_kstats
->atreq_blk_wr_size
+= h_priv
->mblk
.length
;
235 case CMD1394_ASYNCH_LOCK_32
:
236 hal
->hal_kstats
->atreq_lock32
++;
239 case CMD1394_ASYNCH_LOCK_64
:
240 hal
->hal_kstats
->atreq_lock64
++;
244 switch (s_priv
->cmd_priv_xfer_type
) {
245 /* Call the HAL's read entry point */
247 ret
= HAL_CALL(hal
).read(hal
->halinfo
.hal_private
,
248 (cmd1394_cmd_t
*)cmd
,
249 (h1394_cmd_priv_t
*)&s_priv
->hal_cmd_private
,
253 /* Call the HAL's write entry point */
254 case S1394_CMD_WRITE
:
255 ret
= HAL_CALL(hal
).write(hal
->halinfo
.hal_private
,
256 (cmd1394_cmd_t
*)cmd
,
257 (h1394_cmd_priv_t
*)&s_priv
->hal_cmd_private
,
261 /* Call the HAL's lock entry point */
263 ret
= HAL_CALL(hal
).lock(hal
->halinfo
.hal_private
,
264 (cmd1394_cmd_t
*)cmd
,
265 (h1394_cmd_priv_t
*)&s_priv
->hal_cmd_private
,
270 *err
= CMD1394_EUNKNOWN_ERROR
;
272 TNF_PROBE_1(s1394_xfer_asynch_command_error
,
273 S1394_TNF_SL_ATREQ_ERROR
, "", tnf_string
, msg
,
274 "Invalid command type specified");
275 TNF_PROBE_0_DEBUG(s1394_xfer_asynch_command_exit
,
276 S1394_TNF_SL_ATREQ_STACK
, "");
277 return (DDI_FAILURE
);
280 TNF_PROBE_0_DEBUG(s1394_xfer_asynch_command_return_from_HAL
,
281 S1394_TNF_SL_ATREQ_STACK
, "");
283 if (ret
== DDI_FAILURE
) {
284 switch (result_from_hal
) {
285 case H1394_STATUS_EMPTY_TLABEL
:
286 /* Out of TLABELs - Unable to send AT req */
287 *err
= CMD1394_ENO_ATREQ
;
290 case H1394_STATUS_INVALID_BUSGEN
:
291 /* Out of TLABELs - Unable to send AT req */
292 *err
= CMD1394_ESTALE_GENERATION
;
295 case H1394_STATUS_NOMORE_SPACE
:
296 /* No more space on HAL's HW queue */
297 *err
= CMD1394_ENO_ATREQ
;
300 case H1394_STATUS_INTERNAL_ERROR
:
301 dip
= hal
->halinfo
.dip
;
303 /* An unexpected error in the HAL */
304 cmn_err(CE_WARN
, HALT_ERROR_MESSAGE
,
305 ddi_node_name(dip
), ddi_get_instance(dip
));
307 /* Disable the HAL */
308 s1394_hal_shutdown(hal
, B_TRUE
);
310 *err
= CMD1394_EFATAL_ERROR
;
314 dip
= hal
->halinfo
.dip
;
316 /* An unexpected error in the HAL */
317 cmn_err(CE_WARN
, HALT_ERROR_MESSAGE
,
318 ddi_node_name(dip
), ddi_get_instance(dip
));
320 /* Disable the HAL */
321 s1394_hal_shutdown(hal
, B_TRUE
);
323 *err
= CMD1394_EFATAL_ERROR
;
327 TNF_PROBE_2_DEBUG(s1394_xfer_asynch_command_exit
,
328 S1394_TNF_SL_ATREQ_STACK
, "",
329 tnf_int
, result_from_hal
, result_from_hal
,
331 return (DDI_FAILURE
);
334 /* No errors, return success */
335 *err
= CMD1394_NOSTATUS
;
337 TNF_PROBE_0_DEBUG(s1394_xfer_asynch_command_exit
,
338 S1394_TNF_SL_ATREQ_STACK
, "");
339 return (DDI_SUCCESS
);
343 * s1394_setup_asynch_command()
344 * is used to setup an asynch command to be sent down to the HAL and out
345 * onto the bus. This function handles setting up the destination address
346 * (if necessary), speed, max_payload, putting the command onto the
347 * outstanding Q list, and any other things that must be done prior to
351 s1394_setup_asynch_command(s1394_hal_t
*hal
, s1394_target_t
*target
,
352 cmd1394_cmd_t
*cmd
, uint32_t xfer_type
, int *err
)
354 s1394_cmd_priv_t
*s_priv
;
355 h1394_cmd_priv_t
*h_priv
;
359 uint32_t bus_capabilities
;
360 uint_t current_max_payload
;
364 TNF_PROBE_0_DEBUG(s1394_setup_asynch_command_enter
,
365 S1394_TNF_SL_ATREQ_STACK
, "");
367 ASSERT(MUTEX_HELD(&hal
->topology_tree_mutex
));
369 switch (cmd
->cmd_type
) {
370 case CMD1394_ASYNCH_RD_QUAD
:
371 case CMD1394_ASYNCH_WR_QUAD
:
372 case CMD1394_ASYNCH_RD_BLOCK
:
373 case CMD1394_ASYNCH_WR_BLOCK
:
374 case CMD1394_ASYNCH_LOCK_32
:
375 case CMD1394_ASYNCH_LOCK_64
:
379 *err
= CMD1394_EINVALID_COMMAND
;
380 TNF_PROBE_1(s1394_setup_asynch_command_error
,
381 S1394_TNF_SL_ATREQ_ERROR
, "", tnf_string
, msg
,
382 "Invalid command type specified");
383 TNF_PROBE_0_DEBUG(s1394_setup_asynch_command_exit
,
384 S1394_TNF_SL_ATREQ_STACK
, "");
385 return (DDI_FAILURE
);
388 /* Check for potential address roll-over */
389 if (s1394_address_rollover(cmd
) != B_FALSE
) {
390 *err
= CMD1394_EADDRESS_ERROR
;
391 TNF_PROBE_0_DEBUG(s1394_setup_asynch_command_exit
,
392 S1394_TNF_SL_ATREQ_STACK
, "");
393 return (DDI_FAILURE
);
396 /* Get the Services Layer private area */
397 s_priv
= S1394_GET_CMD_PRIV(cmd
);
399 /* Set up who sent command on which hal */
400 s_priv
->sent_by_target
= (s1394_target_t
*)target
;
401 s_priv
->sent_on_hal
= (s1394_hal_t
*)hal
;
403 /* Set up command transfer type */
404 s_priv
->cmd_priv_xfer_type
= xfer_type
;
406 if (cmd
->cmd_options
& CMD1394_OVERRIDE_ADDR
) {
407 /* Compare the current generation from the HAL struct */
408 /* to the one given by the target */
410 /* Speed is to be filled in from speed map */
411 from_node
= IEEE1394_NODE_NUM(hal
->node_id
);
412 to_node
= IEEE1394_ADDR_PHY_ID(cmd
->cmd_addr
);
414 if (cmd
->bus_generation
!= hal
->generation_count
) {
415 *err
= CMD1394_ESTALE_GENERATION
;
416 TNF_PROBE_0_DEBUG(s1394_setup_asynch_command_exit
,
417 S1394_TNF_SL_ATREQ_STACK
, "");
418 return (DDI_FAILURE
);
422 /* Set the generation */
423 cmd
->bus_generation
= hal
->generation_count
;
425 /* If not OVERRIDE_ADDR, then target may not be NULL */
426 ASSERT(target
!= NULL
);
428 rw_enter(&hal
->target_list_rwlock
, RW_READER
);
430 if ((target
->target_state
& S1394_TARG_GONE
) != 0 ||
431 target
->on_node
== NULL
) {
432 rw_exit(&hal
->target_list_rwlock
);
433 *err
= CMD1394_EDEVICE_REMOVED
;
434 TNF_PROBE_0_DEBUG(s1394_setup_asynch_command_exit
,
435 S1394_TNF_SL_ATREQ_STACK
, "");
436 return (DDI_FAILURE
);
439 ASSERT((target
->target_state
& S1394_TARG_GONE
) == 0);
440 node
= target
->on_node
->node_num
;
441 rw_exit(&hal
->target_list_rwlock
);
443 /* Mask in the top 16-bits */
444 cmd
->cmd_addr
= (cmd
->cmd_addr
& IEEE1394_ADDR_OFFSET_MASK
);
445 cmd
->cmd_addr
= (cmd
->cmd_addr
|
446 (node
<< IEEE1394_ADDR_PHY_ID_SHIFT
));
447 cmd
->cmd_addr
= (cmd
->cmd_addr
| IEEE1394_ADDR_BUS_ID_MASK
);
449 /* Speed is to be filled in from speed map */
450 from_node
= IEEE1394_NODE_NUM(hal
->node_id
);
451 to_node
= (uint32_t)node
;
454 /* Get a pointer to the HAL private struct */
455 h_priv
= (h1394_cmd_priv_t
*)&s_priv
->hal_cmd_private
;
457 /* Copy the generation into the HAL's private field */
458 h_priv
->bus_generation
= cmd
->bus_generation
;
460 /* Fill in the nodeID */
461 cmd
->nodeID
= (cmd
->cmd_addr
& IEEE1394_ADDR_NODE_ID_MASK
) >>
462 IEEE1394_ADDR_NODE_ID_SHIFT
;
464 if (cmd
->cmd_options
& CMD1394_OVERRIDE_SPEED
) {
465 if (cmd
->cmd_speed
> IEEE1394_S400
) {
466 *err
= CMD1394_EINVALID_COMMAND
;
467 TNF_PROBE_0_DEBUG(s1394_setup_asynch_command_exit
,
468 S1394_TNF_SL_ATREQ_STACK
, "");
469 return (DDI_FAILURE
);
472 s_priv
->hal_cmd_private
.speed
= (int)cmd
->cmd_speed
;
476 /* Speed is to be filled in from speed map */
477 s_priv
->hal_cmd_private
.speed
= (int)s1394_speed_map_get(hal
,
481 /* Is it a block request? */
482 if ((cmd
->cmd_type
== CMD1394_ASYNCH_RD_BLOCK
) ||
483 (cmd
->cmd_type
== CMD1394_ASYNCH_WR_BLOCK
)) {
485 if (cmd
->cmd_u
.b
.data_block
== NULL
) {
486 *err
= CMD1394_ENULL_MBLK
;
487 TNF_PROBE_0_DEBUG(s1394_setup_asynch_command_exit
,
488 S1394_TNF_SL_ATREQ_STACK
, "");
489 return (DDI_FAILURE
);
492 /* Also need to check for MBLK_TOO_SMALL */
493 if (s1394_mblk_too_small(cmd
) != B_FALSE
) {
494 *err
= CMD1394_EMBLK_TOO_SMALL
;
495 TNF_PROBE_0_DEBUG(s1394_setup_asynch_command_exit
,
496 S1394_TNF_SL_ATREQ_STACK
, "");
497 return (DDI_FAILURE
);
500 /* Initialize bytes_transferred to zero */
501 cmd
->cmd_u
.b
.bytes_transferred
= 0;
503 /* Handle the MAX_PAYLOAD size */
504 if (cmd
->cmd_options
& CMD1394_OVERRIDE_ADDR
) {
506 current_max_payload
= 512 <<
507 (s_priv
->hal_cmd_private
.speed
);
508 if (hal
->topology_tree
[to_node
].cfgrom
) {
510 hal
->topology_tree
[to_node
].cfgrom
[
511 IEEE1212_NODE_CAP_QUAD
];
512 max_rec
= (bus_capabilities
&
513 IEEE1394_BIB_MAXREC_MASK
) >>
514 IEEE1394_BIB_MAXREC_SHIFT
;
519 if ((max_rec
> 0) && (max_rec
< 14)) {
520 max_blk
= 1 << (max_rec
+ 1);
523 /* These are either unspecified or reserved */
526 if (max_blk
< current_max_payload
)
527 current_max_payload
= max_blk
;
530 rw_enter(&hal
->target_list_rwlock
, RW_READER
);
531 current_max_payload
= target
->current_max_payload
;
532 rw_exit(&hal
->target_list_rwlock
);
535 if (cmd
->cmd_options
& CMD1394_OVERRIDE_MAX_PAYLOAD
) {
536 if (current_max_payload
> cmd
->cmd_u
.b
.max_payload
)
537 current_max_payload
= cmd
->cmd_u
.b
.max_payload
;
540 h_priv
->mblk
.curr_mblk
= cmd
->cmd_u
.b
.data_block
;
542 if (cmd
->cmd_type
== CMD1394_ASYNCH_WR_BLOCK
) {
543 h_priv
->mblk
.curr_offset
=
544 cmd
->cmd_u
.b
.data_block
->b_rptr
;
546 h_priv
->mblk
.curr_offset
=
547 cmd
->cmd_u
.b
.data_block
->b_wptr
;
550 if (cmd
->cmd_u
.b
.blk_length
> current_max_payload
) {
551 h_priv
->mblk
.length
= current_max_payload
;
552 s_priv
->data_remaining
= cmd
->cmd_u
.b
.blk_length
;
555 h_priv
->mblk
.length
= cmd
->cmd_u
.b
.blk_length
;
556 s_priv
->data_remaining
= cmd
->cmd_u
.b
.blk_length
;
560 /* Mark command as being used */
561 s_priv
->cmd_in_use
= B_TRUE
;
563 /* Put command on the HAL's outstanding request Q */
564 s1394_insert_q_asynch_cmd(hal
, cmd
);
566 TNF_PROBE_0_DEBUG(s1394_setup_asynch_command_exit
,
567 S1394_TNF_SL_ATREQ_STACK
, "");
568 return (DDI_SUCCESS
);
572 * s1394_insert_q_asynch_cmd()
573 * is used to insert a given command structure onto a HAL's outstanding
577 s1394_insert_q_asynch_cmd(s1394_hal_t
*hal
, cmd1394_cmd_t
*cmd
)
579 s1394_cmd_priv_t
*s_priv
;
580 s1394_cmd_priv_t
*c_priv
;
581 cmd1394_cmd_t
*temp_cmd
;
583 TNF_PROBE_0_DEBUG(s1394_insert_q_asynch_cmd_enter
,
584 S1394_TNF_SL_ATREQ_STACK
, "");
586 mutex_enter(&hal
->outstanding_q_mutex
);
588 /* Get the Services Layer private area */
589 s_priv
= S1394_GET_CMD_PRIV(cmd
);
591 /* Is the outstanding request queue empty? */
592 if ((hal
->outstanding_q_head
== NULL
) &&
593 (hal
->outstanding_q_tail
== NULL
)) {
595 hal
->outstanding_q_head
= (cmd1394_cmd_t
*)cmd
;
596 hal
->outstanding_q_tail
= (cmd1394_cmd_t
*)cmd
;
597 s_priv
->cmd_priv_next
= (cmd1394_cmd_t
*)NULL
;
598 s_priv
->cmd_priv_prev
= (cmd1394_cmd_t
*)NULL
;
601 s_priv
->cmd_priv_next
= hal
->outstanding_q_head
;
602 s_priv
->cmd_priv_prev
= (cmd1394_cmd_t
*)NULL
;
604 temp_cmd
= (cmd1394_cmd_t
*)hal
->outstanding_q_head
;
605 c_priv
= (s1394_cmd_priv_t
*)((uchar_t
*)temp_cmd
+
606 sizeof (cmd1394_cmd_t
));
607 c_priv
->cmd_priv_prev
= (cmd1394_cmd_t
*)cmd
;
609 hal
->outstanding_q_head
= (cmd1394_cmd_t
*)cmd
;
612 mutex_exit(&hal
->outstanding_q_mutex
);
614 TNF_PROBE_0_DEBUG(s1394_insert_q_asynch_cmd_exit
,
615 S1394_TNF_SL_ATREQ_STACK
, "");
619 * s1394_remove_q_asynch_cmd()
620 * is used to remove a given command structure from a HAL's outstanding
624 s1394_remove_q_asynch_cmd(s1394_hal_t
*hal
, cmd1394_cmd_t
*cmd
)
626 s1394_cmd_priv_t
*s_priv
;
627 s1394_cmd_priv_t
*c_priv
;
628 cmd1394_cmd_t
*prev_cmd
;
629 cmd1394_cmd_t
*next_cmd
;
631 TNF_PROBE_0_DEBUG(s1394_remove_q_asynch_cmd_enter
,
632 S1394_TNF_SL_ATREQ_STACK
, "");
634 mutex_enter(&hal
->outstanding_q_mutex
);
636 /* Get the Services Layer private area */
637 s_priv
= S1394_GET_CMD_PRIV(cmd
);
639 prev_cmd
= (cmd1394_cmd_t
*)s_priv
->cmd_priv_prev
;
640 next_cmd
= (cmd1394_cmd_t
*)s_priv
->cmd_priv_next
;
642 s_priv
->cmd_priv_prev
= (cmd1394_cmd_t
*)NULL
;
643 s_priv
->cmd_priv_next
= (cmd1394_cmd_t
*)NULL
;
645 if (prev_cmd
!= NULL
) {
646 c_priv
= (s1394_cmd_priv_t
*)((uchar_t
*)prev_cmd
+
647 sizeof (cmd1394_cmd_t
));
648 c_priv
->cmd_priv_next
= (cmd1394_cmd_t
*)next_cmd
;
651 if (hal
->outstanding_q_head
== (cmd1394_cmd_t
*)cmd
)
652 hal
->outstanding_q_head
= (cmd1394_cmd_t
*)next_cmd
;
655 if (next_cmd
!= NULL
) {
656 c_priv
= (s1394_cmd_priv_t
*)((uchar_t
*)next_cmd
+
657 sizeof (cmd1394_cmd_t
));
658 c_priv
->cmd_priv_prev
= (cmd1394_cmd_t
*)prev_cmd
;
661 if (hal
->outstanding_q_tail
== (cmd1394_cmd_t
*)cmd
)
662 hal
->outstanding_q_tail
= (cmd1394_cmd_t
*)prev_cmd
;
665 mutex_exit(&hal
->outstanding_q_mutex
);
667 TNF_PROBE_0_DEBUG(s1394_remove_q_asynch_cmd_exit
,
668 S1394_TNF_SL_ATREQ_STACK
, "");
672 * s1394_atreq_cmd_complete()
673 * is called by h1394_cmd_is_complete() when an AT request has completed.
674 * Based upon a command's completion status, s1394_atreq_cmd_complete()
675 * determines whether to call the target (or unblock), put the command onto
676 * the pending Q to be sent out later, or to resend the command
677 * (multi-part command).
680 s1394_atreq_cmd_complete(s1394_hal_t
*hal
, cmd1394_cmd_t
*req
, int status
)
682 s1394_cmd_priv_t
*s_priv
;
683 h1394_cmd_priv_t
*h_priv
;
689 TNF_PROBE_0_DEBUG(s1394_atreq_cmd_complete_enter
,
690 S1394_TNF_SL_ATREQ_STACK
, "");
692 /* Get the Services Layer private area */
693 s_priv
= S1394_GET_CMD_PRIV(req
);
695 /* If not an ack_complete... */
696 if (status
!= H1394_CMD_SUCCESS
) {
697 /* kstats - number of failure AT responses */
698 switch (req
->cmd_type
) {
699 case CMD1394_ASYNCH_RD_QUAD
:
700 hal
->hal_kstats
->atresp_quad_rd_fail
++;
703 case CMD1394_ASYNCH_RD_BLOCK
:
704 hal
->hal_kstats
->atresp_blk_rd_fail
++;
707 case CMD1394_ASYNCH_WR_QUAD
:
708 hal
->hal_kstats
->atresp_quad_wr_fail
++;
711 case CMD1394_ASYNCH_WR_BLOCK
:
712 hal
->hal_kstats
->atresp_blk_wr_fail
++;
715 case CMD1394_ASYNCH_LOCK_32
:
716 hal
->hal_kstats
->atresp_lock32_fail
++;
719 case CMD1394_ASYNCH_LOCK_64
:
720 hal
->hal_kstats
->atresp_lock64_fail
++;
726 /* evt_missing_ack */
727 case H1394_CMD_ETIMEOUT
:
728 cmd_result
= CMD1394_ETIMEOUT
;
732 case H1394_CMD_EBUSRESET
:
733 /* Move request to pending Q if cancel on */
734 /* reset is not set */
735 if (req
->cmd_options
& CMD1394_CANCEL_ON_BUS_RESET
) {
736 cmd_result
= CMD1394_EBUSRESET
;
739 s1394_remove_q_asynch_cmd(hal
, req
);
740 s1394_pending_q_insert(hal
, req
, S1394_PENDING_Q_REAR
);
741 TNF_PROBE_0_DEBUG(s1394_atreq_cmd_complete_exit
,
742 S1394_TNF_SL_ATREQ_STACK
, "");
748 case H1394_CMD_EDEVICE_BUSY
:
749 cmd_result
= CMD1394_EDEVICE_BUSY
;
753 case H1394_CMD_EDATA_ERROR
:
754 cmd_result
= CMD1394_EDATA_ERROR
;
758 case H1394_CMD_ETYPE_ERROR
:
759 cmd_result
= CMD1394_ETYPE_ERROR
;
762 /* resp_address_error */
763 /* ack_address_error */
764 case H1394_CMD_EADDR_ERROR
:
765 cmd_result
= CMD1394_EADDRESS_ERROR
;
768 /* resp_conflict_error */
769 /* ack_conflict_error */
770 case H1394_CMD_ERSRC_CONFLICT
:
771 cmd_result
= CMD1394_ERSRC_CONFLICT
;
775 case H1394_CMD_EDEVICE_POWERUP
:
776 cmd_result
= CMD1394_EDEVICE_BUSY
;
779 /* device errors (bad tcodes, ACKs, etc...) */
780 case H1394_CMD_EDEVICE_ERROR
:
781 cmd_result
= CMD1394_EDEVICE_ERROR
;
784 /* Unknown error type */
785 case H1394_CMD_EUNKNOWN_ERROR
:
786 cmd_result
= CMD1394_EUNKNOWN_ERROR
;
789 /* Unrecognized error */
791 dip
= hal
->halinfo
.dip
;
793 /* An unexpected error in the HAL */
794 cmn_err(CE_WARN
, HALT_ERROR_MESSAGE
,
795 ddi_node_name(dip
), ddi_get_instance(dip
));
797 /* Disable the HAL */
798 s1394_hal_shutdown(hal
, B_TRUE
);
800 TNF_PROBE_2(s1394_atreq_cmd_complete_error
,
801 S1394_TNF_SL_ATREQ_ERROR
, "", tnf_string
, msg
,
802 "Unrecognized cmd status code",
803 tnf_int
, status
, status
);
804 TNF_PROBE_0_DEBUG(s1394_atreq_cmd_complete_exit
,
805 S1394_TNF_SL_ATREQ_STACK
, "");
809 /* Remove command from the HAL's outstanding request Q */
810 s1394_remove_q_asynch_cmd(hal
, req
);
812 s_priv
->cmd_in_use
= B_FALSE
;
814 req
->cmd_result
= cmd_result
;
816 /* Is this a blocking command? */
817 if (req
->cmd_options
& CMD1394_BLOCKING
) {
818 /* Unblock the waiting command */
819 mutex_enter(&s_priv
->blocking_mutex
);
820 s_priv
->blocking_flag
= B_TRUE
;
821 cv_signal(&s_priv
->blocking_cv
);
822 mutex_exit(&s_priv
->blocking_mutex
);
824 TNF_PROBE_0_DEBUG(s1394_atreq_cmd_complete_exit
,
825 S1394_TNF_SL_ATREQ_STACK
, "");
829 /* Call the target's completion_callback() */
830 if (req
->completion_callback
!= NULL
) {
831 TNF_PROBE_0_DEBUG(s1394_atreq_cmd_complete_do_callback
,
832 S1394_TNF_SL_ATREQ_STACK
, "");
833 req
->completion_callback(req
);
836 TNF_PROBE_0_DEBUG(s1394_atreq_cmd_complete_exit
,
837 S1394_TNF_SL_ATREQ_STACK
, "");
841 /* Successful unless otherwise modified */
842 err
= CMD1394_CMDSUCCESS
;
844 if ((req
->cmd_type
== CMD1394_ASYNCH_RD_BLOCK
) ||
845 (req
->cmd_type
== CMD1394_ASYNCH_WR_BLOCK
)) {
847 /* Get a pointer to the HAL private struct */
848 h_priv
= (h1394_cmd_priv_t
*)&s_priv
->hal_cmd_private
;
850 /* Update data_remaining */
851 s_priv
->data_remaining
-= h_priv
->mblk
.length
;
853 /* Increment bytes_transferred */
854 req
->cmd_u
.b
.bytes_transferred
+= h_priv
->mblk
.length
;
856 if (req
->cmd_type
== CMD1394_ASYNCH_RD_BLOCK
)
857 hal
->hal_kstats
->atreq_blk_rd_size
+=
860 /* Is there still more to send? */
861 if (s_priv
->data_remaining
> 0) {
863 /* Setup the new mblk and offset */
864 h_priv
->mblk
.curr_mblk
= h_priv
->mblk
.next_mblk
;
865 h_priv
->mblk
.curr_offset
= h_priv
->mblk
.next_offset
;
867 /* Update destination address */
868 if (!(req
->cmd_options
&
869 CMD1394_DISABLE_ADDR_INCREMENT
)) {
870 req
->cmd_addr
+= h_priv
->mblk
.length
;
874 * Use the current MAX_PAYLOAD size. This value
875 * doesn't need to be recalculated because we must
876 * be in the same generation on the bus, else we
877 * would have seen a bus reset error.
879 if (s_priv
->data_remaining
< h_priv
->mblk
.length
) {
880 h_priv
->mblk
.length
= s_priv
->data_remaining
;
883 /* Send command out again */
884 ret
= s1394_xfer_asynch_command(hal
, req
, &err
);
886 if (ret
== DDI_SUCCESS
) {
887 TNF_PROBE_0_DEBUG(s1394_atreq_cmd_complete_exit
,
888 S1394_TNF_SL_ATREQ_STACK
, "");
891 } else if (err
== CMD1394_ESTALE_GENERATION
) {
892 /* Remove cmd from outstanding request Q */
893 s1394_remove_q_asynch_cmd(hal
, req
);
894 s1394_pending_q_insert(hal
, req
,
895 S1394_PENDING_Q_REAR
);
897 TNF_PROBE_0_DEBUG(s1394_atreq_cmd_complete_exit
,
898 S1394_TNF_SL_ATREQ_STACK
, "");
904 /* Remove command from the HAL's outstanding request Q */
905 s1394_remove_q_asynch_cmd(hal
, req
);
907 s_priv
->cmd_in_use
= B_FALSE
;
910 req
->cmd_result
= err
;
912 /* Is this a blocking command? */
913 if (req
->cmd_options
& CMD1394_BLOCKING
) {
914 /* Unblock the waiting command */
915 mutex_enter(&s_priv
->blocking_mutex
);
916 s_priv
->blocking_flag
= B_TRUE
;
917 cv_signal(&s_priv
->blocking_cv
);
918 mutex_exit(&s_priv
->blocking_mutex
);
920 TNF_PROBE_0_DEBUG(s1394_atreq_cmd_complete_exit
,
921 S1394_TNF_SL_ATREQ_STACK
, "");
925 /* Set status and call completion_callback() */
926 if (req
->completion_callback
!= NULL
) {
928 TNF_PROBE_0_DEBUG(s1394_atreq_cmd_complete_do_callback
,
929 S1394_TNF_SL_ATREQ_STACK
, "");
931 req
->completion_callback(req
);
933 TNF_PROBE_0_DEBUG(s1394_atreq_cmd_complete_exit
,
934 S1394_TNF_SL_ATREQ_STACK
, "");
938 TNF_PROBE_0_DEBUG(s1394_atreq_cmd_complete_exit
,
939 S1394_TNF_SL_ATREQ_STACK
, "");
943 * s1394_atresp_cmd_complete()
944 * is similar to s1394_atreq_cmd_complete(). It is also called by
945 * h1394_cmd_is_complete(), but when an AT response has completed.
946 * Again, based upon the command's completion status,
947 * s1394_atresp_cmd_complete() determines whether to call the target or
948 * to simply cleanup the command and return.
951 s1394_atresp_cmd_complete(s1394_hal_t
*hal
, cmd1394_cmd_t
*resp
, int status
)
953 s1394_cmd_priv_t
*s_priv
;
954 h1394_cmd_priv_t
*h_priv
;
956 boolean_t valid_addr_blk
;
959 TNF_PROBE_0_DEBUG(s1394_atresp_cmd_complete_enter
,
960 S1394_TNF_SL_ATRESP_STACK
, "");
962 target_status
= CMD1394_CMDSUCCESS
;
964 /* If not an ack_complete */
965 if (status
!= H1394_CMD_SUCCESS
) {
967 /* evt_missing_ack */
968 case H1394_CMD_ETIMEOUT
:
969 target_status
= CMD1394_ETIMEOUT
;
973 case H1394_CMD_EBUSRESET
:
974 target_status
= CMD1394_EBUSRESET
;
980 case H1394_CMD_EDEVICE_BUSY
:
981 target_status
= CMD1394_EDEVICE_BUSY
;
985 case H1394_CMD_EDATA_ERROR
:
986 target_status
= CMD1394_EDATA_ERROR
;
990 case H1394_CMD_ETYPE_ERROR
:
991 target_status
= CMD1394_ETYPE_ERROR
;
994 /* ack_address_error */
995 case H1394_CMD_EADDR_ERROR
:
996 target_status
= CMD1394_EADDRESS_ERROR
;
999 /* ack_conflict_error */
1000 case H1394_CMD_ERSRC_CONFLICT
:
1001 target_status
= CMD1394_ERSRC_CONFLICT
;
1005 case H1394_CMD_EDEVICE_POWERUP
:
1006 target_status
= CMD1394_EDEVICE_BUSY
;
1009 /* device errors (bad tcodes, ACKs, etc...) */
1010 case H1394_CMD_EDEVICE_ERROR
:
1011 target_status
= CMD1394_EDEVICE_ERROR
;
1014 /* Unknown error type */
1015 case H1394_CMD_EUNKNOWN_ERROR
:
1016 target_status
= CMD1394_EUNKNOWN_ERROR
;
1019 /* Unrecognized error */
1021 dip
= hal
->halinfo
.dip
;
1023 /* An unexpected error in the HAL */
1024 cmn_err(CE_WARN
, HALT_ERROR_MESSAGE
,
1025 ddi_node_name(dip
), ddi_get_instance(dip
));
1027 /* Disable the HAL */
1028 s1394_hal_shutdown(hal
, B_TRUE
);
1030 TNF_PROBE_2(s1394_atresp_cmd_complete_error
,
1031 S1394_TNF_SL_ATRESP_ERROR
, "", tnf_string
, msg
,
1032 "Unrecognized cmd status code",
1033 tnf_int
, status
, status
);
1034 TNF_PROBE_0_DEBUG(s1394_atresp_cmd_complete_exit
,
1035 S1394_TNF_SL_ATRESP_STACK
, "");
1040 /* Get the Services Layer private area */
1041 s_priv
= S1394_GET_CMD_PRIV(resp
);
1043 /* Get a pointer to the HAL private struct */
1044 h_priv
= (h1394_cmd_priv_t
*)&s_priv
->hal_cmd_private
;
1046 valid_addr_blk
= s_priv
->arreq_valid_addr
;
1048 if (valid_addr_blk
== B_TRUE
) {
1049 /* Set the command status */
1050 resp
->cmd_result
= target_status
;
1052 switch (s_priv
->cmd_priv_xfer_type
) {
1053 case S1394_CMD_READ
:
1054 case S1394_CMD_WRITE
:
1055 case S1394_CMD_LOCK
:
1056 if (resp
->completion_callback
!= NULL
) {
1058 s1394_atresp_cmd_complete_do_callback
,
1059 S1394_TNF_SL_ATRESP_STACK
, "");
1060 resp
->completion_callback(resp
);
1065 dip
= hal
->halinfo
.dip
;
1067 /* An unexpected error in the HAL */
1068 cmn_err(CE_WARN
, HALT_ERROR_MESSAGE
,
1069 ddi_node_name(dip
), ddi_get_instance(dip
));
1071 /* Disable the HAL */
1072 s1394_hal_shutdown(hal
, B_TRUE
);
1074 TNF_PROBE_1(s1394_atresp_cmd_complete_error
,
1075 S1394_TNF_SL_ATRESP_ERROR
, "", tnf_string
, msg
,
1076 "Unrecognized transfer type");
1077 TNF_PROBE_0_DEBUG(s1394_atresp_cmd_complete_exit
,
1078 S1394_TNF_SL_ATRESP_STACK
, "");
1083 TNF_PROBE_0_DEBUG(s1394_atresp_cmd_complete_call_hal_cmplt
,
1084 S1394_TNF_SL_ATRESP_STACK
, "");
1086 /* Free the command - Pass it back to the HAL */
1087 HAL_CALL(hal
).response_complete(hal
->halinfo
.hal_private
, resp
, h_priv
);
1089 TNF_PROBE_1_DEBUG(s1394_atresp_cmd_complete_exit
,
1090 S1394_TNF_SL_ATRESP_STACK
, "", tnf_int
, status
, target_status
);
1094 * s1394_send_response()
1095 * is used to send a response to an AR request. Depending on whether the
1096 * request was a broadcast request, a write to posted write address space,
1097 * or some other request, either a response packet is sent, or the command
1098 * is returned to the HAL. A return value of DDI_SUCCESS means that the
1099 * command has been handled correctly. It was either successfully sent to
1100 * the HAL, or, if it was posted_write of broadcast, it was freed up. A
1101 * return value of DDI_FAILURE indicates either a serious error, in which
1102 * case the HAL is shutdown, or a failure returned by the HAL, in which
1103 * case the command is freed up and notice of the failure is returned.
1106 s1394_send_response(s1394_hal_t
*hal
, cmd1394_cmd_t
*resp
)
1108 s1394_cmd_priv_t
*s_priv
;
1109 h1394_cmd_priv_t
*h_priv
;
1114 TNF_PROBE_0_DEBUG(s1394_send_response_enter
, S1394_TNF_SL_ATRESP_STACK
,
1117 /* Get the Services Layer private area */
1118 s_priv
= S1394_GET_CMD_PRIV(resp
);
1120 /* Get a pointer to the HAL private struct */
1121 h_priv
= (h1394_cmd_priv_t
*)&s_priv
->hal_cmd_private
;
1124 * If request was broadcast or a write request to a posted write
1125 * address, don't send a response
1127 if ((resp
->broadcast
== 1) || ((s_priv
->posted_write
== B_TRUE
) &&
1128 ((resp
->cmd_result
== CMD1394_ASYNCH_WR_QUAD
) ||
1129 (resp
->cmd_result
== CMD1394_ASYNCH_WR_BLOCK
)))) {
1131 TNF_PROBE_0_DEBUG(s1394_send_response_call_hal_cmplt
,
1132 S1394_TNF_SL_ATRESP_STACK
, "");
1134 /* Free the command - Pass it back to the HAL */
1135 HAL_CALL(hal
).response_complete(hal
->halinfo
.hal_private
,
1138 TNF_PROBE_0_DEBUG(s1394_send_response_exit
,
1139 S1394_TNF_SL_ATRESP_STACK
, "");
1140 return (DDI_SUCCESS
);
1143 TNF_PROBE_0_DEBUG(s1394_send_response_call_hal_resp
,
1144 S1394_TNF_SL_ATRESP_STACK
, "");
1146 /* kstats - number of failure responses sent */
1147 if (resp
->cmd_result
!= IEEE1394_RESP_COMPLETE
) {
1148 switch (resp
->cmd_type
) {
1149 case CMD1394_ASYNCH_RD_QUAD
:
1150 hal
->hal_kstats
->arresp_quad_rd_fail
++;
1153 case CMD1394_ASYNCH_RD_BLOCK
:
1154 hal
->hal_kstats
->arresp_blk_rd_fail
++;
1157 case CMD1394_ASYNCH_WR_QUAD
:
1158 hal
->hal_kstats
->arresp_quad_wr_fail
++;
1161 case CMD1394_ASYNCH_WR_BLOCK
:
1162 hal
->hal_kstats
->arresp_blk_wr_fail
++;
1165 case CMD1394_ASYNCH_LOCK_32
:
1166 hal
->hal_kstats
->arresp_lock32_fail
++;
1169 case CMD1394_ASYNCH_LOCK_64
:
1170 hal
->hal_kstats
->arresp_lock64_fail
++;
1174 if (resp
->cmd_type
== CMD1394_ASYNCH_RD_BLOCK
)
1175 hal
->hal_kstats
->arreq_blk_rd_size
+=
1176 resp
->cmd_u
.b
.blk_length
;
1179 if (resp
->cmd_type
== CMD1394_ASYNCH_RD_BLOCK
) {
1180 h_priv
->mblk
.curr_mblk
= resp
->cmd_u
.b
.data_block
;
1181 h_priv
->mblk
.curr_offset
= resp
->cmd_u
.b
.data_block
->b_rptr
;
1182 h_priv
->mblk
.length
= resp
->cmd_u
.b
.blk_length
;
1185 switch (s_priv
->cmd_priv_xfer_type
) {
1186 case S1394_CMD_READ
:
1187 ret
= HAL_CALL(hal
).read_response(hal
->halinfo
.hal_private
,
1188 resp
, h_priv
, &result
);
1191 case S1394_CMD_WRITE
:
1192 ret
= HAL_CALL(hal
).write_response(hal
->halinfo
.hal_private
,
1193 resp
, h_priv
, &result
);
1196 case S1394_CMD_LOCK
:
1197 ret
= HAL_CALL(hal
).lock_response(hal
->halinfo
.hal_private
,
1198 resp
, h_priv
, &result
);
1202 dip
= hal
->halinfo
.dip
;
1204 /* An unexpected error in the HAL */
1205 cmn_err(CE_WARN
, HALT_ERROR_MESSAGE
,
1206 ddi_node_name(dip
), ddi_get_instance(dip
));
1208 /* Disable the HAL */
1209 s1394_hal_shutdown(hal
, B_TRUE
);
1211 TNF_PROBE_1(s1394_send_response_error
,
1212 S1394_TNF_SL_ATRESP_ERROR
, "", tnf_string
, msg
,
1213 "Unrecognized transfer type");
1214 TNF_PROBE_0_DEBUG(s1394_send_response_exit
,
1215 S1394_TNF_SL_ATRESP_STACK
, "");
1216 return (DDI_FAILURE
);
1219 /* Unable to send a response */
1220 if (ret
!= DDI_SUCCESS
) {
1221 if (result
== H1394_STATUS_INVALID_BUSGEN
) {
1222 TNF_PROBE_1(s1394_send_response_error
,
1223 S1394_TNF_SL_ATRESP_ERROR
, "", tnf_string
, msg
,
1224 "Invalid generation in response");
1225 } else if (result
== H1394_STATUS_NOMORE_SPACE
) {
1226 TNF_PROBE_1(s1394_send_response_error
,
1227 S1394_TNF_SL_ATRESP_ERROR
, "", tnf_string
, msg
,
1228 "No more space on AT response queue");
1230 TNF_PROBE_1(s1394_send_response_error
,
1231 S1394_TNF_SL_ATRESP_ERROR
, "", tnf_string
, msg
,
1232 "Unknown problem in s1394_send_response");
1234 TNF_PROBE_0_DEBUG(s1394_send_response_call_hal_cmplt
,
1235 S1394_TNF_SL_ATRESP_STACK
, "");
1237 /* Free the command - Pass it back to the HAL */
1238 HAL_CALL(hal
).response_complete(hal
->halinfo
.hal_private
,
1241 TNF_PROBE_0_DEBUG(s1394_send_response_exit
,
1242 S1394_TNF_SL_ATRESP_STACK
, "");
1243 return (DDI_FAILURE
);
1246 TNF_PROBE_0_DEBUG(s1394_send_response_exit
, S1394_TNF_SL_ATRESP_STACK
,
1248 return (DDI_SUCCESS
);
1252 * s1394_compare_swap()
1253 * is used by t1394_lock() to send a lock request. Any of the lock
1254 * requests specified explicitly by the 1394 spec will pass thru here,
1255 * i.e compare-swap, mask-swap, etc.
1258 s1394_compare_swap(s1394_hal_t
*hal
, s1394_target_t
*target
, cmd1394_cmd_t
*cmd
)
1260 s1394_cmd_priv_t
*s_priv
;
1261 s1394_hal_state_t state
;
1265 TNF_PROBE_0_DEBUG(s1394_compare_swap_enter
, S1394_TNF_SL_ATREQ_STACK
,
1268 ASSERT(MUTEX_NOT_HELD(&hal
->topology_tree_mutex
));
1270 /* Lock the topology tree - protect from bus reset */
1271 mutex_enter(&hal
->topology_tree_mutex
);
1273 ret
= s1394_setup_asynch_command(hal
, target
, cmd
, S1394_CMD_LOCK
,
1276 /* Unlock the topology tree */
1277 mutex_exit(&hal
->topology_tree_mutex
);
1279 /* Get the Services Layer private area */
1280 s_priv
= S1394_GET_CMD_PRIV(cmd
);
1282 /* Command has now been put onto the queue! */
1283 if (ret
!= DDI_SUCCESS
) {
1284 /* Copy error code into result */
1285 cmd
->cmd_result
= err
;
1287 TNF_PROBE_0(s1394_compare_swap_error_in_setup_asynch
,
1288 S1394_TNF_SL_ATREQ_ERROR
, "");
1289 TNF_PROBE_0_DEBUG(s1394_compare_swap_exit
,
1290 S1394_TNF_SL_ATREQ_STACK
, "");
1291 return (DDI_FAILURE
);
1294 mutex_enter(&hal
->topology_tree_mutex
);
1295 state
= hal
->hal_state
;
1296 /* If this command was sent during a bus reset, */
1297 /* then put it onto the pending Q. */
1298 if (state
== S1394_HAL_RESET
) {
1299 /* Remove cmd from outstanding request Q */
1300 s1394_remove_q_asynch_cmd(hal
, cmd
);
1302 /* Are we on the bus reset event stack? */
1303 if (s1394_on_br_thread(hal
) == B_TRUE
) {
1304 /* Blocking commands are not allowed */
1305 if (cmd
->cmd_options
& CMD1394_BLOCKING
) {
1306 mutex_exit(&hal
->topology_tree_mutex
);
1308 s_priv
->cmd_in_use
= B_FALSE
;
1310 cmd
->cmd_result
= CMD1394_EINVALID_CONTEXT
;
1312 TNF_PROBE_1(s1394_compare_swap_error
,
1313 S1394_TNF_SL_ATREQ_ERROR
, "", tnf_string
,
1314 msg
, "CMD1394_BLOCKING in bus reset ctxt");
1315 TNF_PROBE_0_DEBUG(s1394_compare_swap_exit
,
1316 S1394_TNF_SL_ATREQ_STACK
, "");
1317 return (DDI_FAILURE
);
1321 s1394_pending_q_insert(hal
, cmd
, S1394_PENDING_Q_FRONT
);
1322 mutex_exit(&hal
->topology_tree_mutex
);
1324 /* Block (if necessary) */
1325 s1394_block_on_asynch_cmd(cmd
);
1327 TNF_PROBE_0_DEBUG(t1394_write_exit
, S1394_TNF_SL_ATREQ_STACK
,
1329 return (DDI_SUCCESS
);
1331 mutex_exit(&hal
->topology_tree_mutex
);
1333 /* Send the command out */
1334 ret
= s1394_xfer_asynch_command(hal
, cmd
, &err
);
1336 if (ret
!= DDI_SUCCESS
) {
1337 if (err
== CMD1394_ESTALE_GENERATION
) {
1338 /* Remove cmd from outstanding request Q */
1339 s1394_remove_q_asynch_cmd(hal
, cmd
);
1340 s1394_pending_q_insert(hal
, cmd
, S1394_PENDING_Q_FRONT
);
1342 /* Block (if necessary) */
1343 s1394_block_on_asynch_cmd(cmd
);
1345 TNF_PROBE_0_DEBUG(s1394_compare_swap_exit
,
1346 S1394_TNF_SL_ATREQ_STACK
, "");
1347 return (DDI_SUCCESS
);
1350 /* Remove cmd from outstanding request Q */
1351 s1394_remove_q_asynch_cmd(hal
, cmd
);
1353 s_priv
->cmd_in_use
= B_FALSE
;
1355 /* Copy error code into result */
1356 cmd
->cmd_result
= err
;
1358 TNF_PROBE_0(s1394_compare_swap_error_in_xfer
,
1359 S1394_TNF_SL_ATREQ_ERROR
, "");
1360 TNF_PROBE_0_DEBUG(s1394_compare_swap_exit
,
1361 S1394_TNF_SL_ATREQ_STACK
, "");
1362 return (DDI_FAILURE
);
1365 /* Block (if necessary) */
1366 s1394_block_on_asynch_cmd(cmd
);
1368 TNF_PROBE_0_DEBUG(s1394_compare_swap_exit
,
1369 S1394_TNF_SL_ATREQ_STACK
, "");
1370 return (DDI_SUCCESS
);
1375 * s1394_split_lock_req()
1376 * is also used by t1394_lock() to send a lock request. The difference
1377 * is that s1394_split_lock_req() is used to send the software supported
1378 * lock types, i.e. bit_and, bit_or, etc. These lock requests require
1379 * more than one transaction, typically compare-swap's.
1382 s1394_split_lock_req(s1394_hal_t
*hal
, s1394_target_t
*target
,
1385 s1394_cmd_priv_t
*s_priv
;
1386 cmd1394_cmd_t
*tmp_cmd
;
1388 TNF_PROBE_0_DEBUG(s1394_split_lock_req_enter
,
1389 S1394_TNF_SL_ATREQ_STACK
, "");
1391 /* Allocate a temporary command */
1392 if (s1394_alloc_cmd(hal
, T1394_ALLOC_CMD_NOSLEEP
, &tmp_cmd
) !=
1394 cmd
->cmd_result
= CMD1394_EUNKNOWN_ERROR
;
1396 TNF_PROBE_0(s1394_split_lock_req_error_alloc_cmd
,
1397 S1394_TNF_SL_ATREQ_ERROR
, "");
1398 TNF_PROBE_0_DEBUG(s1394_split_lock_req_exit
,
1399 S1394_TNF_SL_ATREQ_STACK
, "");
1400 return (DDI_FAILURE
);
1403 /* Get the Services Layer private area */
1404 s_priv
= S1394_GET_CMD_PRIV(tmp_cmd
);
1406 tmp_cmd
->completion_callback
= s1394_handle_lock
;
1407 tmp_cmd
->cmd_callback_arg
= (opaque_t
)cmd
;
1408 tmp_cmd
->cmd_type
= cmd
->cmd_type
;
1409 tmp_cmd
->cmd_addr
= cmd
->cmd_addr
;
1410 tmp_cmd
->cmd_options
= cmd
->cmd_options
;
1411 tmp_cmd
->bus_generation
= cmd
->bus_generation
;
1413 /* The temporary command can not block */
1414 tmp_cmd
->cmd_options
= tmp_cmd
->cmd_options
& ~CMD1394_BLOCKING
;
1416 /* Setup compare-swap with data_value == arg_value (read) */
1417 if (tmp_cmd
->cmd_type
== CMD1394_ASYNCH_LOCK_32
) {
1418 tmp_cmd
->cmd_u
.l32
.data_value
= 0;
1419 tmp_cmd
->cmd_u
.l32
.arg_value
= 0;
1420 tmp_cmd
->cmd_u
.l32
.lock_type
= CMD1394_LOCK_COMPARE_SWAP
;
1421 s_priv
->temp_num_retries
= cmd
->cmd_u
.l32
.num_retries
;
1423 tmp_cmd
->cmd_u
.l64
.data_value
= 0;
1424 tmp_cmd
->cmd_u
.l64
.arg_value
= 0;
1425 tmp_cmd
->cmd_u
.l64
.lock_type
= CMD1394_LOCK_COMPARE_SWAP
;
1426 s_priv
->temp_num_retries
= cmd
->cmd_u
.l64
.num_retries
;
1429 /* Initialize lock_req_step */
1430 s_priv
->lock_req_step
= 0;
1432 /* Get the Services Layer private area for the target cmd */
1433 s_priv
= S1394_GET_CMD_PRIV(cmd
);
1435 s_priv
->cmd_in_use
= B_TRUE
;
1437 /* Send the request */
1438 if (s1394_compare_swap(hal
, target
, tmp_cmd
) != DDI_SUCCESS
) {
1439 s_priv
->cmd_in_use
= B_FALSE
;
1441 /* Free the temporary command */
1442 if (s1394_free_cmd(hal
, &tmp_cmd
) != DDI_SUCCESS
)
1443 cmd
->cmd_result
= CMD1394_EUNKNOWN_ERROR
;
1445 TNF_PROBE_0_DEBUG(s1394_split_lock_req_exit
,
1446 S1394_TNF_SL_ATREQ_STACK
, "");
1447 return (DDI_FAILURE
);
1450 /* Block (if necessary) */
1451 s1394_block_on_asynch_cmd(cmd
);
1453 TNF_PROBE_0_DEBUG(s1394_split_lock_req_exit
,
1454 S1394_TNF_SL_ATREQ_STACK
, "");
1455 return (DDI_SUCCESS
);
1459 * s1394_handle_lock()
1460 * is the callback for s1394_split_lock_req(). It does all of the real
1461 * work. Based on the specific lock type all necessary manipulation is
1462 * performed and another compare swap is sent out. If the transaction
1463 * is unsuccessful, it is retried.
1466 s1394_handle_lock(cmd1394_cmd_t
*cmd
)
1468 s1394_hal_t
*to_hal
;
1469 s1394_target_t
*target
;
1470 s1394_cmd_priv_t
*s_priv
;
1471 cmd1394_cmd_t
*target_cmd
;
1472 uint32_t lock_req_step
;
1477 TNF_PROBE_0_DEBUG(s1394_handle_lock_enter
, S1394_TNF_SL_ATREQ_STACK
,
1480 /* Get the Services Layer private area */
1481 s_priv
= S1394_GET_CMD_PRIV(cmd
);
1483 lock_req_step
= s_priv
->lock_req_step
;
1485 /* Get the target's command */
1486 target_cmd
= (cmd1394_cmd_t
*)cmd
->cmd_callback_arg
;
1488 /* Get the destination of the command */
1489 to_hal
= s_priv
->sent_on_hal
;
1492 /* Is this step 0 completing? */
1493 if (lock_req_step
== 0) {
1494 /* Was the request successful? */
1495 if (cmd
->cmd_result
== CMD1394_CMDSUCCESS
) {
1496 /* Do any math, bit ops, or byte-swapping necessary */
1497 ret
= s1394_process_split_lock(cmd
, target_cmd
);
1499 if (ret
!= DDI_SUCCESS
) {
1500 tcmd_result
= target_cmd
->cmd_result
;
1504 s_priv
->lock_req_step
= 1;
1506 target
= s_priv
->sent_by_target
;
1508 if (s1394_compare_swap(to_hal
, target
, cmd
) !=
1510 tcmd_result
= cmd
->cmd_result
;
1513 TNF_PROBE_0_DEBUG(s1394_handle_lock_exit
,
1514 S1394_TNF_SL_ATREQ_STACK
, "");
1518 /* Command failed for some reason */
1519 tcmd_result
= cmd
->cmd_result
;
1522 } else { /* lock_req_step == 1 */
1523 /* Was the request successful? */
1524 if (cmd
->cmd_result
== CMD1394_CMDSUCCESS
) {
1525 /* Do whatever's necessary to finish up the lock */
1526 ret
= s1394_finish_split_lock(cmd
, target_cmd
);
1528 if (ret
!= DDI_SUCCESS
) {
1530 goto lock_req_step_0
;
1532 tcmd_result
= cmd
->cmd_result
;
1536 /* Command failed for some reason */
1537 tcmd_result
= cmd
->cmd_result
;
1543 if (s1394_free_cmd(to_hal
, &cmd
) != DDI_SUCCESS
) {
1544 TNF_PROBE_0(s1394_handle_lock_error_in_freecmd
,
1545 S1394_TNF_SL_ATREQ_ERROR
, "");
1548 /* Get the Services Layer private area */
1549 s_priv
= S1394_GET_CMD_PRIV(target_cmd
);
1551 s_priv
->cmd_in_use
= B_FALSE
;
1553 target_cmd
->cmd_result
= tcmd_result
;
1555 /* Is this a blocking command? */
1556 if (target_cmd
->cmd_options
& CMD1394_BLOCKING
) {
1557 /* Unblock the waiting command */
1558 mutex_enter(&s_priv
->blocking_mutex
);
1559 s_priv
->blocking_flag
= B_TRUE
;
1560 cv_signal(&s_priv
->blocking_cv
);
1561 mutex_exit(&s_priv
->blocking_mutex
);
1563 TNF_PROBE_0_DEBUG(s1394_handle_lock_exit
,
1564 S1394_TNF_SL_ATREQ_STACK
, "");
1568 /* Call the target's completion_callback() */
1569 if (target_cmd
->completion_callback
!= NULL
)
1570 target_cmd
->completion_callback(target_cmd
);
1572 TNF_PROBE_0_DEBUG(s1394_handle_lock_exit
,
1573 S1394_TNF_SL_ATREQ_STACK
, "");
1577 * s1394_pending_q_insert()
1578 * is used to insert a given command structure onto a HAL's pending queue
1579 * for later processing (after the bus reset). All commands returned by
1580 * the HAL, are inserted onto the rear of the list (first priority), and
1581 * all other commands (from targets during bus reset) are put onto the front.
1584 s1394_pending_q_insert(s1394_hal_t
*hal
, cmd1394_cmd_t
*cmd
, uint_t flags
)
1586 cmd1394_cmd_t
*temp_cmd
;
1587 s1394_cmd_priv_t
*s_priv
;
1588 s1394_cmd_priv_t
*c_priv
;
1590 TNF_PROBE_0_DEBUG(s1394_pending_q_insert_enter
,
1591 S1394_TNF_SL_ATREQ_STACK
, "");
1593 mutex_enter(&hal
->pending_q_mutex
);
1595 /* Get the Services Layer private area */
1596 s_priv
= S1394_GET_CMD_PRIV(cmd
);
1598 /* Is the outstanding request queue empty? */
1599 if ((hal
->pending_q_head
== NULL
) && (hal
->pending_q_tail
== NULL
)) {
1601 hal
->pending_q_head
= (cmd1394_cmd_t
*)cmd
;
1602 hal
->pending_q_tail
= (cmd1394_cmd_t
*)cmd
;
1603 s_priv
->cmd_priv_next
= (cmd1394_cmd_t
*)NULL
;
1604 s_priv
->cmd_priv_prev
= (cmd1394_cmd_t
*)NULL
;
1606 } else if (flags
== S1394_PENDING_Q_FRONT
) {
1607 s_priv
->cmd_priv_next
= hal
->pending_q_head
;
1608 s_priv
->cmd_priv_prev
= (cmd1394_cmd_t
*)NULL
;
1610 temp_cmd
= (cmd1394_cmd_t
*)hal
->pending_q_head
;
1611 c_priv
= (s1394_cmd_priv_t
*)((uchar_t
*)temp_cmd
+
1612 sizeof (cmd1394_cmd_t
));
1613 c_priv
->cmd_priv_prev
= (cmd1394_cmd_t
*)cmd
;
1615 hal
->pending_q_head
= (cmd1394_cmd_t
*)cmd
;
1618 s_priv
->cmd_priv_prev
= hal
->pending_q_tail
;
1619 s_priv
->cmd_priv_next
= (cmd1394_cmd_t
*)NULL
;
1621 temp_cmd
= (cmd1394_cmd_t
*)hal
->pending_q_tail
;
1622 c_priv
= (s1394_cmd_priv_t
*)((uchar_t
*)temp_cmd
+
1623 sizeof (cmd1394_cmd_t
));
1624 c_priv
->cmd_priv_next
= (cmd1394_cmd_t
*)cmd
;
1626 hal
->pending_q_tail
= (cmd1394_cmd_t
*)cmd
;
1629 mutex_exit(&hal
->pending_q_mutex
);
1631 /* kstats - number of pending Q insertions */
1632 hal
->hal_kstats
->pending_q_insert
++;
1634 TNF_PROBE_0_DEBUG(s1394_pending_q_insert_exit
,
1635 S1394_TNF_SL_ATREQ_STACK
, "");
1639 * s1394_pending_q_remove()
1640 * is used to remove a command structure from a HAL's pending queue for
1643 static cmd1394_cmd_t
*
1644 s1394_pending_q_remove(s1394_hal_t
*hal
)
1646 s1394_cmd_priv_t
*s_priv
;
1647 s1394_cmd_priv_t
*c_priv
;
1649 cmd1394_cmd_t
*prev_cmd
;
1651 TNF_PROBE_0_DEBUG(s1394_pending_q_remove_enter
,
1652 S1394_TNF_SL_ATREQ_STACK
, "");
1654 mutex_enter(&hal
->pending_q_mutex
);
1656 cmd
= (cmd1394_cmd_t
*)hal
->pending_q_tail
;
1658 mutex_exit(&hal
->pending_q_mutex
);
1659 TNF_PROBE_0_DEBUG(s1394_pending_q_remove_exit
,
1660 S1394_TNF_SL_ATREQ_STACK
, "");
1664 /* Get the Services Layer private area */
1665 s_priv
= S1394_GET_CMD_PRIV(cmd
);
1667 prev_cmd
= (cmd1394_cmd_t
*)s_priv
->cmd_priv_prev
;
1669 s_priv
->cmd_priv_prev
= (cmd1394_cmd_t
*)NULL
;
1670 s_priv
->cmd_priv_next
= (cmd1394_cmd_t
*)NULL
;
1672 if (prev_cmd
!= NULL
) {
1673 c_priv
= (s1394_cmd_priv_t
*)((uchar_t
*)prev_cmd
+
1674 sizeof (cmd1394_cmd_t
));
1675 c_priv
->cmd_priv_next
= (cmd1394_cmd_t
*)NULL
;
1678 hal
->pending_q_head
= (cmd1394_cmd_t
*)NULL
;
1680 hal
->pending_q_tail
= (cmd1394_cmd_t
*)prev_cmd
;
1682 mutex_exit(&hal
->pending_q_mutex
);
1684 TNF_PROBE_0_DEBUG(s1394_pending_q_remove_exit
,
1685 S1394_TNF_SL_ATREQ_STACK
, "");
1690 * s1394_resend_pending_cmds()
1691 * is called when the pending queue is to be flushed. After most of the
1692 * bus reset processing is completed, the pending commands are sent/resent.
1695 s1394_resend_pending_cmds(s1394_hal_t
*hal
)
1699 TNF_PROBE_0_DEBUG(s1394_resend_pending_cmds_enter
,
1700 S1394_TNF_SL_BR_STACK
, "");
1702 ASSERT(MUTEX_NOT_HELD(&hal
->topology_tree_mutex
));
1705 done
= s1394_process_pending_q(hal
);
1706 } while (done
== B_FALSE
);
1708 ASSERT(MUTEX_NOT_HELD(&hal
->topology_tree_mutex
));
1710 TNF_PROBE_0_DEBUG(s1394_resend_pending_cmds_exit
,
1711 S1394_TNF_SL_BR_STACK
, "");
1715 * s1394_process_pending_q()
1716 * is called to send/resend the commands on the pending queue. All command
1717 * handling can be done here, including notifying the target of failed
1718 * commands, etc. If it is necessary to recompute the address, speed,
1719 * or max_payload for a command, that can be done here too. And if there
1720 * is no reason not to continue sending commands from the pending queue,
1721 * then a B_FALSE is returned, else B_TRUE is returned.
1724 s1394_process_pending_q(s1394_hal_t
*hal
)
1726 s1394_cmd_priv_t
*s_priv
;
1727 h1394_cmd_priv_t
*h_priv
;
1728 s1394_target_t
*target
;
1733 uint_t current_max_payload
;
1736 TNF_PROBE_0_DEBUG(s1394_process_pending_q_enter
,
1737 S1394_TNF_SL_BR_STACK
, "");
1739 ASSERT(MUTEX_NOT_HELD(&hal
->topology_tree_mutex
));
1741 /* Pull a command from the Pending Q */
1742 cmd
= s1394_pending_q_remove(hal
);
1745 TNF_PROBE_0_DEBUG(s1394_process_pending_q_exit
,
1746 S1394_TNF_SL_BR_STACK
, "");
1750 /* Get the Services Layer private area */
1751 s_priv
= S1394_GET_CMD_PRIV(cmd
);
1753 /* Get a pointer to the HAL private struct */
1754 h_priv
= (h1394_cmd_priv_t
*)&s_priv
->hal_cmd_private
;
1756 if ((cmd
->cmd_options
& CMD1394_OVERRIDE_ADDR
) ||
1757 (cmd
->cmd_options
& CMD1394_CANCEL_ON_BUS_RESET
)) {
1758 if (h_priv
->bus_generation
== hal
->generation_count
) {
1759 ret
= s1394_pending_q_helper(hal
, cmd
);
1763 s_priv
->cmd_in_use
= B_FALSE
;
1765 cmd
->cmd_result
= CMD1394_EBUSRESET
;
1767 /* Is this a blocking command? */
1768 if (cmd
->cmd_options
& CMD1394_BLOCKING
) {
1769 /* Unblock the waiting command */
1770 mutex_enter(&s_priv
->blocking_mutex
);
1771 s_priv
->blocking_flag
= B_TRUE
;
1772 cv_signal(&s_priv
->blocking_cv
);
1773 mutex_exit(&s_priv
->blocking_mutex
);
1775 TNF_PROBE_0_DEBUG(s1394_process_pending_q_exit
,
1776 S1394_TNF_SL_BR_STACK
, "");
1780 /* Call the target's completion_callback() */
1781 if (cmd
->completion_callback
!= NULL
) {
1782 cmd
->completion_callback(cmd
);
1785 TNF_PROBE_0_DEBUG(s1394_process_pending_q_exit
,
1786 S1394_TNF_SL_BR_STACK
, "");
1790 if (h_priv
->bus_generation
== hal
->generation_count
) {
1791 ret
= s1394_pending_q_helper(hal
, cmd
);
1794 /* Make sure we can get the topology_tree_mutex */
1795 if (s1394_lock_tree(hal
) != DDI_SUCCESS
)
1798 /* Set the generation */
1799 cmd
->bus_generation
= hal
->generation_count
;
1801 /* Copy the generation into the HAL's private field */
1802 h_priv
->bus_generation
= cmd
->bus_generation
;
1804 target
= s_priv
->sent_by_target
;
1806 /* If not OVERRIDE_ADDR, then target may not be NULL */
1807 ASSERT(target
!= NULL
);
1809 rw_enter(&hal
->target_list_rwlock
, RW_READER
);
1811 if (((target
->target_state
& S1394_TARG_GONE
) == 0) &&
1812 (target
->on_node
!= NULL
)) {
1813 node
= target
->on_node
->node_num
;
1814 rw_exit(&hal
->target_list_rwlock
);
1816 rw_exit(&hal
->target_list_rwlock
);
1818 s_priv
->cmd_in_use
= B_FALSE
;
1820 cmd
->cmd_result
= CMD1394_EDEVICE_REMOVED
;
1822 /* Is this a blocking command? */
1823 if (cmd
->cmd_options
& CMD1394_BLOCKING
) {
1824 s1394_unlock_tree(hal
);
1826 /* Unblock the waiting command */
1827 mutex_enter(&s_priv
->blocking_mutex
);
1828 s_priv
->blocking_flag
= B_TRUE
;
1829 cv_signal(&s_priv
->blocking_cv
);
1830 mutex_exit(&s_priv
->blocking_mutex
);
1833 s1394_process_pending_q_exit
,
1834 S1394_TNF_SL_BR_STACK
,
1839 /* Call the target's completion_callback() */
1840 if (cmd
->completion_callback
!= NULL
) {
1841 s1394_unlock_tree(hal
);
1842 cmd
->completion_callback(cmd
);
1844 s1394_process_pending_q_exit
,
1845 S1394_TNF_SL_BR_STACK
, "");
1848 s1394_unlock_tree(hal
);
1850 s1394_process_pending_q_exit
,
1851 S1394_TNF_SL_BR_STACK
, "");
1856 /* Mask in the top 16-bits */
1857 cmd
->cmd_addr
= cmd
->cmd_addr
&
1858 IEEE1394_ADDR_OFFSET_MASK
;
1859 cmd
->cmd_addr
= cmd
->cmd_addr
|
1860 (node
<< IEEE1394_ADDR_PHY_ID_SHIFT
);
1861 cmd
->cmd_addr
= cmd
->cmd_addr
|
1862 IEEE1394_ADDR_BUS_ID_MASK
;
1864 /* Speed is to be filled in from speed map */
1865 from_node
= IEEE1394_NODE_NUM(hal
->node_id
);
1866 to_node
= (uint32_t)node
;
1868 /* Fill in the nodeID */
1870 (cmd
->cmd_addr
& IEEE1394_ADDR_NODE_ID_MASK
) >>
1871 IEEE1394_ADDR_NODE_ID_SHIFT
;
1873 if (cmd
->cmd_options
& CMD1394_OVERRIDE_SPEED
) {
1874 s_priv
->hal_cmd_private
.speed
=
1875 (int)cmd
->cmd_speed
;
1877 /* Speed is to be filled in from speed map */
1878 s_priv
->hal_cmd_private
.speed
=
1879 (int)s1394_speed_map_get(hal
, from_node
,
1883 /* Is it a block request? */
1884 if ((cmd
->cmd_type
== CMD1394_ASYNCH_RD_BLOCK
) ||
1885 (cmd
->cmd_type
== CMD1394_ASYNCH_WR_BLOCK
)) {
1887 /* Get a pointer to the HAL private struct */
1888 h_priv
= (h1394_cmd_priv_t
*)&s_priv
->
1891 /* Handle the MAX_PAYLOAD size */
1892 if (s_priv
->sent_by_target
!= NULL
) {
1893 current_max_payload
=
1894 s_priv
->sent_by_target
->
1895 current_max_payload
;
1897 current_max_payload
= 4;
1899 if (cmd
->cmd_options
&
1900 CMD1394_OVERRIDE_MAX_PAYLOAD
) {
1901 if (current_max_payload
>
1902 cmd
->cmd_u
.b
.max_payload
)
1903 current_max_payload
=
1904 cmd
->cmd_u
.b
.max_payload
;
1906 if (s_priv
->data_remaining
<
1907 current_max_payload
) {
1908 h_priv
->mblk
.length
=
1909 s_priv
->data_remaining
;
1911 h_priv
->mblk
.length
=
1912 current_max_payload
;
1915 s1394_unlock_tree(hal
);
1916 ret
= s1394_pending_q_helper(hal
, cmd
);
1917 TNF_PROBE_0_DEBUG(s1394_process_pending_q_exit
,
1918 S1394_TNF_SL_BR_STACK
, "");
1925 * s1394_pending_q_helper()
1926 * is a "helper" function for s1394_process_pending_q(). It attempts to
1927 * resend commands, handling error conditions whenever necessary.
1930 s1394_pending_q_helper(s1394_hal_t
*hal
, cmd1394_cmd_t
*cmd
)
1932 s1394_cmd_priv_t
*s_priv
;
1936 TNF_PROBE_0_DEBUG(s1394_pending_q_helper_enter
,
1937 S1394_TNF_SL_BR_STACK
, "");
1939 ASSERT(MUTEX_NOT_HELD(&hal
->topology_tree_mutex
));
1941 /* Get the Services Layer private area */
1942 s_priv
= S1394_GET_CMD_PRIV(cmd
);
1944 /* Put cmd on outstanding request Q */
1945 s1394_insert_q_asynch_cmd(hal
, cmd
);
1947 /* Send command out again */
1948 ret
= s1394_xfer_asynch_command(hal
, cmd
, &err
);
1950 if (ret
!= DDI_SUCCESS
) {
1951 if (err
== CMD1394_ESTALE_GENERATION
) {
1952 /* Remove cmd outstanding req Q */
1953 s1394_remove_q_asynch_cmd(hal
, cmd
);
1954 s1394_pending_q_insert(hal
, cmd
, S1394_PENDING_Q_FRONT
);
1956 TNF_PROBE_0_DEBUG(s1394_pending_q_helper_exit
,
1957 S1394_TNF_SL_BR_STACK
, "");
1960 /* Remove cmd from outstanding request Q */
1961 s1394_remove_q_asynch_cmd(hal
, cmd
);
1963 s_priv
->cmd_in_use
= B_FALSE
;
1965 cmd
->cmd_result
= err
;
1967 /* Is this a blocking command? */
1968 if (cmd
->cmd_options
& CMD1394_BLOCKING
) {
1969 /* Unblock waiting command */
1970 mutex_enter(&s_priv
->blocking_mutex
);
1971 s_priv
->blocking_flag
= B_TRUE
;
1972 cv_signal(&s_priv
->blocking_cv
);
1973 mutex_exit(&s_priv
->blocking_mutex
);
1975 TNF_PROBE_0_DEBUG(s1394_pending_q_helper_exit
,
1976 S1394_TNF_SL_BR_STACK
, "");
1980 /* Call target completion_callback() */
1981 if (cmd
->completion_callback
!= NULL
) {
1982 cmd
->completion_callback(cmd
);
1983 TNF_PROBE_0_DEBUG(s1394_pending_q_helper_exit
,
1984 S1394_TNF_SL_BR_STACK
, "");
1987 TNF_PROBE_0_DEBUG(s1394_pending_q_helper_exit
,
1988 S1394_TNF_SL_BR_STACK
, "");
1994 TNF_PROBE_0_DEBUG(s1394_pending_q_helper_exit
,
1995 S1394_TNF_SL_BR_STACK
, "");
2000 * s1394_process_split_lock()
2001 * is a "helper" function for the s1394_handle_lock() callback. Its
2002 * job is to perform whatever manipulation is required for the given
2006 s1394_process_split_lock(cmd1394_cmd_t
*cmd
, cmd1394_cmd_t
*target_cmd
)
2008 uint64_t new_value64
;
2009 uint64_t data_value64
;
2010 uint64_t arg_value64
;
2011 uint64_t old_value64
;
2012 uint64_t temp_value64
;
2013 uint32_t new_value32
;
2014 uint32_t data_value32
;
2015 uint32_t arg_value32
;
2016 uint32_t old_value32
;
2017 uint32_t temp_value32
;
2019 TNF_PROBE_0_DEBUG(s1394_process_split_lock_enter
,
2020 S1394_TNF_SL_ATREQ_STACK
, "");
2022 if (cmd
->cmd_type
== CMD1394_ASYNCH_LOCK_32
) {
2023 old_value32
= cmd
->cmd_u
.l32
.old_value
;
2024 data_value32
= target_cmd
->cmd_u
.l32
.data_value
;
2025 arg_value32
= target_cmd
->cmd_u
.l32
.arg_value
;
2027 /* Lock type specific */
2028 switch (target_cmd
->cmd_u
.l32
.lock_type
) {
2029 case CMD1394_LOCK_BIT_AND
:
2030 new_value32
= old_value32
& data_value32
;
2033 case CMD1394_LOCK_BIT_OR
:
2034 new_value32
= old_value32
| data_value32
;
2037 case CMD1394_LOCK_BIT_XOR
:
2038 new_value32
= old_value32
^ data_value32
;
2041 case CMD1394_LOCK_INCREMENT
:
2042 old_value32
= T1394_DATA32(old_value32
);
2043 new_value32
= old_value32
+ 1;
2044 new_value32
= T1394_DATA32(new_value32
);
2045 old_value32
= T1394_DATA32(old_value32
);
2048 case CMD1394_LOCK_DECREMENT
:
2049 old_value32
= T1394_DATA32(old_value32
);
2050 new_value32
= old_value32
- 1;
2051 new_value32
= T1394_DATA32(new_value32
);
2052 old_value32
= T1394_DATA32(old_value32
);
2055 case CMD1394_LOCK_ADD
:
2056 old_value32
= T1394_DATA32(old_value32
);
2057 new_value32
= old_value32
+ data_value32
;
2058 new_value32
= T1394_DATA32(new_value32
);
2059 old_value32
= T1394_DATA32(old_value32
);
2062 case CMD1394_LOCK_SUBTRACT
:
2063 old_value32
= T1394_DATA32(old_value32
);
2064 new_value32
= old_value32
- data_value32
;
2065 new_value32
= T1394_DATA32(new_value32
);
2066 old_value32
= T1394_DATA32(old_value32
);
2069 case CMD1394_LOCK_THRESH_ADD
:
2070 old_value32
= T1394_DATA32(old_value32
);
2071 temp_value32
= (old_value32
+ data_value32
);
2072 if ((temp_value32
>= old_value32
) &&
2073 (temp_value32
<= arg_value32
)) {
2074 new_value32
= T1394_DATA32(temp_value32
);
2075 old_value32
= T1394_DATA32(old_value32
);
2077 /* Failed threshold add */
2078 target_cmd
->cmd_u
.l32
.old_value
=
2079 T1394_DATA32(cmd
->cmd_u
.l32
.old_value
);
2080 target_cmd
->cmd_result
= CMD1394_CMDSUCCESS
;
2082 s1394_process_split_lock_exit
,
2083 S1394_TNF_SL_ATREQ_STACK
, "");
2084 return (DDI_FAILURE
);
2088 case CMD1394_LOCK_THRESH_SUBTRACT
:
2089 old_value32
= T1394_DATA32(old_value32
);
2090 temp_value32
= (old_value32
- data_value32
);
2091 if ((old_value32
>= data_value32
) &&
2092 (temp_value32
>= arg_value32
)) {
2093 new_value32
= T1394_DATA32(temp_value32
);
2094 old_value32
= T1394_DATA32(old_value32
);
2096 /* Failed threshold subtract */
2097 target_cmd
->cmd_u
.l32
.old_value
=
2098 T1394_DATA32(cmd
->cmd_u
.l32
.old_value
);
2099 target_cmd
->cmd_result
= CMD1394_CMDSUCCESS
;
2101 s1394_process_split_lock_exit
,
2102 S1394_TNF_SL_ATREQ_STACK
, "");
2103 return (DDI_FAILURE
);
2107 case CMD1394_LOCK_CLIP_ADD
:
2108 old_value32
= T1394_DATA32(old_value32
);
2109 temp_value32
= (old_value32
+ data_value32
);
2110 if ((temp_value32
< old_value32
) ||
2111 (temp_value32
> arg_value32
))
2112 new_value32
= T1394_DATA32(arg_value32
);
2114 new_value32
= T1394_DATA32(temp_value32
);
2115 old_value32
= T1394_DATA32(old_value32
);
2118 case CMD1394_LOCK_CLIP_SUBTRACT
:
2119 old_value32
= T1394_DATA32(old_value32
);
2120 temp_value32
= (old_value32
- data_value32
);
2121 if ((data_value32
> old_value32
) ||
2122 (temp_value32
< arg_value32
))
2123 new_value32
= T1394_DATA32(arg_value32
);
2125 new_value32
= T1394_DATA32(temp_value32
);
2126 old_value32
= T1394_DATA32(old_value32
);
2130 /* Send compare-swap lock request */
2131 cmd
->cmd_u
.l32
.arg_value
= old_value32
;
2132 cmd
->cmd_u
.l32
.data_value
= new_value32
;
2134 old_value64
= cmd
->cmd_u
.l64
.old_value
;
2135 data_value64
= target_cmd
->cmd_u
.l64
.data_value
;
2136 arg_value64
= target_cmd
->cmd_u
.l64
.arg_value
;
2138 /* Lock type specific */
2139 switch (target_cmd
->cmd_u
.l64
.lock_type
) {
2140 case CMD1394_LOCK_BIT_AND
:
2141 new_value64
= old_value64
& data_value64
;
2144 case CMD1394_LOCK_BIT_OR
:
2145 new_value64
= old_value64
| data_value64
;
2148 case CMD1394_LOCK_BIT_XOR
:
2149 new_value64
= old_value64
^ data_value64
;
2152 case CMD1394_LOCK_INCREMENT
:
2153 old_value64
= T1394_DATA64(old_value64
);
2154 new_value64
= old_value64
+ 1;
2155 new_value64
= T1394_DATA64(new_value64
);
2156 old_value64
= T1394_DATA64(old_value64
);
2159 case CMD1394_LOCK_DECREMENT
:
2160 old_value64
= T1394_DATA64(old_value64
);
2161 new_value64
= old_value64
- 1;
2162 new_value64
= T1394_DATA64(new_value64
);
2163 old_value64
= T1394_DATA64(old_value64
);
2166 case CMD1394_LOCK_ADD
:
2167 old_value64
= T1394_DATA64(old_value64
);
2168 new_value64
= old_value64
+ data_value64
;
2169 new_value64
= T1394_DATA64(new_value64
);
2170 old_value64
= T1394_DATA64(old_value64
);
2173 case CMD1394_LOCK_SUBTRACT
:
2174 old_value64
= T1394_DATA64(old_value64
);
2175 new_value64
= old_value64
- data_value64
;
2176 new_value64
= T1394_DATA64(new_value64
);
2177 old_value64
= T1394_DATA64(old_value64
);
2180 case CMD1394_LOCK_THRESH_ADD
:
2181 old_value64
= T1394_DATA64(old_value64
);
2182 temp_value64
= (old_value64
+ data_value64
);
2183 if ((temp_value64
>= old_value64
) &&
2184 (temp_value64
<= arg_value64
)) {
2185 new_value64
= T1394_DATA64(temp_value64
);
2186 old_value64
= T1394_DATA64(old_value64
);
2188 /* Failed threshold add */
2189 target_cmd
->cmd_u
.l64
.old_value
=
2190 T1394_DATA64(cmd
->cmd_u
.l64
.old_value
);
2191 target_cmd
->cmd_result
= CMD1394_CMDSUCCESS
;
2193 s1394_process_split_lock_exit
,
2194 S1394_TNF_SL_ATREQ_STACK
, "");
2195 return (DDI_FAILURE
);
2199 case CMD1394_LOCK_THRESH_SUBTRACT
:
2200 old_value64
= T1394_DATA64(old_value64
);
2201 temp_value64
= (old_value64
- data_value64
);
2202 if ((old_value64
>= data_value64
) &&
2203 (temp_value64
>= arg_value64
)) {
2204 new_value64
= T1394_DATA64(temp_value64
);
2205 old_value64
= T1394_DATA64(old_value64
);
2207 /* Failed threshold subtract */
2208 target_cmd
->cmd_u
.l64
.old_value
=
2209 T1394_DATA64(cmd
->cmd_u
.l64
.old_value
);
2210 target_cmd
->cmd_result
= CMD1394_CMDSUCCESS
;
2212 s1394_process_split_lock_exit
,
2213 S1394_TNF_SL_ATREQ_STACK
, "");
2214 return (DDI_FAILURE
);
2218 case CMD1394_LOCK_CLIP_ADD
:
2219 old_value64
= T1394_DATA64(old_value64
);
2220 temp_value64
= (old_value64
+ data_value64
);
2221 if ((temp_value64
< old_value64
) ||
2222 (temp_value64
> arg_value64
))
2223 new_value64
= T1394_DATA64(arg_value64
);
2225 new_value64
= T1394_DATA64(temp_value64
);
2226 old_value64
= T1394_DATA64(old_value64
);
2229 case CMD1394_LOCK_CLIP_SUBTRACT
:
2230 old_value64
= T1394_DATA64(old_value64
);
2231 temp_value64
= (old_value64
- data_value64
);
2232 if ((data_value64
> old_value64
) ||
2233 (temp_value64
< arg_value64
))
2234 new_value64
= T1394_DATA64(arg_value64
);
2236 new_value64
= T1394_DATA64(temp_value64
);
2237 old_value64
= T1394_DATA64(old_value64
);
2241 /* Send compare-swap lock request */
2242 cmd
->cmd_u
.l64
.arg_value
= old_value64
;
2243 cmd
->cmd_u
.l64
.data_value
= new_value64
;
2246 TNF_PROBE_0_DEBUG(s1394_process_split_lock_exit
,
2247 S1394_TNF_SL_ATREQ_STACK
, "");
2248 return (DDI_SUCCESS
);
2252 * s1394_finish_split_lock()
2253 * is another "helper" function for the s1394_handle_lock() callback.
2254 * Its job is to finish up whatever lock request procesing is necessary.
2257 s1394_finish_split_lock(cmd1394_cmd_t
*cmd
, cmd1394_cmd_t
*target_cmd
)
2259 s1394_cmd_priv_t
*s_priv
;
2260 uint64_t tmp_value64
;
2261 uint32_t tmp_value32
;
2263 TNF_PROBE_0_DEBUG(s1394_finish_split_lock_enter
,
2264 S1394_TNF_SL_ATREQ_STACK
, "");
2266 /* Get the Services Layer private area */
2267 s_priv
= S1394_GET_CMD_PRIV(cmd
);
2269 if (((cmd
->cmd_type
== CMD1394_ASYNCH_LOCK_32
) &&
2270 (cmd
->cmd_u
.l32
.old_value
== cmd
->cmd_u
.l32
.arg_value
)) ||
2271 ((cmd
->cmd_type
== CMD1394_ASYNCH_LOCK_64
) &&
2272 (cmd
->cmd_u
.l64
.old_value
== cmd
->cmd_u
.l64
.arg_value
))) {
2274 if (cmd
->cmd_type
== CMD1394_ASYNCH_LOCK_32
) {
2275 switch (cmd
->cmd_u
.l32
.lock_type
) {
2276 case CMD1394_LOCK_INCREMENT
:
2277 case CMD1394_LOCK_DECREMENT
:
2278 case CMD1394_LOCK_ADD
:
2279 case CMD1394_LOCK_SUBTRACT
:
2280 case CMD1394_LOCK_THRESH_ADD
:
2281 case CMD1394_LOCK_THRESH_SUBTRACT
:
2282 case CMD1394_LOCK_CLIP_ADD
:
2283 case CMD1394_LOCK_CLIP_SUBTRACT
:
2284 tmp_value32
= cmd
->cmd_u
.l32
.old_value
;
2285 tmp_value32
= T1394_DATA32(tmp_value32
);
2286 target_cmd
->cmd_u
.l32
.old_value
= tmp_value32
;
2289 tmp_value32
= cmd
->cmd_u
.l32
.old_value
;
2290 target_cmd
->cmd_u
.l32
.old_value
= tmp_value32
;
2294 switch (cmd
->cmd_u
.l64
.lock_type
) {
2295 case CMD1394_LOCK_INCREMENT
:
2296 case CMD1394_LOCK_DECREMENT
:
2297 case CMD1394_LOCK_ADD
:
2298 case CMD1394_LOCK_SUBTRACT
:
2299 case CMD1394_LOCK_THRESH_ADD
:
2300 case CMD1394_LOCK_THRESH_SUBTRACT
:
2301 case CMD1394_LOCK_CLIP_ADD
:
2302 case CMD1394_LOCK_CLIP_SUBTRACT
:
2303 tmp_value64
= cmd
->cmd_u
.l64
.old_value
;
2304 tmp_value64
= T1394_DATA64(tmp_value64
);
2305 target_cmd
->cmd_u
.l64
.old_value
= tmp_value64
;
2308 tmp_value64
= cmd
->cmd_u
.l64
.old_value
;
2309 target_cmd
->cmd_u
.l64
.old_value
= tmp_value64
;
2314 target_cmd
->cmd_result
= CMD1394_CMDSUCCESS
;
2315 TNF_PROBE_0_DEBUG(s1394_finish_split_lock_exit
,
2316 S1394_TNF_SL_ATREQ_STACK
, "");
2317 return (DDI_SUCCESS
);
2319 if (s_priv
->temp_num_retries
> 0) {
2320 /* Decrement retry count */
2321 s_priv
->temp_num_retries
--;
2323 /* Reset lock_req_step */
2324 s_priv
->lock_req_step
= 0;
2326 TNF_PROBE_0_DEBUG(s1394_finish_split_lock_start_over
,
2327 S1394_TNF_SL_ATREQ_STACK
, "");
2328 /* Resend... start at step 0 again */
2329 TNF_PROBE_0_DEBUG(s1394_finish_split_lock_exit
,
2330 S1394_TNF_SL_ATREQ_STACK
, "");
2331 return (DDI_FAILURE
);
2333 /* Failed... RETRIES_EXCEEDED */
2334 target_cmd
->cmd_result
= CMD1394_ERETRIES_EXCEEDED
;
2335 TNF_PROBE_0_DEBUG(s1394_finish_split_lock_exit
,
2336 S1394_TNF_SL_ATREQ_STACK
, "");
2337 return (DDI_SUCCESS
);