/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* 1394 Services Layer Asynchronous Communications Routines
* These routines handle all of the tasks relating to asynch commands
*/
#include <sys/tnf_probe.h>
/*
* s1394_alloc_cmd()
* is used to allocate a command for a target or for a HAL.
*/
int
{
void *hal_overhead;
int alloc_sleep;
if ((alloc_sleep == KM_SLEEP) &&
(servicing_interrupt())) {
S1394_TNF_SL_ATREQ_STACK, "");
return (DDI_FAILURE);
}
/* either FCP command or response, but not both */
if ((flags &
S1394_TNF_SL_ATREQ_STACK, "");
return (DDI_FAILURE);
}
S1394_TNF_SL_STACK, "");
return (DDI_FAILURE);
}
cmd_size = sizeof (cmd1394_cmd_t) +
/* Get the Services Layer private area */
/* Set extension type */
if (flags & T1394_ALLOC_CMD_FCP_COMMAND) {
} else if (flags & T1394_ALLOC_CMD_FCP_RESPONSE) {
}
/* Set up the hal_overhead ptr in the hal_cmd_private */
/* kstats - number of cmd allocs */
return (DDI_SUCCESS);
}
/*
* s1394_free_cmd()
* is used to free a command that had been previously allocated by
* s1394_alloc_cmd().
*/
int
{
/* Get the Services Layer private area */
/* Check that command isn't in use */
return (DDI_FAILURE);
}
/* kstats - number of cmd allocs */
/* Command pointer is set to NULL before returning */
/* kstats - number of cmd frees */
return (DDI_SUCCESS);
}
/*
* s1394_xfer_asynch_command()
* is used to send an asynch command down to the HAL. Based upon the type
* of command that is being sent, the appropriate HAL function is called.
* the HAL, depending on the severity of the error.
*/
int
{
int result_from_hal;
int ret;
S1394_TNF_SL_ATREQ_STACK, "");
S1394_TNF_SL_ATREQ_STACK, "");
return (DDI_FAILURE);
}
/* Get the Services Layer private area */
/* Get a pointer to the HAL private struct */
/* kstats - number of AT requests sent */
case CMD1394_ASYNCH_RD_QUAD:
break;
case CMD1394_ASYNCH_RD_BLOCK:
break;
case CMD1394_ASYNCH_WR_QUAD:
break;
case CMD1394_ASYNCH_WR_BLOCK:
break;
case CMD1394_ASYNCH_LOCK_32:
break;
case CMD1394_ASYNCH_LOCK_64:
break;
}
switch (s_priv->cmd_priv_xfer_type) {
/* Call the HAL's read entry point */
case S1394_CMD_READ:
(cmd1394_cmd_t *)cmd,
break;
/* Call the HAL's write entry point */
case S1394_CMD_WRITE:
(cmd1394_cmd_t *)cmd,
break;
/* Call the HAL's lock entry point */
case S1394_CMD_LOCK:
(cmd1394_cmd_t *)cmd,
break;
default:
"Invalid command type specified");
S1394_TNF_SL_ATREQ_STACK, "");
return (DDI_FAILURE);
}
S1394_TNF_SL_ATREQ_STACK, "");
if (ret == DDI_FAILURE) {
switch (result_from_hal) {
/* Out of TLABELs - Unable to send AT req */
*err = CMD1394_ENO_ATREQ;
break;
/* Out of TLABELs - Unable to send AT req */
break;
/* No more space on HAL's HW queue */
*err = CMD1394_ENO_ATREQ;
break;
/* An unexpected error in the HAL */
/* Disable the HAL */
break;
default:
/* An unexpected error in the HAL */
/* Disable the HAL */
break;
}
return (DDI_FAILURE);
}
/* No errors, return success */
*err = CMD1394_NOSTATUS;
S1394_TNF_SL_ATREQ_STACK, "");
return (DDI_SUCCESS);
}
/*
* s1394_setup_asynch_command()
* is used to setup an asynch command to be sent down to the HAL and out
* onto the bus. This function handles setting up the destination address
* (if necessary), speed, max_payload, putting the command onto the
* outstanding Q list, and any other things that must be done prior to
* calling the HAL.
*/
int
{
S1394_TNF_SL_ATREQ_STACK, "");
case CMD1394_ASYNCH_RD_QUAD:
case CMD1394_ASYNCH_WR_QUAD:
case CMD1394_ASYNCH_RD_BLOCK:
case CMD1394_ASYNCH_WR_BLOCK:
case CMD1394_ASYNCH_LOCK_32:
case CMD1394_ASYNCH_LOCK_64:
break;
default:
"Invalid command type specified");
S1394_TNF_SL_ATREQ_STACK, "");
return (DDI_FAILURE);
}
/* Check for potential address roll-over */
S1394_TNF_SL_ATREQ_STACK, "");
return (DDI_FAILURE);
}
/* Get the Services Layer private area */
/* Set up who sent command on which hal */
/* Set up command transfer type */
/* Compare the current generation from the HAL struct */
/* to the one given by the target */
/* Speed is to be filled in from speed map */
S1394_TNF_SL_ATREQ_STACK, "");
return (DDI_FAILURE);
}
} else {
/* Set the generation */
/* If not OVERRIDE_ADDR, then target may not be NULL */
S1394_TNF_SL_ATREQ_STACK, "");
return (DDI_FAILURE);
}
/* Mask in the top 16-bits */
(node << IEEE1394_ADDR_PHY_ID_SHIFT));
/* Speed is to be filled in from speed map */
}
/* Get a pointer to the HAL private struct */
/* Copy the generation into the HAL's private field */
/* Fill in the nodeID */
S1394_TNF_SL_ATREQ_STACK, "");
return (DDI_FAILURE);
} else {
}
} else {
/* Speed is to be filled in from speed map */
}
/* Is it a block request? */
S1394_TNF_SL_ATREQ_STACK, "");
return (DDI_FAILURE);
}
/* Also need to check for MBLK_TOO_SMALL */
S1394_TNF_SL_ATREQ_STACK, "");
return (DDI_FAILURE);
}
/* Initialize bytes_transferred to zero */
/* Handle the MAX_PAYLOAD size */
current_max_payload = 512 <<
max_rec = (bus_capabilities &
} else {
max_rec = 0;
}
} else {
/* These are either unspecified or reserved */
max_blk = 4;
}
if (max_blk < current_max_payload)
} else {
}
}
} else {
}
} else {
}
}
/* Mark command as being used */
/* Put command on the HAL's outstanding request Q */
S1394_TNF_SL_ATREQ_STACK, "");
return (DDI_SUCCESS);
}
/*
* s1394_insert_q_asynch_cmd()
* is used to insert a given command structure onto a HAL's outstanding
* asynch queue.
*/
void
{
S1394_TNF_SL_ATREQ_STACK, "");
/* Get the Services Layer private area */
/* Is the outstanding request queue empty? */
} else {
sizeof (cmd1394_cmd_t));
}
S1394_TNF_SL_ATREQ_STACK, "");
}
/*
* s1394_remove_q_asynch_cmd()
* is used to remove a given command structure from a HAL's outstanding
* asynch queue.
*/
void
{
S1394_TNF_SL_ATREQ_STACK, "");
/* Get the Services Layer private area */
sizeof (cmd1394_cmd_t));
} else {
}
sizeof (cmd1394_cmd_t));
} else {
}
S1394_TNF_SL_ATREQ_STACK, "");
}
/*
* s1394_atreq_cmd_complete()
* is called by h1394_cmd_is_complete() when an AT request has completed.
* Based upon a command's completion status, s1394_atreq_cmd_complete()
* determines whether to call the target (or unblock), put the command onto
* the pending Q to be sent out later, or to resend the command
* (multi-part command).
*/
void
{
int ret;
int cmd_result;
int err;
S1394_TNF_SL_ATREQ_STACK, "");
/* Get the Services Layer private area */
/* If not an ack_complete... */
if (status != H1394_CMD_SUCCESS) {
/* kstats - number of failure AT responses */
case CMD1394_ASYNCH_RD_QUAD:
break;
case CMD1394_ASYNCH_RD_BLOCK:
break;
case CMD1394_ASYNCH_WR_QUAD:
break;
case CMD1394_ASYNCH_WR_BLOCK:
break;
case CMD1394_ASYNCH_LOCK_32:
break;
case CMD1394_ASYNCH_LOCK_64:
break;
}
switch (status) {
/* evt_missing_ack */
case H1394_CMD_ETIMEOUT:
break;
/* evt_flushed */
case H1394_CMD_EBUSRESET:
/* Move request to pending Q if cancel on */
/* reset is not set */
break;
}
S1394_TNF_SL_ATREQ_STACK, "");
return;
/* ack_busy_X */
/* ack_busy_A */
/* ack_busy_B */
case H1394_CMD_EDEVICE_BUSY:
break;
/* ack_data_error */
case H1394_CMD_EDATA_ERROR:
break;
/* ack_type_error */
case H1394_CMD_ETYPE_ERROR:
break;
/* resp_address_error */
/* ack_address_error */
case H1394_CMD_EADDR_ERROR:
break;
/* resp_conflict_error */
/* ack_conflict_error */
case H1394_CMD_ERSRC_CONFLICT:
break;
/* ack_tardy */
break;
/* device errors (bad tcodes, ACKs, etc...) */
case H1394_CMD_EDEVICE_ERROR:
break;
/* Unknown error type */
case H1394_CMD_EUNKNOWN_ERROR:
break;
/* Unrecognized error */
default:
/* An unexpected error in the HAL */
/* Disable the HAL */
"Unrecognized cmd status code",
S1394_TNF_SL_ATREQ_STACK, "");
return;
}
/* Remove command from the HAL's outstanding request Q */
/* Is this a blocking command? */
/* Unblock the waiting command */
S1394_TNF_SL_ATREQ_STACK, "");
return;
}
/* Call the target's completion_callback() */
S1394_TNF_SL_ATREQ_STACK, "");
}
S1394_TNF_SL_ATREQ_STACK, "");
return;
}
/* Successful unless otherwise modified */
/* Get a pointer to the HAL private struct */
/* Update data_remaining */
/* Increment bytes_transferred */
/* Is there still more to send? */
if (s_priv->data_remaining > 0) {
/* Setup the new mblk and offset */
/* Update destination address */
if (!(req->cmd_options &
}
/*
* Use the current MAX_PAYLOAD size. This value
* doesn't need to be recalculated because we must
* be in the same generation on the bus, else we
* would have seen a bus reset error.
*/
}
/* Send command out again */
if (ret == DDI_SUCCESS) {
S1394_TNF_SL_ATREQ_STACK, "");
return;
} else if (err == CMD1394_ESTALE_GENERATION) {
/* Remove cmd from outstanding request Q */
S1394_TNF_SL_ATREQ_STACK, "");
return;
}
}
}
/* Remove command from the HAL's outstanding request Q */
/* Set status */
/* Is this a blocking command? */
/* Unblock the waiting command */
S1394_TNF_SL_ATREQ_STACK, "");
return;
}
/* Set status and call completion_callback() */
S1394_TNF_SL_ATREQ_STACK, "");
S1394_TNF_SL_ATREQ_STACK, "");
return;
}
S1394_TNF_SL_ATREQ_STACK, "");
}
/*
* s1394_atresp_cmd_complete()
* is similar to s1394_atreq_cmd_complete(). It is also called by
* h1394_cmd_is_complete(), but when an AT response has completed.
* Again, based upon the command's completion status,
* s1394_atresp_cmd_complete() determines whether to call the target or
* to simply cleanup the command and return.
*/
void
{
int target_status;
/* If not an ack_complete */
if (status != H1394_CMD_SUCCESS) {
switch (status) {
/* evt_missing_ack */
case H1394_CMD_ETIMEOUT:
break;
/* evt_flushed */
case H1394_CMD_EBUSRESET:
break;
/* ack_busy_X */
/* ack_busy_A */
/* ack_busy_B */
case H1394_CMD_EDEVICE_BUSY:
break;
/* ack_data_error */
case H1394_CMD_EDATA_ERROR:
break;
/* ack_type_error */
case H1394_CMD_ETYPE_ERROR:
break;
/* ack_address_error */
case H1394_CMD_EADDR_ERROR:
break;
/* ack_conflict_error */
case H1394_CMD_ERSRC_CONFLICT:
break;
/* ack_tardy */
break;
/* device errors (bad tcodes, ACKs, etc...) */
case H1394_CMD_EDEVICE_ERROR:
break;
/* Unknown error type */
case H1394_CMD_EUNKNOWN_ERROR:
break;
/* Unrecognized error */
default:
/* An unexpected error in the HAL */
/* Disable the HAL */
"Unrecognized cmd status code",
return;
}
}
/* Get the Services Layer private area */
/* Get a pointer to the HAL private struct */
if (valid_addr_blk == B_TRUE) {
/* Set the command status */
switch (s_priv->cmd_priv_xfer_type) {
case S1394_CMD_READ:
case S1394_CMD_WRITE:
case S1394_CMD_LOCK:
}
break;
default:
/* An unexpected error in the HAL */
/* Disable the HAL */
"Unrecognized transfer type");
return;
}
}
/* Free the command - Pass it back to the HAL */
}
/*
* s1394_send_response()
* is used to send a response to an AR request. Depending on whether the
* request was a broadcast request, a write to posted write address space,
* or some other request, either a response packet is sent, or the command
* is returned to the HAL. A return value of DDI_SUCCESS means that the
* command has been handled correctly. It was either successfully sent to
* the HAL, or, if it was posted_write of broadcast, it was freed up. A
* return value of DDI_FAILURE indicates either a serious error, in which
* case the HAL is shutdown, or a failure returned by the HAL, in which
* case the command is freed up and notice of the failure is returned.
*/
int
{
int ret;
int result;
"");
/* Get the Services Layer private area */
/* Get a pointer to the HAL private struct */
/*
* If request was broadcast or a write request to a posted write
* address, don't send a response
*/
/* Free the command - Pass it back to the HAL */
return (DDI_SUCCESS);
}
/* kstats - number of failure responses sent */
case CMD1394_ASYNCH_RD_QUAD:
break;
case CMD1394_ASYNCH_RD_BLOCK:
break;
case CMD1394_ASYNCH_WR_QUAD:
break;
case CMD1394_ASYNCH_WR_BLOCK:
break;
case CMD1394_ASYNCH_LOCK_32:
break;
case CMD1394_ASYNCH_LOCK_64:
break;
}
} else {
}
}
switch (s_priv->cmd_priv_xfer_type) {
case S1394_CMD_READ:
break;
case S1394_CMD_WRITE:
break;
case S1394_CMD_LOCK:
break;
default:
/* An unexpected error in the HAL */
/* Disable the HAL */
"Unrecognized transfer type");
return (DDI_FAILURE);
}
/* Unable to send a response */
if (ret != DDI_SUCCESS) {
if (result == H1394_STATUS_INVALID_BUSGEN) {
"Invalid generation in response");
} else if (result == H1394_STATUS_NOMORE_SPACE) {
"No more space on AT response queue");
} else {
"Unknown problem in s1394_send_response");
}
/* Free the command - Pass it back to the HAL */
return (DDI_FAILURE);
}
"");
return (DDI_SUCCESS);
}
/*
* s1394_compare_swap()
* is used by t1394_lock() to send a lock request. Any of the lock
* requests specified explicitly by the 1394 spec will pass thru here,
* i.e compare-swap, mask-swap, etc.
*/
int
{
int err;
int ret;
"");
/* Lock the topology tree - protect from bus reset */
&err);
/* Unlock the topology tree */
/* Get the Services Layer private area */
/* Command has now been put onto the queue! */
if (ret != DDI_SUCCESS) {
/* Copy error code into result */
S1394_TNF_SL_ATREQ_ERROR, "");
S1394_TNF_SL_ATREQ_STACK, "");
return (DDI_FAILURE);
}
/* If this command was sent during a bus reset, */
/* then put it onto the pending Q. */
if (state == S1394_HAL_RESET) {
/* Remove cmd from outstanding request Q */
/* Are we on the bus reset event stack? */
/* Blocking commands are not allowed */
msg, "CMD1394_BLOCKING in bus reset ctxt");
S1394_TNF_SL_ATREQ_STACK, "");
return (DDI_FAILURE);
}
}
/* Block (if necessary) */
"");
return (DDI_SUCCESS);
}
/* Send the command out */
if (ret != DDI_SUCCESS) {
if (err == CMD1394_ESTALE_GENERATION) {
/* Remove cmd from outstanding request Q */
/* Block (if necessary) */
S1394_TNF_SL_ATREQ_STACK, "");
return (DDI_SUCCESS);
} else {
/* Remove cmd from outstanding request Q */
/* Copy error code into result */
S1394_TNF_SL_ATREQ_ERROR, "");
S1394_TNF_SL_ATREQ_STACK, "");
return (DDI_FAILURE);
}
} else {
/* Block (if necessary) */
S1394_TNF_SL_ATREQ_STACK, "");
return (DDI_SUCCESS);
}
}
/*
* s1394_split_lock_req()
* is also used by t1394_lock() to send a lock request. The difference
* is that s1394_split_lock_req() is used to send the software supported
* lock types, i.e. bit_and, bit_or, etc. These lock requests require
* more than one transaction, typically compare-swap's.
*/
int
{
S1394_TNF_SL_ATREQ_STACK, "");
/* Allocate a temporary command */
DDI_SUCCESS) {
S1394_TNF_SL_ATREQ_ERROR, "");
S1394_TNF_SL_ATREQ_STACK, "");
return (DDI_FAILURE);
}
/* Get the Services Layer private area */
/* The temporary command can not block */
/* Setup compare-swap with data_value == arg_value (read) */
} else {
}
/* Initialize lock_req_step */
s_priv->lock_req_step = 0;
/* Get the Services Layer private area for the target cmd */
/* Send the request */
/* Free the temporary command */
S1394_TNF_SL_ATREQ_STACK, "");
return (DDI_FAILURE);
}
/* Block (if necessary) */
S1394_TNF_SL_ATREQ_STACK, "");
return (DDI_SUCCESS);
}
/*
* s1394_handle_lock()
* is the callback for s1394_split_lock_req(). It does all of the real
* work. Based on the specific lock type all necessary manipulation is
* performed and another compare swap is sent out. If the transaction
* is unsuccessful, it is retried.
*/
static void
{
int tcmd_result;
int ret;
"");
/* Get the Services Layer private area */
/* Get the target's command */
/* Get the destination of the command */
/* Is this step 0 completing? */
if (lock_req_step == 0) {
/* Was the request successful? */
/* Do any math, bit ops, or byte-swapping necessary */
if (ret != DDI_SUCCESS) {
goto lock_req_done;
}
DDI_SUCCESS) {
goto lock_req_done;
} else {
S1394_TNF_SL_ATREQ_STACK, "");
return;
}
} else {
/* Command failed for some reason */
goto lock_req_done;
}
} else { /* lock_req_step == 1 */
/* Was the request successful? */
/* Do whatever's necessary to finish up the lock */
if (ret != DDI_SUCCESS) {
lock_req_step = 0;
goto lock_req_step_0;
} else {
goto lock_req_done;
}
} else {
/* Command failed for some reason */
goto lock_req_done;
}
}
S1394_TNF_SL_ATREQ_ERROR, "");
}
/* Get the Services Layer private area */
/* Is this a blocking command? */
/* Unblock the waiting command */
S1394_TNF_SL_ATREQ_STACK, "");
return;
}
/* Call the target's completion_callback() */
S1394_TNF_SL_ATREQ_STACK, "");
}
/*
* s1394_pending_q_insert()
* is used to insert a given command structure onto a HAL's pending queue
* for later processing (after the bus reset). All commands returned by
* the HAL, are inserted onto the rear of the list (first priority), and
* all other commands (from targets during bus reset) are put onto the front.
*/
void
{
S1394_TNF_SL_ATREQ_STACK, "");
/* Get the Services Layer private area */
/* Is the outstanding request queue empty? */
} else if (flags == S1394_PENDING_Q_FRONT) {
sizeof (cmd1394_cmd_t));
} else {
sizeof (cmd1394_cmd_t));
}
/* kstats - number of pending Q insertions */
S1394_TNF_SL_ATREQ_STACK, "");
}
/*
* s1394_pending_q_remove()
* is used to remove a command structure from a HAL's pending queue for
* processing.
*/
static cmd1394_cmd_t *
{
S1394_TNF_SL_ATREQ_STACK, "");
S1394_TNF_SL_ATREQ_STACK, "");
return (NULL);
}
/* Get the Services Layer private area */
sizeof (cmd1394_cmd_t));
} else {
}
S1394_TNF_SL_ATREQ_STACK, "");
return (cmd);
}
/*
* s1394_resend_pending_cmds()
* is called when the pending queue is to be flushed. After most of the
*/
void
{
int done;
S1394_TNF_SL_BR_STACK, "");
do {
S1394_TNF_SL_BR_STACK, "");
}
/*
* s1394_process_pending_q()
* handling can be done here, including notifying the target of failed
* commands, etc. If it is necessary to recompute the address, speed,
* or max_payload for a command, that can be done here too. And if there
* is no reason not to continue sending commands from the pending queue,
* then a B_FALSE is returned, else B_TRUE is returned.
*/
static boolean_t
{
int ret;
S1394_TNF_SL_BR_STACK, "");
/* Pull a command from the Pending Q */
S1394_TNF_SL_BR_STACK, "");
return (B_TRUE);
}
/* Get the Services Layer private area */
/* Get a pointer to the HAL private struct */
return (ret);
} else {
/* Is this a blocking command? */
/* Unblock the waiting command */
S1394_TNF_SL_BR_STACK, "");
return (B_FALSE);
}
/* Call the target's completion_callback() */
}
S1394_TNF_SL_BR_STACK, "");
return (B_FALSE);
}
} else {
return (ret);
} else {
/* Make sure we can get the topology_tree_mutex */
return (B_TRUE);
/* Set the generation */
/* Copy the generation into the HAL's private field */
/* If not OVERRIDE_ADDR, then target may not be NULL */
} else {
/* Is this a blocking command? */
/* Unblock the waiting command */
"");
return (B_FALSE);
}
/* Call the target's completion_callback() */
S1394_TNF_SL_BR_STACK, "");
return (B_FALSE);
} else {
S1394_TNF_SL_BR_STACK, "");
return (B_FALSE);
}
}
/* Mask in the top 16-bits */
/* Speed is to be filled in from speed map */
/* Fill in the nodeID */
} else {
/* Speed is to be filled in from speed map */
to_node);
}
/* Is it a block request? */
/* Get a pointer to the HAL private struct */
/* Handle the MAX_PAYLOAD size */
} else {
current_max_payload = 4;
}
if (cmd->cmd_options &
if (current_max_payload >
}
if (s_priv->data_remaining <
} else {
}
}
S1394_TNF_SL_BR_STACK, "");
return (ret);
}
}
}
/*
* s1394_pending_q_helper()
* is a "helper" function for s1394_process_pending_q(). It attempts to
* resend commands, handling error conditions whenever necessary.
*/
static boolean_t
{
int err;
int ret;
S1394_TNF_SL_BR_STACK, "");
/* Get the Services Layer private area */
/* Put cmd on outstanding request Q */
/* Send command out again */
if (ret != DDI_SUCCESS) {
if (err == CMD1394_ESTALE_GENERATION) {
/* Remove cmd outstanding req Q */
S1394_TNF_SL_BR_STACK, "");
return (B_TRUE);
} else {
/* Remove cmd from outstanding request Q */
/* Is this a blocking command? */
/* Unblock waiting command */
S1394_TNF_SL_BR_STACK, "");
return (B_FALSE);
}
/* Call target completion_callback() */
S1394_TNF_SL_BR_STACK, "");
return (B_FALSE);
} else {
S1394_TNF_SL_BR_STACK, "");
return (B_FALSE);
}
}
}
S1394_TNF_SL_BR_STACK, "");
return (B_FALSE);
}
/*
* s1394_process_split_lock()
* is a "helper" function for the s1394_handle_lock() callback. Its
* job is to perform whatever manipulation is required for the given
* request.
*/
static int
{
S1394_TNF_SL_ATREQ_STACK, "");
/* Lock type specific */
case CMD1394_LOCK_BIT_AND:
break;
case CMD1394_LOCK_BIT_OR:
break;
case CMD1394_LOCK_BIT_XOR:
break;
case CMD1394_LOCK_INCREMENT:
break;
case CMD1394_LOCK_DECREMENT:
break;
case CMD1394_LOCK_ADD:
break;
case CMD1394_LOCK_SUBTRACT:
break;
case CMD1394_LOCK_THRESH_ADD:
if ((temp_value32 >= old_value32) &&
(temp_value32 <= arg_value32)) {
} else {
/* Failed threshold add */
S1394_TNF_SL_ATREQ_STACK, "");
return (DDI_FAILURE);
}
break;
if ((old_value32 >= data_value32) &&
(temp_value32 >= arg_value32)) {
} else {
/* Failed threshold subtract */
S1394_TNF_SL_ATREQ_STACK, "");
return (DDI_FAILURE);
}
break;
case CMD1394_LOCK_CLIP_ADD:
if ((temp_value32 < old_value32) ||
(temp_value32 > arg_value32))
else
break;
if ((data_value32 > old_value32) ||
(temp_value32 < arg_value32))
else
break;
}
/* Send compare-swap lock request */
} else {
/* Lock type specific */
case CMD1394_LOCK_BIT_AND:
break;
case CMD1394_LOCK_BIT_OR:
break;
case CMD1394_LOCK_BIT_XOR:
break;
case CMD1394_LOCK_INCREMENT:
break;
case CMD1394_LOCK_DECREMENT:
break;
case CMD1394_LOCK_ADD:
break;
case CMD1394_LOCK_SUBTRACT:
break;
case CMD1394_LOCK_THRESH_ADD:
if ((temp_value64 >= old_value64) &&
(temp_value64 <= arg_value64)) {
} else {
/* Failed threshold add */
S1394_TNF_SL_ATREQ_STACK, "");
return (DDI_FAILURE);
}
break;
if ((old_value64 >= data_value64) &&
(temp_value64 >= arg_value64)) {
} else {
/* Failed threshold subtract */
S1394_TNF_SL_ATREQ_STACK, "");
return (DDI_FAILURE);
}
break;
case CMD1394_LOCK_CLIP_ADD:
if ((temp_value64 < old_value64) ||
(temp_value64 > arg_value64))
else
break;
if ((data_value64 > old_value64) ||
(temp_value64 < arg_value64))
else
break;
}
/* Send compare-swap lock request */
}
S1394_TNF_SL_ATREQ_STACK, "");
return (DDI_SUCCESS);
}
/*
* s1394_finish_split_lock()
* is another "helper" function for the s1394_handle_lock() callback.
* Its job is to finish up whatever lock request procesing is necessary.
*/
static int
{
S1394_TNF_SL_ATREQ_STACK, "");
/* Get the Services Layer private area */
case CMD1394_LOCK_INCREMENT:
case CMD1394_LOCK_DECREMENT:
case CMD1394_LOCK_ADD:
case CMD1394_LOCK_SUBTRACT:
case CMD1394_LOCK_THRESH_ADD:
case CMD1394_LOCK_CLIP_ADD:
break;
default:
break;
}
} else {
case CMD1394_LOCK_INCREMENT:
case CMD1394_LOCK_DECREMENT:
case CMD1394_LOCK_ADD:
case CMD1394_LOCK_SUBTRACT:
case CMD1394_LOCK_THRESH_ADD:
case CMD1394_LOCK_CLIP_ADD:
break;
default:
break;
}
}
/* Set status */
S1394_TNF_SL_ATREQ_STACK, "");
return (DDI_SUCCESS);
} else {
if (s_priv->temp_num_retries > 0) {
/* Decrement retry count */
/* Reset lock_req_step */
s_priv->lock_req_step = 0;
S1394_TNF_SL_ATREQ_STACK, "");
/* Resend... start at step 0 again */
S1394_TNF_SL_ATREQ_STACK, "");
return (DDI_FAILURE);
} else {
/* Failed... RETRIES_EXCEEDED */
S1394_TNF_SL_ATREQ_STACK, "");
return (DDI_SUCCESS);
}
}
}