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 /* 23 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. 24 */ 25 26 #include <sys/types.h> 27 #include <sys/scsi/generic/commands.h> 28 #include <sys/scsi/impl/commands.h> 29 #include <sys/scsi/generic/smp_frames.h> 30 31 #include <scsi/libsmp.h> 32 #include <scsi/libsmp_plugin.h> 33 #include "sas2.h" 34 35 /*ARGSUSED*/ 36 static size_t 37 sas2_rq_len(size_t user, smp_target_t *tp) 38 { 39 if (user != 0) { 40 (void) smp_set_errno(ESMP_RANGE); 41 return (0); 42 } 43 44 return (SMP_REQ_MINLEN); 45 } 46 47 /*ARGSUSED*/ 48 static off_t 49 sas2_rq_dataoff(smp_action_t *ap, smp_target_t *tp) 50 { 51 size_t len; 52 53 smp_action_get_request_frame(ap, NULL, &len); 54 55 if (len > SMP_REQ_MINLEN) 56 return (offsetof(smp_request_frame_t, srf_data[0])); 57 58 return (-1); 59 } 60 61 static void 62 sas2_rq_setframe(smp_action_t *ap, smp_target_t *tp) 63 { 64 const smp_function_def_t *dp = smp_action_get_function_def(ap); 65 smp_request_frame_t *fp; 66 uint_t cap; 67 uint16_t change_count; 68 uint16_t *rqcc; 69 size_t rqlen, rslen; 70 71 smp_action_get_request_frame(ap, (void *)&fp, &rqlen); 72 smp_action_get_response_frame(ap, NULL, &rslen); 73 cap = smp_target_getcap(tp); 74 75 fp->srf_frame_type = SMP_FRAME_TYPE_REQUEST; 76 fp->srf_function = dp->sfd_function; 77 78 if (cap & SMP_TARGET_C_LONG_RESP) { 79 fp->srf_allocated_response_len = (rslen - SMP_RESP_MINLEN) / 4; 80 fp->srf_request_len = (rqlen - SMP_REQ_MINLEN) / 4; 81 } else { 82 fp->srf_allocated_response_len = 0; 83 fp->srf_request_len = 0; 84 } 85 86 /* 87 * If this command requires that the expected expander change count 88 * be set (as many do), we will attempt to set it based on the 89 * most recently executed command. However, if the user has set it 90 * already, we will not overwrite that setting. It is the consumer's 91 * responsibility to keep track of expander changes each time it 92 * receives a new change count in a response. 93 */ 94 if (dp->sfd_flags & SMP_FD_F_NEEDS_CHANGE_COUNT) { 95 ASSERT(rqlen >= SMP_REQ_MINLEN + sizeof (uint16_t)); 96 /* LINTED - alignment */ 97 rqcc = (uint16_t *)(&fp->srf_data[0]); 98 if (SCSI_READ16(rqcc) == 0) { 99 change_count = smp_target_get_change_count(tp); 100 SCSI_WRITE16(rqcc, change_count); 101 } 102 } 103 } 104 105 /*ARGSUSED*/ 106 static size_t 107 sas2_rs_datalen(smp_action_t *ap, smp_target_t *tp) 108 { 109 smp_response_frame_t *fp; 110 size_t len; 111 112 smp_action_get_response_frame(ap, (void **)&fp, &len); 113 114 if (len >= SMP_RESP_MINLEN) 115 len -= SMP_RESP_MINLEN; 116 else 117 return (0); 118 119 len &= ~3; 120 121 if (fp->srf_response_len == 0) 122 return (0); 123 124 return (MIN(len, 4 * (fp->srf_response_len))); 125 } 126 127 /*ARGSUSED*/ 128 static off_t 129 sas2_rs_dataoff(smp_action_t *ap, smp_target_t *tp) 130 { 131 size_t len; 132 133 smp_action_get_response_frame(ap, NULL, &len); 134 135 if (len > SMP_RESP_MINLEN) 136 return (offsetof(smp_request_frame_t, srf_data[0])); 137 138 return (-1); 139 } 140 141 static void 142 sas2_rs_getparams(smp_action_t *ap, smp_target_t *tp) 143 { 144 const smp_function_def_t *dp; 145 smp_response_frame_t *fp; 146 size_t len; 147 uint16_t change_count; 148 149 dp = smp_action_get_function_def(ap); 150 151 smp_action_get_response_frame(ap, (void **)&fp, &len); 152 153 smp_action_set_result(ap, fp->srf_result); 154 155 if (!(dp->sfd_flags & SMP_FD_F_PROVIDES_CHANGE_COUNT)) 156 return; 157 158 if (len <= SMP_RESP_MINLEN + sizeof (uint16_t)) 159 return; 160 161 change_count = SCSI_READ16(&fp->srf_data[0]); 162 smp_target_set_change_count(tp, change_count); 163 } 164 165 /*ARGSUSED*/ 166 static size_t 167 sas2_report_general_rs_datalen(smp_action_t *ap, smp_target_t *tp) 168 { 169 const smp_function_def_t *dp = smp_action_get_function_def(ap); 170 smp_response_frame_t *fp; 171 size_t len; 172 173 ASSERT(dp->sfd_function == SMP_FUNC_REPORT_GENERAL); 174 smp_action_get_response_frame(ap, (void **)&fp, &len); 175 176 if (len >= SMP_RESP_MINLEN) 177 len -= SMP_RESP_MINLEN; 178 else 179 return (0); 180 181 len &= ~3; 182 183 if (fp->srf_response_len == 0) 184 return (MIN(len, 24)); 185 186 return (MIN(len, 4 * (fp->srf_response_len))); 187 } 188 189 /*ARGSUSED*/ 190 static size_t 191 sas2_report_manufacturer_info_rs_datalen(smp_action_t *ap, smp_target_t *tp) 192 { 193 const smp_function_def_t *dp = smp_action_get_function_def(ap); 194 smp_response_frame_t *fp; 195 size_t len; 196 197 ASSERT(dp->sfd_function == SMP_FUNC_REPORT_MANUFACTURER_INFO); 198 smp_action_get_response_frame(ap, (void **)&fp, &len); 199 200 if (len >= SMP_RESP_MINLEN) 201 len -= SMP_RESP_MINLEN; 202 else 203 return (0); 204 205 len &= ~3; 206 207 if (fp->srf_response_len == 0) 208 return (MIN(len, 56)); 209 210 return (MIN(len, 4 * (fp->srf_response_len))); 211 } 212 213 /*ARGSUSED*/ 214 static size_t 215 sas2_report_self_config_status_rq_len(size_t user, smp_target_t *tp) 216 { 217 if (user != 0) { 218 (void) smp_set_errno(ESMP_RANGE); 219 return (0); 220 } 221 222 return (SMP_REQ_MINLEN + sizeof (smp_report_self_config_status_req_t)); 223 } 224 225 /*ARGSUSED*/ 226 static size_t 227 sas2_report_zone_perm_table_rq_len(size_t user, smp_target_t *tp) 228 { 229 if (user != 0) { 230 (void) smp_set_errno(ESMP_RANGE); 231 return (0); 232 } 233 234 return (SMP_REQ_MINLEN + sizeof (smp_report_zone_perm_table_req_t)); 235 } 236 237 /*ARGSUSED*/ 238 static size_t 239 sas2_report_zone_mgr_password_rq_len(size_t user, smp_target_t *tp) 240 { 241 if (user != 0) { 242 (void) smp_set_errno(ESMP_RANGE); 243 return (0); 244 } 245 246 return (SMP_REQ_MINLEN + sizeof (smp_report_zone_perm_table_req_t)); 247 } 248 249 /*ARGSUSED*/ 250 static size_t 251 sas2_report_broadcast_rq_len(size_t user, smp_target_t *tp) 252 { 253 if (user != 0) { 254 (void) smp_set_errno(ESMP_RANGE); 255 return (0); 256 } 257 258 return (SMP_REQ_MINLEN + sizeof (smp_report_broadcast_req_t)); 259 } 260 261 /*ARGSUSED*/ 262 static size_t 263 sas2_discover_rq_len(size_t user, smp_target_t *tp) 264 { 265 if (user != 0) { 266 (void) smp_set_errno(ESMP_RANGE); 267 return (0); 268 } 269 270 return (SMP_REQ_MINLEN + sizeof (smp_discover_req_t)); 271 } 272 273 /*ARGSUSED*/ 274 static size_t 275 sas2_discover_rs_datalen(smp_action_t *ap, smp_target_t *tp) 276 { 277 const smp_function_def_t *dp = smp_action_get_function_def(ap); 278 smp_response_frame_t *fp; 279 size_t len; 280 281 ASSERT(dp->sfd_function == SMP_FUNC_DISCOVER); 282 smp_action_get_response_frame(ap, (void **)&fp, &len); 283 284 if (len >= SMP_RESP_MINLEN) 285 len -= SMP_RESP_MINLEN; 286 else 287 return (0); 288 289 len &= ~3; 290 291 if (fp->srf_response_len == 0) 292 return (MIN(len, 48)); 293 294 return (MIN(len, 4 * (fp->srf_response_len))); 295 } 296 297 /*ARGSUSED*/ 298 static size_t 299 sas2_report_phy_error_log_rq_len(size_t user, smp_target_t *tp) 300 { 301 if (user != 0) { 302 (void) smp_set_errno(ESMP_RANGE); 303 return (0); 304 } 305 306 return (SMP_REQ_MINLEN + sizeof (smp_report_phy_error_log_req_t)); 307 } 308 309 /*ARGSUSED*/ 310 static size_t 311 sas2_report_phy_error_log_rs_datalen(smp_action_t *ap, smp_target_t *tp) 312 { 313 const smp_function_def_t *dp = smp_action_get_function_def(ap); 314 smp_response_frame_t *fp; 315 size_t len; 316 317 ASSERT(dp->sfd_function == SMP_FUNC_REPORT_PHY_ERROR_LOG); 318 smp_action_get_response_frame(ap, (void **)&fp, &len); 319 320 if (len >= SMP_RESP_MINLEN) 321 len -= SMP_RESP_MINLEN; 322 else 323 return (0); 324 325 len &= ~3; 326 327 if (fp->srf_response_len == 0) 328 return (MIN(len, sizeof (smp_report_phy_error_log_resp_t))); 329 330 return (MIN(len, 4 * (fp->srf_response_len))); 331 } 332 333 /*ARGSUSED*/ 334 static size_t 335 sas2_report_phy_sata_rq_len(size_t user, smp_target_t *tp) 336 { 337 if (user != 0) { 338 (void) smp_set_errno(ESMP_RANGE); 339 return (0); 340 } 341 342 return (SMP_REQ_MINLEN + sizeof (smp_report_phy_sata_req_t)); 343 } 344 345 /*ARGSUSED*/ 346 static size_t 347 sas2_report_phy_sata_rs_datalen(smp_action_t *ap, smp_target_t *tp) 348 { 349 const smp_function_def_t *dp = smp_action_get_function_def(ap); 350 smp_response_frame_t *fp; 351 size_t len; 352 353 ASSERT(dp->sfd_function == SMP_FUNC_REPORT_PHY_SATA); 354 smp_action_get_response_frame(ap, (void **)&fp, &len); 355 356 if (len >= SMP_RESP_MINLEN) 357 len -= SMP_RESP_MINLEN; 358 else 359 return (0); 360 361 len &= ~3; 362 363 if (fp->srf_response_len == 0) 364 return (MIN(len, 52)); 365 366 return (MIN(len, 4 * (fp->srf_response_len))); 367 } 368 369 /*ARGSUSED*/ 370 static size_t 371 sas2_report_route_info_rq_len(size_t user, smp_target_t *tp) 372 { 373 if (user != 0) { 374 (void) smp_set_errno(ESMP_RANGE); 375 return (0); 376 } 377 378 return (SMP_REQ_MINLEN + sizeof (smp_report_route_info_req_t)); 379 } 380 381 /*ARGSUSED*/ 382 static size_t 383 sas2_report_route_info_rs_datalen(smp_action_t *ap, smp_target_t *tp) 384 { 385 const smp_function_def_t *dp = smp_action_get_function_def(ap); 386 smp_response_frame_t *fp; 387 size_t len; 388 389 ASSERT(dp->sfd_function == SMP_FUNC_REPORT_ROUTE_INFO); 390 smp_action_get_response_frame(ap, (void **)&fp, &len); 391 392 if (len >= SMP_RESP_MINLEN) 393 len -= SMP_RESP_MINLEN; 394 else 395 return (0); 396 397 len &= ~3; 398 399 if (fp->srf_response_len == 0) 400 return (MIN(len, sizeof (smp_report_route_info_resp_t))); 401 402 return (MIN(len, 4 * (fp->srf_response_len))); 403 } 404 405 /*ARGSUSED*/ 406 static size_t 407 sas2_report_phy_event_rq_len(size_t user, smp_target_t *tp) 408 { 409 if (user != 0) { 410 (void) smp_set_errno(ESMP_RANGE); 411 return (0); 412 } 413 414 return (SMP_REQ_MINLEN + sizeof (smp_report_phy_event_req_t)); 415 } 416 417 /*ARGSUSED*/ 418 static size_t 419 sas2_discover_list_rq_len(size_t user, smp_target_t *tp) 420 { 421 if (user != 0) { 422 (void) smp_set_errno(ESMP_RANGE); 423 return (0); 424 } 425 426 return (SMP_REQ_MINLEN + sizeof (smp_discover_list_req_t)); 427 } 428 429 /*ARGSUSED*/ 430 static size_t 431 sas2_report_phy_event_list_rq_len(size_t user, smp_target_t *tp) 432 { 433 if (user != 0) { 434 (void) smp_set_errno(ESMP_RANGE); 435 return (0); 436 } 437 438 return (SMP_REQ_MINLEN + sizeof (smp_report_phy_event_list_req_t)); 439 } 440 441 /*ARGSUSED*/ 442 static size_t 443 sas2_report_exp_route_table_list_rq_len(size_t user, smp_target_t *tp) 444 { 445 if (user != 0) { 446 (void) smp_set_errno(ESMP_RANGE); 447 return (0); 448 } 449 450 return (SMP_REQ_MINLEN + 451 sizeof (smp_report_exp_route_table_list_req_t)); 452 } 453 454 /*ARGSUSED*/ 455 static size_t 456 sas2_config_general_rq_len(size_t user, smp_target_t *tp) 457 { 458 if (user != 0) { 459 (void) smp_set_errno(ESMP_RANGE); 460 return (0); 461 } 462 463 return (SMP_REQ_MINLEN + sizeof (smp_config_general_req_t)); 464 } 465 466 /*ARGSUSED*/ 467 static size_t 468 sas2_enable_disable_zoning_rq_len(size_t user, smp_target_t *tp) 469 { 470 if (user != 0) { 471 (void) smp_set_errno(ESMP_RANGE); 472 return (0); 473 } 474 475 return (SMP_REQ_MINLEN + sizeof (smp_enable_disable_zoning_req_t)); 476 } 477 478 /*ARGSUSED*/ 479 static size_t 480 sas2_zoned_broadcast_rq_len(size_t user, smp_target_t *tp) 481 { 482 size_t descrsz; 483 484 if (user == 0 || user > 1008) { 485 (void) smp_set_errno(ESMP_RANGE); 486 return (0); 487 } 488 489 descrsz = P2ROUNDUP((user - 1), 4); 490 491 return (SMP_REQ_MINLEN + descrsz + sizeof (smp_zoned_broadcast_req_t)); 492 } 493 494 /*ARGSUSED*/ 495 static size_t 496 sas2_zone_lock_rq_len(size_t user, smp_target_t *tp) 497 { 498 if (user != 0) { 499 (void) smp_set_errno(ESMP_RANGE); 500 return (0); 501 } 502 503 return (SMP_REQ_MINLEN + sizeof (smp_zone_lock_req_t)); 504 } 505 506 /*ARGSUSED*/ 507 static size_t 508 sas2_zone_activate_rq_len(size_t user, smp_target_t *tp) 509 { 510 if (user != 0) { 511 (void) smp_set_errno(ESMP_RANGE); 512 return (0); 513 } 514 515 return (SMP_REQ_MINLEN + sizeof (smp_zone_activate_req_t)); 516 } 517 518 /*ARGSUSED*/ 519 static size_t 520 sas2_zone_unlock_rq_len(size_t user, smp_target_t *tp) 521 { 522 if (user != 0) { 523 (void) smp_set_errno(ESMP_RANGE); 524 return (0); 525 } 526 527 return (SMP_REQ_MINLEN + sizeof (smp_zone_unlock_req_t)); 528 } 529 530 /*ARGSUSED*/ 531 static size_t 532 sas2_config_zone_manager_password_rq_len(size_t user, smp_target_t *tp) 533 { 534 if (user != 0) { 535 (void) smp_set_errno(ESMP_RANGE); 536 return (0); 537 } 538 539 return (SMP_REQ_MINLEN + 540 sizeof (smp_config_zone_manager_password_req_t)); 541 } 542 543 /*ARGSUSED*/ 544 static size_t 545 sas2_config_zone_phy_info_rq_len(size_t user, smp_target_t *tp) 546 { 547 if (user == 0 || user > 252) { 548 (void) smp_set_errno(ESMP_RANGE); 549 return (0); 550 } 551 552 return (SMP_REQ_MINLEN + sizeof (smp_config_zone_phy_info_req_t) + 553 (user - 1) * sizeof (smp_zone_phy_config_descr_t)); 554 } 555 556 static size_t 557 sas2_config_zone_perm_table_rq_len(size_t user, smp_target_t *tp) 558 { 559 uint_t cap = smp_target_getcap(tp); 560 size_t maxdescr, descrsz; 561 562 if (cap & SMP_TARGET_C_ZG_256) 563 descrsz = sizeof (smp_zone_perm_descr256_t); 564 else 565 descrsz = sizeof (smp_zone_perm_descr128_t); 566 567 maxdescr = (1020 - sizeof (smp_config_zone_perm_table_req_t)) / descrsz; 568 569 if (user == 0 || user > maxdescr) { 570 (void) smp_set_errno(ESMP_RANGE); 571 return (0); 572 } 573 574 return (SMP_REQ_MINLEN + sizeof (smp_config_zone_perm_table_req_t) - 1 + 575 user * descrsz); 576 } 577 578 /*ARGSUSED*/ 579 static size_t 580 sas2_config_route_info_rq_len(size_t user, smp_target_t *tp) 581 { 582 if (user != 0) { 583 (void) smp_set_errno(ESMP_RANGE); 584 return (0); 585 } 586 587 return (SMP_REQ_MINLEN + sizeof (smp_config_route_info_req_t)); 588 } 589 590 /*ARGSUSED*/ 591 static size_t 592 sas2_phy_control_rq_len(size_t user, smp_target_t *tp) 593 { 594 if (user != 0) { 595 (void) smp_set_errno(ESMP_RANGE); 596 return (0); 597 } 598 599 return (SMP_REQ_MINLEN + sizeof (smp_phy_control_req_t)); 600 } 601 602 /*ARGSUSED*/ 603 static size_t 604 sas2_phy_test_function_rq_len(size_t user, smp_target_t *tp) 605 { 606 if (user != 0) { 607 (void) smp_set_errno(ESMP_RANGE); 608 return (0); 609 } 610 611 return (SMP_REQ_MINLEN + sizeof (smp_phy_test_function_req_t)); 612 } 613 614 /*ARGSUSED*/ 615 static size_t 616 sas2_config_phy_event_rq_len(size_t user, smp_target_t *tp) 617 { 618 if (user == 0 || user > 126) { 619 (void) smp_set_errno(ESMP_RANGE); 620 return (0); 621 } 622 623 return (SMP_REQ_MINLEN + sizeof (smp_config_phy_event_req_t) + 624 (user - 1) * sizeof (smp_phy_event_config_descr_t)); 625 } 626 627 smp_function_def_t sas2_functions[] = { 628 { 629 .sfd_function = SMP_FUNC_REPORT_GENERAL, 630 .sfd_flags = SMP_FD_F_READ | SMP_FD_F_PROVIDES_CHANGE_COUNT, 631 .sfd_rq_len = sas2_rq_len, 632 .sfd_rq_dataoff = sas2_rq_dataoff, 633 .sfd_rq_setframe = sas2_rq_setframe, 634 .sfd_rs_datalen = sas2_report_general_rs_datalen, 635 .sfd_rs_dataoff = sas2_rs_dataoff, 636 .sfd_rs_getparams = sas2_rs_getparams 637 }, 638 { 639 .sfd_function = SMP_FUNC_REPORT_MANUFACTURER_INFO, 640 .sfd_flags = SMP_FD_F_READ | SMP_FD_F_PROVIDES_CHANGE_COUNT, 641 .sfd_rq_len = sas2_rq_len, 642 .sfd_rq_dataoff = sas2_rq_dataoff, 643 .sfd_rq_setframe = sas2_rq_setframe, 644 .sfd_rs_datalen = sas2_report_manufacturer_info_rs_datalen, 645 .sfd_rs_dataoff = sas2_rs_dataoff, 646 .sfd_rs_getparams = sas2_rs_getparams 647 }, 648 { 649 .sfd_function = SMP_FUNC_REPORT_SELF_CONFIG_STATUS, 650 .sfd_flags = SMP_FD_F_READ | SMP_FD_F_WRITE | 651 SMP_FD_F_PROVIDES_CHANGE_COUNT, 652 .sfd_rq_len = sas2_report_self_config_status_rq_len, 653 .sfd_rq_dataoff = sas2_rq_dataoff, 654 .sfd_rq_setframe = sas2_rq_setframe, 655 .sfd_rs_datalen = sas2_rs_datalen, 656 .sfd_rs_dataoff = sas2_rs_dataoff, 657 .sfd_rs_getparams = sas2_rs_getparams 658 }, 659 { 660 .sfd_function = SMP_FUNC_REPORT_ZONE_PERM_TABLE, 661 .sfd_flags = SMP_FD_F_READ | SMP_FD_F_WRITE | 662 SMP_FD_F_PROVIDES_CHANGE_COUNT, 663 .sfd_rq_len = sas2_report_zone_perm_table_rq_len, 664 .sfd_rq_dataoff = sas2_rq_dataoff, 665 .sfd_rq_setframe = sas2_rq_setframe, 666 .sfd_rs_datalen = sas2_rs_datalen, 667 .sfd_rs_dataoff = sas2_rs_dataoff, 668 .sfd_rs_getparams = sas2_rs_getparams 669 }, 670 { 671 .sfd_function = SMP_FUNC_REPORT_ZONE_MANAGER_PASSWORD, 672 .sfd_flags = SMP_FD_F_READ | SMP_FD_F_PROVIDES_CHANGE_COUNT, 673 .sfd_rq_len = sas2_report_zone_mgr_password_rq_len, 674 .sfd_rq_dataoff = sas2_rq_dataoff, 675 .sfd_rq_setframe = sas2_rq_setframe, 676 .sfd_rs_datalen = sas2_rs_datalen, 677 .sfd_rs_dataoff = sas2_rs_dataoff, 678 .sfd_rs_getparams = sas2_rs_getparams 679 }, 680 { 681 .sfd_function = SMP_FUNC_REPORT_BROADCAST, 682 .sfd_flags = SMP_FD_F_READ | SMP_FD_F_WRITE | 683 SMP_FD_F_PROVIDES_CHANGE_COUNT, 684 .sfd_rq_len = sas2_report_broadcast_rq_len, 685 .sfd_rq_dataoff = sas2_rq_dataoff, 686 .sfd_rq_setframe = sas2_rq_setframe, 687 .sfd_rs_datalen = sas2_rs_datalen, 688 .sfd_rs_dataoff = sas2_rs_dataoff, 689 .sfd_rs_getparams = sas2_rs_getparams 690 }, 691 { 692 .sfd_function = SMP_FUNC_DISCOVER, 693 .sfd_flags = SMP_FD_F_READ | SMP_FD_F_WRITE | 694 SMP_FD_F_PROVIDES_CHANGE_COUNT, 695 .sfd_rq_len = sas2_discover_rq_len, 696 .sfd_rq_dataoff = sas2_rq_dataoff, 697 .sfd_rq_setframe = sas2_rq_setframe, 698 .sfd_rs_datalen = sas2_discover_rs_datalen, 699 .sfd_rs_dataoff = sas2_rs_dataoff, 700 .sfd_rs_getparams = sas2_rs_getparams 701 }, 702 { 703 .sfd_function = SMP_FUNC_REPORT_PHY_ERROR_LOG, 704 .sfd_flags = SMP_FD_F_READ | SMP_FD_F_WRITE | 705 SMP_FD_F_PROVIDES_CHANGE_COUNT, 706 .sfd_rq_len = sas2_report_phy_error_log_rq_len, 707 .sfd_rq_dataoff = sas2_rq_dataoff, 708 .sfd_rq_setframe = sas2_rq_setframe, 709 .sfd_rs_datalen = sas2_report_phy_error_log_rs_datalen, 710 .sfd_rs_dataoff = sas2_rs_dataoff, 711 .sfd_rs_getparams = sas2_rs_getparams 712 }, 713 { 714 .sfd_function = SMP_FUNC_REPORT_PHY_SATA, 715 .sfd_flags = SMP_FD_F_READ | SMP_FD_F_WRITE | 716 SMP_FD_F_PROVIDES_CHANGE_COUNT, 717 .sfd_rq_len = sas2_report_phy_sata_rq_len, 718 .sfd_rq_dataoff = sas2_rq_dataoff, 719 .sfd_rq_setframe = sas2_rq_setframe, 720 .sfd_rs_datalen = sas2_report_phy_sata_rs_datalen, 721 .sfd_rs_dataoff = sas2_rs_dataoff, 722 .sfd_rs_getparams = sas2_rs_getparams 723 }, 724 { 725 .sfd_function = SMP_FUNC_REPORT_ROUTE_INFO, 726 .sfd_flags = SMP_FD_F_READ | SMP_FD_F_WRITE | 727 SMP_FD_F_PROVIDES_CHANGE_COUNT, 728 .sfd_rq_len = sas2_report_route_info_rq_len, 729 .sfd_rq_dataoff = sas2_rq_dataoff, 730 .sfd_rq_setframe = sas2_rq_setframe, 731 .sfd_rs_datalen = sas2_report_route_info_rs_datalen, 732 .sfd_rs_dataoff = sas2_rs_dataoff, 733 .sfd_rs_getparams = sas2_rs_getparams 734 }, 735 { 736 .sfd_function = SMP_FUNC_REPORT_PHY_EVENT, 737 .sfd_flags = SMP_FD_F_READ | SMP_FD_F_WRITE | 738 SMP_FD_F_PROVIDES_CHANGE_COUNT, 739 .sfd_rq_len = sas2_report_phy_event_rq_len, 740 .sfd_rq_dataoff = sas2_rq_dataoff, 741 .sfd_rq_setframe = sas2_rq_setframe, 742 .sfd_rs_datalen = sas2_rs_datalen, 743 .sfd_rs_dataoff = sas2_rs_dataoff, 744 .sfd_rs_getparams = sas2_rs_getparams 745 }, 746 { 747 .sfd_function = SMP_FUNC_DISCOVER_LIST, 748 .sfd_flags = SMP_FD_F_READ | SMP_FD_F_WRITE | 749 SMP_FD_F_PROVIDES_CHANGE_COUNT, 750 .sfd_rq_len = sas2_discover_list_rq_len, 751 .sfd_rq_dataoff = sas2_rq_dataoff, 752 .sfd_rq_setframe = sas2_rq_setframe, 753 .sfd_rs_datalen = sas2_rs_datalen, 754 .sfd_rs_dataoff = sas2_rs_dataoff, 755 .sfd_rs_getparams = sas2_rs_getparams 756 }, 757 { 758 .sfd_function = SMP_FUNC_REPORT_PHY_EVENT_LIST, 759 .sfd_flags = SMP_FD_F_READ | SMP_FD_F_WRITE | 760 SMP_FD_F_PROVIDES_CHANGE_COUNT, 761 .sfd_rq_len = sas2_report_phy_event_list_rq_len, 762 .sfd_rq_dataoff = sas2_rq_dataoff, 763 .sfd_rq_setframe = sas2_rq_setframe, 764 .sfd_rs_datalen = sas2_rs_datalen, 765 .sfd_rs_dataoff = sas2_rs_dataoff, 766 .sfd_rs_getparams = sas2_rs_getparams 767 }, 768 { 769 .sfd_function = SMP_FUNC_REPORT_EXP_ROUTE_TABLE_LIST, 770 .sfd_flags = SMP_FD_F_READ | SMP_FD_F_WRITE | 771 SMP_FD_F_PROVIDES_CHANGE_COUNT, 772 .sfd_rq_len = sas2_report_exp_route_table_list_rq_len, 773 .sfd_rq_dataoff = sas2_rq_dataoff, 774 .sfd_rq_setframe = sas2_rq_setframe, 775 .sfd_rs_datalen = sas2_rs_datalen, 776 .sfd_rs_dataoff = sas2_rs_dataoff, 777 .sfd_rs_getparams = sas2_rs_getparams 778 }, 779 { 780 .sfd_function = SMP_FUNC_CONFIG_GENERAL, 781 .sfd_flags = SMP_FD_F_WRITE | SMP_FD_F_NEEDS_CHANGE_COUNT, 782 .sfd_rq_len = sas2_config_general_rq_len, 783 .sfd_rq_dataoff = sas2_rq_dataoff, 784 .sfd_rq_setframe = sas2_rq_setframe, 785 .sfd_rs_datalen = sas2_rs_datalen, 786 .sfd_rs_dataoff = sas2_rs_dataoff, 787 .sfd_rs_getparams = sas2_rs_getparams 788 }, 789 { 790 .sfd_function = SMP_FUNC_ENABLE_DISABLE_ZONING, 791 .sfd_flags = SMP_FD_F_WRITE | SMP_FD_F_NEEDS_CHANGE_COUNT, 792 .sfd_rq_len = sas2_enable_disable_zoning_rq_len, 793 .sfd_rq_dataoff = sas2_rq_dataoff, 794 .sfd_rq_setframe = sas2_rq_setframe, 795 .sfd_rs_datalen = sas2_rs_datalen, 796 .sfd_rs_dataoff = sas2_rs_dataoff, 797 .sfd_rs_getparams = sas2_rs_getparams 798 }, 799 { 800 .sfd_function = SMP_FUNC_ZONED_BROADCAST, 801 .sfd_flags = SMP_FD_F_WRITE, 802 .sfd_rq_len = sas2_zoned_broadcast_rq_len, 803 .sfd_rq_dataoff = sas2_rq_dataoff, 804 .sfd_rq_setframe = sas2_rq_setframe, 805 .sfd_rs_datalen = sas2_rs_datalen, 806 .sfd_rs_dataoff = sas2_rs_dataoff, 807 .sfd_rs_getparams = sas2_rs_getparams 808 }, 809 { 810 .sfd_function = SMP_FUNC_ZONE_LOCK, 811 .sfd_flags = SMP_FD_F_READ | SMP_FD_F_WRITE | 812 SMP_FD_F_NEEDS_CHANGE_COUNT, 813 .sfd_rq_len = sas2_zone_lock_rq_len, 814 .sfd_rq_dataoff = sas2_rq_dataoff, 815 .sfd_rq_setframe = sas2_rq_setframe, 816 .sfd_rs_datalen = sas2_rs_datalen, 817 .sfd_rs_dataoff = sas2_rs_dataoff, 818 .sfd_rs_getparams = sas2_rs_getparams 819 }, 820 { 821 .sfd_function = SMP_FUNC_ZONE_ACTIVATE, 822 .sfd_flags = SMP_FD_F_WRITE | SMP_FD_F_NEEDS_CHANGE_COUNT, 823 .sfd_rq_len = sas2_zone_activate_rq_len, 824 .sfd_rq_dataoff = sas2_rq_dataoff, 825 .sfd_rq_setframe = sas2_rq_setframe, 826 .sfd_rs_datalen = sas2_rs_datalen, 827 .sfd_rs_dataoff = sas2_rs_dataoff, 828 .sfd_rs_getparams = sas2_rs_getparams 829 }, 830 { 831 .sfd_function = SMP_FUNC_ZONE_UNLOCK, 832 .sfd_flags = SMP_FD_F_WRITE, 833 .sfd_rq_len = sas2_zone_unlock_rq_len, 834 .sfd_rq_dataoff = sas2_rq_dataoff, 835 .sfd_rq_setframe = sas2_rq_setframe, 836 .sfd_rs_datalen = sas2_rs_datalen, 837 .sfd_rs_dataoff = sas2_rs_dataoff, 838 .sfd_rs_getparams = sas2_rs_getparams 839 }, 840 { 841 .sfd_function = SMP_FUNC_CONFIG_ZONE_MANAGER_PASSWORD, 842 .sfd_flags = SMP_FD_F_WRITE | SMP_FD_F_NEEDS_CHANGE_COUNT, 843 .sfd_rq_len = sas2_config_zone_manager_password_rq_len, 844 .sfd_rq_dataoff = sas2_rq_dataoff, 845 .sfd_rq_setframe = sas2_rq_setframe, 846 .sfd_rs_datalen = sas2_rs_datalen, 847 .sfd_rs_dataoff = sas2_rs_dataoff, 848 .sfd_rs_getparams = sas2_rs_getparams 849 }, 850 { 851 .sfd_function = SMP_FUNC_CONFIG_ZONE_PHY_INFO, 852 .sfd_flags = SMP_FD_F_WRITE | SMP_FD_F_NEEDS_CHANGE_COUNT, 853 .sfd_rq_len = sas2_config_zone_phy_info_rq_len, 854 .sfd_rq_dataoff = sas2_rq_dataoff, 855 .sfd_rq_setframe = sas2_rq_setframe, 856 .sfd_rs_datalen = sas2_rs_datalen, 857 .sfd_rs_dataoff = sas2_rs_dataoff, 858 .sfd_rs_getparams = sas2_rs_getparams 859 }, 860 { 861 .sfd_function = SMP_FUNC_CONFIG_ZONE_PERM_TABLE, 862 .sfd_flags = SMP_FD_F_WRITE | SMP_FD_F_NEEDS_CHANGE_COUNT, 863 .sfd_rq_len = sas2_config_zone_perm_table_rq_len, 864 .sfd_rq_dataoff = sas2_rq_dataoff, 865 .sfd_rq_setframe = sas2_rq_setframe, 866 .sfd_rs_datalen = sas2_rs_datalen, 867 .sfd_rs_dataoff = sas2_rs_dataoff, 868 .sfd_rs_getparams = sas2_rs_getparams 869 }, 870 { 871 .sfd_function = SMP_FUNC_CONFIG_ROUTE_INFO, 872 .sfd_flags = SMP_FD_F_WRITE | SMP_FD_F_NEEDS_CHANGE_COUNT, 873 .sfd_rq_len = sas2_config_route_info_rq_len, 874 .sfd_rq_dataoff = sas2_rq_dataoff, 875 .sfd_rq_setframe = sas2_rq_setframe, 876 .sfd_rs_datalen = sas2_rs_datalen, 877 .sfd_rs_dataoff = sas2_rs_dataoff, 878 .sfd_rs_getparams = sas2_rs_getparams 879 }, 880 { 881 .sfd_function = SMP_FUNC_PHY_CONTROL, 882 .sfd_flags = SMP_FD_F_WRITE | SMP_FD_F_NEEDS_CHANGE_COUNT, 883 .sfd_rq_len = sas2_phy_control_rq_len, 884 .sfd_rq_dataoff = sas2_rq_dataoff, 885 .sfd_rq_setframe = sas2_rq_setframe, 886 .sfd_rs_datalen = sas2_rs_datalen, 887 .sfd_rs_dataoff = sas2_rs_dataoff, 888 .sfd_rs_getparams = sas2_rs_getparams 889 }, 890 { 891 .sfd_function = SMP_FUNC_PHY_TEST_FUNCTION, 892 .sfd_flags = SMP_FD_F_WRITE | SMP_FD_F_NEEDS_CHANGE_COUNT, 893 .sfd_rq_len = sas2_phy_test_function_rq_len, 894 .sfd_rq_dataoff = sas2_rq_dataoff, 895 .sfd_rq_setframe = sas2_rq_setframe, 896 .sfd_rs_datalen = sas2_rs_datalen, 897 .sfd_rs_dataoff = sas2_rs_dataoff, 898 .sfd_rs_getparams = sas2_rs_getparams 899 }, 900 { 901 .sfd_function = SMP_FUNC_CONFIG_PHY_EVENT, 902 .sfd_flags = SMP_FD_F_WRITE | SMP_FD_F_NEEDS_CHANGE_COUNT, 903 .sfd_rq_len = sas2_config_phy_event_rq_len, 904 .sfd_rq_dataoff = sas2_rq_dataoff, 905 .sfd_rq_setframe = sas2_rq_setframe, 906 .sfd_rs_datalen = sas2_rs_datalen, 907 .sfd_rs_dataoff = sas2_rs_dataoff, 908 .sfd_rs_getparams = sas2_rs_getparams 909 }, 910 { 911 .sfd_function = -1 912 } 913 }; 914 915 /* 916 * Returns the number of bytes in the request frame, including the header 917 * and footer, for the given function and capabilities. Presently the only 918 * relevant capability is long-request, which in some cases increases the 919 * size of the request from the SAS-1 spec to that found in SAS-2. 920 * 921 * Variably-sized request frames have no default size; we return 0 in that 922 * case, which will often be interpreted by the caller as an error although 923 * in general it is not. 924 */ 925 size_t 926 smp_default_request_len(uint_t cap, smp_function_t fn) 927 { 928 switch (fn) { 929 case SMP_FUNC_REPORT_GENERAL: 930 case SMP_FUNC_REPORT_MANUFACTURER_INFO: 931 return (SMP_REQ_MINLEN); 932 case SMP_FUNC_REPORT_ZONE_MANAGER_PASSWORD: 933 return (SMP_REQ_MINLEN + 934 sizeof (smp_report_zone_mgr_password_req_t)); 935 case SMP_FUNC_REPORT_SELF_CONFIG_STATUS: 936 if (cap & SMP_TARGET_C_LONG_RESP) 937 return (SMP_REQ_MINLEN + 938 sizeof (smp_report_self_config_status_req_t)); 939 return (SMP_REQ_MINLEN); 940 case SMP_FUNC_REPORT_ZONE_PERM_TABLE: 941 if (cap & SMP_TARGET_C_LONG_RESP) 942 return (SMP_REQ_MINLEN + 943 sizeof (smp_report_zone_perm_table_req_t)); 944 return (SMP_REQ_MINLEN); 945 case SMP_FUNC_REPORT_BROADCAST: 946 if (cap & SMP_TARGET_C_LONG_RESP) 947 return (SMP_REQ_MINLEN + 948 sizeof (smp_report_broadcast_req_t)); 949 return (SMP_REQ_MINLEN); 950 case SMP_FUNC_DISCOVER: 951 return (SMP_REQ_MINLEN + sizeof (smp_discover_req_t)); 952 case SMP_FUNC_REPORT_PHY_ERROR_LOG: 953 return (SMP_REQ_MINLEN + 954 sizeof (smp_report_phy_error_log_req_t)); 955 case SMP_FUNC_REPORT_PHY_SATA: 956 return (SMP_REQ_MINLEN + sizeof (smp_report_phy_sata_req_t)); 957 case SMP_FUNC_REPORT_ROUTE_INFO: 958 return (SMP_REQ_MINLEN + sizeof (smp_report_route_info_req_t)); 959 case SMP_FUNC_REPORT_PHY_EVENT: 960 if (cap & SMP_TARGET_C_LONG_RESP) 961 return (SMP_REQ_MINLEN + 962 sizeof (smp_report_phy_event_req_t)); 963 return (SMP_REQ_MINLEN); 964 case SMP_FUNC_DISCOVER_LIST: 965 if (cap & SMP_TARGET_C_LONG_RESP) 966 return (SMP_REQ_MINLEN + 967 sizeof (smp_discover_list_req_t)); 968 return (SMP_REQ_MINLEN); 969 case SMP_FUNC_REPORT_PHY_EVENT_LIST: 970 if (cap & SMP_TARGET_C_LONG_RESP) 971 return (SMP_REQ_MINLEN + 972 sizeof (smp_report_phy_event_list_req_t)); 973 return (SMP_REQ_MINLEN); 974 case SMP_FUNC_REPORT_EXP_ROUTE_TABLE_LIST: 975 if (cap & SMP_TARGET_C_LONG_RESP) 976 return (SMP_REQ_MINLEN + 977 sizeof (smp_report_exp_route_table_list_req_t)); 978 return (SMP_REQ_MINLEN); 979 case SMP_FUNC_CONFIG_GENERAL: 980 if (cap & SMP_TARGET_C_LONG_RESP) 981 return (SMP_REQ_MINLEN + 982 sizeof (smp_config_general_req_t)); 983 return (SMP_REQ_MINLEN); 984 case SMP_FUNC_ENABLE_DISABLE_ZONING: 985 if (cap & SMP_TARGET_C_LONG_RESP) 986 return (SMP_REQ_MINLEN + 987 sizeof (smp_enable_disable_zoning_req_t)); 988 return (SMP_REQ_MINLEN); 989 case SMP_FUNC_ZONE_LOCK: 990 if (cap & SMP_TARGET_C_LONG_RESP) 991 return (SMP_REQ_MINLEN + 992 sizeof (smp_zone_lock_req_t)); 993 return (SMP_REQ_MINLEN); 994 case SMP_FUNC_ZONE_ACTIVATE: 995 if (cap & SMP_TARGET_C_LONG_RESP) 996 return (SMP_REQ_MINLEN + 997 sizeof (smp_zone_activate_req_t)); 998 return (SMP_REQ_MINLEN); 999 case SMP_FUNC_ZONE_UNLOCK: 1000 if (cap & SMP_TARGET_C_LONG_RESP) 1001 return (SMP_REQ_MINLEN + 1002 sizeof (smp_zone_unlock_req_t)); 1003 return (SMP_REQ_MINLEN); 1004 case SMP_FUNC_CONFIG_ZONE_MANAGER_PASSWORD: 1005 if (cap & SMP_TARGET_C_LONG_RESP) 1006 return (SMP_REQ_MINLEN + 1007 sizeof (smp_config_zone_manager_password_req_t)); 1008 return (SMP_REQ_MINLEN); 1009 case SMP_FUNC_CONFIG_ROUTE_INFO: 1010 return (SMP_REQ_MINLEN + sizeof (smp_config_route_info_req_t)); 1011 case SMP_FUNC_PHY_CONTROL: 1012 return (SMP_REQ_MINLEN + sizeof (smp_phy_control_req_t)); 1013 case SMP_FUNC_PHY_TEST_FUNCTION: 1014 return (SMP_REQ_MINLEN + sizeof (smp_phy_test_function_req_t)); 1015 1016 case SMP_FUNC_ZONED_BROADCAST: 1017 case SMP_FUNC_CONFIG_ZONE_PHY_INFO: 1018 case SMP_FUNC_CONFIG_ZONE_PERM_TABLE: 1019 case SMP_FUNC_CONFIG_PHY_EVENT: 1020 default: 1021 return (0); 1022 } 1023 } 1024 1025 /* 1026 * This is slightly different - return the length in bytes, including the 1027 * header and footer, to be assumed for the response frame type if the 1028 * length field is zero. Since the length field will not be zero unless the 1029 * long response bit is clear or the target is buggy, we always assume that 1030 * the caller wants the size of the v1 frame. 1031 */ 1032 /*ARGSUSED*/ 1033 size_t 1034 smp_default_response_len(uint_t cap, smp_function_t fn) 1035 { 1036 switch (fn) { 1037 case SMP_FUNC_REPORT_SELF_CONFIG_STATUS: 1038 case SMP_FUNC_REPORT_ZONE_PERM_TABLE: 1039 case SMP_FUNC_REPORT_BROADCAST: 1040 case SMP_FUNC_REPORT_PHY_EVENT: 1041 case SMP_FUNC_DISCOVER_LIST: 1042 case SMP_FUNC_REPORT_PHY_EVENT_LIST: 1043 case SMP_FUNC_REPORT_EXP_ROUTE_TABLE_LIST: 1044 case SMP_FUNC_CONFIG_GENERAL: 1045 case SMP_FUNC_ENABLE_DISABLE_ZONING: 1046 case SMP_FUNC_ZONED_BROADCAST: 1047 case SMP_FUNC_ZONE_LOCK: 1048 case SMP_FUNC_ZONE_ACTIVATE: 1049 case SMP_FUNC_ZONE_UNLOCK: 1050 case SMP_FUNC_CONFIG_ZONE_MANAGER_PASSWORD: 1051 case SMP_FUNC_CONFIG_ZONE_PHY_INFO: 1052 case SMP_FUNC_CONFIG_ZONE_PERM_TABLE: 1053 case SMP_FUNC_CONFIG_ROUTE_INFO: 1054 case SMP_FUNC_PHY_CONTROL: 1055 case SMP_FUNC_PHY_TEST_FUNCTION: 1056 case SMP_FUNC_CONFIG_PHY_EVENT: 1057 return (SMP_RESP_MINLEN); 1058 case SMP_FUNC_REPORT_ZONE_MANAGER_PASSWORD: 1059 return (SMP_RESP_MINLEN + 1060 sizeof (smp_report_zone_mgr_password_resp_t)); 1061 case SMP_FUNC_REPORT_GENERAL: 1062 return (SMP_RESP_MINLEN + 24); 1063 case SMP_FUNC_REPORT_MANUFACTURER_INFO: 1064 return (SMP_RESP_MINLEN + 1065 sizeof (smp_report_manufacturer_info_resp_t)); 1066 case SMP_FUNC_DISCOVER: 1067 return (SMP_RESP_MINLEN + 48); 1068 case SMP_FUNC_REPORT_PHY_ERROR_LOG: 1069 return (SMP_RESP_MINLEN + 1070 sizeof (smp_report_phy_error_log_resp_t)); 1071 case SMP_FUNC_REPORT_PHY_SATA: 1072 return (SMP_RESP_MINLEN + 52); 1073 case SMP_FUNC_REPORT_ROUTE_INFO: 1074 return (SMP_RESP_MINLEN + 1075 sizeof (smp_report_route_info_resp_t)); 1076 1077 default: 1078 return (0); 1079 } 1080 } 1081