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_broadcast_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_broadcast_req_t)); 247 } 248 249 /*ARGSUSED*/ 250 static size_t 251 sas2_discover_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_discover_req_t)); 259 } 260 261 /*ARGSUSED*/ 262 static size_t 263 sas2_discover_rs_datalen(smp_action_t *ap, smp_target_t *tp) 264 { 265 const smp_function_def_t *dp = smp_action_get_function_def(ap); 266 smp_response_frame_t *fp; 267 size_t len; 268 269 ASSERT(dp->sfd_function == SMP_FUNC_DISCOVER); 270 smp_action_get_response_frame(ap, (void **)&fp, &len); 271 272 if (len >= SMP_RESP_MINLEN) 273 len -= SMP_RESP_MINLEN; 274 else 275 return (0); 276 277 len &= ~3; 278 279 if (fp->srf_response_len == 0) 280 return (MIN(len, 48)); 281 282 return (MIN(len, 4 * (fp->srf_response_len))); 283 } 284 285 /*ARGSUSED*/ 286 static size_t 287 sas2_report_phy_error_log_rq_len(size_t user, smp_target_t *tp) 288 { 289 if (user != 0) { 290 (void) smp_set_errno(ESMP_RANGE); 291 return (0); 292 } 293 294 return (SMP_REQ_MINLEN + sizeof (smp_report_phy_error_log_req_t)); 295 } 296 297 /*ARGSUSED*/ 298 static size_t 299 sas2_report_phy_error_log_rs_datalen(smp_action_t *ap, smp_target_t *tp) 300 { 301 const smp_function_def_t *dp = smp_action_get_function_def(ap); 302 smp_response_frame_t *fp; 303 size_t len; 304 305 ASSERT(dp->sfd_function == SMP_FUNC_REPORT_PHY_ERROR_LOG); 306 smp_action_get_response_frame(ap, (void **)&fp, &len); 307 308 if (len >= SMP_RESP_MINLEN) 309 len -= SMP_RESP_MINLEN; 310 else 311 return (0); 312 313 len &= ~3; 314 315 if (fp->srf_response_len == 0) 316 return (MIN(len, sizeof (smp_report_phy_error_log_resp_t))); 317 318 return (MIN(len, 4 * (fp->srf_response_len))); 319 } 320 321 /*ARGSUSED*/ 322 static size_t 323 sas2_report_phy_sata_rq_len(size_t user, smp_target_t *tp) 324 { 325 if (user != 0) { 326 (void) smp_set_errno(ESMP_RANGE); 327 return (0); 328 } 329 330 return (SMP_REQ_MINLEN + sizeof (smp_report_phy_sata_req_t)); 331 } 332 333 /*ARGSUSED*/ 334 static size_t 335 sas2_report_phy_sata_rs_datalen(smp_action_t *ap, smp_target_t *tp) 336 { 337 const smp_function_def_t *dp = smp_action_get_function_def(ap); 338 smp_response_frame_t *fp; 339 size_t len; 340 341 ASSERT(dp->sfd_function == SMP_FUNC_REPORT_PHY_SATA); 342 smp_action_get_response_frame(ap, (void **)&fp, &len); 343 344 if (len >= SMP_RESP_MINLEN) 345 len -= SMP_RESP_MINLEN; 346 else 347 return (0); 348 349 len &= ~3; 350 351 if (fp->srf_response_len == 0) 352 return (MIN(len, 52)); 353 354 return (MIN(len, 4 * (fp->srf_response_len))); 355 } 356 357 /*ARGSUSED*/ 358 static size_t 359 sas2_report_route_info_rq_len(size_t user, smp_target_t *tp) 360 { 361 if (user != 0) { 362 (void) smp_set_errno(ESMP_RANGE); 363 return (0); 364 } 365 366 return (SMP_REQ_MINLEN + sizeof (smp_report_route_info_req_t)); 367 } 368 369 /*ARGSUSED*/ 370 static size_t 371 sas2_report_route_info_rs_datalen(smp_action_t *ap, smp_target_t *tp) 372 { 373 const smp_function_def_t *dp = smp_action_get_function_def(ap); 374 smp_response_frame_t *fp; 375 size_t len; 376 377 ASSERT(dp->sfd_function == SMP_FUNC_REPORT_ROUTE_INFO); 378 smp_action_get_response_frame(ap, (void **)&fp, &len); 379 380 if (len >= SMP_RESP_MINLEN) 381 len -= SMP_RESP_MINLEN; 382 else 383 return (0); 384 385 len &= ~3; 386 387 if (fp->srf_response_len == 0) 388 return (MIN(len, sizeof (smp_report_route_info_resp_t))); 389 390 return (MIN(len, 4 * (fp->srf_response_len))); 391 } 392 393 /*ARGSUSED*/ 394 static size_t 395 sas2_report_phy_event_rq_len(size_t user, smp_target_t *tp) 396 { 397 if (user != 0) { 398 (void) smp_set_errno(ESMP_RANGE); 399 return (0); 400 } 401 402 return (SMP_REQ_MINLEN + sizeof (smp_report_phy_event_req_t)); 403 } 404 405 /*ARGSUSED*/ 406 static size_t 407 sas2_discover_list_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_discover_list_req_t)); 415 } 416 417 /*ARGSUSED*/ 418 static size_t 419 sas2_report_phy_event_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_report_phy_event_list_req_t)); 427 } 428 429 /*ARGSUSED*/ 430 static size_t 431 sas2_report_exp_route_table_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 + 439 sizeof (smp_report_exp_route_table_list_req_t)); 440 } 441 442 /*ARGSUSED*/ 443 static size_t 444 sas2_config_general_rq_len(size_t user, smp_target_t *tp) 445 { 446 if (user != 0) { 447 (void) smp_set_errno(ESMP_RANGE); 448 return (0); 449 } 450 451 return (SMP_REQ_MINLEN + sizeof (smp_config_general_req_t)); 452 } 453 454 /*ARGSUSED*/ 455 static size_t 456 sas2_enable_disable_zoning_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_enable_disable_zoning_req_t)); 464 } 465 466 /*ARGSUSED*/ 467 static size_t 468 sas2_zoned_broadcast_rq_len(size_t user, smp_target_t *tp) 469 { 470 size_t descrsz; 471 472 if (user == 0 || user > 1008) { 473 (void) smp_set_errno(ESMP_RANGE); 474 return (0); 475 } 476 477 descrsz = P2ROUNDUP((user - 1), 4); 478 479 return (SMP_REQ_MINLEN + descrsz + sizeof (smp_zoned_broadcast_req_t)); 480 } 481 482 /*ARGSUSED*/ 483 static size_t 484 sas2_zone_lock_rq_len(size_t user, smp_target_t *tp) 485 { 486 if (user != 0) { 487 (void) smp_set_errno(ESMP_RANGE); 488 return (0); 489 } 490 491 return (SMP_REQ_MINLEN + sizeof (smp_zone_lock_req_t)); 492 } 493 494 /*ARGSUSED*/ 495 static size_t 496 sas2_zone_activate_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_activate_req_t)); 504 } 505 506 /*ARGSUSED*/ 507 static size_t 508 sas2_zone_unlock_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_unlock_req_t)); 516 } 517 518 /*ARGSUSED*/ 519 static size_t 520 sas2_config_zone_manager_password_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 + 528 sizeof (smp_config_zone_manager_password_req_t)); 529 } 530 531 /*ARGSUSED*/ 532 static size_t 533 sas2_config_zone_phy_info_rq_len(size_t user, smp_target_t *tp) 534 { 535 if (user == 0 || user > 252) { 536 (void) smp_set_errno(ESMP_RANGE); 537 return (0); 538 } 539 540 return (SMP_REQ_MINLEN + sizeof (smp_config_zone_phy_info_req_t) + 541 (user - 1) * sizeof (smp_zone_phy_config_descr_t)); 542 } 543 544 static size_t 545 sas2_config_zone_perm_table_rq_len(size_t user, smp_target_t *tp) 546 { 547 uint_t cap = smp_target_getcap(tp); 548 size_t maxdescr, descrsz; 549 550 if (cap & SMP_TARGET_C_ZG_256) 551 descrsz = sizeof (smp_zone_perm_descr256_t); 552 else 553 descrsz = sizeof (smp_zone_perm_descr128_t); 554 555 maxdescr = (1020 - sizeof (smp_config_zone_perm_table_req_t)) / descrsz; 556 557 if (user == 0 || user > maxdescr) { 558 (void) smp_set_errno(ESMP_RANGE); 559 return (0); 560 } 561 562 return (SMP_REQ_MINLEN + sizeof (smp_config_zone_perm_table_req_t) - 1 + 563 user * descrsz); 564 } 565 566 /*ARGSUSED*/ 567 static size_t 568 sas2_config_route_info_rq_len(size_t user, smp_target_t *tp) 569 { 570 if (user != 0) { 571 (void) smp_set_errno(ESMP_RANGE); 572 return (0); 573 } 574 575 return (SMP_REQ_MINLEN + sizeof (smp_config_route_info_req_t)); 576 } 577 578 /*ARGSUSED*/ 579 static size_t 580 sas2_phy_control_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_phy_control_req_t)); 588 } 589 590 /*ARGSUSED*/ 591 static size_t 592 sas2_phy_test_function_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_test_function_req_t)); 600 } 601 602 /*ARGSUSED*/ 603 static size_t 604 sas2_config_phy_event_rq_len(size_t user, smp_target_t *tp) 605 { 606 if (user == 0 || user > 126) { 607 (void) smp_set_errno(ESMP_RANGE); 608 return (0); 609 } 610 611 return (SMP_REQ_MINLEN + sizeof (smp_config_phy_event_req_t) + 612 (user - 1) * sizeof (smp_phy_event_config_descr_t)); 613 } 614 615 smp_function_def_t sas2_functions[] = { 616 { 617 .sfd_function = SMP_FUNC_REPORT_GENERAL, 618 .sfd_flags = SMP_FD_F_READ | SMP_FD_F_PROVIDES_CHANGE_COUNT, 619 .sfd_rq_len = sas2_rq_len, 620 .sfd_rq_dataoff = sas2_rq_dataoff, 621 .sfd_rq_setframe = sas2_rq_setframe, 622 .sfd_rs_datalen = sas2_report_general_rs_datalen, 623 .sfd_rs_dataoff = sas2_rs_dataoff, 624 .sfd_rs_getparams = sas2_rs_getparams 625 }, 626 { 627 .sfd_function = SMP_FUNC_REPORT_MANUFACTURER_INFO, 628 .sfd_flags = SMP_FD_F_READ | SMP_FD_F_PROVIDES_CHANGE_COUNT, 629 .sfd_rq_len = sas2_rq_len, 630 .sfd_rq_dataoff = sas2_rq_dataoff, 631 .sfd_rq_setframe = sas2_rq_setframe, 632 .sfd_rs_datalen = sas2_report_manufacturer_info_rs_datalen, 633 .sfd_rs_dataoff = sas2_rs_dataoff, 634 .sfd_rs_getparams = sas2_rs_getparams 635 }, 636 { 637 .sfd_function = SMP_FUNC_REPORT_SELF_CONFIG_STATUS, 638 .sfd_flags = SMP_FD_F_READ | SMP_FD_F_WRITE | 639 SMP_FD_F_PROVIDES_CHANGE_COUNT, 640 .sfd_rq_len = sas2_report_self_config_status_rq_len, 641 .sfd_rq_dataoff = sas2_rq_dataoff, 642 .sfd_rq_setframe = sas2_rq_setframe, 643 .sfd_rs_datalen = sas2_rs_datalen, 644 .sfd_rs_dataoff = sas2_rs_dataoff, 645 .sfd_rs_getparams = sas2_rs_getparams 646 }, 647 { 648 .sfd_function = SMP_FUNC_REPORT_ZONE_PERM_TABLE, 649 .sfd_flags = SMP_FD_F_READ | SMP_FD_F_WRITE | 650 SMP_FD_F_PROVIDES_CHANGE_COUNT, 651 .sfd_rq_len = sas2_report_zone_perm_table_rq_len, 652 .sfd_rq_dataoff = sas2_rq_dataoff, 653 .sfd_rq_setframe = sas2_rq_setframe, 654 .sfd_rs_datalen = sas2_rs_datalen, 655 .sfd_rs_dataoff = sas2_rs_dataoff, 656 .sfd_rs_getparams = sas2_rs_getparams 657 }, 658 { 659 .sfd_function = SMP_FUNC_REPORT_ZONE_MANAGER_PASSWORD, 660 .sfd_flags = SMP_FD_F_READ | SMP_FD_F_PROVIDES_CHANGE_COUNT, 661 .sfd_rq_len = sas2_rq_len, 662 .sfd_rq_dataoff = sas2_rq_dataoff, 663 .sfd_rq_setframe = sas2_rq_setframe, 664 .sfd_rs_datalen = sas2_rs_datalen, 665 .sfd_rs_dataoff = sas2_rs_dataoff, 666 .sfd_rs_getparams = sas2_rs_getparams 667 }, 668 { 669 .sfd_function = SMP_FUNC_REPORT_BROADCAST, 670 .sfd_flags = SMP_FD_F_READ | SMP_FD_F_WRITE | 671 SMP_FD_F_PROVIDES_CHANGE_COUNT, 672 .sfd_rq_len = sas2_report_broadcast_rq_len, 673 .sfd_rq_dataoff = sas2_rq_dataoff, 674 .sfd_rq_setframe = sas2_rq_setframe, 675 .sfd_rs_datalen = sas2_rs_datalen, 676 .sfd_rs_dataoff = sas2_rs_dataoff, 677 .sfd_rs_getparams = sas2_rs_getparams 678 }, 679 { 680 .sfd_function = SMP_FUNC_DISCOVER, 681 .sfd_flags = SMP_FD_F_READ | SMP_FD_F_WRITE | 682 SMP_FD_F_PROVIDES_CHANGE_COUNT, 683 .sfd_rq_len = sas2_discover_rq_len, 684 .sfd_rq_dataoff = sas2_rq_dataoff, 685 .sfd_rq_setframe = sas2_rq_setframe, 686 .sfd_rs_datalen = sas2_discover_rs_datalen, 687 .sfd_rs_dataoff = sas2_rs_dataoff, 688 .sfd_rs_getparams = sas2_rs_getparams 689 }, 690 { 691 .sfd_function = SMP_FUNC_REPORT_PHY_ERROR_LOG, 692 .sfd_flags = SMP_FD_F_READ | SMP_FD_F_WRITE | 693 SMP_FD_F_PROVIDES_CHANGE_COUNT, 694 .sfd_rq_len = sas2_report_phy_error_log_rq_len, 695 .sfd_rq_dataoff = sas2_rq_dataoff, 696 .sfd_rq_setframe = sas2_rq_setframe, 697 .sfd_rs_datalen = sas2_report_phy_error_log_rs_datalen, 698 .sfd_rs_dataoff = sas2_rs_dataoff, 699 .sfd_rs_getparams = sas2_rs_getparams 700 }, 701 { 702 .sfd_function = SMP_FUNC_REPORT_PHY_SATA, 703 .sfd_flags = SMP_FD_F_READ | SMP_FD_F_WRITE | 704 SMP_FD_F_PROVIDES_CHANGE_COUNT, 705 .sfd_rq_len = sas2_report_phy_sata_rq_len, 706 .sfd_rq_dataoff = sas2_rq_dataoff, 707 .sfd_rq_setframe = sas2_rq_setframe, 708 .sfd_rs_datalen = sas2_report_phy_sata_rs_datalen, 709 .sfd_rs_dataoff = sas2_rs_dataoff, 710 .sfd_rs_getparams = sas2_rs_getparams 711 }, 712 { 713 .sfd_function = SMP_FUNC_REPORT_ROUTE_INFO, 714 .sfd_flags = SMP_FD_F_READ | SMP_FD_F_WRITE | 715 SMP_FD_F_PROVIDES_CHANGE_COUNT, 716 .sfd_rq_len = sas2_report_route_info_rq_len, 717 .sfd_rq_dataoff = sas2_rq_dataoff, 718 .sfd_rq_setframe = sas2_rq_setframe, 719 .sfd_rs_datalen = sas2_report_route_info_rs_datalen, 720 .sfd_rs_dataoff = sas2_rs_dataoff, 721 .sfd_rs_getparams = sas2_rs_getparams 722 }, 723 { 724 .sfd_function = SMP_FUNC_REPORT_PHY_EVENT, 725 .sfd_flags = SMP_FD_F_READ | SMP_FD_F_WRITE | 726 SMP_FD_F_PROVIDES_CHANGE_COUNT, 727 .sfd_rq_len = sas2_report_phy_event_rq_len, 728 .sfd_rq_dataoff = sas2_rq_dataoff, 729 .sfd_rq_setframe = sas2_rq_setframe, 730 .sfd_rs_datalen = sas2_rs_datalen, 731 .sfd_rs_dataoff = sas2_rs_dataoff, 732 .sfd_rs_getparams = sas2_rs_getparams 733 }, 734 { 735 .sfd_function = SMP_FUNC_DISCOVER_LIST, 736 .sfd_flags = SMP_FD_F_READ | SMP_FD_F_WRITE | 737 SMP_FD_F_PROVIDES_CHANGE_COUNT, 738 .sfd_rq_len = sas2_discover_list_rq_len, 739 .sfd_rq_dataoff = sas2_rq_dataoff, 740 .sfd_rq_setframe = sas2_rq_setframe, 741 .sfd_rs_datalen = sas2_rs_datalen, 742 .sfd_rs_dataoff = sas2_rs_dataoff, 743 .sfd_rs_getparams = sas2_rs_getparams 744 }, 745 { 746 .sfd_function = SMP_FUNC_REPORT_PHY_EVENT_LIST, 747 .sfd_flags = SMP_FD_F_READ | SMP_FD_F_WRITE | 748 SMP_FD_F_PROVIDES_CHANGE_COUNT, 749 .sfd_rq_len = sas2_report_phy_event_list_rq_len, 750 .sfd_rq_dataoff = sas2_rq_dataoff, 751 .sfd_rq_setframe = sas2_rq_setframe, 752 .sfd_rs_datalen = sas2_rs_datalen, 753 .sfd_rs_dataoff = sas2_rs_dataoff, 754 .sfd_rs_getparams = sas2_rs_getparams 755 }, 756 { 757 .sfd_function = SMP_FUNC_REPORT_EXP_ROUTE_TABLE_LIST, 758 .sfd_flags = SMP_FD_F_READ | SMP_FD_F_WRITE | 759 SMP_FD_F_PROVIDES_CHANGE_COUNT, 760 .sfd_rq_len = sas2_report_exp_route_table_list_rq_len, 761 .sfd_rq_dataoff = sas2_rq_dataoff, 762 .sfd_rq_setframe = sas2_rq_setframe, 763 .sfd_rs_datalen = sas2_rs_datalen, 764 .sfd_rs_dataoff = sas2_rs_dataoff, 765 .sfd_rs_getparams = sas2_rs_getparams 766 }, 767 { 768 .sfd_function = SMP_FUNC_CONFIG_GENERAL, 769 .sfd_flags = SMP_FD_F_WRITE | SMP_FD_F_NEEDS_CHANGE_COUNT, 770 .sfd_rq_len = sas2_config_general_rq_len, 771 .sfd_rq_dataoff = sas2_rq_dataoff, 772 .sfd_rq_setframe = sas2_rq_setframe, 773 .sfd_rs_datalen = sas2_rs_datalen, 774 .sfd_rs_dataoff = sas2_rs_dataoff, 775 .sfd_rs_getparams = sas2_rs_getparams 776 }, 777 { 778 .sfd_function = SMP_FUNC_ENABLE_DISABLE_ZONING, 779 .sfd_flags = SMP_FD_F_WRITE | SMP_FD_F_NEEDS_CHANGE_COUNT, 780 .sfd_rq_len = sas2_enable_disable_zoning_rq_len, 781 .sfd_rq_dataoff = sas2_rq_dataoff, 782 .sfd_rq_setframe = sas2_rq_setframe, 783 .sfd_rs_datalen = sas2_rs_datalen, 784 .sfd_rs_dataoff = sas2_rs_dataoff, 785 .sfd_rs_getparams = sas2_rs_getparams 786 }, 787 { 788 .sfd_function = SMP_FUNC_ZONED_BROADCAST, 789 .sfd_flags = SMP_FD_F_WRITE, 790 .sfd_rq_len = sas2_zoned_broadcast_rq_len, 791 .sfd_rq_dataoff = sas2_rq_dataoff, 792 .sfd_rq_setframe = sas2_rq_setframe, 793 .sfd_rs_datalen = sas2_rs_datalen, 794 .sfd_rs_dataoff = sas2_rs_dataoff, 795 .sfd_rs_getparams = sas2_rs_getparams 796 }, 797 { 798 .sfd_function = SMP_FUNC_ZONE_LOCK, 799 .sfd_flags = SMP_FD_F_READ | SMP_FD_F_WRITE | 800 SMP_FD_F_NEEDS_CHANGE_COUNT, 801 .sfd_rq_len = sas2_zone_lock_rq_len, 802 .sfd_rq_dataoff = sas2_rq_dataoff, 803 .sfd_rq_setframe = sas2_rq_setframe, 804 .sfd_rs_datalen = sas2_rs_datalen, 805 .sfd_rs_dataoff = sas2_rs_dataoff, 806 .sfd_rs_getparams = sas2_rs_getparams 807 }, 808 { 809 .sfd_function = SMP_FUNC_ZONE_ACTIVATE, 810 .sfd_flags = SMP_FD_F_WRITE | SMP_FD_F_NEEDS_CHANGE_COUNT, 811 .sfd_rq_len = sas2_zone_activate_rq_len, 812 .sfd_rq_dataoff = sas2_rq_dataoff, 813 .sfd_rq_setframe = sas2_rq_setframe, 814 .sfd_rs_datalen = sas2_rs_datalen, 815 .sfd_rs_dataoff = sas2_rs_dataoff, 816 .sfd_rs_getparams = sas2_rs_getparams 817 }, 818 { 819 .sfd_function = SMP_FUNC_ZONE_UNLOCK, 820 .sfd_flags = SMP_FD_F_WRITE, 821 .sfd_rq_len = sas2_zone_unlock_rq_len, 822 .sfd_rq_dataoff = sas2_rq_dataoff, 823 .sfd_rq_setframe = sas2_rq_setframe, 824 .sfd_rs_datalen = sas2_rs_datalen, 825 .sfd_rs_dataoff = sas2_rs_dataoff, 826 .sfd_rs_getparams = sas2_rs_getparams 827 }, 828 { 829 .sfd_function = SMP_FUNC_CONFIG_ZONE_MANAGER_PASSWORD, 830 .sfd_flags = SMP_FD_F_WRITE | SMP_FD_F_NEEDS_CHANGE_COUNT, 831 .sfd_rq_len = sas2_config_zone_manager_password_rq_len, 832 .sfd_rq_dataoff = sas2_rq_dataoff, 833 .sfd_rq_setframe = sas2_rq_setframe, 834 .sfd_rs_datalen = sas2_rs_datalen, 835 .sfd_rs_dataoff = sas2_rs_dataoff, 836 .sfd_rs_getparams = sas2_rs_getparams 837 }, 838 { 839 .sfd_function = SMP_FUNC_CONFIG_ZONE_PHY_INFO, 840 .sfd_flags = SMP_FD_F_WRITE | SMP_FD_F_NEEDS_CHANGE_COUNT, 841 .sfd_rq_len = sas2_config_zone_phy_info_rq_len, 842 .sfd_rq_dataoff = sas2_rq_dataoff, 843 .sfd_rq_setframe = sas2_rq_setframe, 844 .sfd_rs_datalen = sas2_rs_datalen, 845 .sfd_rs_dataoff = sas2_rs_dataoff, 846 .sfd_rs_getparams = sas2_rs_getparams 847 }, 848 { 849 .sfd_function = SMP_FUNC_CONFIG_ZONE_PERM_TABLE, 850 .sfd_flags = SMP_FD_F_WRITE | SMP_FD_F_NEEDS_CHANGE_COUNT, 851 .sfd_rq_len = sas2_config_zone_perm_table_rq_len, 852 .sfd_rq_dataoff = sas2_rq_dataoff, 853 .sfd_rq_setframe = sas2_rq_setframe, 854 .sfd_rs_datalen = sas2_rs_datalen, 855 .sfd_rs_dataoff = sas2_rs_dataoff, 856 .sfd_rs_getparams = sas2_rs_getparams 857 }, 858 { 859 .sfd_function = SMP_FUNC_CONFIG_ROUTE_INFO, 860 .sfd_flags = SMP_FD_F_WRITE | SMP_FD_F_NEEDS_CHANGE_COUNT, 861 .sfd_rq_len = sas2_config_route_info_rq_len, 862 .sfd_rq_dataoff = sas2_rq_dataoff, 863 .sfd_rq_setframe = sas2_rq_setframe, 864 .sfd_rs_datalen = sas2_rs_datalen, 865 .sfd_rs_dataoff = sas2_rs_dataoff, 866 .sfd_rs_getparams = sas2_rs_getparams 867 }, 868 { 869 .sfd_function = SMP_FUNC_PHY_CONTROL, 870 .sfd_flags = SMP_FD_F_WRITE | SMP_FD_F_NEEDS_CHANGE_COUNT, 871 .sfd_rq_len = sas2_phy_control_rq_len, 872 .sfd_rq_dataoff = sas2_rq_dataoff, 873 .sfd_rq_setframe = sas2_rq_setframe, 874 .sfd_rs_datalen = sas2_rs_datalen, 875 .sfd_rs_dataoff = sas2_rs_dataoff, 876 .sfd_rs_getparams = sas2_rs_getparams 877 }, 878 { 879 .sfd_function = SMP_FUNC_PHY_TEST_FUNCTION, 880 .sfd_flags = SMP_FD_F_WRITE | SMP_FD_F_NEEDS_CHANGE_COUNT, 881 .sfd_rq_len = sas2_phy_test_function_rq_len, 882 .sfd_rq_dataoff = sas2_rq_dataoff, 883 .sfd_rq_setframe = sas2_rq_setframe, 884 .sfd_rs_datalen = sas2_rs_datalen, 885 .sfd_rs_dataoff = sas2_rs_dataoff, 886 .sfd_rs_getparams = sas2_rs_getparams 887 }, 888 { 889 .sfd_function = SMP_FUNC_CONFIG_PHY_EVENT, 890 .sfd_flags = SMP_FD_F_WRITE | SMP_FD_F_NEEDS_CHANGE_COUNT, 891 .sfd_rq_len = sas2_config_phy_event_rq_len, 892 .sfd_rq_dataoff = sas2_rq_dataoff, 893 .sfd_rq_setframe = sas2_rq_setframe, 894 .sfd_rs_datalen = sas2_rs_datalen, 895 .sfd_rs_dataoff = sas2_rs_dataoff, 896 .sfd_rs_getparams = sas2_rs_getparams 897 }, 898 { 899 .sfd_function = -1 900 } 901 }; 902 903 /* 904 * Returns the number of bytes in the request frame, including the header 905 * and footer, for the given function and capabilities. Presently the only 906 * relevant capability is long-request, which in some cases increases the 907 * size of the request from the SAS-1 spec to that found in SAS-2. 908 * 909 * Variably-sized request frames have no default size; we return 0 in that 910 * case, which will often be interpreted by the caller as an error although 911 * in general it is not. 912 */ 913 size_t 914 smp_default_request_len(uint_t cap, smp_function_t fn) 915 { 916 switch (fn) { 917 case SMP_FUNC_REPORT_GENERAL: 918 case SMP_FUNC_REPORT_MANUFACTURER_INFO: 919 case SMP_FUNC_REPORT_ZONE_MANAGER_PASSWORD: 920 return (SMP_REQ_MINLEN); 921 922 case SMP_FUNC_REPORT_SELF_CONFIG_STATUS: 923 if (cap & SMP_TARGET_C_LONG_RESP) 924 return (SMP_REQ_MINLEN + 925 sizeof (smp_report_self_config_status_req_t)); 926 return (SMP_REQ_MINLEN); 927 case SMP_FUNC_REPORT_ZONE_PERM_TABLE: 928 if (cap & SMP_TARGET_C_LONG_RESP) 929 return (SMP_REQ_MINLEN + 930 sizeof (smp_report_zone_perm_table_req_t)); 931 return (SMP_REQ_MINLEN); 932 case SMP_FUNC_REPORT_BROADCAST: 933 if (cap & SMP_TARGET_C_LONG_RESP) 934 return (SMP_REQ_MINLEN + 935 sizeof (smp_report_broadcast_req_t)); 936 return (SMP_REQ_MINLEN); 937 case SMP_FUNC_DISCOVER: 938 return (SMP_REQ_MINLEN + sizeof (smp_discover_req_t)); 939 case SMP_FUNC_REPORT_PHY_ERROR_LOG: 940 return (SMP_REQ_MINLEN + 941 sizeof (smp_report_phy_error_log_req_t)); 942 case SMP_FUNC_REPORT_PHY_SATA: 943 return (SMP_REQ_MINLEN + sizeof (smp_report_phy_sata_req_t)); 944 case SMP_FUNC_REPORT_ROUTE_INFO: 945 return (SMP_REQ_MINLEN + sizeof (smp_report_route_info_req_t)); 946 case SMP_FUNC_REPORT_PHY_EVENT: 947 if (cap & SMP_TARGET_C_LONG_RESP) 948 return (SMP_REQ_MINLEN + 949 sizeof (smp_report_phy_event_req_t)); 950 return (SMP_REQ_MINLEN); 951 case SMP_FUNC_DISCOVER_LIST: 952 if (cap & SMP_TARGET_C_LONG_RESP) 953 return (SMP_REQ_MINLEN + 954 sizeof (smp_discover_list_req_t)); 955 return (SMP_REQ_MINLEN); 956 case SMP_FUNC_REPORT_PHY_EVENT_LIST: 957 if (cap & SMP_TARGET_C_LONG_RESP) 958 return (SMP_REQ_MINLEN + 959 sizeof (smp_report_phy_event_list_req_t)); 960 return (SMP_REQ_MINLEN); 961 case SMP_FUNC_REPORT_EXP_ROUTE_TABLE_LIST: 962 if (cap & SMP_TARGET_C_LONG_RESP) 963 return (SMP_REQ_MINLEN + 964 sizeof (smp_report_exp_route_table_list_req_t)); 965 return (SMP_REQ_MINLEN); 966 case SMP_FUNC_CONFIG_GENERAL: 967 if (cap & SMP_TARGET_C_LONG_RESP) 968 return (SMP_REQ_MINLEN + 969 sizeof (smp_config_general_req_t)); 970 return (SMP_REQ_MINLEN); 971 case SMP_FUNC_ENABLE_DISABLE_ZONING: 972 if (cap & SMP_TARGET_C_LONG_RESP) 973 return (SMP_REQ_MINLEN + 974 sizeof (smp_enable_disable_zoning_req_t)); 975 return (SMP_REQ_MINLEN); 976 case SMP_FUNC_ZONE_LOCK: 977 if (cap & SMP_TARGET_C_LONG_RESP) 978 return (SMP_REQ_MINLEN + 979 sizeof (smp_zone_lock_req_t)); 980 return (SMP_REQ_MINLEN); 981 case SMP_FUNC_ZONE_ACTIVATE: 982 if (cap & SMP_TARGET_C_LONG_RESP) 983 return (SMP_REQ_MINLEN + 984 sizeof (smp_zone_activate_req_t)); 985 return (SMP_REQ_MINLEN); 986 case SMP_FUNC_ZONE_UNLOCK: 987 if (cap & SMP_TARGET_C_LONG_RESP) 988 return (SMP_REQ_MINLEN + 989 sizeof (smp_zone_unlock_req_t)); 990 return (SMP_REQ_MINLEN); 991 case SMP_FUNC_CONFIG_ZONE_MANAGER_PASSWORD: 992 if (cap & SMP_TARGET_C_LONG_RESP) 993 return (SMP_REQ_MINLEN + 994 sizeof (smp_config_zone_manager_password_req_t)); 995 return (SMP_REQ_MINLEN); 996 case SMP_FUNC_CONFIG_ROUTE_INFO: 997 return (SMP_REQ_MINLEN + sizeof (smp_config_route_info_req_t)); 998 case SMP_FUNC_PHY_CONTROL: 999 return (SMP_REQ_MINLEN + sizeof (smp_phy_control_req_t)); 1000 case SMP_FUNC_PHY_TEST_FUNCTION: 1001 return (SMP_REQ_MINLEN + sizeof (smp_phy_test_function_req_t)); 1002 1003 case SMP_FUNC_ZONED_BROADCAST: 1004 case SMP_FUNC_CONFIG_ZONE_PHY_INFO: 1005 case SMP_FUNC_CONFIG_ZONE_PERM_TABLE: 1006 case SMP_FUNC_CONFIG_PHY_EVENT: 1007 default: 1008 return (0); 1009 } 1010 } 1011 1012 /* 1013 * This is slightly different - return the length in bytes, including the 1014 * header and footer, to be assumed for the response frame type if the 1015 * length field is zero. Since the length field will not be zero unless the 1016 * long response bit is clear or the target is buggy, we always assume that 1017 * the caller wants the size of the v1 frame. 1018 */ 1019 /*ARGSUSED*/ 1020 size_t 1021 smp_default_response_len(uint_t cap, smp_function_t fn) 1022 { 1023 switch (fn) { 1024 case SMP_FUNC_REPORT_SELF_CONFIG_STATUS: 1025 case SMP_FUNC_REPORT_ZONE_PERM_TABLE: 1026 case SMP_FUNC_REPORT_ZONE_MANAGER_PASSWORD: 1027 case SMP_FUNC_REPORT_BROADCAST: 1028 case SMP_FUNC_REPORT_PHY_EVENT: 1029 case SMP_FUNC_DISCOVER_LIST: 1030 case SMP_FUNC_REPORT_PHY_EVENT_LIST: 1031 case SMP_FUNC_REPORT_EXP_ROUTE_TABLE_LIST: 1032 case SMP_FUNC_CONFIG_GENERAL: 1033 case SMP_FUNC_ENABLE_DISABLE_ZONING: 1034 case SMP_FUNC_ZONED_BROADCAST: 1035 case SMP_FUNC_ZONE_LOCK: 1036 case SMP_FUNC_ZONE_ACTIVATE: 1037 case SMP_FUNC_ZONE_UNLOCK: 1038 case SMP_FUNC_CONFIG_ZONE_MANAGER_PASSWORD: 1039 case SMP_FUNC_CONFIG_ZONE_PHY_INFO: 1040 case SMP_FUNC_CONFIG_ZONE_PERM_TABLE: 1041 case SMP_FUNC_CONFIG_ROUTE_INFO: 1042 case SMP_FUNC_PHY_CONTROL: 1043 case SMP_FUNC_PHY_TEST_FUNCTION: 1044 case SMP_FUNC_CONFIG_PHY_EVENT: 1045 return (SMP_RESP_MINLEN); 1046 1047 case SMP_FUNC_REPORT_GENERAL: 1048 return (SMP_RESP_MINLEN + 24); 1049 case SMP_FUNC_REPORT_MANUFACTURER_INFO: 1050 return (SMP_RESP_MINLEN + 1051 sizeof (smp_report_manufacturer_info_resp_t)); 1052 case SMP_FUNC_DISCOVER: 1053 return (SMP_RESP_MINLEN + 48); 1054 case SMP_FUNC_REPORT_PHY_ERROR_LOG: 1055 return (SMP_RESP_MINLEN + 1056 sizeof (smp_report_phy_error_log_resp_t)); 1057 case SMP_FUNC_REPORT_PHY_SATA: 1058 return (SMP_RESP_MINLEN + 52); 1059 case SMP_FUNC_REPORT_ROUTE_INFO: 1060 return (SMP_RESP_MINLEN + 1061 sizeof (smp_report_route_info_resp_t)); 1062 1063 default: 1064 return (0); 1065 } 1066 } 1067