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 /* 27 * s1394_asynch.c 28 * 1394 Services Layer Asynchronous Communications Routines 29 * These routines handle all of the tasks relating to asynch commands 30 */ 31 32 #include <sys/conf.h> 33 #include <sys/ddi.h> 34 #include <sys/sunddi.h> 35 #include <sys/cmn_err.h> 36 #include <sys/types.h> 37 #include <sys/kmem.h> 38 #include <sys/disp.h> 39 #include <sys/1394/t1394.h> 40 #include <sys/1394/s1394.h> 41 #include <sys/1394/h1394.h> 42 #include <sys/1394/ieee1394.h> 43 #include <sys/1394/ieee1212.h> 44 45 static void s1394_handle_lock(cmd1394_cmd_t *cmd); 46 47 static cmd1394_cmd_t *s1394_pending_q_remove(s1394_hal_t *hal); 48 49 static boolean_t s1394_process_pending_q(s1394_hal_t *hal); 50 51 static boolean_t s1394_pending_q_helper(s1394_hal_t *hal, cmd1394_cmd_t *cmd); 52 53 static int s1394_process_split_lock(cmd1394_cmd_t *cmd, 54 cmd1394_cmd_t *target_cmd); 55 56 static int s1394_finish_split_lock(cmd1394_cmd_t *cmd, 57 cmd1394_cmd_t *target_cmd); 58 59 /* 60 * s1394_alloc_cmd() 61 * is used to allocate a command for a target or for a HAL. 62 */ 63 int 64 s1394_alloc_cmd(s1394_hal_t *hal, uint_t flags, cmd1394_cmd_t **cmdp) 65 { 66 s1394_cmd_priv_t *s_priv; 67 void *hal_overhead; 68 uint_t cmd_size; 69 int alloc_sleep; 70 71 alloc_sleep = (flags & T1394_ALLOC_CMD_NOSLEEP) ? KM_NOSLEEP : KM_SLEEP; 72 73 if ((alloc_sleep == KM_SLEEP) && 74 (servicing_interrupt())) { 75 ASSERT(alloc_sleep != KM_SLEEP); /* fail */ 76 return (DDI_FAILURE); 77 } 78 79 /* either FCP command or response, but not both */ 80 if ((flags & 81 (T1394_ALLOC_CMD_FCP_COMMAND | T1394_ALLOC_CMD_FCP_RESPONSE)) == 82 (T1394_ALLOC_CMD_FCP_COMMAND | T1394_ALLOC_CMD_FCP_RESPONSE)) { 83 return (DDI_FAILURE); 84 } 85 86 *cmdp = kmem_cache_alloc(hal->hal_kmem_cachep, alloc_sleep); 87 if (*cmdp == NULL) { 88 return (DDI_FAILURE); 89 } 90 cmd_size = sizeof (cmd1394_cmd_t) + 91 sizeof (s1394_cmd_priv_t) + hal->halinfo.hal_overhead; 92 bzero((void *)*cmdp, cmd_size); 93 94 (*cmdp)->cmd_version = T1394_VERSION_V1; 95 (*cmdp)->cmd_result = CMD1394_NOSTATUS; 96 97 /* Get the Services Layer private area */ 98 s_priv = S1394_GET_CMD_PRIV(*cmdp); 99 100 /* Set extension type */ 101 if (flags & T1394_ALLOC_CMD_FCP_COMMAND) { 102 s1394_fa_init_cmd(s_priv, S1394_FA_TYPE_FCP_CTL); 103 } else if (flags & T1394_ALLOC_CMD_FCP_RESPONSE) { 104 s1394_fa_init_cmd(s_priv, S1394_FA_TYPE_FCP_TGT); 105 } 106 107 /* Set up the hal_overhead ptr in the hal_cmd_private */ 108 hal_overhead = (uchar_t *)s_priv + sizeof (s1394_cmd_priv_t); 109 s_priv->hal_cmd_private.hal_overhead = (void *)hal_overhead; 110 111 /* kstats - number of cmd allocs */ 112 hal->hal_kstats->cmd_alloc++; 113 114 return (DDI_SUCCESS); 115 } 116 117 /* 118 * s1394_free_cmd() 119 * is used to free a command that had been previously allocated by 120 * s1394_alloc_cmd(). 121 */ 122 int 123 s1394_free_cmd(s1394_hal_t *hal, cmd1394_cmd_t **cmdp) 124 { 125 s1394_cmd_priv_t *s_priv; 126 127 /* Get the Services Layer private area */ 128 s_priv = S1394_GET_CMD_PRIV(*cmdp); 129 130 /* Check that command isn't in use */ 131 if (s_priv->cmd_in_use == B_TRUE) { 132 ASSERT(s_priv->cmd_in_use == B_FALSE); 133 return (DDI_FAILURE); 134 } 135 136 /* kstats - number of cmd allocs */ 137 kmem_cache_free(hal->hal_kmem_cachep, *cmdp); 138 139 /* Command pointer is set to NULL before returning */ 140 *cmdp = NULL; 141 142 /* kstats - number of cmd frees */ 143 hal->hal_kstats->cmd_free++; 144 145 return (DDI_SUCCESS); 146 } 147 148 /* 149 * s1394_xfer_asynch_command() 150 * is used to send an asynch command down to the HAL. Based upon the type 151 * of command that is being sent, the appropriate HAL function is called. 152 * Command failures are handled be returning an error and/or shutting down 153 * the HAL, depending on the severity of the error. 154 */ 155 int 156 s1394_xfer_asynch_command(s1394_hal_t *hal, cmd1394_cmd_t *cmd, int *err) 157 { 158 s1394_cmd_priv_t *s_priv; 159 h1394_cmd_priv_t *h_priv; 160 s1394_hal_state_t state; 161 dev_info_t *dip; 162 int result_from_hal; 163 int ret; 164 165 ASSERT(MUTEX_NOT_HELD(&hal->topology_tree_mutex)); 166 167 mutex_enter(&hal->topology_tree_mutex); 168 state = hal->hal_state; 169 if (((state != S1394_HAL_NORMAL) && (state != S1394_HAL_RESET)) || 170 (hal->disable_requests_bit == 1)) { 171 *err = s1394_HAL_asynch_error(hal, cmd, state); 172 mutex_exit(&hal->topology_tree_mutex); 173 return (DDI_FAILURE); 174 } 175 mutex_exit(&hal->topology_tree_mutex); 176 177 /* Get the Services Layer private area */ 178 s_priv = S1394_GET_CMD_PRIV(cmd); 179 180 /* Get a pointer to the HAL private struct */ 181 h_priv = (h1394_cmd_priv_t *)&s_priv->hal_cmd_private; 182 183 /* kstats - number of AT requests sent */ 184 switch (cmd->cmd_type) { 185 case CMD1394_ASYNCH_RD_QUAD: 186 hal->hal_kstats->atreq_quad_rd++; 187 break; 188 189 case CMD1394_ASYNCH_RD_BLOCK: 190 hal->hal_kstats->atreq_blk_rd++; 191 break; 192 193 case CMD1394_ASYNCH_WR_QUAD: 194 hal->hal_kstats->atreq_quad_wr++; 195 break; 196 197 case CMD1394_ASYNCH_WR_BLOCK: 198 hal->hal_kstats->atreq_blk_wr++; 199 hal->hal_kstats->atreq_blk_wr_size += h_priv->mblk.length; 200 break; 201 202 case CMD1394_ASYNCH_LOCK_32: 203 hal->hal_kstats->atreq_lock32++; 204 break; 205 206 case CMD1394_ASYNCH_LOCK_64: 207 hal->hal_kstats->atreq_lock64++; 208 break; 209 } 210 211 switch (s_priv->cmd_priv_xfer_type) { 212 /* Call the HAL's read entry point */ 213 case S1394_CMD_READ: 214 ret = HAL_CALL(hal).read(hal->halinfo.hal_private, 215 (cmd1394_cmd_t *)cmd, 216 (h1394_cmd_priv_t *)&s_priv->hal_cmd_private, 217 &result_from_hal); 218 break; 219 220 /* Call the HAL's write entry point */ 221 case S1394_CMD_WRITE: 222 ret = HAL_CALL(hal).write(hal->halinfo.hal_private, 223 (cmd1394_cmd_t *)cmd, 224 (h1394_cmd_priv_t *)&s_priv->hal_cmd_private, 225 &result_from_hal); 226 break; 227 228 /* Call the HAL's lock entry point */ 229 case S1394_CMD_LOCK: 230 ret = HAL_CALL(hal).lock(hal->halinfo.hal_private, 231 (cmd1394_cmd_t *)cmd, 232 (h1394_cmd_priv_t *)&s_priv->hal_cmd_private, 233 &result_from_hal); 234 break; 235 236 default: 237 *err = CMD1394_EUNKNOWN_ERROR; 238 239 return (DDI_FAILURE); 240 } 241 242 if (ret == DDI_FAILURE) { 243 switch (result_from_hal) { 244 case H1394_STATUS_EMPTY_TLABEL: 245 /* Out of TLABELs - Unable to send AT req */ 246 *err = CMD1394_ENO_ATREQ; 247 break; 248 249 case H1394_STATUS_INVALID_BUSGEN: 250 /* Out of TLABELs - Unable to send AT req */ 251 *err = CMD1394_ESTALE_GENERATION; 252 break; 253 254 case H1394_STATUS_NOMORE_SPACE: 255 /* No more space on HAL's HW queue */ 256 *err = CMD1394_ENO_ATREQ; 257 break; 258 259 case H1394_STATUS_INTERNAL_ERROR: 260 dip = hal->halinfo.dip; 261 262 /* An unexpected error in the HAL */ 263 cmn_err(CE_WARN, HALT_ERROR_MESSAGE, 264 ddi_node_name(dip), ddi_get_instance(dip)); 265 266 /* Disable the HAL */ 267 s1394_hal_shutdown(hal, B_TRUE); 268 269 *err = CMD1394_EFATAL_ERROR; 270 break; 271 272 default: 273 dip = hal->halinfo.dip; 274 275 /* An unexpected error in the HAL */ 276 cmn_err(CE_WARN, HALT_ERROR_MESSAGE, 277 ddi_node_name(dip), ddi_get_instance(dip)); 278 279 /* Disable the HAL */ 280 s1394_hal_shutdown(hal, B_TRUE); 281 282 *err = CMD1394_EFATAL_ERROR; 283 break; 284 } 285 286 return (DDI_FAILURE); 287 } 288 289 /* No errors, return success */ 290 *err = CMD1394_NOSTATUS; 291 292 return (DDI_SUCCESS); 293 } 294 295 /* 296 * s1394_setup_asynch_command() 297 * is used to setup an asynch command to be sent down to the HAL and out 298 * onto the bus. This function handles setting up the destination address 299 * (if necessary), speed, max_payload, putting the command onto the 300 * outstanding Q list, and any other things that must be done prior to 301 * calling the HAL. 302 */ 303 int 304 s1394_setup_asynch_command(s1394_hal_t *hal, s1394_target_t *target, 305 cmd1394_cmd_t *cmd, uint32_t xfer_type, int *err) 306 { 307 s1394_cmd_priv_t *s_priv; 308 h1394_cmd_priv_t *h_priv; 309 uint64_t node; 310 uint32_t from_node; 311 uint32_t to_node; 312 uint32_t bus_capabilities; 313 uint_t current_max_payload; 314 uint_t max_rec; 315 uint_t max_blk; 316 317 ASSERT(MUTEX_HELD(&hal->topology_tree_mutex)); 318 319 switch (cmd->cmd_type) { 320 case CMD1394_ASYNCH_RD_QUAD: 321 case CMD1394_ASYNCH_WR_QUAD: 322 case CMD1394_ASYNCH_RD_BLOCK: 323 case CMD1394_ASYNCH_WR_BLOCK: 324 case CMD1394_ASYNCH_LOCK_32: 325 case CMD1394_ASYNCH_LOCK_64: 326 break; 327 328 default: 329 *err = CMD1394_EINVALID_COMMAND; 330 return (DDI_FAILURE); 331 } 332 333 /* Check for potential address roll-over */ 334 if (s1394_address_rollover(cmd) != B_FALSE) { 335 *err = CMD1394_EADDRESS_ERROR; 336 return (DDI_FAILURE); 337 } 338 339 /* Get the Services Layer private area */ 340 s_priv = S1394_GET_CMD_PRIV(cmd); 341 342 /* Set up who sent command on which hal */ 343 s_priv->sent_by_target = (s1394_target_t *)target; 344 s_priv->sent_on_hal = (s1394_hal_t *)hal; 345 346 /* Set up command transfer type */ 347 s_priv->cmd_priv_xfer_type = xfer_type; 348 349 if (cmd->cmd_options & CMD1394_OVERRIDE_ADDR) { 350 /* Compare the current generation from the HAL struct */ 351 /* to the one given by the target */ 352 353 /* Speed is to be filled in from speed map */ 354 from_node = IEEE1394_NODE_NUM(hal->node_id); 355 to_node = IEEE1394_ADDR_PHY_ID(cmd->cmd_addr); 356 357 if (cmd->bus_generation != hal->generation_count) { 358 *err = CMD1394_ESTALE_GENERATION; 359 return (DDI_FAILURE); 360 } 361 362 } else { 363 /* Set the generation */ 364 cmd->bus_generation = hal->generation_count; 365 366 /* If not OVERRIDE_ADDR, then target may not be NULL */ 367 ASSERT(target != NULL); 368 369 rw_enter(&hal->target_list_rwlock, RW_READER); 370 371 if ((target->target_state & S1394_TARG_GONE) != 0 || 372 target->on_node == NULL) { 373 rw_exit(&hal->target_list_rwlock); 374 *err = CMD1394_EDEVICE_REMOVED; 375 return (DDI_FAILURE); 376 } 377 378 ASSERT((target->target_state & S1394_TARG_GONE) == 0); 379 node = target->on_node->node_num; 380 rw_exit(&hal->target_list_rwlock); 381 382 /* Mask in the top 16-bits */ 383 cmd->cmd_addr = (cmd->cmd_addr & IEEE1394_ADDR_OFFSET_MASK); 384 cmd->cmd_addr = (cmd->cmd_addr | 385 (node << IEEE1394_ADDR_PHY_ID_SHIFT)); 386 cmd->cmd_addr = (cmd->cmd_addr | IEEE1394_ADDR_BUS_ID_MASK); 387 388 /* Speed is to be filled in from speed map */ 389 from_node = IEEE1394_NODE_NUM(hal->node_id); 390 to_node = (uint32_t)node; 391 } 392 393 /* Get a pointer to the HAL private struct */ 394 h_priv = (h1394_cmd_priv_t *)&s_priv->hal_cmd_private; 395 396 /* Copy the generation into the HAL's private field */ 397 h_priv->bus_generation = cmd->bus_generation; 398 399 /* Fill in the nodeID */ 400 cmd->nodeID = (cmd->cmd_addr & IEEE1394_ADDR_NODE_ID_MASK) >> 401 IEEE1394_ADDR_NODE_ID_SHIFT; 402 403 if (cmd->cmd_options & CMD1394_OVERRIDE_SPEED) { 404 if (cmd->cmd_speed > IEEE1394_S400) { 405 *err = CMD1394_EINVALID_COMMAND; 406 return (DDI_FAILURE); 407 408 } else { 409 s_priv->hal_cmd_private.speed = (int)cmd->cmd_speed; 410 } 411 412 } else { 413 /* Speed is to be filled in from speed map */ 414 s_priv->hal_cmd_private.speed = (int)s1394_speed_map_get(hal, 415 from_node, to_node); 416 } 417 418 /* Is it a block request? */ 419 if ((cmd->cmd_type == CMD1394_ASYNCH_RD_BLOCK) || 420 (cmd->cmd_type == CMD1394_ASYNCH_WR_BLOCK)) { 421 422 if (cmd->cmd_u.b.data_block == NULL) { 423 *err = CMD1394_ENULL_MBLK; 424 return (DDI_FAILURE); 425 } 426 427 /* Also need to check for MBLK_TOO_SMALL */ 428 if (s1394_mblk_too_small(cmd) != B_FALSE) { 429 *err = CMD1394_EMBLK_TOO_SMALL; 430 return (DDI_FAILURE); 431 } 432 433 /* Initialize bytes_transferred to zero */ 434 cmd->cmd_u.b.bytes_transferred = 0; 435 436 /* Handle the MAX_PAYLOAD size */ 437 if (cmd->cmd_options & CMD1394_OVERRIDE_ADDR) { 438 439 current_max_payload = 512 << 440 (s_priv->hal_cmd_private.speed); 441 if (hal->topology_tree[to_node].cfgrom) { 442 bus_capabilities = 443 hal->topology_tree[to_node].cfgrom[ 444 IEEE1212_NODE_CAP_QUAD]; 445 max_rec = (bus_capabilities & 446 IEEE1394_BIB_MAXREC_MASK) >> 447 IEEE1394_BIB_MAXREC_SHIFT; 448 } else { 449 max_rec = 0; 450 } 451 452 if ((max_rec > 0) && (max_rec < 14)) { 453 max_blk = 1 << (max_rec + 1); 454 455 } else { 456 /* These are either unspecified or reserved */ 457 max_blk = 4; 458 } 459 if (max_blk < current_max_payload) 460 current_max_payload = max_blk; 461 462 } else { 463 rw_enter(&hal->target_list_rwlock, RW_READER); 464 current_max_payload = target->current_max_payload; 465 rw_exit(&hal->target_list_rwlock); 466 } 467 468 if (cmd->cmd_options & CMD1394_OVERRIDE_MAX_PAYLOAD) { 469 if (current_max_payload > cmd->cmd_u.b.max_payload) 470 current_max_payload = cmd->cmd_u.b.max_payload; 471 } 472 473 h_priv->mblk.curr_mblk = cmd->cmd_u.b.data_block; 474 475 if (cmd->cmd_type == CMD1394_ASYNCH_WR_BLOCK) { 476 h_priv->mblk.curr_offset = 477 cmd->cmd_u.b.data_block->b_rptr; 478 } else { 479 h_priv->mblk.curr_offset = 480 cmd->cmd_u.b.data_block->b_wptr; 481 } 482 483 if (cmd->cmd_u.b.blk_length > current_max_payload) { 484 h_priv->mblk.length = current_max_payload; 485 s_priv->data_remaining = cmd->cmd_u.b.blk_length; 486 487 } else { 488 h_priv->mblk.length = cmd->cmd_u.b.blk_length; 489 s_priv->data_remaining = cmd->cmd_u.b.blk_length; 490 } 491 } 492 493 /* Mark command as being used */ 494 s_priv->cmd_in_use = B_TRUE; 495 496 /* Put command on the HAL's outstanding request Q */ 497 s1394_insert_q_asynch_cmd(hal, cmd); 498 499 return (DDI_SUCCESS); 500 } 501 502 /* 503 * s1394_insert_q_asynch_cmd() 504 * is used to insert a given command structure onto a HAL's outstanding 505 * asynch queue. 506 */ 507 void 508 s1394_insert_q_asynch_cmd(s1394_hal_t *hal, cmd1394_cmd_t *cmd) 509 { 510 s1394_cmd_priv_t *s_priv; 511 s1394_cmd_priv_t *c_priv; 512 cmd1394_cmd_t *temp_cmd; 513 514 mutex_enter(&hal->outstanding_q_mutex); 515 516 /* Get the Services Layer private area */ 517 s_priv = S1394_GET_CMD_PRIV(cmd); 518 519 /* Is the outstanding request queue empty? */ 520 if ((hal->outstanding_q_head == NULL) && 521 (hal->outstanding_q_tail == NULL)) { 522 523 hal->outstanding_q_head = (cmd1394_cmd_t *)cmd; 524 hal->outstanding_q_tail = (cmd1394_cmd_t *)cmd; 525 s_priv->cmd_priv_next = (cmd1394_cmd_t *)NULL; 526 s_priv->cmd_priv_prev = (cmd1394_cmd_t *)NULL; 527 528 } else { 529 s_priv->cmd_priv_next = hal->outstanding_q_head; 530 s_priv->cmd_priv_prev = (cmd1394_cmd_t *)NULL; 531 532 temp_cmd = (cmd1394_cmd_t *)hal->outstanding_q_head; 533 c_priv = (s1394_cmd_priv_t *)((uchar_t *)temp_cmd + 534 sizeof (cmd1394_cmd_t)); 535 c_priv->cmd_priv_prev = (cmd1394_cmd_t *)cmd; 536 537 hal->outstanding_q_head = (cmd1394_cmd_t *)cmd; 538 } 539 540 mutex_exit(&hal->outstanding_q_mutex); 541 } 542 543 /* 544 * s1394_remove_q_asynch_cmd() 545 * is used to remove a given command structure from a HAL's outstanding 546 * asynch queue. 547 */ 548 void 549 s1394_remove_q_asynch_cmd(s1394_hal_t *hal, cmd1394_cmd_t *cmd) 550 { 551 s1394_cmd_priv_t *s_priv; 552 s1394_cmd_priv_t *c_priv; 553 cmd1394_cmd_t *prev_cmd; 554 cmd1394_cmd_t *next_cmd; 555 556 mutex_enter(&hal->outstanding_q_mutex); 557 558 /* Get the Services Layer private area */ 559 s_priv = S1394_GET_CMD_PRIV(cmd); 560 561 prev_cmd = (cmd1394_cmd_t *)s_priv->cmd_priv_prev; 562 next_cmd = (cmd1394_cmd_t *)s_priv->cmd_priv_next; 563 564 s_priv->cmd_priv_prev = (cmd1394_cmd_t *)NULL; 565 s_priv->cmd_priv_next = (cmd1394_cmd_t *)NULL; 566 567 if (prev_cmd != NULL) { 568 c_priv = (s1394_cmd_priv_t *)((uchar_t *)prev_cmd + 569 sizeof (cmd1394_cmd_t)); 570 c_priv->cmd_priv_next = (cmd1394_cmd_t *)next_cmd; 571 572 } else { 573 if (hal->outstanding_q_head == (cmd1394_cmd_t *)cmd) 574 hal->outstanding_q_head = (cmd1394_cmd_t *)next_cmd; 575 } 576 577 if (next_cmd != NULL) { 578 c_priv = (s1394_cmd_priv_t *)((uchar_t *)next_cmd + 579 sizeof (cmd1394_cmd_t)); 580 c_priv->cmd_priv_prev = (cmd1394_cmd_t *)prev_cmd; 581 582 } else { 583 if (hal->outstanding_q_tail == (cmd1394_cmd_t *)cmd) 584 hal->outstanding_q_tail = (cmd1394_cmd_t *)prev_cmd; 585 } 586 587 mutex_exit(&hal->outstanding_q_mutex); 588 } 589 590 /* 591 * s1394_atreq_cmd_complete() 592 * is called by h1394_cmd_is_complete() when an AT request has completed. 593 * Based upon a command's completion status, s1394_atreq_cmd_complete() 594 * determines whether to call the target (or unblock), put the command onto 595 * the pending Q to be sent out later, or to resend the command 596 * (multi-part command). 597 */ 598 void 599 s1394_atreq_cmd_complete(s1394_hal_t *hal, cmd1394_cmd_t *req, int status) 600 { 601 s1394_cmd_priv_t *s_priv; 602 h1394_cmd_priv_t *h_priv; 603 dev_info_t *dip; 604 int ret; 605 int cmd_result; 606 int err; 607 608 /* Get the Services Layer private area */ 609 s_priv = S1394_GET_CMD_PRIV(req); 610 611 /* If not an ack_complete... */ 612 if (status != H1394_CMD_SUCCESS) { 613 /* kstats - number of failure AT responses */ 614 switch (req->cmd_type) { 615 case CMD1394_ASYNCH_RD_QUAD: 616 hal->hal_kstats->atresp_quad_rd_fail++; 617 break; 618 619 case CMD1394_ASYNCH_RD_BLOCK: 620 hal->hal_kstats->atresp_blk_rd_fail++; 621 break; 622 623 case CMD1394_ASYNCH_WR_QUAD: 624 hal->hal_kstats->atresp_quad_wr_fail++; 625 break; 626 627 case CMD1394_ASYNCH_WR_BLOCK: 628 hal->hal_kstats->atresp_blk_wr_fail++; 629 break; 630 631 case CMD1394_ASYNCH_LOCK_32: 632 hal->hal_kstats->atresp_lock32_fail++; 633 break; 634 635 case CMD1394_ASYNCH_LOCK_64: 636 hal->hal_kstats->atresp_lock64_fail++; 637 break; 638 } 639 640 641 switch (status) { 642 /* evt_missing_ack */ 643 case H1394_CMD_ETIMEOUT: 644 cmd_result = CMD1394_ETIMEOUT; 645 break; 646 647 /* evt_flushed */ 648 case H1394_CMD_EBUSRESET: 649 /* Move request to pending Q if cancel on */ 650 /* reset is not set */ 651 if (req->cmd_options & CMD1394_CANCEL_ON_BUS_RESET) { 652 cmd_result = CMD1394_EBUSRESET; 653 break; 654 } 655 s1394_remove_q_asynch_cmd(hal, req); 656 s1394_pending_q_insert(hal, req, S1394_PENDING_Q_REAR); 657 return; 658 659 /* ack_busy_X */ 660 /* ack_busy_A */ 661 /* ack_busy_B */ 662 case H1394_CMD_EDEVICE_BUSY: 663 cmd_result = CMD1394_EDEVICE_BUSY; 664 break; 665 666 /* ack_data_error */ 667 case H1394_CMD_EDATA_ERROR: 668 cmd_result = CMD1394_EDATA_ERROR; 669 break; 670 671 /* ack_type_error */ 672 case H1394_CMD_ETYPE_ERROR: 673 cmd_result = CMD1394_ETYPE_ERROR; 674 break; 675 676 /* resp_address_error */ 677 /* ack_address_error */ 678 case H1394_CMD_EADDR_ERROR: 679 cmd_result = CMD1394_EADDRESS_ERROR; 680 break; 681 682 /* resp_conflict_error */ 683 /* ack_conflict_error */ 684 case H1394_CMD_ERSRC_CONFLICT: 685 cmd_result = CMD1394_ERSRC_CONFLICT; 686 break; 687 688 /* ack_tardy */ 689 case H1394_CMD_EDEVICE_POWERUP: 690 cmd_result = CMD1394_EDEVICE_BUSY; 691 break; 692 693 /* device errors (bad tcodes, ACKs, etc...) */ 694 case H1394_CMD_EDEVICE_ERROR: 695 cmd_result = CMD1394_EDEVICE_ERROR; 696 break; 697 698 /* Unknown error type */ 699 case H1394_CMD_EUNKNOWN_ERROR: 700 cmd_result = CMD1394_EUNKNOWN_ERROR; 701 break; 702 703 /* Unrecognized error */ 704 default: 705 dip = hal->halinfo.dip; 706 707 /* An unexpected error in the HAL */ 708 cmn_err(CE_WARN, HALT_ERROR_MESSAGE, 709 ddi_node_name(dip), ddi_get_instance(dip)); 710 711 /* Disable the HAL */ 712 s1394_hal_shutdown(hal, B_TRUE); 713 714 return; 715 } 716 717 /* Remove command from the HAL's outstanding request Q */ 718 s1394_remove_q_asynch_cmd(hal, req); 719 720 s_priv->cmd_in_use = B_FALSE; 721 722 req->cmd_result = cmd_result; 723 724 /* Is this a blocking command? */ 725 if (req->cmd_options & CMD1394_BLOCKING) { 726 /* Unblock the waiting command */ 727 mutex_enter(&s_priv->blocking_mutex); 728 s_priv->blocking_flag = B_TRUE; 729 cv_signal(&s_priv->blocking_cv); 730 mutex_exit(&s_priv->blocking_mutex); 731 732 return; 733 } 734 735 /* Call the target's completion_callback() */ 736 if (req->completion_callback != NULL) { 737 req->completion_callback(req); 738 } 739 740 return; 741 } 742 743 /* Successful unless otherwise modified */ 744 err = CMD1394_CMDSUCCESS; 745 746 if ((req->cmd_type == CMD1394_ASYNCH_RD_BLOCK) || 747 (req->cmd_type == CMD1394_ASYNCH_WR_BLOCK)) { 748 749 /* Get a pointer to the HAL private struct */ 750 h_priv = (h1394_cmd_priv_t *)&s_priv->hal_cmd_private; 751 752 /* Update data_remaining */ 753 s_priv->data_remaining -= h_priv->mblk.length; 754 755 /* Increment bytes_transferred */ 756 req->cmd_u.b.bytes_transferred += h_priv->mblk.length; 757 758 if (req->cmd_type == CMD1394_ASYNCH_RD_BLOCK) 759 hal->hal_kstats->atreq_blk_rd_size += 760 h_priv->mblk.length; 761 762 /* Is there still more to send? */ 763 if (s_priv->data_remaining > 0) { 764 765 /* Setup the new mblk and offset */ 766 h_priv->mblk.curr_mblk = h_priv->mblk.next_mblk; 767 h_priv->mblk.curr_offset = h_priv->mblk.next_offset; 768 769 /* Update destination address */ 770 if (!(req->cmd_options & 771 CMD1394_DISABLE_ADDR_INCREMENT)) { 772 req->cmd_addr += h_priv->mblk.length; 773 } 774 775 /* 776 * Use the current MAX_PAYLOAD size. This value 777 * doesn't need to be recalculated because we must 778 * be in the same generation on the bus, else we 779 * would have seen a bus reset error. 780 */ 781 if (s_priv->data_remaining < h_priv->mblk.length) { 782 h_priv->mblk.length = s_priv->data_remaining; 783 } 784 785 /* Send command out again */ 786 ret = s1394_xfer_asynch_command(hal, req, &err); 787 788 if (ret == DDI_SUCCESS) { 789 return; 790 791 } else if (err == CMD1394_ESTALE_GENERATION) { 792 /* Remove cmd from outstanding request Q */ 793 s1394_remove_q_asynch_cmd(hal, req); 794 s1394_pending_q_insert(hal, req, 795 S1394_PENDING_Q_REAR); 796 797 return; 798 } 799 } 800 } 801 802 /* Remove command from the HAL's outstanding request Q */ 803 s1394_remove_q_asynch_cmd(hal, req); 804 805 s_priv->cmd_in_use = B_FALSE; 806 807 /* Set status */ 808 req->cmd_result = err; 809 810 /* Is this a blocking command? */ 811 if (req->cmd_options & CMD1394_BLOCKING) { 812 /* Unblock the waiting command */ 813 mutex_enter(&s_priv->blocking_mutex); 814 s_priv->blocking_flag = B_TRUE; 815 cv_signal(&s_priv->blocking_cv); 816 mutex_exit(&s_priv->blocking_mutex); 817 818 return; 819 } 820 821 /* Set status and call completion_callback() */ 822 if (req->completion_callback != NULL) { 823 824 req->completion_callback(req); 825 826 return; 827 } 828 } 829 830 /* 831 * s1394_atresp_cmd_complete() 832 * is similar to s1394_atreq_cmd_complete(). It is also called by 833 * h1394_cmd_is_complete(), but when an AT response has completed. 834 * Again, based upon the command's completion status, 835 * s1394_atresp_cmd_complete() determines whether to call the target or 836 * to simply cleanup the command and return. 837 */ 838 void 839 s1394_atresp_cmd_complete(s1394_hal_t *hal, cmd1394_cmd_t *resp, int status) 840 { 841 s1394_cmd_priv_t *s_priv; 842 h1394_cmd_priv_t *h_priv; 843 dev_info_t *dip; 844 boolean_t valid_addr_blk; 845 int target_status; 846 847 target_status = CMD1394_CMDSUCCESS; 848 849 /* If not an ack_complete */ 850 if (status != H1394_CMD_SUCCESS) { 851 switch (status) { 852 /* evt_missing_ack */ 853 case H1394_CMD_ETIMEOUT: 854 target_status = CMD1394_ETIMEOUT; 855 break; 856 857 /* evt_flushed */ 858 case H1394_CMD_EBUSRESET: 859 target_status = CMD1394_EBUSRESET; 860 break; 861 862 /* ack_busy_X */ 863 /* ack_busy_A */ 864 /* ack_busy_B */ 865 case H1394_CMD_EDEVICE_BUSY: 866 target_status = CMD1394_EDEVICE_BUSY; 867 break; 868 869 /* ack_data_error */ 870 case H1394_CMD_EDATA_ERROR: 871 target_status = CMD1394_EDATA_ERROR; 872 break; 873 874 /* ack_type_error */ 875 case H1394_CMD_ETYPE_ERROR: 876 target_status = CMD1394_ETYPE_ERROR; 877 break; 878 879 /* ack_address_error */ 880 case H1394_CMD_EADDR_ERROR: 881 target_status = CMD1394_EADDRESS_ERROR; 882 break; 883 884 /* ack_conflict_error */ 885 case H1394_CMD_ERSRC_CONFLICT: 886 target_status = CMD1394_ERSRC_CONFLICT; 887 break; 888 889 /* ack_tardy */ 890 case H1394_CMD_EDEVICE_POWERUP: 891 target_status = CMD1394_EDEVICE_BUSY; 892 break; 893 894 /* device errors (bad tcodes, ACKs, etc...) */ 895 case H1394_CMD_EDEVICE_ERROR: 896 target_status = CMD1394_EDEVICE_ERROR; 897 break; 898 899 /* Unknown error type */ 900 case H1394_CMD_EUNKNOWN_ERROR: 901 target_status = CMD1394_EUNKNOWN_ERROR; 902 break; 903 904 /* Unrecognized error */ 905 default: 906 dip = hal->halinfo.dip; 907 908 /* An unexpected error in the HAL */ 909 cmn_err(CE_WARN, HALT_ERROR_MESSAGE, 910 ddi_node_name(dip), ddi_get_instance(dip)); 911 912 /* Disable the HAL */ 913 s1394_hal_shutdown(hal, B_TRUE); 914 915 return; 916 } 917 } 918 919 /* Get the Services Layer private area */ 920 s_priv = S1394_GET_CMD_PRIV(resp); 921 922 /* Get a pointer to the HAL private struct */ 923 h_priv = (h1394_cmd_priv_t *)&s_priv->hal_cmd_private; 924 925 valid_addr_blk = s_priv->arreq_valid_addr; 926 927 if (valid_addr_blk == B_TRUE) { 928 /* Set the command status */ 929 resp->cmd_result = target_status; 930 931 switch (s_priv->cmd_priv_xfer_type) { 932 case S1394_CMD_READ: 933 case S1394_CMD_WRITE: 934 case S1394_CMD_LOCK: 935 if (resp->completion_callback != NULL) { 936 resp->completion_callback(resp); 937 } 938 break; 939 940 default: 941 dip = hal->halinfo.dip; 942 943 /* An unexpected error in the HAL */ 944 cmn_err(CE_WARN, HALT_ERROR_MESSAGE, 945 ddi_node_name(dip), ddi_get_instance(dip)); 946 947 /* Disable the HAL */ 948 s1394_hal_shutdown(hal, B_TRUE); 949 950 return; 951 } 952 } 953 954 /* Free the command - Pass it back to the HAL */ 955 HAL_CALL(hal).response_complete(hal->halinfo.hal_private, resp, h_priv); 956 } 957 958 /* 959 * s1394_send_response() 960 * is used to send a response to an AR request. Depending on whether the 961 * request was a broadcast request, a write to posted write address space, 962 * or some other request, either a response packet is sent, or the command 963 * is returned to the HAL. A return value of DDI_SUCCESS means that the 964 * command has been handled correctly. It was either successfully sent to 965 * the HAL, or, if it was posted_write of broadcast, it was freed up. A 966 * return value of DDI_FAILURE indicates either a serious error, in which 967 * case the HAL is shutdown, or a failure returned by the HAL, in which 968 * case the command is freed up and notice of the failure is returned. 969 */ 970 int 971 s1394_send_response(s1394_hal_t *hal, cmd1394_cmd_t *resp) 972 { 973 s1394_cmd_priv_t *s_priv; 974 h1394_cmd_priv_t *h_priv; 975 dev_info_t *dip; 976 int ret; 977 int result; 978 979 /* Get the Services Layer private area */ 980 s_priv = S1394_GET_CMD_PRIV(resp); 981 982 /* Get a pointer to the HAL private struct */ 983 h_priv = (h1394_cmd_priv_t *)&s_priv->hal_cmd_private; 984 985 /* 986 * If request was broadcast or a write request to a posted write 987 * address, don't send a response 988 */ 989 if ((resp->broadcast == 1) || ((s_priv->posted_write == B_TRUE) && 990 ((resp->cmd_result == CMD1394_ASYNCH_WR_QUAD) || 991 (resp->cmd_result == CMD1394_ASYNCH_WR_BLOCK)))) { 992 993 /* Free the command - Pass it back to the HAL */ 994 HAL_CALL(hal).response_complete(hal->halinfo.hal_private, 995 resp, h_priv); 996 997 return (DDI_SUCCESS); 998 } 999 1000 /* kstats - number of failure responses sent */ 1001 if (resp->cmd_result != IEEE1394_RESP_COMPLETE) { 1002 switch (resp->cmd_type) { 1003 case CMD1394_ASYNCH_RD_QUAD: 1004 hal->hal_kstats->arresp_quad_rd_fail++; 1005 break; 1006 1007 case CMD1394_ASYNCH_RD_BLOCK: 1008 hal->hal_kstats->arresp_blk_rd_fail++; 1009 break; 1010 1011 case CMD1394_ASYNCH_WR_QUAD: 1012 hal->hal_kstats->arresp_quad_wr_fail++; 1013 break; 1014 1015 case CMD1394_ASYNCH_WR_BLOCK: 1016 hal->hal_kstats->arresp_blk_wr_fail++; 1017 break; 1018 1019 case CMD1394_ASYNCH_LOCK_32: 1020 hal->hal_kstats->arresp_lock32_fail++; 1021 break; 1022 1023 case CMD1394_ASYNCH_LOCK_64: 1024 hal->hal_kstats->arresp_lock64_fail++; 1025 break; 1026 } 1027 } else { 1028 if (resp->cmd_type == CMD1394_ASYNCH_RD_BLOCK) 1029 hal->hal_kstats->arreq_blk_rd_size += 1030 resp->cmd_u.b.blk_length; 1031 } 1032 1033 if (resp->cmd_type == CMD1394_ASYNCH_RD_BLOCK) { 1034 h_priv->mblk.curr_mblk = resp->cmd_u.b.data_block; 1035 h_priv->mblk.curr_offset = resp->cmd_u.b.data_block->b_rptr; 1036 h_priv->mblk.length = resp->cmd_u.b.blk_length; 1037 } 1038 1039 switch (s_priv->cmd_priv_xfer_type) { 1040 case S1394_CMD_READ: 1041 ret = HAL_CALL(hal).read_response(hal->halinfo.hal_private, 1042 resp, h_priv, &result); 1043 break; 1044 1045 case S1394_CMD_WRITE: 1046 ret = HAL_CALL(hal).write_response(hal->halinfo.hal_private, 1047 resp, h_priv, &result); 1048 break; 1049 1050 case S1394_CMD_LOCK: 1051 ret = HAL_CALL(hal).lock_response(hal->halinfo.hal_private, 1052 resp, h_priv, &result); 1053 break; 1054 1055 default: 1056 dip = hal->halinfo.dip; 1057 1058 /* An unexpected error in the HAL */ 1059 cmn_err(CE_WARN, HALT_ERROR_MESSAGE, 1060 ddi_node_name(dip), ddi_get_instance(dip)); 1061 1062 /* Disable the HAL */ 1063 s1394_hal_shutdown(hal, B_TRUE); 1064 1065 return (DDI_FAILURE); 1066 } 1067 1068 /* Unable to send a response */ 1069 if (ret != DDI_SUCCESS) { 1070 /* Free the command - Pass it back to the HAL */ 1071 HAL_CALL(hal).response_complete(hal->halinfo.hal_private, 1072 resp, h_priv); 1073 1074 return (DDI_FAILURE); 1075 } 1076 1077 return (DDI_SUCCESS); 1078 } 1079 1080 /* 1081 * s1394_compare_swap() 1082 * is used by t1394_lock() to send a lock request. Any of the lock 1083 * requests specified explicitly by the 1394 spec will pass thru here, 1084 * i.e compare-swap, mask-swap, etc. 1085 */ 1086 int 1087 s1394_compare_swap(s1394_hal_t *hal, s1394_target_t *target, cmd1394_cmd_t *cmd) 1088 { 1089 s1394_cmd_priv_t *s_priv; 1090 s1394_hal_state_t state; 1091 int err; 1092 int ret; 1093 1094 ASSERT(MUTEX_NOT_HELD(&hal->topology_tree_mutex)); 1095 1096 /* Lock the topology tree - protect from bus reset */ 1097 mutex_enter(&hal->topology_tree_mutex); 1098 1099 ret = s1394_setup_asynch_command(hal, target, cmd, S1394_CMD_LOCK, 1100 &err); 1101 1102 /* Unlock the topology tree */ 1103 mutex_exit(&hal->topology_tree_mutex); 1104 1105 /* Get the Services Layer private area */ 1106 s_priv = S1394_GET_CMD_PRIV(cmd); 1107 1108 /* Command has now been put onto the queue! */ 1109 if (ret != DDI_SUCCESS) { 1110 /* Copy error code into result */ 1111 cmd->cmd_result = err; 1112 1113 return (DDI_FAILURE); 1114 } 1115 1116 mutex_enter(&hal->topology_tree_mutex); 1117 state = hal->hal_state; 1118 /* If this command was sent during a bus reset, */ 1119 /* then put it onto the pending Q. */ 1120 if (state == S1394_HAL_RESET) { 1121 /* Remove cmd from outstanding request Q */ 1122 s1394_remove_q_asynch_cmd(hal, cmd); 1123 1124 /* Are we on the bus reset event stack? */ 1125 if (s1394_on_br_thread(hal) == B_TRUE) { 1126 /* Blocking commands are not allowed */ 1127 if (cmd->cmd_options & CMD1394_BLOCKING) { 1128 mutex_exit(&hal->topology_tree_mutex); 1129 1130 s_priv->cmd_in_use = B_FALSE; 1131 1132 cmd->cmd_result = CMD1394_EINVALID_CONTEXT; 1133 1134 return (DDI_FAILURE); 1135 } 1136 } 1137 1138 s1394_pending_q_insert(hal, cmd, S1394_PENDING_Q_FRONT); 1139 mutex_exit(&hal->topology_tree_mutex); 1140 1141 /* Block (if necessary) */ 1142 s1394_block_on_asynch_cmd(cmd); 1143 1144 return (DDI_SUCCESS); 1145 } 1146 mutex_exit(&hal->topology_tree_mutex); 1147 1148 /* Send the command out */ 1149 ret = s1394_xfer_asynch_command(hal, cmd, &err); 1150 1151 if (ret != DDI_SUCCESS) { 1152 if (err == CMD1394_ESTALE_GENERATION) { 1153 /* Remove cmd from outstanding request Q */ 1154 s1394_remove_q_asynch_cmd(hal, cmd); 1155 s1394_pending_q_insert(hal, cmd, S1394_PENDING_Q_FRONT); 1156 1157 /* Block (if necessary) */ 1158 s1394_block_on_asynch_cmd(cmd); 1159 1160 return (DDI_SUCCESS); 1161 1162 } else { 1163 /* Remove cmd from outstanding request Q */ 1164 s1394_remove_q_asynch_cmd(hal, cmd); 1165 1166 s_priv->cmd_in_use = B_FALSE; 1167 1168 /* Copy error code into result */ 1169 cmd->cmd_result = err; 1170 1171 return (DDI_FAILURE); 1172 } 1173 } else { 1174 /* Block (if necessary) */ 1175 s1394_block_on_asynch_cmd(cmd); 1176 1177 return (DDI_SUCCESS); 1178 } 1179 } 1180 1181 /* 1182 * s1394_split_lock_req() 1183 * is also used by t1394_lock() to send a lock request. The difference 1184 * is that s1394_split_lock_req() is used to send the software supported 1185 * lock types, i.e. bit_and, bit_or, etc. These lock requests require 1186 * more than one transaction, typically compare-swap's. 1187 */ 1188 int 1189 s1394_split_lock_req(s1394_hal_t *hal, s1394_target_t *target, 1190 cmd1394_cmd_t *cmd) 1191 { 1192 s1394_cmd_priv_t *s_priv; 1193 cmd1394_cmd_t *tmp_cmd; 1194 1195 /* Allocate a temporary command */ 1196 if (s1394_alloc_cmd(hal, T1394_ALLOC_CMD_NOSLEEP, &tmp_cmd) != 1197 DDI_SUCCESS) { 1198 cmd->cmd_result = CMD1394_EUNKNOWN_ERROR; 1199 1200 return (DDI_FAILURE); 1201 } 1202 1203 /* Get the Services Layer private area */ 1204 s_priv = S1394_GET_CMD_PRIV(tmp_cmd); 1205 1206 tmp_cmd->completion_callback = s1394_handle_lock; 1207 tmp_cmd->cmd_callback_arg = (opaque_t)cmd; 1208 tmp_cmd->cmd_type = cmd->cmd_type; 1209 tmp_cmd->cmd_addr = cmd->cmd_addr; 1210 tmp_cmd->cmd_options = cmd->cmd_options; 1211 tmp_cmd->bus_generation = cmd->bus_generation; 1212 1213 /* The temporary command can not block */ 1214 tmp_cmd->cmd_options = tmp_cmd->cmd_options & ~CMD1394_BLOCKING; 1215 1216 /* Setup compare-swap with data_value == arg_value (read) */ 1217 if (tmp_cmd->cmd_type == CMD1394_ASYNCH_LOCK_32) { 1218 tmp_cmd->cmd_u.l32.data_value = 0; 1219 tmp_cmd->cmd_u.l32.arg_value = 0; 1220 tmp_cmd->cmd_u.l32.lock_type = CMD1394_LOCK_COMPARE_SWAP; 1221 s_priv->temp_num_retries = cmd->cmd_u.l32.num_retries; 1222 } else { 1223 tmp_cmd->cmd_u.l64.data_value = 0; 1224 tmp_cmd->cmd_u.l64.arg_value = 0; 1225 tmp_cmd->cmd_u.l64.lock_type = CMD1394_LOCK_COMPARE_SWAP; 1226 s_priv->temp_num_retries = cmd->cmd_u.l64.num_retries; 1227 } 1228 1229 /* Initialize lock_req_step */ 1230 s_priv->lock_req_step = 0; 1231 1232 /* Get the Services Layer private area for the target cmd */ 1233 s_priv = S1394_GET_CMD_PRIV(cmd); 1234 1235 s_priv->cmd_in_use = B_TRUE; 1236 1237 /* Send the request */ 1238 if (s1394_compare_swap(hal, target, tmp_cmd) != DDI_SUCCESS) { 1239 s_priv->cmd_in_use = B_FALSE; 1240 1241 /* Free the temporary command */ 1242 if (s1394_free_cmd(hal, &tmp_cmd) != DDI_SUCCESS) 1243 cmd->cmd_result = CMD1394_EUNKNOWN_ERROR; 1244 1245 return (DDI_FAILURE); 1246 } 1247 1248 /* Block (if necessary) */ 1249 s1394_block_on_asynch_cmd(cmd); 1250 1251 return (DDI_SUCCESS); 1252 } 1253 1254 /* 1255 * s1394_handle_lock() 1256 * is the callback for s1394_split_lock_req(). It does all of the real 1257 * work. Based on the specific lock type all necessary manipulation is 1258 * performed and another compare swap is sent out. If the transaction 1259 * is unsuccessful, it is retried. 1260 */ 1261 static void 1262 s1394_handle_lock(cmd1394_cmd_t *cmd) 1263 { 1264 s1394_hal_t *to_hal; 1265 s1394_target_t *target; 1266 s1394_cmd_priv_t *s_priv; 1267 cmd1394_cmd_t *target_cmd; 1268 uint32_t lock_req_step; 1269 int tcmd_result; 1270 int ret; 1271 1272 /* Get the Services Layer private area */ 1273 s_priv = S1394_GET_CMD_PRIV(cmd); 1274 1275 lock_req_step = s_priv->lock_req_step; 1276 1277 /* Get the target's command */ 1278 target_cmd = (cmd1394_cmd_t *)cmd->cmd_callback_arg; 1279 1280 /* Get the destination of the command */ 1281 to_hal = s_priv->sent_on_hal; 1282 1283 lock_req_step_0: 1284 /* Is this step 0 completing? */ 1285 if (lock_req_step == 0) { 1286 /* Was the request successful? */ 1287 if (cmd->cmd_result == CMD1394_CMDSUCCESS) { 1288 /* Do any math, bit ops, or byte-swapping necessary */ 1289 ret = s1394_process_split_lock(cmd, target_cmd); 1290 1291 if (ret != DDI_SUCCESS) { 1292 tcmd_result = target_cmd->cmd_result; 1293 goto lock_req_done; 1294 } 1295 1296 s_priv->lock_req_step = 1; 1297 1298 target = s_priv->sent_by_target; 1299 1300 if (s1394_compare_swap(to_hal, target, cmd) != 1301 DDI_SUCCESS) { 1302 tcmd_result = cmd->cmd_result; 1303 goto lock_req_done; 1304 } else { 1305 return; 1306 } 1307 } else { 1308 /* Command failed for some reason */ 1309 tcmd_result = cmd->cmd_result; 1310 goto lock_req_done; 1311 } 1312 } else { /* lock_req_step == 1 */ 1313 /* Was the request successful? */ 1314 if (cmd->cmd_result == CMD1394_CMDSUCCESS) { 1315 /* Do whatever's necessary to finish up the lock */ 1316 ret = s1394_finish_split_lock(cmd, target_cmd); 1317 1318 if (ret != DDI_SUCCESS) { 1319 lock_req_step = 0; 1320 goto lock_req_step_0; 1321 } else { 1322 tcmd_result = cmd->cmd_result; 1323 goto lock_req_done; 1324 } 1325 } else { 1326 /* Command failed for some reason */ 1327 tcmd_result = cmd->cmd_result; 1328 goto lock_req_done; 1329 } 1330 } 1331 1332 lock_req_done: 1333 (void) s1394_free_cmd(to_hal, &cmd); 1334 1335 /* Get the Services Layer private area */ 1336 s_priv = S1394_GET_CMD_PRIV(target_cmd); 1337 1338 s_priv->cmd_in_use = B_FALSE; 1339 1340 target_cmd->cmd_result = tcmd_result; 1341 1342 /* Is this a blocking command? */ 1343 if (target_cmd->cmd_options & CMD1394_BLOCKING) { 1344 /* Unblock the waiting command */ 1345 mutex_enter(&s_priv->blocking_mutex); 1346 s_priv->blocking_flag = B_TRUE; 1347 cv_signal(&s_priv->blocking_cv); 1348 mutex_exit(&s_priv->blocking_mutex); 1349 1350 return; 1351 } 1352 1353 /* Call the target's completion_callback() */ 1354 if (target_cmd->completion_callback != NULL) 1355 target_cmd->completion_callback(target_cmd); 1356 } 1357 1358 /* 1359 * s1394_pending_q_insert() 1360 * is used to insert a given command structure onto a HAL's pending queue 1361 * for later processing (after the bus reset). All commands returned by 1362 * the HAL, are inserted onto the rear of the list (first priority), and 1363 * all other commands (from targets during bus reset) are put onto the front. 1364 */ 1365 void 1366 s1394_pending_q_insert(s1394_hal_t *hal, cmd1394_cmd_t *cmd, uint_t flags) 1367 { 1368 cmd1394_cmd_t *temp_cmd; 1369 s1394_cmd_priv_t *s_priv; 1370 s1394_cmd_priv_t *c_priv; 1371 1372 mutex_enter(&hal->pending_q_mutex); 1373 1374 /* Get the Services Layer private area */ 1375 s_priv = S1394_GET_CMD_PRIV(cmd); 1376 1377 /* Is the outstanding request queue empty? */ 1378 if ((hal->pending_q_head == NULL) && (hal->pending_q_tail == NULL)) { 1379 1380 hal->pending_q_head = (cmd1394_cmd_t *)cmd; 1381 hal->pending_q_tail = (cmd1394_cmd_t *)cmd; 1382 s_priv->cmd_priv_next = (cmd1394_cmd_t *)NULL; 1383 s_priv->cmd_priv_prev = (cmd1394_cmd_t *)NULL; 1384 1385 } else if (flags == S1394_PENDING_Q_FRONT) { 1386 s_priv->cmd_priv_next = hal->pending_q_head; 1387 s_priv->cmd_priv_prev = (cmd1394_cmd_t *)NULL; 1388 1389 temp_cmd = (cmd1394_cmd_t *)hal->pending_q_head; 1390 c_priv = (s1394_cmd_priv_t *)((uchar_t *)temp_cmd + 1391 sizeof (cmd1394_cmd_t)); 1392 c_priv->cmd_priv_prev = (cmd1394_cmd_t *)cmd; 1393 1394 hal->pending_q_head = (cmd1394_cmd_t *)cmd; 1395 1396 } else { 1397 s_priv->cmd_priv_prev = hal->pending_q_tail; 1398 s_priv->cmd_priv_next = (cmd1394_cmd_t *)NULL; 1399 1400 temp_cmd = (cmd1394_cmd_t *)hal->pending_q_tail; 1401 c_priv = (s1394_cmd_priv_t *)((uchar_t *)temp_cmd + 1402 sizeof (cmd1394_cmd_t)); 1403 c_priv->cmd_priv_next = (cmd1394_cmd_t *)cmd; 1404 1405 hal->pending_q_tail = (cmd1394_cmd_t *)cmd; 1406 } 1407 1408 mutex_exit(&hal->pending_q_mutex); 1409 1410 /* kstats - number of pending Q insertions */ 1411 hal->hal_kstats->pending_q_insert++; 1412 } 1413 1414 /* 1415 * s1394_pending_q_remove() 1416 * is used to remove a command structure from a HAL's pending queue for 1417 * processing. 1418 */ 1419 static cmd1394_cmd_t * 1420 s1394_pending_q_remove(s1394_hal_t *hal) 1421 { 1422 s1394_cmd_priv_t *s_priv; 1423 s1394_cmd_priv_t *c_priv; 1424 cmd1394_cmd_t *cmd; 1425 cmd1394_cmd_t *prev_cmd; 1426 1427 mutex_enter(&hal->pending_q_mutex); 1428 1429 cmd = (cmd1394_cmd_t *)hal->pending_q_tail; 1430 if (cmd == NULL) { 1431 mutex_exit(&hal->pending_q_mutex); 1432 return (NULL); 1433 } 1434 1435 /* Get the Services Layer private area */ 1436 s_priv = S1394_GET_CMD_PRIV(cmd); 1437 1438 prev_cmd = (cmd1394_cmd_t *)s_priv->cmd_priv_prev; 1439 1440 s_priv->cmd_priv_prev = (cmd1394_cmd_t *)NULL; 1441 s_priv->cmd_priv_next = (cmd1394_cmd_t *)NULL; 1442 1443 if (prev_cmd != NULL) { 1444 c_priv = (s1394_cmd_priv_t *)((uchar_t *)prev_cmd + 1445 sizeof (cmd1394_cmd_t)); 1446 c_priv->cmd_priv_next = (cmd1394_cmd_t *)NULL; 1447 1448 } else { 1449 hal->pending_q_head = (cmd1394_cmd_t *)NULL; 1450 } 1451 hal->pending_q_tail = (cmd1394_cmd_t *)prev_cmd; 1452 1453 mutex_exit(&hal->pending_q_mutex); 1454 1455 return (cmd); 1456 } 1457 1458 /* 1459 * s1394_resend_pending_cmds() 1460 * is called when the pending queue is to be flushed. After most of the 1461 * bus reset processing is completed, the pending commands are sent/resent. 1462 */ 1463 void 1464 s1394_resend_pending_cmds(s1394_hal_t *hal) 1465 { 1466 int done; 1467 1468 ASSERT(MUTEX_NOT_HELD(&hal->topology_tree_mutex)); 1469 1470 do { 1471 done = s1394_process_pending_q(hal); 1472 } while (done == B_FALSE); 1473 1474 ASSERT(MUTEX_NOT_HELD(&hal->topology_tree_mutex)); 1475 } 1476 1477 /* 1478 * s1394_process_pending_q() 1479 * is called to send/resend the commands on the pending queue. All command 1480 * handling can be done here, including notifying the target of failed 1481 * commands, etc. If it is necessary to recompute the address, speed, 1482 * or max_payload for a command, that can be done here too. And if there 1483 * is no reason not to continue sending commands from the pending queue, 1484 * then a B_FALSE is returned, else B_TRUE is returned. 1485 */ 1486 static boolean_t 1487 s1394_process_pending_q(s1394_hal_t *hal) 1488 { 1489 s1394_cmd_priv_t *s_priv; 1490 h1394_cmd_priv_t *h_priv; 1491 s1394_target_t *target; 1492 cmd1394_cmd_t *cmd; 1493 uint64_t node; 1494 uint32_t from_node; 1495 uint32_t to_node; 1496 uint_t current_max_payload; 1497 int ret; 1498 1499 ASSERT(MUTEX_NOT_HELD(&hal->topology_tree_mutex)); 1500 1501 /* Pull a command from the Pending Q */ 1502 cmd = s1394_pending_q_remove(hal); 1503 1504 if (cmd == NULL) { 1505 return (B_TRUE); 1506 } 1507 1508 /* Get the Services Layer private area */ 1509 s_priv = S1394_GET_CMD_PRIV(cmd); 1510 1511 /* Get a pointer to the HAL private struct */ 1512 h_priv = (h1394_cmd_priv_t *)&s_priv->hal_cmd_private; 1513 1514 if ((cmd->cmd_options & CMD1394_OVERRIDE_ADDR) || 1515 (cmd->cmd_options & CMD1394_CANCEL_ON_BUS_RESET)) { 1516 if (h_priv->bus_generation == hal->generation_count) { 1517 ret = s1394_pending_q_helper(hal, cmd); 1518 return (ret); 1519 } else { 1520 1521 s_priv->cmd_in_use = B_FALSE; 1522 1523 cmd->cmd_result = CMD1394_EBUSRESET; 1524 1525 /* Is this a blocking command? */ 1526 if (cmd->cmd_options & CMD1394_BLOCKING) { 1527 /* Unblock the waiting command */ 1528 mutex_enter(&s_priv->blocking_mutex); 1529 s_priv->blocking_flag = B_TRUE; 1530 cv_signal(&s_priv->blocking_cv); 1531 mutex_exit(&s_priv->blocking_mutex); 1532 1533 return (B_FALSE); 1534 } 1535 1536 /* Call the target's completion_callback() */ 1537 if (cmd->completion_callback != NULL) { 1538 cmd->completion_callback(cmd); 1539 } 1540 1541 return (B_FALSE); 1542 } 1543 } else { 1544 if (h_priv->bus_generation == hal->generation_count) { 1545 ret = s1394_pending_q_helper(hal, cmd); 1546 return (ret); 1547 } else { 1548 /* Make sure we can get the topology_tree_mutex */ 1549 if (s1394_lock_tree(hal) != DDI_SUCCESS) 1550 return (B_TRUE); 1551 1552 /* Set the generation */ 1553 cmd->bus_generation = hal->generation_count; 1554 1555 /* Copy the generation into the HAL's private field */ 1556 h_priv->bus_generation = cmd->bus_generation; 1557 1558 target = s_priv->sent_by_target; 1559 1560 /* If not OVERRIDE_ADDR, then target may not be NULL */ 1561 ASSERT(target != NULL); 1562 1563 rw_enter(&hal->target_list_rwlock, RW_READER); 1564 1565 if (((target->target_state & S1394_TARG_GONE) == 0) && 1566 (target->on_node != NULL)) { 1567 node = target->on_node->node_num; 1568 rw_exit(&hal->target_list_rwlock); 1569 } else { 1570 rw_exit(&hal->target_list_rwlock); 1571 1572 s_priv->cmd_in_use = B_FALSE; 1573 1574 cmd->cmd_result = CMD1394_EDEVICE_REMOVED; 1575 1576 /* Is this a blocking command? */ 1577 if (cmd->cmd_options & CMD1394_BLOCKING) { 1578 s1394_unlock_tree(hal); 1579 1580 /* Unblock the waiting command */ 1581 mutex_enter(&s_priv->blocking_mutex); 1582 s_priv->blocking_flag = B_TRUE; 1583 cv_signal(&s_priv->blocking_cv); 1584 mutex_exit(&s_priv->blocking_mutex); 1585 1586 return (B_FALSE); 1587 } 1588 1589 /* Call the target's completion_callback() */ 1590 if (cmd->completion_callback != NULL) { 1591 s1394_unlock_tree(hal); 1592 cmd->completion_callback(cmd); 1593 return (B_FALSE); 1594 } else { 1595 s1394_unlock_tree(hal); 1596 return (B_FALSE); 1597 } 1598 } 1599 1600 /* Mask in the top 16-bits */ 1601 cmd->cmd_addr = cmd->cmd_addr & 1602 IEEE1394_ADDR_OFFSET_MASK; 1603 cmd->cmd_addr = cmd->cmd_addr | 1604 (node << IEEE1394_ADDR_PHY_ID_SHIFT); 1605 cmd->cmd_addr = cmd->cmd_addr | 1606 IEEE1394_ADDR_BUS_ID_MASK; 1607 1608 /* Speed is to be filled in from speed map */ 1609 from_node = IEEE1394_NODE_NUM(hal->node_id); 1610 to_node = (uint32_t)node; 1611 1612 /* Fill in the nodeID */ 1613 cmd->nodeID = 1614 (cmd->cmd_addr & IEEE1394_ADDR_NODE_ID_MASK) >> 1615 IEEE1394_ADDR_NODE_ID_SHIFT; 1616 1617 if (cmd->cmd_options & CMD1394_OVERRIDE_SPEED) { 1618 s_priv->hal_cmd_private.speed = 1619 (int)cmd->cmd_speed; 1620 } else { 1621 /* Speed is to be filled in from speed map */ 1622 s_priv->hal_cmd_private.speed = 1623 (int)s1394_speed_map_get(hal, from_node, 1624 to_node); 1625 } 1626 1627 /* Is it a block request? */ 1628 if ((cmd->cmd_type == CMD1394_ASYNCH_RD_BLOCK) || 1629 (cmd->cmd_type == CMD1394_ASYNCH_WR_BLOCK)) { 1630 1631 /* Get a pointer to the HAL private struct */ 1632 h_priv = (h1394_cmd_priv_t *)&s_priv-> 1633 hal_cmd_private; 1634 1635 /* Handle the MAX_PAYLOAD size */ 1636 if (s_priv->sent_by_target != NULL) { 1637 current_max_payload = 1638 s_priv->sent_by_target-> 1639 current_max_payload; 1640 } else { 1641 current_max_payload = 4; 1642 } 1643 if (cmd->cmd_options & 1644 CMD1394_OVERRIDE_MAX_PAYLOAD) { 1645 if (current_max_payload > 1646 cmd->cmd_u.b.max_payload) 1647 current_max_payload = 1648 cmd->cmd_u.b.max_payload; 1649 } 1650 if (s_priv->data_remaining < 1651 current_max_payload) { 1652 h_priv->mblk.length = 1653 s_priv->data_remaining; 1654 } else { 1655 h_priv->mblk.length = 1656 current_max_payload; 1657 } 1658 } 1659 s1394_unlock_tree(hal); 1660 ret = s1394_pending_q_helper(hal, cmd); 1661 return (ret); 1662 } 1663 } 1664 } 1665 1666 /* 1667 * s1394_pending_q_helper() 1668 * is a "helper" function for s1394_process_pending_q(). It attempts to 1669 * resend commands, handling error conditions whenever necessary. 1670 */ 1671 static boolean_t 1672 s1394_pending_q_helper(s1394_hal_t *hal, cmd1394_cmd_t *cmd) 1673 { 1674 s1394_cmd_priv_t *s_priv; 1675 int err; 1676 int ret; 1677 1678 ASSERT(MUTEX_NOT_HELD(&hal->topology_tree_mutex)); 1679 1680 /* Get the Services Layer private area */ 1681 s_priv = S1394_GET_CMD_PRIV(cmd); 1682 1683 /* Put cmd on outstanding request Q */ 1684 s1394_insert_q_asynch_cmd(hal, cmd); 1685 1686 /* Send command out again */ 1687 ret = s1394_xfer_asynch_command(hal, cmd, &err); 1688 1689 if (ret != DDI_SUCCESS) { 1690 if (err == CMD1394_ESTALE_GENERATION) { 1691 /* Remove cmd outstanding req Q */ 1692 s1394_remove_q_asynch_cmd(hal, cmd); 1693 s1394_pending_q_insert(hal, cmd, S1394_PENDING_Q_FRONT); 1694 1695 return (B_TRUE); 1696 } else { 1697 /* Remove cmd from outstanding request Q */ 1698 s1394_remove_q_asynch_cmd(hal, cmd); 1699 1700 s_priv->cmd_in_use = B_FALSE; 1701 1702 cmd->cmd_result = err; 1703 1704 /* Is this a blocking command? */ 1705 if (cmd->cmd_options & CMD1394_BLOCKING) { 1706 /* Unblock waiting command */ 1707 mutex_enter(&s_priv->blocking_mutex); 1708 s_priv->blocking_flag = B_TRUE; 1709 cv_signal(&s_priv->blocking_cv); 1710 mutex_exit(&s_priv->blocking_mutex); 1711 1712 return (B_FALSE); 1713 } 1714 1715 /* Call target completion_callback() */ 1716 if (cmd->completion_callback != NULL) { 1717 cmd->completion_callback(cmd); 1718 return (B_FALSE); 1719 } else { 1720 return (B_FALSE); 1721 } 1722 } 1723 } 1724 1725 return (B_FALSE); 1726 } 1727 1728 /* 1729 * s1394_process_split_lock() 1730 * is a "helper" function for the s1394_handle_lock() callback. Its 1731 * job is to perform whatever manipulation is required for the given 1732 * request. 1733 */ 1734 static int 1735 s1394_process_split_lock(cmd1394_cmd_t *cmd, cmd1394_cmd_t *target_cmd) 1736 { 1737 uint64_t new_value64; 1738 uint64_t data_value64; 1739 uint64_t arg_value64; 1740 uint64_t old_value64; 1741 uint64_t temp_value64; 1742 uint32_t new_value32; 1743 uint32_t data_value32; 1744 uint32_t arg_value32; 1745 uint32_t old_value32; 1746 uint32_t temp_value32; 1747 1748 if (cmd->cmd_type == CMD1394_ASYNCH_LOCK_32) { 1749 old_value32 = cmd->cmd_u.l32.old_value; 1750 data_value32 = target_cmd->cmd_u.l32.data_value; 1751 arg_value32 = target_cmd->cmd_u.l32.arg_value; 1752 1753 /* Lock type specific */ 1754 switch (target_cmd->cmd_u.l32.lock_type) { 1755 case CMD1394_LOCK_BIT_AND: 1756 new_value32 = old_value32 & data_value32; 1757 break; 1758 1759 case CMD1394_LOCK_BIT_OR: 1760 new_value32 = old_value32 | data_value32; 1761 break; 1762 1763 case CMD1394_LOCK_BIT_XOR: 1764 new_value32 = old_value32 ^ data_value32; 1765 break; 1766 1767 case CMD1394_LOCK_INCREMENT: 1768 old_value32 = T1394_DATA32(old_value32); 1769 new_value32 = old_value32 + 1; 1770 new_value32 = T1394_DATA32(new_value32); 1771 old_value32 = T1394_DATA32(old_value32); 1772 break; 1773 1774 case CMD1394_LOCK_DECREMENT: 1775 old_value32 = T1394_DATA32(old_value32); 1776 new_value32 = old_value32 - 1; 1777 new_value32 = T1394_DATA32(new_value32); 1778 old_value32 = T1394_DATA32(old_value32); 1779 break; 1780 1781 case CMD1394_LOCK_ADD: 1782 old_value32 = T1394_DATA32(old_value32); 1783 new_value32 = old_value32 + data_value32; 1784 new_value32 = T1394_DATA32(new_value32); 1785 old_value32 = T1394_DATA32(old_value32); 1786 break; 1787 1788 case CMD1394_LOCK_SUBTRACT: 1789 old_value32 = T1394_DATA32(old_value32); 1790 new_value32 = old_value32 - data_value32; 1791 new_value32 = T1394_DATA32(new_value32); 1792 old_value32 = T1394_DATA32(old_value32); 1793 break; 1794 1795 case CMD1394_LOCK_THRESH_ADD: 1796 old_value32 = T1394_DATA32(old_value32); 1797 temp_value32 = (old_value32 + data_value32); 1798 if ((temp_value32 >= old_value32) && 1799 (temp_value32 <= arg_value32)) { 1800 new_value32 = T1394_DATA32(temp_value32); 1801 old_value32 = T1394_DATA32(old_value32); 1802 } else { 1803 /* Failed threshold add */ 1804 target_cmd->cmd_u.l32.old_value = 1805 T1394_DATA32(cmd->cmd_u.l32.old_value); 1806 target_cmd->cmd_result = CMD1394_CMDSUCCESS; 1807 return (DDI_FAILURE); 1808 } 1809 break; 1810 1811 case CMD1394_LOCK_THRESH_SUBTRACT: 1812 old_value32 = T1394_DATA32(old_value32); 1813 temp_value32 = (old_value32 - data_value32); 1814 if ((old_value32 >= data_value32) && 1815 (temp_value32 >= arg_value32)) { 1816 new_value32 = T1394_DATA32(temp_value32); 1817 old_value32 = T1394_DATA32(old_value32); 1818 } else { 1819 /* Failed threshold subtract */ 1820 target_cmd->cmd_u.l32.old_value = 1821 T1394_DATA32(cmd->cmd_u.l32.old_value); 1822 target_cmd->cmd_result = CMD1394_CMDSUCCESS; 1823 return (DDI_FAILURE); 1824 } 1825 break; 1826 1827 case CMD1394_LOCK_CLIP_ADD: 1828 old_value32 = T1394_DATA32(old_value32); 1829 temp_value32 = (old_value32 + data_value32); 1830 if ((temp_value32 < old_value32) || 1831 (temp_value32 > arg_value32)) 1832 new_value32 = T1394_DATA32(arg_value32); 1833 else 1834 new_value32 = T1394_DATA32(temp_value32); 1835 old_value32 = T1394_DATA32(old_value32); 1836 break; 1837 1838 case CMD1394_LOCK_CLIP_SUBTRACT: 1839 old_value32 = T1394_DATA32(old_value32); 1840 temp_value32 = (old_value32 - data_value32); 1841 if ((data_value32 > old_value32) || 1842 (temp_value32 < arg_value32)) 1843 new_value32 = T1394_DATA32(arg_value32); 1844 else 1845 new_value32 = T1394_DATA32(temp_value32); 1846 old_value32 = T1394_DATA32(old_value32); 1847 break; 1848 } 1849 1850 /* Send compare-swap lock request */ 1851 cmd->cmd_u.l32.arg_value = old_value32; 1852 cmd->cmd_u.l32.data_value = new_value32; 1853 } else { 1854 old_value64 = cmd->cmd_u.l64.old_value; 1855 data_value64 = target_cmd->cmd_u.l64.data_value; 1856 arg_value64 = target_cmd->cmd_u.l64.arg_value; 1857 1858 /* Lock type specific */ 1859 switch (target_cmd->cmd_u.l64.lock_type) { 1860 case CMD1394_LOCK_BIT_AND: 1861 new_value64 = old_value64 & data_value64; 1862 break; 1863 1864 case CMD1394_LOCK_BIT_OR: 1865 new_value64 = old_value64 | data_value64; 1866 break; 1867 1868 case CMD1394_LOCK_BIT_XOR: 1869 new_value64 = old_value64 ^ data_value64; 1870 break; 1871 1872 case CMD1394_LOCK_INCREMENT: 1873 old_value64 = T1394_DATA64(old_value64); 1874 new_value64 = old_value64 + 1; 1875 new_value64 = T1394_DATA64(new_value64); 1876 old_value64 = T1394_DATA64(old_value64); 1877 break; 1878 1879 case CMD1394_LOCK_DECREMENT: 1880 old_value64 = T1394_DATA64(old_value64); 1881 new_value64 = old_value64 - 1; 1882 new_value64 = T1394_DATA64(new_value64); 1883 old_value64 = T1394_DATA64(old_value64); 1884 break; 1885 1886 case CMD1394_LOCK_ADD: 1887 old_value64 = T1394_DATA64(old_value64); 1888 new_value64 = old_value64 + data_value64; 1889 new_value64 = T1394_DATA64(new_value64); 1890 old_value64 = T1394_DATA64(old_value64); 1891 break; 1892 1893 case CMD1394_LOCK_SUBTRACT: 1894 old_value64 = T1394_DATA64(old_value64); 1895 new_value64 = old_value64 - data_value64; 1896 new_value64 = T1394_DATA64(new_value64); 1897 old_value64 = T1394_DATA64(old_value64); 1898 break; 1899 1900 case CMD1394_LOCK_THRESH_ADD: 1901 old_value64 = T1394_DATA64(old_value64); 1902 temp_value64 = (old_value64 + data_value64); 1903 if ((temp_value64 >= old_value64) && 1904 (temp_value64 <= arg_value64)) { 1905 new_value64 = T1394_DATA64(temp_value64); 1906 old_value64 = T1394_DATA64(old_value64); 1907 } else { 1908 /* Failed threshold add */ 1909 target_cmd->cmd_u.l64.old_value = 1910 T1394_DATA64(cmd->cmd_u.l64.old_value); 1911 target_cmd->cmd_result = CMD1394_CMDSUCCESS; 1912 return (DDI_FAILURE); 1913 } 1914 break; 1915 1916 case CMD1394_LOCK_THRESH_SUBTRACT: 1917 old_value64 = T1394_DATA64(old_value64); 1918 temp_value64 = (old_value64 - data_value64); 1919 if ((old_value64 >= data_value64) && 1920 (temp_value64 >= arg_value64)) { 1921 new_value64 = T1394_DATA64(temp_value64); 1922 old_value64 = T1394_DATA64(old_value64); 1923 } else { 1924 /* Failed threshold subtract */ 1925 target_cmd->cmd_u.l64.old_value = 1926 T1394_DATA64(cmd->cmd_u.l64.old_value); 1927 target_cmd->cmd_result = CMD1394_CMDSUCCESS; 1928 return (DDI_FAILURE); 1929 } 1930 break; 1931 1932 case CMD1394_LOCK_CLIP_ADD: 1933 old_value64 = T1394_DATA64(old_value64); 1934 temp_value64 = (old_value64 + data_value64); 1935 if ((temp_value64 < old_value64) || 1936 (temp_value64 > arg_value64)) 1937 new_value64 = T1394_DATA64(arg_value64); 1938 else 1939 new_value64 = T1394_DATA64(temp_value64); 1940 old_value64 = T1394_DATA64(old_value64); 1941 break; 1942 1943 case CMD1394_LOCK_CLIP_SUBTRACT: 1944 old_value64 = T1394_DATA64(old_value64); 1945 temp_value64 = (old_value64 - data_value64); 1946 if ((data_value64 > old_value64) || 1947 (temp_value64 < arg_value64)) 1948 new_value64 = T1394_DATA64(arg_value64); 1949 else 1950 new_value64 = T1394_DATA64(temp_value64); 1951 old_value64 = T1394_DATA64(old_value64); 1952 break; 1953 } 1954 1955 /* Send compare-swap lock request */ 1956 cmd->cmd_u.l64.arg_value = old_value64; 1957 cmd->cmd_u.l64.data_value = new_value64; 1958 } 1959 1960 return (DDI_SUCCESS); 1961 } 1962 1963 /* 1964 * s1394_finish_split_lock() 1965 * is another "helper" function for the s1394_handle_lock() callback. 1966 * Its job is to finish up whatever lock request procesing is necessary. 1967 */ 1968 static int 1969 s1394_finish_split_lock(cmd1394_cmd_t *cmd, cmd1394_cmd_t *target_cmd) 1970 { 1971 s1394_cmd_priv_t *s_priv; 1972 uint64_t tmp_value64; 1973 uint32_t tmp_value32; 1974 1975 /* Get the Services Layer private area */ 1976 s_priv = S1394_GET_CMD_PRIV(cmd); 1977 1978 if (((cmd->cmd_type == CMD1394_ASYNCH_LOCK_32) && 1979 (cmd->cmd_u.l32.old_value == cmd->cmd_u.l32.arg_value)) || 1980 ((cmd->cmd_type == CMD1394_ASYNCH_LOCK_64) && 1981 (cmd->cmd_u.l64.old_value == cmd->cmd_u.l64.arg_value))) { 1982 1983 if (cmd->cmd_type == CMD1394_ASYNCH_LOCK_32) { 1984 switch (cmd->cmd_u.l32.lock_type) { 1985 case CMD1394_LOCK_INCREMENT: 1986 case CMD1394_LOCK_DECREMENT: 1987 case CMD1394_LOCK_ADD: 1988 case CMD1394_LOCK_SUBTRACT: 1989 case CMD1394_LOCK_THRESH_ADD: 1990 case CMD1394_LOCK_THRESH_SUBTRACT: 1991 case CMD1394_LOCK_CLIP_ADD: 1992 case CMD1394_LOCK_CLIP_SUBTRACT: 1993 tmp_value32 = cmd->cmd_u.l32.old_value; 1994 tmp_value32 = T1394_DATA32(tmp_value32); 1995 target_cmd->cmd_u.l32.old_value = tmp_value32; 1996 break; 1997 default: 1998 tmp_value32 = cmd->cmd_u.l32.old_value; 1999 target_cmd->cmd_u.l32.old_value = tmp_value32; 2000 break; 2001 } 2002 } else { 2003 switch (cmd->cmd_u.l64.lock_type) { 2004 case CMD1394_LOCK_INCREMENT: 2005 case CMD1394_LOCK_DECREMENT: 2006 case CMD1394_LOCK_ADD: 2007 case CMD1394_LOCK_SUBTRACT: 2008 case CMD1394_LOCK_THRESH_ADD: 2009 case CMD1394_LOCK_THRESH_SUBTRACT: 2010 case CMD1394_LOCK_CLIP_ADD: 2011 case CMD1394_LOCK_CLIP_SUBTRACT: 2012 tmp_value64 = cmd->cmd_u.l64.old_value; 2013 tmp_value64 = T1394_DATA64(tmp_value64); 2014 target_cmd->cmd_u.l64.old_value = tmp_value64; 2015 break; 2016 default: 2017 tmp_value64 = cmd->cmd_u.l64.old_value; 2018 target_cmd->cmd_u.l64.old_value = tmp_value64; 2019 break; 2020 } 2021 } 2022 /* Set status */ 2023 target_cmd->cmd_result = CMD1394_CMDSUCCESS; 2024 return (DDI_SUCCESS); 2025 } else { 2026 if (s_priv->temp_num_retries > 0) { 2027 /* Decrement retry count */ 2028 s_priv->temp_num_retries--; 2029 2030 /* Reset lock_req_step */ 2031 s_priv->lock_req_step = 0; 2032 2033 /* Resend... start at step 0 again */ 2034 return (DDI_FAILURE); 2035 } else { 2036 /* Failed... RETRIES_EXCEEDED */ 2037 target_cmd->cmd_result = CMD1394_ERETRIES_EXCEEDED; 2038 return (DDI_SUCCESS); 2039 } 2040 } 2041 } 2042