1 /*
2  * CDDL HEADER START
3  *
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.
7  *
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.
12  *
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]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 /*
29  * s1394_asynch.c
30  *    1394 Services Layer Asynchronous Communications Routines
31  *    These routines handle all of the tasks relating to asynch commands
32  */
33 
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>
42 
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>
48 
49 static void s1394_handle_lock(cmd1394_cmd_t *cmd);
50 
51 static cmd1394_cmd_t *s1394_pending_q_remove(s1394_hal_t *hal);
52 
53 static boolean_t s1394_process_pending_q(s1394_hal_t *hal);
54 
55 static boolean_t s1394_pending_q_helper(s1394_hal_t *hal, cmd1394_cmd_t *cmd);
56 
57 static int s1394_process_split_lock(cmd1394_cmd_t *cmd,
58     cmd1394_cmd_t *target_cmd);
59 
60 static int s1394_finish_split_lock(cmd1394_cmd_t *cmd,
61     cmd1394_cmd_t *target_cmd);
62 
63 /*
64  * s1394_alloc_cmd()
65  *    is used to allocate a command for a target or for a HAL.
66  */
67 int
s1394_alloc_cmd(s1394_hal_t * hal,uint_t flags,cmd1394_cmd_t ** cmdp)68 s1394_alloc_cmd(s1394_hal_t *hal, uint_t flags, cmd1394_cmd_t **cmdp)
69 {
70 	s1394_cmd_priv_t *s_priv;
71 	void		 *hal_overhead;
72 	uint_t		 cmd_size;
73 	int		 alloc_sleep;
74 
75 	TNF_PROBE_0_DEBUG(s1394_alloc_cmd_enter, S1394_TNF_SL_STACK, "");
76 
77 	alloc_sleep = (flags & T1394_ALLOC_CMD_NOSLEEP) ? KM_NOSLEEP : KM_SLEEP;
78 
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 */
86 		return (DDI_FAILURE);
87 	}
88 
89 	/* either FCP command or response, but not both */
90 	if ((flags &
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, "");
97 		return (DDI_FAILURE);
98 	}
99 
100 	*cmdp = kmem_cache_alloc(hal->hal_kmem_cachep, alloc_sleep);
101 	if (*cmdp == NULL) {
102 		TNF_PROBE_0_DEBUG(s1394_alloc_cmd_exit,
103 		    S1394_TNF_SL_STACK, "");
104 		return (DDI_FAILURE);
105 	}
106 	cmd_size = sizeof (cmd1394_cmd_t) +
107 	    sizeof (s1394_cmd_priv_t) + hal->halinfo.hal_overhead;
108 	bzero((void *)*cmdp, cmd_size);
109 
110 	(*cmdp)->cmd_version = T1394_VERSION_V1;
111 	(*cmdp)->cmd_result = CMD1394_NOSTATUS;
112 
113 	/* Get the Services Layer private area */
114 	s_priv = S1394_GET_CMD_PRIV(*cmdp);
115 
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);
121 	}
122 
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;
126 
127 	TNF_PROBE_1_DEBUG(s1394_alloc_cmd, S1394_TNF_SL_STACK, "",
128 	    tnf_opaque, cmd, *cmdp);
129 
130 	/* kstats - number of cmd allocs */
131 	hal->hal_kstats->cmd_alloc++;
132 
133 	TNF_PROBE_0_DEBUG(s1394_alloc_cmd_exit, S1394_TNF_SL_STACK, "");
134 	return (DDI_SUCCESS);
135 }
136 
137 /*
138  * s1394_free_cmd()
139  *    is used to free a command that had been previously allocated by
140  *    s1394_alloc_cmd().
141  */
142 int
s1394_free_cmd(s1394_hal_t * hal,cmd1394_cmd_t ** cmdp)143 s1394_free_cmd(s1394_hal_t *hal, cmd1394_cmd_t **cmdp)
144 {
145 	s1394_cmd_priv_t *s_priv;
146 
147 	TNF_PROBE_0_DEBUG(s1394_free_cmd_enter, S1394_TNF_SL_STACK, "");
148 
149 	/* Get the Services Layer private area */
150 	s_priv = S1394_GET_CMD_PRIV(*cmdp);
151 
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);
159 	}
160 	TNF_PROBE_1_DEBUG(s1394_free_cmd, S1394_TNF_SL_STACK, "",
161 	    tnf_opaque, cmd, *cmdp);
162 
163 	/* kstats - number of cmd allocs */
164 	kmem_cache_free(hal->hal_kmem_cachep, *cmdp);
165 
166 	/* Command pointer is set to NULL before returning */
167 	*cmdp = NULL;
168 
169 	/* kstats - number of cmd frees */
170 	hal->hal_kstats->cmd_free++;
171 
172 	TNF_PROBE_0_DEBUG(s1394_free_cmd_exit, S1394_TNF_SL_STACK, "");
173 	return (DDI_SUCCESS);
174 }
175 
176 /*
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.
182  */
183 int
s1394_xfer_asynch_command(s1394_hal_t * hal,cmd1394_cmd_t * cmd,int * err)184 s1394_xfer_asynch_command(s1394_hal_t *hal, cmd1394_cmd_t *cmd, int *err)
185 {
186 	s1394_cmd_priv_t  *s_priv;
187 	h1394_cmd_priv_t  *h_priv;
188 	s1394_hal_state_t state;
189 	dev_info_t	  *dip;
190 	int		  result_from_hal;
191 	int		  ret;
192 
193 	TNF_PROBE_0_DEBUG(s1394_xfer_asynch_command_enter,
194 	    S1394_TNF_SL_ATREQ_STACK, "");
195 
196 	ASSERT(MUTEX_NOT_HELD(&hal->topology_tree_mutex));
197 
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);
207 	}
208 	mutex_exit(&hal->topology_tree_mutex);
209 
210 	/* Get the Services Layer private area */
211 	s_priv = S1394_GET_CMD_PRIV(cmd);
212 
213 	/* Get a pointer to the HAL private struct */
214 	h_priv = (h1394_cmd_priv_t *)&s_priv->hal_cmd_private;
215 
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++;
220 		break;
221 
222 	case CMD1394_ASYNCH_RD_BLOCK:
223 		hal->hal_kstats->atreq_blk_rd++;
224 		break;
225 
226 	case CMD1394_ASYNCH_WR_QUAD:
227 		hal->hal_kstats->atreq_quad_wr++;
228 		break;
229 
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;
233 		break;
234 
235 	case CMD1394_ASYNCH_LOCK_32:
236 		hal->hal_kstats->atreq_lock32++;
237 		break;
238 
239 	case CMD1394_ASYNCH_LOCK_64:
240 		hal->hal_kstats->atreq_lock64++;
241 		break;
242 	}
243 
244 	switch (s_priv->cmd_priv_xfer_type) {
245 	/* Call the HAL's read entry point */
246 	case S1394_CMD_READ:
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,
250 		    &result_from_hal);
251 		break;
252 
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,
258 		    &result_from_hal);
259 		break;
260 
261 	/* Call the HAL's lock entry point */
262 	case S1394_CMD_LOCK:
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,
266 		    &result_from_hal);
267 		break;
268 
269 	default:
270 		*err = CMD1394_EUNKNOWN_ERROR;
271 
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);
278 	}
279 
280 	TNF_PROBE_0_DEBUG(s1394_xfer_asynch_command_return_from_HAL,
281 	    S1394_TNF_SL_ATREQ_STACK, "");
282 
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;
288 			break;
289 
290 		case H1394_STATUS_INVALID_BUSGEN:
291 			/* Out of TLABELs - Unable to send AT req */
292 			*err = CMD1394_ESTALE_GENERATION;
293 			break;
294 
295 		case H1394_STATUS_NOMORE_SPACE:
296 			/* No more space on HAL's HW queue */
297 			*err = CMD1394_ENO_ATREQ;
298 			break;
299 
300 		case H1394_STATUS_INTERNAL_ERROR:
301 			dip = hal->halinfo.dip;
302 
303 			/* An unexpected error in the HAL */
304 			cmn_err(CE_WARN, HALT_ERROR_MESSAGE,
305 			    ddi_node_name(dip), ddi_get_instance(dip));
306 
307 			/* Disable the HAL */
308 			s1394_hal_shutdown(hal, B_TRUE);
309 
310 			*err = CMD1394_EFATAL_ERROR;
311 			break;
312 
313 		default:
314 			dip = hal->halinfo.dip;
315 
316 			/* An unexpected error in the HAL */
317 			cmn_err(CE_WARN, HALT_ERROR_MESSAGE,
318 			    ddi_node_name(dip), ddi_get_instance(dip));
319 
320 			/* Disable the HAL */
321 			s1394_hal_shutdown(hal, B_TRUE);
322 
323 			*err = CMD1394_EFATAL_ERROR;
324 			break;
325 		}
326 
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,
330 		    tnf_int, err, *err);
331 		return (DDI_FAILURE);
332 	}
333 
334 	/* No errors, return success */
335 	*err = CMD1394_NOSTATUS;
336 
337 	TNF_PROBE_0_DEBUG(s1394_xfer_asynch_command_exit,
338 	    S1394_TNF_SL_ATREQ_STACK, "");
339 	return (DDI_SUCCESS);
340 }
341 
342 /*
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
348  *    calling the HAL.
349  */
350 int
s1394_setup_asynch_command(s1394_hal_t * hal,s1394_target_t * target,cmd1394_cmd_t * cmd,uint32_t xfer_type,int * err)351 s1394_setup_asynch_command(s1394_hal_t *hal, s1394_target_t *target,
352     cmd1394_cmd_t *cmd, uint32_t xfer_type, int *err)
353 {
354 	s1394_cmd_priv_t  *s_priv;
355 	h1394_cmd_priv_t  *h_priv;
356 	uint64_t	  node;
357 	uint32_t	  from_node;
358 	uint32_t	  to_node;
359 	uint32_t	  bus_capabilities;
360 	uint_t		  current_max_payload;
361 	uint_t		  max_rec;
362 	uint_t		  max_blk;
363 
364 	TNF_PROBE_0_DEBUG(s1394_setup_asynch_command_enter,
365 	    S1394_TNF_SL_ATREQ_STACK, "");
366 
367 	ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
368 
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:
376 		break;
377 
378 	default:
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);
386 	}
387 
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);
394 	}
395 
396 	/* Get the Services Layer private area */
397 	s_priv = S1394_GET_CMD_PRIV(cmd);
398 
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;
402 
403 	/* Set up command transfer type */
404 	s_priv->cmd_priv_xfer_type = xfer_type;
405 
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 */
409 
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);
413 
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);
419 		}
420 
421 	} else {
422 		/* Set the generation */
423 		cmd->bus_generation = hal->generation_count;
424 
425 		/* If not OVERRIDE_ADDR, then target may not be NULL */
426 		ASSERT(target != NULL);
427 
428 		rw_enter(&hal->target_list_rwlock, RW_READER);
429 
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);
437 		}
438 
439 		ASSERT((target->target_state & S1394_TARG_GONE) == 0);
440 		node = target->on_node->node_num;
441 		rw_exit(&hal->target_list_rwlock);
442 
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);
448 
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;
452 	}
453 
454 	/* Get a pointer to the HAL private struct */
455 	h_priv = (h1394_cmd_priv_t *)&s_priv->hal_cmd_private;
456 
457 	/* Copy the generation into the HAL's private field */
458 	h_priv->bus_generation = cmd->bus_generation;
459 
460 	/* Fill in the nodeID */
461 	cmd->nodeID = (cmd->cmd_addr & IEEE1394_ADDR_NODE_ID_MASK) >>
462 	    IEEE1394_ADDR_NODE_ID_SHIFT;
463 
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);
470 
471 		} else {
472 			s_priv->hal_cmd_private.speed = (int)cmd->cmd_speed;
473 		}
474 
475 	} else {
476 		/* Speed is to be filled in from speed map */
477 		s_priv->hal_cmd_private.speed = (int)s1394_speed_map_get(hal,
478 		    from_node, to_node);
479 	}
480 
481 	/* Is it a block request? */
482 	if ((cmd->cmd_type == CMD1394_ASYNCH_RD_BLOCK) ||
483 	    (cmd->cmd_type == CMD1394_ASYNCH_WR_BLOCK)) {
484 
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);
490 		}
491 
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);
498 		}
499 
500 		/* Initialize bytes_transferred to zero */
501 		cmd->cmd_u.b.bytes_transferred = 0;
502 
503 		/* Handle the MAX_PAYLOAD size */
504 		if (cmd->cmd_options & CMD1394_OVERRIDE_ADDR) {
505 
506 			current_max_payload = 512 <<
507 			    (s_priv->hal_cmd_private.speed);
508 			if (hal->topology_tree[to_node].cfgrom) {
509 				bus_capabilities =
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;
515 			} else {
516 				max_rec = 0;
517 			}
518 
519 			if ((max_rec > 0) && (max_rec < 14)) {
520 				max_blk = 1 << (max_rec + 1);
521 
522 			} else {
523 				/* These are either unspecified or reserved */
524 				max_blk = 4;
525 			}
526 			if (max_blk < current_max_payload)
527 				current_max_payload = max_blk;
528 
529 		} else {
530 			rw_enter(&hal->target_list_rwlock, RW_READER);
531 			current_max_payload = target->current_max_payload;
532 			rw_exit(&hal->target_list_rwlock);
533 		}
534 
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;
538 		}
539 
540 		h_priv->mblk.curr_mblk = cmd->cmd_u.b.data_block;
541 
542 		if (cmd->cmd_type == CMD1394_ASYNCH_WR_BLOCK) {
543 			h_priv->mblk.curr_offset =
544 			    cmd->cmd_u.b.data_block->b_rptr;
545 		} else {
546 			h_priv->mblk.curr_offset =
547 			    cmd->cmd_u.b.data_block->b_wptr;
548 		}
549 
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;
553 
554 		} else {
555 			h_priv->mblk.length = cmd->cmd_u.b.blk_length;
556 			s_priv->data_remaining = cmd->cmd_u.b.blk_length;
557 		}
558 	}
559 
560 	/* Mark command as being used */
561 	s_priv->cmd_in_use = B_TRUE;
562 
563 	/* Put command on the HAL's outstanding request Q */
564 	s1394_insert_q_asynch_cmd(hal, cmd);
565 
566 	TNF_PROBE_0_DEBUG(s1394_setup_asynch_command_exit,
567 	    S1394_TNF_SL_ATREQ_STACK, "");
568 	return (DDI_SUCCESS);
569 }
570 
571 /*
572  * s1394_insert_q_asynch_cmd()
573  *    is used to insert a given command structure onto a HAL's outstanding
574  *    asynch queue.
575  */
576 void
s1394_insert_q_asynch_cmd(s1394_hal_t * hal,cmd1394_cmd_t * cmd)577 s1394_insert_q_asynch_cmd(s1394_hal_t *hal, cmd1394_cmd_t *cmd)
578 {
579 	s1394_cmd_priv_t *s_priv;
580 	s1394_cmd_priv_t *c_priv;
581 	cmd1394_cmd_t	 *temp_cmd;
582 
583 	TNF_PROBE_0_DEBUG(s1394_insert_q_asynch_cmd_enter,
584 	    S1394_TNF_SL_ATREQ_STACK, "");
585 
586 	mutex_enter(&hal->outstanding_q_mutex);
587 
588 	/* Get the Services Layer private area */
589 	s_priv = S1394_GET_CMD_PRIV(cmd);
590 
591 	/* Is the outstanding request queue empty? */
592 	if ((hal->outstanding_q_head == NULL) &&
593 	    (hal->outstanding_q_tail == NULL)) {
594 
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;
599 
600 	} else {
601 		s_priv->cmd_priv_next = hal->outstanding_q_head;
602 		s_priv->cmd_priv_prev = (cmd1394_cmd_t *)NULL;
603 
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;
608 
609 		hal->outstanding_q_head = (cmd1394_cmd_t *)cmd;
610 	}
611 
612 	mutex_exit(&hal->outstanding_q_mutex);
613 
614 	TNF_PROBE_0_DEBUG(s1394_insert_q_asynch_cmd_exit,
615 	    S1394_TNF_SL_ATREQ_STACK, "");
616 }
617 
618 /*
619  * s1394_remove_q_asynch_cmd()
620  *    is used to remove a given command structure from a HAL's outstanding
621  *    asynch queue.
622  */
623 void
s1394_remove_q_asynch_cmd(s1394_hal_t * hal,cmd1394_cmd_t * cmd)624 s1394_remove_q_asynch_cmd(s1394_hal_t *hal, cmd1394_cmd_t *cmd)
625 {
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;
630 
631 	TNF_PROBE_0_DEBUG(s1394_remove_q_asynch_cmd_enter,
632 	    S1394_TNF_SL_ATREQ_STACK, "");
633 
634 	mutex_enter(&hal->outstanding_q_mutex);
635 
636 	/* Get the Services Layer private area */
637 	s_priv = S1394_GET_CMD_PRIV(cmd);
638 
639 	prev_cmd = (cmd1394_cmd_t *)s_priv->cmd_priv_prev;
640 	next_cmd = (cmd1394_cmd_t *)s_priv->cmd_priv_next;
641 
642 	s_priv->cmd_priv_prev = (cmd1394_cmd_t *)NULL;
643 	s_priv->cmd_priv_next = (cmd1394_cmd_t *)NULL;
644 
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;
649 
650 	} else {
651 		if (hal->outstanding_q_head == (cmd1394_cmd_t *)cmd)
652 			hal->outstanding_q_head = (cmd1394_cmd_t *)next_cmd;
653 	}
654 
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;
659 
660 	} else {
661 		if (hal->outstanding_q_tail == (cmd1394_cmd_t *)cmd)
662 			hal->outstanding_q_tail = (cmd1394_cmd_t *)prev_cmd;
663 	}
664 
665 	mutex_exit(&hal->outstanding_q_mutex);
666 
667 	TNF_PROBE_0_DEBUG(s1394_remove_q_asynch_cmd_exit,
668 	    S1394_TNF_SL_ATREQ_STACK, "");
669 }
670 
671 /*
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).
678  */
679 void
s1394_atreq_cmd_complete(s1394_hal_t * hal,cmd1394_cmd_t * req,int status)680 s1394_atreq_cmd_complete(s1394_hal_t *hal, cmd1394_cmd_t *req, int status)
681 {
682 	s1394_cmd_priv_t *s_priv;
683 	h1394_cmd_priv_t *h_priv;
684 	dev_info_t	 *dip;
685 	int		 ret;
686 	int		 cmd_result;
687 	int		 err;
688 
689 	TNF_PROBE_0_DEBUG(s1394_atreq_cmd_complete_enter,
690 	    S1394_TNF_SL_ATREQ_STACK, "");
691 
692 	/* Get the Services Layer private area */
693 	s_priv = S1394_GET_CMD_PRIV(req);
694 
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++;
701 			break;
702 
703 		case CMD1394_ASYNCH_RD_BLOCK:
704 			hal->hal_kstats->atresp_blk_rd_fail++;
705 			break;
706 
707 		case CMD1394_ASYNCH_WR_QUAD:
708 			hal->hal_kstats->atresp_quad_wr_fail++;
709 			break;
710 
711 		case CMD1394_ASYNCH_WR_BLOCK:
712 			hal->hal_kstats->atresp_blk_wr_fail++;
713 			break;
714 
715 		case CMD1394_ASYNCH_LOCK_32:
716 			hal->hal_kstats->atresp_lock32_fail++;
717 			break;
718 
719 		case CMD1394_ASYNCH_LOCK_64:
720 			hal->hal_kstats->atresp_lock64_fail++;
721 			break;
722 		}
723 
724 
725 		switch (status) {
726 		/* evt_missing_ack */
727 		case H1394_CMD_ETIMEOUT:
728 			cmd_result = CMD1394_ETIMEOUT;
729 			break;
730 
731 		/* evt_flushed */
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;
737 				break;
738 			}
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, "");
743 			return;
744 
745 		/* ack_busy_X */
746 		/* ack_busy_A */
747 		/* ack_busy_B */
748 		case H1394_CMD_EDEVICE_BUSY:
749 			cmd_result = CMD1394_EDEVICE_BUSY;
750 			break;
751 
752 		/* ack_data_error */
753 		case H1394_CMD_EDATA_ERROR:
754 			cmd_result = CMD1394_EDATA_ERROR;
755 			break;
756 
757 		/* ack_type_error */
758 		case H1394_CMD_ETYPE_ERROR:
759 			cmd_result = CMD1394_ETYPE_ERROR;
760 			break;
761 
762 		/* resp_address_error */
763 		/* ack_address_error */
764 		case H1394_CMD_EADDR_ERROR:
765 			cmd_result = CMD1394_EADDRESS_ERROR;
766 			break;
767 
768 		/* resp_conflict_error */
769 		/* ack_conflict_error */
770 		case H1394_CMD_ERSRC_CONFLICT:
771 			cmd_result = CMD1394_ERSRC_CONFLICT;
772 			break;
773 
774 		/* ack_tardy */
775 		case H1394_CMD_EDEVICE_POWERUP:
776 			cmd_result = CMD1394_EDEVICE_BUSY;
777 			break;
778 
779 		/* device errors (bad tcodes, ACKs, etc...) */
780 		case H1394_CMD_EDEVICE_ERROR:
781 			cmd_result = CMD1394_EDEVICE_ERROR;
782 			break;
783 
784 		/* Unknown error type */
785 		case H1394_CMD_EUNKNOWN_ERROR:
786 			cmd_result = CMD1394_EUNKNOWN_ERROR;
787 			break;
788 
789 		/* Unrecognized error */
790 		default:
791 			dip = hal->halinfo.dip;
792 
793 			/* An unexpected error in the HAL */
794 			cmn_err(CE_WARN, HALT_ERROR_MESSAGE,
795 			    ddi_node_name(dip), ddi_get_instance(dip));
796 
797 			/* Disable the HAL */
798 			s1394_hal_shutdown(hal, B_TRUE);
799 
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, "");
806 			return;
807 		}
808 
809 		/* Remove command from the HAL's outstanding request Q */
810 		s1394_remove_q_asynch_cmd(hal, req);
811 
812 		s_priv->cmd_in_use = B_FALSE;
813 
814 		req->cmd_result = cmd_result;
815 
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);
823 
824 			TNF_PROBE_0_DEBUG(s1394_atreq_cmd_complete_exit,
825 			    S1394_TNF_SL_ATREQ_STACK, "");
826 			return;
827 		}
828 
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);
834 		}
835 
836 		TNF_PROBE_0_DEBUG(s1394_atreq_cmd_complete_exit,
837 		    S1394_TNF_SL_ATREQ_STACK, "");
838 		return;
839 	}
840 
841 	/* Successful unless otherwise modified */
842 	err = CMD1394_CMDSUCCESS;
843 
844 	if ((req->cmd_type == CMD1394_ASYNCH_RD_BLOCK) ||
845 	    (req->cmd_type == CMD1394_ASYNCH_WR_BLOCK)) {
846 
847 		/* Get a pointer to the HAL private struct */
848 		h_priv = (h1394_cmd_priv_t *)&s_priv->hal_cmd_private;
849 
850 		/* Update data_remaining */
851 		s_priv->data_remaining -= h_priv->mblk.length;
852 
853 		/* Increment bytes_transferred */
854 		req->cmd_u.b.bytes_transferred += h_priv->mblk.length;
855 
856 		if (req->cmd_type == CMD1394_ASYNCH_RD_BLOCK)
857 			hal->hal_kstats->atreq_blk_rd_size +=
858 			    h_priv->mblk.length;
859 
860 		/* Is there still more to send? */
861 		if (s_priv->data_remaining > 0) {
862 
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;
866 
867 			/* Update destination address */
868 			if (!(req->cmd_options &
869 			    CMD1394_DISABLE_ADDR_INCREMENT)) {
870 				req->cmd_addr += h_priv->mblk.length;
871 			}
872 
873 			/*
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.
878 			 */
879 			if (s_priv->data_remaining < h_priv->mblk.length) {
880 				h_priv->mblk.length = s_priv->data_remaining;
881 			}
882 
883 			/* Send command out again */
884 			ret = s1394_xfer_asynch_command(hal, req, &err);
885 
886 			if (ret == DDI_SUCCESS) {
887 				TNF_PROBE_0_DEBUG(s1394_atreq_cmd_complete_exit,
888 				    S1394_TNF_SL_ATREQ_STACK, "");
889 				return;
890 
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);
896 
897 				TNF_PROBE_0_DEBUG(s1394_atreq_cmd_complete_exit,
898 				    S1394_TNF_SL_ATREQ_STACK, "");
899 				return;
900 			}
901 		}
902 	}
903 
904 	/* Remove command from the HAL's outstanding request Q */
905 	s1394_remove_q_asynch_cmd(hal, req);
906 
907 	s_priv->cmd_in_use = B_FALSE;
908 
909 	/* Set status */
910 	req->cmd_result = err;
911 
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);
919 
920 		TNF_PROBE_0_DEBUG(s1394_atreq_cmd_complete_exit,
921 		    S1394_TNF_SL_ATREQ_STACK, "");
922 		return;
923 	}
924 
925 	/* Set status and call completion_callback() */
926 	if (req->completion_callback != NULL) {
927 
928 		TNF_PROBE_0_DEBUG(s1394_atreq_cmd_complete_do_callback,
929 		    S1394_TNF_SL_ATREQ_STACK, "");
930 
931 		req->completion_callback(req);
932 
933 		TNF_PROBE_0_DEBUG(s1394_atreq_cmd_complete_exit,
934 		    S1394_TNF_SL_ATREQ_STACK, "");
935 		return;
936 	}
937 
938 	TNF_PROBE_0_DEBUG(s1394_atreq_cmd_complete_exit,
939 	    S1394_TNF_SL_ATREQ_STACK, "");
940 }
941 
942 /*
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.
949  */
950 void
s1394_atresp_cmd_complete(s1394_hal_t * hal,cmd1394_cmd_t * resp,int status)951 s1394_atresp_cmd_complete(s1394_hal_t *hal, cmd1394_cmd_t *resp, int status)
952 {
953 	s1394_cmd_priv_t *s_priv;
954 	h1394_cmd_priv_t *h_priv;
955 	dev_info_t	 *dip;
956 	boolean_t	 valid_addr_blk;
957 	int		 target_status;
958 
959 	TNF_PROBE_0_DEBUG(s1394_atresp_cmd_complete_enter,
960 	    S1394_TNF_SL_ATRESP_STACK, "");
961 
962 	target_status = CMD1394_CMDSUCCESS;
963 
964 	/* If not an ack_complete */
965 	if (status != H1394_CMD_SUCCESS) {
966 		switch (status) {
967 		/* evt_missing_ack */
968 		case H1394_CMD_ETIMEOUT:
969 			target_status = CMD1394_ETIMEOUT;
970 			break;
971 
972 		/* evt_flushed */
973 		case H1394_CMD_EBUSRESET:
974 			target_status = CMD1394_EBUSRESET;
975 			break;
976 
977 		/* ack_busy_X */
978 		/* ack_busy_A */
979 		/* ack_busy_B */
980 		case H1394_CMD_EDEVICE_BUSY:
981 			target_status = CMD1394_EDEVICE_BUSY;
982 			break;
983 
984 		/* ack_data_error */
985 		case H1394_CMD_EDATA_ERROR:
986 			target_status = CMD1394_EDATA_ERROR;
987 			break;
988 
989 		/* ack_type_error */
990 		case H1394_CMD_ETYPE_ERROR:
991 			target_status = CMD1394_ETYPE_ERROR;
992 			break;
993 
994 		/* ack_address_error */
995 		case H1394_CMD_EADDR_ERROR:
996 			target_status = CMD1394_EADDRESS_ERROR;
997 			break;
998 
999 		/* ack_conflict_error */
1000 		case H1394_CMD_ERSRC_CONFLICT:
1001 			target_status = CMD1394_ERSRC_CONFLICT;
1002 			break;
1003 
1004 		/* ack_tardy */
1005 		case H1394_CMD_EDEVICE_POWERUP:
1006 			target_status = CMD1394_EDEVICE_BUSY;
1007 			break;
1008 
1009 		/* device errors (bad tcodes, ACKs, etc...) */
1010 		case H1394_CMD_EDEVICE_ERROR:
1011 			target_status = CMD1394_EDEVICE_ERROR;
1012 			break;
1013 
1014 		/* Unknown error type */
1015 		case H1394_CMD_EUNKNOWN_ERROR:
1016 			target_status = CMD1394_EUNKNOWN_ERROR;
1017 			break;
1018 
1019 		/* Unrecognized error */
1020 		default:
1021 			dip = hal->halinfo.dip;
1022 
1023 			/* An unexpected error in the HAL */
1024 			cmn_err(CE_WARN, HALT_ERROR_MESSAGE,
1025 			    ddi_node_name(dip), ddi_get_instance(dip));
1026 
1027 			/* Disable the HAL */
1028 			s1394_hal_shutdown(hal, B_TRUE);
1029 
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, "");
1036 			return;
1037 		}
1038 	}
1039 
1040 	/* Get the Services Layer private area */
1041 	s_priv = S1394_GET_CMD_PRIV(resp);
1042 
1043 	/* Get a pointer to the HAL private struct */
1044 	h_priv = (h1394_cmd_priv_t *)&s_priv->hal_cmd_private;
1045 
1046 	valid_addr_blk = s_priv->arreq_valid_addr;
1047 
1048 	if (valid_addr_blk == B_TRUE) {
1049 		/* Set the command status */
1050 		resp->cmd_result = target_status;
1051 
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) {
1057 				TNF_PROBE_0_DEBUG(
1058 				    s1394_atresp_cmd_complete_do_callback,
1059 				    S1394_TNF_SL_ATRESP_STACK, "");
1060 				resp->completion_callback(resp);
1061 			}
1062 			break;
1063 
1064 		default:
1065 			dip = hal->halinfo.dip;
1066 
1067 			/* An unexpected error in the HAL */
1068 			cmn_err(CE_WARN, HALT_ERROR_MESSAGE,
1069 			    ddi_node_name(dip), ddi_get_instance(dip));
1070 
1071 			/* Disable the HAL */
1072 			s1394_hal_shutdown(hal, B_TRUE);
1073 
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, "");
1079 			return;
1080 		}
1081 	}
1082 
1083 	TNF_PROBE_0_DEBUG(s1394_atresp_cmd_complete_call_hal_cmplt,
1084 	    S1394_TNF_SL_ATRESP_STACK, "");
1085 
1086 	/* Free the command - Pass it back to the HAL */
1087 	HAL_CALL(hal).response_complete(hal->halinfo.hal_private, resp, h_priv);
1088 
1089 	TNF_PROBE_1_DEBUG(s1394_atresp_cmd_complete_exit,
1090 	    S1394_TNF_SL_ATRESP_STACK, "", tnf_int, status, target_status);
1091 }
1092 
1093 /*
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.
1104  */
1105 int
s1394_send_response(s1394_hal_t * hal,cmd1394_cmd_t * resp)1106 s1394_send_response(s1394_hal_t *hal, cmd1394_cmd_t *resp)
1107 {
1108 	s1394_cmd_priv_t *s_priv;
1109 	h1394_cmd_priv_t *h_priv;
1110 	dev_info_t	 *dip;
1111 	int		 ret;
1112 	int		 result;
1113 
1114 	TNF_PROBE_0_DEBUG(s1394_send_response_enter, S1394_TNF_SL_ATRESP_STACK,
1115 	    "");
1116 
1117 	/* Get the Services Layer private area */
1118 	s_priv = S1394_GET_CMD_PRIV(resp);
1119 
1120 	/* Get a pointer to the HAL private struct */
1121 	h_priv = (h1394_cmd_priv_t *)&s_priv->hal_cmd_private;
1122 
1123 	/*
1124 	 * If request was broadcast or a write request to a posted write
1125 	 * address, don't send a response
1126 	 */
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)))) {
1130 
1131 		TNF_PROBE_0_DEBUG(s1394_send_response_call_hal_cmplt,
1132 		    S1394_TNF_SL_ATRESP_STACK, "");
1133 
1134 		/* Free the command - Pass it back to the HAL */
1135 		HAL_CALL(hal).response_complete(hal->halinfo.hal_private,
1136 		    resp, h_priv);
1137 
1138 		TNF_PROBE_0_DEBUG(s1394_send_response_exit,
1139 		    S1394_TNF_SL_ATRESP_STACK, "");
1140 		return (DDI_SUCCESS);
1141 	}
1142 
1143 	TNF_PROBE_0_DEBUG(s1394_send_response_call_hal_resp,
1144 	    S1394_TNF_SL_ATRESP_STACK, "");
1145 
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++;
1151 			break;
1152 
1153 		case CMD1394_ASYNCH_RD_BLOCK:
1154 			hal->hal_kstats->arresp_blk_rd_fail++;
1155 			break;
1156 
1157 		case CMD1394_ASYNCH_WR_QUAD:
1158 			hal->hal_kstats->arresp_quad_wr_fail++;
1159 			break;
1160 
1161 		case CMD1394_ASYNCH_WR_BLOCK:
1162 			hal->hal_kstats->arresp_blk_wr_fail++;
1163 			break;
1164 
1165 		case CMD1394_ASYNCH_LOCK_32:
1166 			hal->hal_kstats->arresp_lock32_fail++;
1167 			break;
1168 
1169 		case CMD1394_ASYNCH_LOCK_64:
1170 			hal->hal_kstats->arresp_lock64_fail++;
1171 			break;
1172 		}
1173 	} else {
1174 		if (resp->cmd_type == CMD1394_ASYNCH_RD_BLOCK)
1175 			hal->hal_kstats->arreq_blk_rd_size +=
1176 			    resp->cmd_u.b.blk_length;
1177 	}
1178 
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;
1183 	}
1184 
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);
1189 		break;
1190 
1191 	case S1394_CMD_WRITE:
1192 		ret = HAL_CALL(hal).write_response(hal->halinfo.hal_private,
1193 		    resp, h_priv, &result);
1194 		break;
1195 
1196 	case S1394_CMD_LOCK:
1197 		ret = HAL_CALL(hal).lock_response(hal->halinfo.hal_private,
1198 		    resp, h_priv, &result);
1199 		break;
1200 
1201 	default:
1202 		dip = hal->halinfo.dip;
1203 
1204 		/* An unexpected error in the HAL */
1205 		cmn_err(CE_WARN, HALT_ERROR_MESSAGE,
1206 		    ddi_node_name(dip), ddi_get_instance(dip));
1207 
1208 		/* Disable the HAL */
1209 		s1394_hal_shutdown(hal, B_TRUE);
1210 
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);
1217 	}
1218 
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");
1229 		} else {
1230 			TNF_PROBE_1(s1394_send_response_error,
1231 			    S1394_TNF_SL_ATRESP_ERROR, "", tnf_string, msg,
1232 			    "Unknown problem in s1394_send_response");
1233 		}
1234 		TNF_PROBE_0_DEBUG(s1394_send_response_call_hal_cmplt,
1235 		    S1394_TNF_SL_ATRESP_STACK, "");
1236 
1237 		/* Free the command - Pass it back to the HAL */
1238 		HAL_CALL(hal).response_complete(hal->halinfo.hal_private,
1239 		    resp, h_priv);
1240 
1241 		TNF_PROBE_0_DEBUG(s1394_send_response_exit,
1242 		    S1394_TNF_SL_ATRESP_STACK, "");
1243 		return (DDI_FAILURE);
1244 	}
1245 
1246 	TNF_PROBE_0_DEBUG(s1394_send_response_exit, S1394_TNF_SL_ATRESP_STACK,
1247 	    "");
1248 	return (DDI_SUCCESS);
1249 }
1250 
1251 /*
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.
1256  */
1257 int
s1394_compare_swap(s1394_hal_t * hal,s1394_target_t * target,cmd1394_cmd_t * cmd)1258 s1394_compare_swap(s1394_hal_t *hal, s1394_target_t *target, cmd1394_cmd_t *cmd)
1259 {
1260 	s1394_cmd_priv_t	*s_priv;
1261 	s1394_hal_state_t	state;
1262 	int			err;
1263 	int			ret;
1264 
1265 	TNF_PROBE_0_DEBUG(s1394_compare_swap_enter, S1394_TNF_SL_ATREQ_STACK,
1266 	    "");
1267 
1268 	ASSERT(MUTEX_NOT_HELD(&hal->topology_tree_mutex));
1269 
1270 	/* Lock the topology tree - protect from bus reset */
1271 	mutex_enter(&hal->topology_tree_mutex);
1272 
1273 	ret = s1394_setup_asynch_command(hal, target, cmd, S1394_CMD_LOCK,
1274 	    &err);
1275 
1276 	/* Unlock the topology tree */
1277 	mutex_exit(&hal->topology_tree_mutex);
1278 
1279 	/* Get the Services Layer private area */
1280 	s_priv = S1394_GET_CMD_PRIV(cmd);
1281 
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;
1286 
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);
1292 	}
1293 
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);
1301 
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);
1307 
1308 				s_priv->cmd_in_use = B_FALSE;
1309 
1310 				cmd->cmd_result = CMD1394_EINVALID_CONTEXT;
1311 
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);
1318 			}
1319 		}
1320 
1321 		s1394_pending_q_insert(hal, cmd, S1394_PENDING_Q_FRONT);
1322 		mutex_exit(&hal->topology_tree_mutex);
1323 
1324 		/* Block (if necessary) */
1325 		s1394_block_on_asynch_cmd(cmd);
1326 
1327 		TNF_PROBE_0_DEBUG(t1394_write_exit, S1394_TNF_SL_ATREQ_STACK,
1328 		    "");
1329 		return (DDI_SUCCESS);
1330 	}
1331 	mutex_exit(&hal->topology_tree_mutex);
1332 
1333 	/* Send the command out */
1334 	ret = s1394_xfer_asynch_command(hal, cmd, &err);
1335 
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);
1341 
1342 			/* Block (if necessary) */
1343 			s1394_block_on_asynch_cmd(cmd);
1344 
1345 			TNF_PROBE_0_DEBUG(s1394_compare_swap_exit,
1346 			    S1394_TNF_SL_ATREQ_STACK, "");
1347 			return (DDI_SUCCESS);
1348 
1349 		} else {
1350 			/* Remove cmd from outstanding request Q */
1351 			s1394_remove_q_asynch_cmd(hal, cmd);
1352 
1353 			s_priv->cmd_in_use = B_FALSE;
1354 
1355 			/* Copy error code into result */
1356 			cmd->cmd_result = err;
1357 
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);
1363 		}
1364 	} else {
1365 		/* Block (if necessary) */
1366 		s1394_block_on_asynch_cmd(cmd);
1367 
1368 		TNF_PROBE_0_DEBUG(s1394_compare_swap_exit,
1369 		    S1394_TNF_SL_ATREQ_STACK, "");
1370 		return (DDI_SUCCESS);
1371 	}
1372 }
1373 
1374 /*
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.
1380  */
1381 int
s1394_split_lock_req(s1394_hal_t * hal,s1394_target_t * target,cmd1394_cmd_t * cmd)1382 s1394_split_lock_req(s1394_hal_t *hal, s1394_target_t *target,
1383     cmd1394_cmd_t *cmd)
1384 {
1385 	s1394_cmd_priv_t *s_priv;
1386 	cmd1394_cmd_t	 *tmp_cmd;
1387 
1388 	TNF_PROBE_0_DEBUG(s1394_split_lock_req_enter,
1389 	    S1394_TNF_SL_ATREQ_STACK, "");
1390 
1391 	/* Allocate a temporary command */
1392 	if (s1394_alloc_cmd(hal, T1394_ALLOC_CMD_NOSLEEP, &tmp_cmd) !=
1393 	    DDI_SUCCESS) {
1394 		cmd->cmd_result = CMD1394_EUNKNOWN_ERROR;
1395 
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);
1401 	}
1402 
1403 	/* Get the Services Layer private area */
1404 	s_priv = S1394_GET_CMD_PRIV(tmp_cmd);
1405 
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;
1412 
1413 	/* The temporary command can not block */
1414 	tmp_cmd->cmd_options = tmp_cmd->cmd_options & ~CMD1394_BLOCKING;
1415 
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;
1422 	} else {
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;
1427 	}
1428 
1429 	/* Initialize lock_req_step */
1430 	s_priv->lock_req_step = 0;
1431 
1432 	/* Get the Services Layer private area for the target cmd */
1433 	s_priv = S1394_GET_CMD_PRIV(cmd);
1434 
1435 	s_priv->cmd_in_use = B_TRUE;
1436 
1437 	/* Send the request */
1438 	if (s1394_compare_swap(hal, target, tmp_cmd) != DDI_SUCCESS) {
1439 		s_priv->cmd_in_use = B_FALSE;
1440 
1441 		/* Free the temporary command */
1442 		if (s1394_free_cmd(hal, &tmp_cmd) != DDI_SUCCESS)
1443 			cmd->cmd_result = CMD1394_EUNKNOWN_ERROR;
1444 
1445 		TNF_PROBE_0_DEBUG(s1394_split_lock_req_exit,
1446 		    S1394_TNF_SL_ATREQ_STACK, "");
1447 		return (DDI_FAILURE);
1448 	}
1449 
1450 	/* Block (if necessary) */
1451 	s1394_block_on_asynch_cmd(cmd);
1452 
1453 	TNF_PROBE_0_DEBUG(s1394_split_lock_req_exit,
1454 	    S1394_TNF_SL_ATREQ_STACK, "");
1455 	return (DDI_SUCCESS);
1456 }
1457 
1458 /*
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.
1464  */
1465 static void
s1394_handle_lock(cmd1394_cmd_t * cmd)1466 s1394_handle_lock(cmd1394_cmd_t *cmd)
1467 {
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;
1473 	int		 tcmd_result;
1474 	int		 ret;
1475 
1476 
1477 	TNF_PROBE_0_DEBUG(s1394_handle_lock_enter, S1394_TNF_SL_ATREQ_STACK,
1478 	    "");
1479 
1480 	/* Get the Services Layer private area */
1481 	s_priv = S1394_GET_CMD_PRIV(cmd);
1482 
1483 	lock_req_step = s_priv->lock_req_step;
1484 
1485 	/* Get the target's command */
1486 	target_cmd = (cmd1394_cmd_t *)cmd->cmd_callback_arg;
1487 
1488 	/* Get the destination of the command */
1489 	to_hal = s_priv->sent_on_hal;
1490 
1491 lock_req_step_0:
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);
1498 
1499 			if (ret != DDI_SUCCESS) {
1500 				tcmd_result = target_cmd->cmd_result;
1501 				goto lock_req_done;
1502 			}
1503 
1504 			s_priv->lock_req_step = 1;
1505 
1506 			target = s_priv->sent_by_target;
1507 
1508 			if (s1394_compare_swap(to_hal, target, cmd) !=
1509 			    DDI_SUCCESS) {
1510 				tcmd_result = cmd->cmd_result;
1511 				goto lock_req_done;
1512 			} else {
1513 				TNF_PROBE_0_DEBUG(s1394_handle_lock_exit,
1514 				    S1394_TNF_SL_ATREQ_STACK, "");
1515 				return;
1516 			}
1517 		} else {
1518 			/* Command failed for some reason */
1519 			tcmd_result = cmd->cmd_result;
1520 			goto lock_req_done;
1521 		}
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);
1527 
1528 			if (ret != DDI_SUCCESS) {
1529 				lock_req_step = 0;
1530 				goto lock_req_step_0;
1531 			} else {
1532 				tcmd_result = cmd->cmd_result;
1533 				goto lock_req_done;
1534 			}
1535 		} else {
1536 			/* Command failed for some reason */
1537 			tcmd_result = cmd->cmd_result;
1538 			goto lock_req_done;
1539 		}
1540 	}
1541 
1542 lock_req_done:
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, "");
1546 	}
1547 
1548 	/* Get the Services Layer private area */
1549 	s_priv = S1394_GET_CMD_PRIV(target_cmd);
1550 
1551 	s_priv->cmd_in_use = B_FALSE;
1552 
1553 	target_cmd->cmd_result = tcmd_result;
1554 
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);
1562 
1563 		TNF_PROBE_0_DEBUG(s1394_handle_lock_exit,
1564 		    S1394_TNF_SL_ATREQ_STACK, "");
1565 		return;
1566 	}
1567 
1568 	/* Call the target's completion_callback() */
1569 	if (target_cmd->completion_callback != NULL)
1570 		target_cmd->completion_callback(target_cmd);
1571 
1572 	TNF_PROBE_0_DEBUG(s1394_handle_lock_exit,
1573 	    S1394_TNF_SL_ATREQ_STACK, "");
1574 }
1575 
1576 /*
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.
1582  */
1583 void
s1394_pending_q_insert(s1394_hal_t * hal,cmd1394_cmd_t * cmd,uint_t flags)1584 s1394_pending_q_insert(s1394_hal_t *hal, cmd1394_cmd_t *cmd, uint_t flags)
1585 {
1586 	cmd1394_cmd_t *temp_cmd;
1587 	s1394_cmd_priv_t *s_priv;
1588 	s1394_cmd_priv_t *c_priv;
1589 
1590 	TNF_PROBE_0_DEBUG(s1394_pending_q_insert_enter,
1591 	    S1394_TNF_SL_ATREQ_STACK, "");
1592 
1593 	mutex_enter(&hal->pending_q_mutex);
1594 
1595 	/* Get the Services Layer private area */
1596 	s_priv = S1394_GET_CMD_PRIV(cmd);
1597 
1598 	/* Is the outstanding request queue empty? */
1599 	if ((hal->pending_q_head == NULL) && (hal->pending_q_tail == NULL)) {
1600 
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;
1605 
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;
1609 
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;
1614 
1615 		hal->pending_q_head = (cmd1394_cmd_t *)cmd;
1616 
1617 	} else {
1618 		s_priv->cmd_priv_prev = hal->pending_q_tail;
1619 		s_priv->cmd_priv_next = (cmd1394_cmd_t *)NULL;
1620 
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;
1625 
1626 		hal->pending_q_tail = (cmd1394_cmd_t *)cmd;
1627 	}
1628 
1629 	mutex_exit(&hal->pending_q_mutex);
1630 
1631 	/* kstats - number of pending Q insertions */
1632 	hal->hal_kstats->pending_q_insert++;
1633 
1634 	TNF_PROBE_0_DEBUG(s1394_pending_q_insert_exit,
1635 	    S1394_TNF_SL_ATREQ_STACK, "");
1636 }
1637 
1638 /*
1639  * s1394_pending_q_remove()
1640  *    is used to remove a command structure from a HAL's pending queue for
1641  *    processing.
1642  */
1643 static cmd1394_cmd_t *
s1394_pending_q_remove(s1394_hal_t * hal)1644 s1394_pending_q_remove(s1394_hal_t *hal)
1645 {
1646 	s1394_cmd_priv_t *s_priv;
1647 	s1394_cmd_priv_t *c_priv;
1648 	cmd1394_cmd_t	 *cmd;
1649 	cmd1394_cmd_t	 *prev_cmd;
1650 
1651 	TNF_PROBE_0_DEBUG(s1394_pending_q_remove_enter,
1652 	    S1394_TNF_SL_ATREQ_STACK, "");
1653 
1654 	mutex_enter(&hal->pending_q_mutex);
1655 
1656 	cmd = (cmd1394_cmd_t *)hal->pending_q_tail;
1657 	if (cmd == NULL) {
1658 		mutex_exit(&hal->pending_q_mutex);
1659 		TNF_PROBE_0_DEBUG(s1394_pending_q_remove_exit,
1660 		    S1394_TNF_SL_ATREQ_STACK, "");
1661 		return (NULL);
1662 	}
1663 
1664 	/* Get the Services Layer private area */
1665 	s_priv = S1394_GET_CMD_PRIV(cmd);
1666 
1667 	prev_cmd = (cmd1394_cmd_t *)s_priv->cmd_priv_prev;
1668 
1669 	s_priv->cmd_priv_prev = (cmd1394_cmd_t *)NULL;
1670 	s_priv->cmd_priv_next = (cmd1394_cmd_t *)NULL;
1671 
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;
1676 
1677 	} else {
1678 		hal->pending_q_head = (cmd1394_cmd_t *)NULL;
1679 	}
1680 	hal->pending_q_tail = (cmd1394_cmd_t *)prev_cmd;
1681 
1682 	mutex_exit(&hal->pending_q_mutex);
1683 
1684 	TNF_PROBE_0_DEBUG(s1394_pending_q_remove_exit,
1685 	    S1394_TNF_SL_ATREQ_STACK, "");
1686 	return (cmd);
1687 }
1688 
1689 /*
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.
1693  */
1694 void
s1394_resend_pending_cmds(s1394_hal_t * hal)1695 s1394_resend_pending_cmds(s1394_hal_t *hal)
1696 {
1697 	int done;
1698 
1699 	TNF_PROBE_0_DEBUG(s1394_resend_pending_cmds_enter,
1700 	    S1394_TNF_SL_BR_STACK, "");
1701 
1702 	ASSERT(MUTEX_NOT_HELD(&hal->topology_tree_mutex));
1703 
1704 	do {
1705 		done = s1394_process_pending_q(hal);
1706 	} while (done == B_FALSE);
1707 
1708 	ASSERT(MUTEX_NOT_HELD(&hal->topology_tree_mutex));
1709 
1710 	TNF_PROBE_0_DEBUG(s1394_resend_pending_cmds_exit,
1711 	    S1394_TNF_SL_BR_STACK, "");
1712 }
1713 
1714 /*
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.
1722  */
1723 static boolean_t
s1394_process_pending_q(s1394_hal_t * hal)1724 s1394_process_pending_q(s1394_hal_t *hal)
1725 {
1726 	s1394_cmd_priv_t *s_priv;
1727 	h1394_cmd_priv_t *h_priv;
1728 	s1394_target_t	 *target;
1729 	cmd1394_cmd_t	 *cmd;
1730 	uint64_t	 node;
1731 	uint32_t	 from_node;
1732 	uint32_t	 to_node;
1733 	uint_t		 current_max_payload;
1734 	int		 ret;
1735 
1736 	TNF_PROBE_0_DEBUG(s1394_process_pending_q_enter,
1737 	    S1394_TNF_SL_BR_STACK, "");
1738 
1739 	ASSERT(MUTEX_NOT_HELD(&hal->topology_tree_mutex));
1740 
1741 	/* Pull a command from the Pending Q */
1742 	cmd = s1394_pending_q_remove(hal);
1743 
1744 	if (cmd == NULL) {
1745 		TNF_PROBE_0_DEBUG(s1394_process_pending_q_exit,
1746 		    S1394_TNF_SL_BR_STACK, "");
1747 		return (B_TRUE);
1748 	}
1749 
1750 	/* Get the Services Layer private area */
1751 	s_priv = S1394_GET_CMD_PRIV(cmd);
1752 
1753 	/* Get a pointer to the HAL private struct */
1754 	h_priv = (h1394_cmd_priv_t *)&s_priv->hal_cmd_private;
1755 
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);
1760 			return (ret);
1761 		} else {
1762 
1763 			s_priv->cmd_in_use = B_FALSE;
1764 
1765 			cmd->cmd_result = CMD1394_EBUSRESET;
1766 
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);
1774 
1775 				TNF_PROBE_0_DEBUG(s1394_process_pending_q_exit,
1776 				    S1394_TNF_SL_BR_STACK, "");
1777 				return (B_FALSE);
1778 			}
1779 
1780 			/* Call the target's completion_callback() */
1781 			if (cmd->completion_callback != NULL) {
1782 				cmd->completion_callback(cmd);
1783 			}
1784 
1785 			TNF_PROBE_0_DEBUG(s1394_process_pending_q_exit,
1786 			    S1394_TNF_SL_BR_STACK, "");
1787 			return (B_FALSE);
1788 		}
1789 	} else {
1790 		if (h_priv->bus_generation == hal->generation_count) {
1791 			ret = s1394_pending_q_helper(hal, cmd);
1792 			return (ret);
1793 		} else {
1794 			/* Make sure we can get the topology_tree_mutex */
1795 			if (s1394_lock_tree(hal) != DDI_SUCCESS)
1796 				return (B_TRUE);
1797 
1798 			/* Set the generation */
1799 			cmd->bus_generation = hal->generation_count;
1800 
1801 			/* Copy the generation into the HAL's private field */
1802 			h_priv->bus_generation = cmd->bus_generation;
1803 
1804 			target = s_priv->sent_by_target;
1805 
1806 			/* If not OVERRIDE_ADDR, then target may not be NULL */
1807 			ASSERT(target != NULL);
1808 
1809 			rw_enter(&hal->target_list_rwlock, RW_READER);
1810 
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);
1815 			} else {
1816 				rw_exit(&hal->target_list_rwlock);
1817 
1818 				s_priv->cmd_in_use = B_FALSE;
1819 
1820 				cmd->cmd_result = CMD1394_EDEVICE_REMOVED;
1821 
1822 				/* Is this a blocking command? */
1823 				if (cmd->cmd_options & CMD1394_BLOCKING) {
1824 					s1394_unlock_tree(hal);
1825 
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);
1831 
1832 					TNF_PROBE_0_DEBUG(
1833 					    s1394_process_pending_q_exit,
1834 					    S1394_TNF_SL_BR_STACK,
1835 					    "");
1836 					return (B_FALSE);
1837 				}
1838 
1839 				/* Call the target's completion_callback() */
1840 				if (cmd->completion_callback != NULL) {
1841 					s1394_unlock_tree(hal);
1842 					cmd->completion_callback(cmd);
1843 					TNF_PROBE_0_DEBUG(
1844 					    s1394_process_pending_q_exit,
1845 					    S1394_TNF_SL_BR_STACK, "");
1846 					return (B_FALSE);
1847 				} else {
1848 					s1394_unlock_tree(hal);
1849 					TNF_PROBE_0_DEBUG(
1850 					    s1394_process_pending_q_exit,
1851 					    S1394_TNF_SL_BR_STACK, "");
1852 					return (B_FALSE);
1853 				}
1854 			}
1855 
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;
1863 
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;
1867 
1868 			/* Fill in the nodeID */
1869 			cmd->nodeID =
1870 			    (cmd->cmd_addr & IEEE1394_ADDR_NODE_ID_MASK) >>
1871 				IEEE1394_ADDR_NODE_ID_SHIFT;
1872 
1873 			if (cmd->cmd_options & CMD1394_OVERRIDE_SPEED) {
1874 				s_priv->hal_cmd_private.speed =
1875 				    (int)cmd->cmd_speed;
1876 			} else {
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,
1880 				    to_node);
1881 			}
1882 
1883 			/* Is it a block request? */
1884 			if ((cmd->cmd_type == CMD1394_ASYNCH_RD_BLOCK) ||
1885 			    (cmd->cmd_type == CMD1394_ASYNCH_WR_BLOCK)) {
1886 
1887 				/* Get a pointer to the HAL private struct */
1888 				h_priv = (h1394_cmd_priv_t *)&s_priv->
1889 				    hal_cmd_private;
1890 
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;
1896 				} else {
1897 					current_max_payload = 4;
1898 				}
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;
1905 				}
1906 				if (s_priv->data_remaining <
1907 				    current_max_payload) {
1908 					h_priv->mblk.length =
1909 					    s_priv->data_remaining;
1910 				} else {
1911 					h_priv->mblk.length =
1912 					    current_max_payload;
1913 				}
1914 			}
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, "");
1919 			return (ret);
1920 		}
1921 	}
1922 }
1923 
1924 /*
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.
1928  */
1929 static boolean_t
s1394_pending_q_helper(s1394_hal_t * hal,cmd1394_cmd_t * cmd)1930 s1394_pending_q_helper(s1394_hal_t *hal, cmd1394_cmd_t *cmd)
1931 {
1932 	s1394_cmd_priv_t *s_priv;
1933 	int		 err;
1934 	int		 ret;
1935 
1936 	TNF_PROBE_0_DEBUG(s1394_pending_q_helper_enter,
1937 	    S1394_TNF_SL_BR_STACK, "");
1938 
1939 	ASSERT(MUTEX_NOT_HELD(&hal->topology_tree_mutex));
1940 
1941 	/* Get the Services Layer private area */
1942 	s_priv = S1394_GET_CMD_PRIV(cmd);
1943 
1944 	/* Put cmd on outstanding request Q */
1945 	s1394_insert_q_asynch_cmd(hal, cmd);
1946 
1947 	/* Send command out again */
1948 	ret = s1394_xfer_asynch_command(hal, cmd, &err);
1949 
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);
1955 
1956 			TNF_PROBE_0_DEBUG(s1394_pending_q_helper_exit,
1957 			    S1394_TNF_SL_BR_STACK, "");
1958 			return (B_TRUE);
1959 		} else {
1960 			/* Remove cmd from outstanding request Q */
1961 			s1394_remove_q_asynch_cmd(hal, cmd);
1962 
1963 			s_priv->cmd_in_use = B_FALSE;
1964 
1965 			cmd->cmd_result = err;
1966 
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);
1974 
1975 				TNF_PROBE_0_DEBUG(s1394_pending_q_helper_exit,
1976 				    S1394_TNF_SL_BR_STACK, "");
1977 				return (B_FALSE);
1978 			}
1979 
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, "");
1985 				return (B_FALSE);
1986 			} else {
1987 				TNF_PROBE_0_DEBUG(s1394_pending_q_helper_exit,
1988 				    S1394_TNF_SL_BR_STACK, "");
1989 				return (B_FALSE);
1990 			}
1991 		}
1992 	}
1993 
1994 	TNF_PROBE_0_DEBUG(s1394_pending_q_helper_exit,
1995 	    S1394_TNF_SL_BR_STACK, "");
1996 	return (B_FALSE);
1997 }
1998 
1999 /*
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
2003  *    request.
2004  */
2005 static int
s1394_process_split_lock(cmd1394_cmd_t * cmd,cmd1394_cmd_t * target_cmd)2006 s1394_process_split_lock(cmd1394_cmd_t *cmd, cmd1394_cmd_t *target_cmd)
2007 {
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;
2018 
2019 	TNF_PROBE_0_DEBUG(s1394_process_split_lock_enter,
2020 	    S1394_TNF_SL_ATREQ_STACK, "");
2021 
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;
2026 
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;
2031 			break;
2032 
2033 		case CMD1394_LOCK_BIT_OR:
2034 			new_value32 = old_value32 | data_value32;
2035 			break;
2036 
2037 		case CMD1394_LOCK_BIT_XOR:
2038 			new_value32 = old_value32 ^ data_value32;
2039 			break;
2040 
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);
2046 			break;
2047 
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);
2053 			break;
2054 
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);
2060 			break;
2061 
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);
2067 			break;
2068 
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);
2076 			} else {
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;
2081 				TNF_PROBE_0_DEBUG(
2082 				    s1394_process_split_lock_exit,
2083 				    S1394_TNF_SL_ATREQ_STACK, "");
2084 				return (DDI_FAILURE);
2085 			}
2086 			break;
2087 
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);
2095 			} else {
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;
2100 				TNF_PROBE_0_DEBUG(
2101 				    s1394_process_split_lock_exit,
2102 				    S1394_TNF_SL_ATREQ_STACK, "");
2103 				return (DDI_FAILURE);
2104 			}
2105 			break;
2106 
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);
2113 			else
2114 				new_value32 = T1394_DATA32(temp_value32);
2115 			old_value32 = T1394_DATA32(old_value32);
2116 			break;
2117 
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);
2124 			else
2125 				new_value32 = T1394_DATA32(temp_value32);
2126 			old_value32 = T1394_DATA32(old_value32);
2127 			break;
2128 		}
2129 
2130 		/* Send compare-swap lock request */
2131 		cmd->cmd_u.l32.arg_value  = old_value32;
2132 		cmd->cmd_u.l32.data_value = new_value32;
2133 	} else {
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;
2137 
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;
2142 			break;
2143 
2144 		case CMD1394_LOCK_BIT_OR:
2145 			new_value64 = old_value64 | data_value64;
2146 			break;
2147 
2148 		case CMD1394_LOCK_BIT_XOR:
2149 			new_value64 = old_value64 ^ data_value64;
2150 			break;
2151 
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);
2157 			break;
2158 
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);
2164 			break;
2165 
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);
2171 			break;
2172 
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);
2178 			break;
2179 
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);
2187 			} else {
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;
2192 				TNF_PROBE_0_DEBUG(
2193 				    s1394_process_split_lock_exit,
2194 				    S1394_TNF_SL_ATREQ_STACK, "");
2195 				return (DDI_FAILURE);
2196 			}
2197 			break;
2198 
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);
2206 			} else {
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;
2211 				TNF_PROBE_0_DEBUG(
2212 				    s1394_process_split_lock_exit,
2213 				    S1394_TNF_SL_ATREQ_STACK, "");
2214 				return (DDI_FAILURE);
2215 			}
2216 			break;
2217 
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);
2224 			else
2225 				new_value64 = T1394_DATA64(temp_value64);
2226 			old_value64 = T1394_DATA64(old_value64);
2227 			break;
2228 
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);
2235 			else
2236 				new_value64 = T1394_DATA64(temp_value64);
2237 			old_value64 = T1394_DATA64(old_value64);
2238 			break;
2239 		}
2240 
2241 		/* Send compare-swap lock request */
2242 		cmd->cmd_u.l64.arg_value  = old_value64;
2243 		cmd->cmd_u.l64.data_value = new_value64;
2244 	}
2245 
2246 	TNF_PROBE_0_DEBUG(s1394_process_split_lock_exit,
2247 	    S1394_TNF_SL_ATREQ_STACK, "");
2248 	return (DDI_SUCCESS);
2249 }
2250 
2251 /*
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.
2255  */
2256 static int
s1394_finish_split_lock(cmd1394_cmd_t * cmd,cmd1394_cmd_t * target_cmd)2257 s1394_finish_split_lock(cmd1394_cmd_t *cmd, cmd1394_cmd_t *target_cmd)
2258 {
2259 	s1394_cmd_priv_t *s_priv;
2260 	uint64_t	 tmp_value64;
2261 	uint32_t	 tmp_value32;
2262 
2263 	TNF_PROBE_0_DEBUG(s1394_finish_split_lock_enter,
2264 	    S1394_TNF_SL_ATREQ_STACK, "");
2265 
2266 	/* Get the Services Layer private area */
2267 	s_priv = S1394_GET_CMD_PRIV(cmd);
2268 
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))) {
2273 
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;
2287 				break;
2288 			default:
2289 				tmp_value32 = cmd->cmd_u.l32.old_value;
2290 				target_cmd->cmd_u.l32.old_value = tmp_value32;
2291 				break;
2292 			}
2293 		} else {
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;
2306 				break;
2307 			default:
2308 				tmp_value64 = cmd->cmd_u.l64.old_value;
2309 				target_cmd->cmd_u.l64.old_value = tmp_value64;
2310 				break;
2311 			}
2312 		}
2313 		/* Set status */
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);
2318 	} else {
2319 		if (s_priv->temp_num_retries > 0) {
2320 			/* Decrement retry count */
2321 			s_priv->temp_num_retries--;
2322 
2323 			/* Reset lock_req_step */
2324 			s_priv->lock_req_step = 0;
2325 
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);
2332 		} else {
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);
2338 		}
2339 	}
2340 }
2341