Merge remote-tracking branch 'origin/master'
[unleashed/lotheac.git] / usr / src / uts / common / io / 1394 / s1394_asynch.c
blobc3ddd986efbcf6ecdaeae3994327585df68a15a0
1 /*
2 * CDDL HEADER START
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]
19 * CDDL HEADER END
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
29 * s1394_asynch.c
30 * 1394 Services Layer Asynchronous Communications Routines
31 * These routines handle all of the tasks relating to asynch commands
34 #include <sys/conf.h>
35 #include <sys/ddi.h>
36 #include <sys/sunddi.h>
37 #include <sys/cmn_err.h>
38 #include <sys/types.h>
39 #include <sys/kmem.h>
40 #include <sys/disp.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);
64 * s1394_alloc_cmd()
65 * is used to allocate a command for a target or for a HAL.
67 int
68 s1394_alloc_cmd(s1394_hal_t *hal, uint_t flags, cmd1394_cmd_t **cmdp)
70 s1394_cmd_priv_t *s_priv;
71 void *hal_overhead;
72 uint_t cmd_size;
73 int alloc_sleep;
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 */
80 return (DDI_FAILURE);
83 /* either FCP command or response, but not both */
84 if ((flags &
85 (T1394_ALLOC_CMD_FCP_COMMAND | T1394_ALLOC_CMD_FCP_RESPONSE)) ==
86 (T1394_ALLOC_CMD_FCP_COMMAND | T1394_ALLOC_CMD_FCP_RESPONSE)) {
87 return (DDI_FAILURE);
90 *cmdp = kmem_cache_alloc(hal->hal_kmem_cachep, alloc_sleep);
91 if (*cmdp == NULL) {
92 return (DDI_FAILURE);
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);
122 * s1394_free_cmd()
123 * is used to free a command that had been previously allocated by
124 * s1394_alloc_cmd().
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 */
144 *cmdp = NULL;
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;
165 dev_info_t *dip;
166 int result_from_hal;
167 int ret;
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++;
191 break;
193 case CMD1394_ASYNCH_RD_BLOCK:
194 hal->hal_kstats->atreq_blk_rd++;
195 break;
197 case CMD1394_ASYNCH_WR_QUAD:
198 hal->hal_kstats->atreq_quad_wr++;
199 break;
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;
204 break;
206 case CMD1394_ASYNCH_LOCK_32:
207 hal->hal_kstats->atreq_lock32++;
208 break;
210 case CMD1394_ASYNCH_LOCK_64:
211 hal->hal_kstats->atreq_lock64++;
212 break;
215 switch (s_priv->cmd_priv_xfer_type) {
216 /* Call the HAL's read entry point */
217 case S1394_CMD_READ:
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,
221 &result_from_hal);
222 break;
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,
229 &result_from_hal);
230 break;
232 /* Call the HAL's lock entry point */
233 case S1394_CMD_LOCK:
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,
237 &result_from_hal);
238 break;
240 default:
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;
251 break;
253 case H1394_STATUS_INVALID_BUSGEN:
254 /* Out of TLABELs - Unable to send AT req */
255 *err = CMD1394_ESTALE_GENERATION;
256 break;
258 case H1394_STATUS_NOMORE_SPACE:
259 /* No more space on HAL's HW queue */
260 *err = CMD1394_ENO_ATREQ;
261 break;
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;
274 break;
276 default:
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;
287 break;
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
305 * calling the HAL.
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;
313 uint64_t node;
314 uint32_t from_node;
315 uint32_t to_node;
316 uint32_t bus_capabilities;
317 uint_t current_max_payload;
318 uint_t max_rec;
319 uint_t max_blk;
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:
330 break;
332 default:
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);
366 } else {
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);
412 } else {
413 s_priv->hal_cmd_private.speed = (int)cmd->cmd_speed;
416 } else {
417 /* Speed is to be filled in from speed map */
418 s_priv->hal_cmd_private.speed = (int)s1394_speed_map_get(hal,
419 from_node, to_node);
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) {
446 bus_capabilities =
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;
452 } else {
453 max_rec = 0;
456 if ((max_rec > 0) && (max_rec < 14)) {
457 max_blk = 1 << (max_rec + 1);
459 } else {
460 /* These are either unspecified or reserved */
461 max_blk = 4;
463 if (max_blk < current_max_payload)
464 current_max_payload = max_blk;
466 } else {
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;
482 } else {
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;
491 } else {
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
509 * asynch queue.
511 void
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;
532 } else {
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
550 * asynch queue.
552 void
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;
576 } else {
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;
586 } else {
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).
602 void
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;
607 dev_info_t *dip;
608 int ret;
609 int cmd_result;
610 int err;
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++;
621 break;
623 case CMD1394_ASYNCH_RD_BLOCK:
624 hal->hal_kstats->atresp_blk_rd_fail++;
625 break;
627 case CMD1394_ASYNCH_WR_QUAD:
628 hal->hal_kstats->atresp_quad_wr_fail++;
629 break;
631 case CMD1394_ASYNCH_WR_BLOCK:
632 hal->hal_kstats->atresp_blk_wr_fail++;
633 break;
635 case CMD1394_ASYNCH_LOCK_32:
636 hal->hal_kstats->atresp_lock32_fail++;
637 break;
639 case CMD1394_ASYNCH_LOCK_64:
640 hal->hal_kstats->atresp_lock64_fail++;
641 break;
645 switch (status) {
646 /* evt_missing_ack */
647 case H1394_CMD_ETIMEOUT:
648 cmd_result = CMD1394_ETIMEOUT;
649 break;
651 /* evt_flushed */
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;
657 break;
659 s1394_remove_q_asynch_cmd(hal, req);
660 s1394_pending_q_insert(hal, req, S1394_PENDING_Q_REAR);
661 return;
663 /* ack_busy_X */
664 /* ack_busy_A */
665 /* ack_busy_B */
666 case H1394_CMD_EDEVICE_BUSY:
667 cmd_result = CMD1394_EDEVICE_BUSY;
668 break;
670 /* ack_data_error */
671 case H1394_CMD_EDATA_ERROR:
672 cmd_result = CMD1394_EDATA_ERROR;
673 break;
675 /* ack_type_error */
676 case H1394_CMD_ETYPE_ERROR:
677 cmd_result = CMD1394_ETYPE_ERROR;
678 break;
680 /* resp_address_error */
681 /* ack_address_error */
682 case H1394_CMD_EADDR_ERROR:
683 cmd_result = CMD1394_EADDRESS_ERROR;
684 break;
686 /* resp_conflict_error */
687 /* ack_conflict_error */
688 case H1394_CMD_ERSRC_CONFLICT:
689 cmd_result = CMD1394_ERSRC_CONFLICT;
690 break;
692 /* ack_tardy */
693 case H1394_CMD_EDEVICE_POWERUP:
694 cmd_result = CMD1394_EDEVICE_BUSY;
695 break;
697 /* device errors (bad tcodes, ACKs, etc...) */
698 case H1394_CMD_EDEVICE_ERROR:
699 cmd_result = CMD1394_EDEVICE_ERROR;
700 break;
702 /* Unknown error type */
703 case H1394_CMD_EUNKNOWN_ERROR:
704 cmd_result = CMD1394_EUNKNOWN_ERROR;
705 break;
707 /* Unrecognized error */
708 default:
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);
718 return;
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);
736 return;
739 /* Call the target's completion_callback() */
740 if (req->completion_callback != NULL) {
741 req->completion_callback(req);
744 return;
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 +=
764 h_priv->mblk.length;
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) {
793 return;
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);
801 return;
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;
811 /* Set status */
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);
822 return;
825 /* Set status and call completion_callback() */
826 if (req->completion_callback != NULL) {
828 req->completion_callback(req);
830 return;
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.
842 void
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;
847 dev_info_t *dip;
848 boolean_t valid_addr_blk;
849 int target_status;
851 target_status = CMD1394_CMDSUCCESS;
853 /* If not an ack_complete */
854 if (status != H1394_CMD_SUCCESS) {
855 switch (status) {
856 /* evt_missing_ack */
857 case H1394_CMD_ETIMEOUT:
858 target_status = CMD1394_ETIMEOUT;
859 break;
861 /* evt_flushed */
862 case H1394_CMD_EBUSRESET:
863 target_status = CMD1394_EBUSRESET;
864 break;
866 /* ack_busy_X */
867 /* ack_busy_A */
868 /* ack_busy_B */
869 case H1394_CMD_EDEVICE_BUSY:
870 target_status = CMD1394_EDEVICE_BUSY;
871 break;
873 /* ack_data_error */
874 case H1394_CMD_EDATA_ERROR:
875 target_status = CMD1394_EDATA_ERROR;
876 break;
878 /* ack_type_error */
879 case H1394_CMD_ETYPE_ERROR:
880 target_status = CMD1394_ETYPE_ERROR;
881 break;
883 /* ack_address_error */
884 case H1394_CMD_EADDR_ERROR:
885 target_status = CMD1394_EADDRESS_ERROR;
886 break;
888 /* ack_conflict_error */
889 case H1394_CMD_ERSRC_CONFLICT:
890 target_status = CMD1394_ERSRC_CONFLICT;
891 break;
893 /* ack_tardy */
894 case H1394_CMD_EDEVICE_POWERUP:
895 target_status = CMD1394_EDEVICE_BUSY;
896 break;
898 /* device errors (bad tcodes, ACKs, etc...) */
899 case H1394_CMD_EDEVICE_ERROR:
900 target_status = CMD1394_EDEVICE_ERROR;
901 break;
903 /* Unknown error type */
904 case H1394_CMD_EUNKNOWN_ERROR:
905 target_status = CMD1394_EUNKNOWN_ERROR;
906 break;
908 /* Unrecognized error */
909 default:
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);
919 return;
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) {
936 case S1394_CMD_READ:
937 case S1394_CMD_WRITE:
938 case S1394_CMD_LOCK:
939 if (resp->completion_callback != NULL) {
940 resp->completion_callback(resp);
942 break;
944 default:
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);
954 return;
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;
979 dev_info_t *dip;
980 int ret;
981 int result;
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,
999 resp, h_priv);
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++;
1009 break;
1011 case CMD1394_ASYNCH_RD_BLOCK:
1012 hal->hal_kstats->arresp_blk_rd_fail++;
1013 break;
1015 case CMD1394_ASYNCH_WR_QUAD:
1016 hal->hal_kstats->arresp_quad_wr_fail++;
1017 break;
1019 case CMD1394_ASYNCH_WR_BLOCK:
1020 hal->hal_kstats->arresp_blk_wr_fail++;
1021 break;
1023 case CMD1394_ASYNCH_LOCK_32:
1024 hal->hal_kstats->arresp_lock32_fail++;
1025 break;
1027 case CMD1394_ASYNCH_LOCK_64:
1028 hal->hal_kstats->arresp_lock64_fail++;
1029 break;
1031 } else {
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);
1047 break;
1049 case S1394_CMD_WRITE:
1050 ret = HAL_CALL(hal).write_response(hal->halinfo.hal_private,
1051 resp, h_priv, &result);
1052 break;
1054 case S1394_CMD_LOCK:
1055 ret = HAL_CALL(hal).lock_response(hal->halinfo.hal_private,
1056 resp, h_priv, &result);
1057 break;
1059 default:
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,
1076 resp, h_priv);
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;
1095 int err;
1096 int ret;
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,
1104 &err);
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);
1166 } else {
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);
1177 } else {
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,
1194 cmd1394_cmd_t *cmd)
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) !=
1201 DDI_SUCCESS) {
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;
1226 } else {
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.
1265 static void
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;
1273 int tcmd_result;
1274 int ret;
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;
1287 lock_req_step_0:
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;
1297 goto lock_req_done;
1300 s_priv->lock_req_step = 1;
1302 target = s_priv->sent_by_target;
1304 if (s1394_compare_swap(to_hal, target, cmd) !=
1305 DDI_SUCCESS) {
1306 tcmd_result = cmd->cmd_result;
1307 goto lock_req_done;
1308 } else {
1309 return;
1311 } else {
1312 /* Command failed for some reason */
1313 tcmd_result = cmd->cmd_result;
1314 goto lock_req_done;
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) {
1323 lock_req_step = 0;
1324 goto lock_req_step_0;
1325 } else {
1326 tcmd_result = cmd->cmd_result;
1327 goto lock_req_done;
1329 } else {
1330 /* Command failed for some reason */
1331 tcmd_result = cmd->cmd_result;
1332 goto lock_req_done;
1336 lock_req_done:
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);
1355 return;
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.
1370 void
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;
1401 } else {
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
1422 * processing.
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;
1429 cmd1394_cmd_t *cmd;
1430 cmd1394_cmd_t *prev_cmd;
1432 mutex_enter(&hal->pending_q_mutex);
1434 cmd = (cmd1394_cmd_t *)hal->pending_q_tail;
1435 if (cmd == NULL) {
1436 mutex_exit(&hal->pending_q_mutex);
1437 return (NULL);
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;
1453 } else {
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);
1460 return (cmd);
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.
1468 void
1469 s1394_resend_pending_cmds(s1394_hal_t *hal)
1471 int done;
1473 ASSERT(MUTEX_NOT_HELD(&hal->topology_tree_mutex));
1475 do {
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.
1491 static boolean_t
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;
1497 cmd1394_cmd_t *cmd;
1498 uint64_t node;
1499 uint32_t from_node;
1500 uint32_t to_node;
1501 uint_t current_max_payload;
1502 int ret;
1504 ASSERT(MUTEX_NOT_HELD(&hal->topology_tree_mutex));
1506 /* Pull a command from the Pending Q */
1507 cmd = s1394_pending_q_remove(hal);
1509 if (cmd == NULL) {
1510 return (B_TRUE);
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);
1523 return (ret);
1524 } else {
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);
1538 return (B_FALSE);
1541 /* Call the target's completion_callback() */
1542 if (cmd->completion_callback != NULL) {
1543 cmd->completion_callback(cmd);
1546 return (B_FALSE);
1548 } else {
1549 if (h_priv->bus_generation == hal->generation_count) {
1550 ret = s1394_pending_q_helper(hal, cmd);
1551 return (ret);
1552 } else {
1553 /* Make sure we can get the topology_tree_mutex */
1554 if (s1394_lock_tree(hal) != DDI_SUCCESS)
1555 return (B_TRUE);
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);
1574 } else {
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);
1591 return (B_FALSE);
1594 /* Call the target's completion_callback() */
1595 if (cmd->completion_callback != NULL) {
1596 s1394_unlock_tree(hal);
1597 cmd->completion_callback(cmd);
1598 return (B_FALSE);
1599 } else {
1600 s1394_unlock_tree(hal);
1601 return (B_FALSE);
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 */
1618 cmd->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;
1625 } else {
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,
1629 to_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->
1638 hal_cmd_private;
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;
1645 } else {
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;
1659 } else {
1660 h_priv->mblk.length =
1661 current_max_payload;
1664 s1394_unlock_tree(hal);
1665 ret = s1394_pending_q_helper(hal, cmd);
1666 return (ret);
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.
1676 static boolean_t
1677 s1394_pending_q_helper(s1394_hal_t *hal, cmd1394_cmd_t *cmd)
1679 s1394_cmd_priv_t *s_priv;
1680 int err;
1681 int ret;
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);
1700 return (B_TRUE);
1701 } else {
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);
1717 return (B_FALSE);
1720 /* Call target completion_callback() */
1721 if (cmd->completion_callback != NULL) {
1722 cmd->completion_callback(cmd);
1723 return (B_FALSE);
1724 } else {
1725 return (B_FALSE);
1730 return (B_FALSE);
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
1737 * request.
1739 static int
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;
1762 break;
1764 case CMD1394_LOCK_BIT_OR:
1765 new_value32 = old_value32 | data_value32;
1766 break;
1768 case CMD1394_LOCK_BIT_XOR:
1769 new_value32 = old_value32 ^ data_value32;
1770 break;
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);
1777 break;
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);
1784 break;
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);
1791 break;
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);
1798 break;
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);
1807 } else {
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);
1814 break;
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);
1823 } else {
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);
1830 break;
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);
1838 else
1839 new_value32 = T1394_DATA32(temp_value32);
1840 old_value32 = T1394_DATA32(old_value32);
1841 break;
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);
1849 else
1850 new_value32 = T1394_DATA32(temp_value32);
1851 old_value32 = T1394_DATA32(old_value32);
1852 break;
1855 /* Send compare-swap lock request */
1856 cmd->cmd_u.l32.arg_value = old_value32;
1857 cmd->cmd_u.l32.data_value = new_value32;
1858 } else {
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;
1867 break;
1869 case CMD1394_LOCK_BIT_OR:
1870 new_value64 = old_value64 | data_value64;
1871 break;
1873 case CMD1394_LOCK_BIT_XOR:
1874 new_value64 = old_value64 ^ data_value64;
1875 break;
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);
1882 break;
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);
1889 break;
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);
1896 break;
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);
1903 break;
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);
1912 } else {
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);
1919 break;
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);
1928 } else {
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);
1935 break;
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);
1943 else
1944 new_value64 = T1394_DATA64(temp_value64);
1945 old_value64 = T1394_DATA64(old_value64);
1946 break;
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);
1954 else
1955 new_value64 = T1394_DATA64(temp_value64);
1956 old_value64 = T1394_DATA64(old_value64);
1957 break;
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.
1973 static int
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;
2001 break;
2002 default:
2003 tmp_value32 = cmd->cmd_u.l32.old_value;
2004 target_cmd->cmd_u.l32.old_value = tmp_value32;
2005 break;
2007 } else {
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;
2020 break;
2021 default:
2022 tmp_value64 = cmd->cmd_u.l64.old_value;
2023 target_cmd->cmd_u.l64.old_value = tmp_value64;
2024 break;
2027 /* Set status */
2028 target_cmd->cmd_result = CMD1394_CMDSUCCESS;
2029 return (DDI_SUCCESS);
2030 } else {
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);
2041 } else {
2042 /* Failed... RETRIES_EXCEEDED */
2043 target_cmd->cmd_result = CMD1394_ERETRIES_EXCEEDED;
2044 return (DDI_SUCCESS);