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 (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. 23 */ 24 25 /* 26 * XXX TODO 27 * #includes cribbed from stmf.c -- undoubtedly only a small subset of these 28 * are actually needed. 29 */ 30 #include <sys/conf.h> 31 #include <sys/file.h> 32 #include <sys/ddi.h> 33 #include <sys/sunddi.h> 34 #include <sys/scsi/scsi.h> 35 #include <sys/scsi/generic/persist.h> 36 #include <sys/byteorder.h> 37 #include <sys/nvpair.h> 38 #include <sys/door.h> 39 40 #include <sys/stmf.h> 41 #include <sys/lpif.h> 42 #include <sys/stmf_ioctl.h> 43 #include <sys/portif.h> 44 #include <sys/pppt_ic_if.h> 45 46 #include "pppt.h" 47 48 /* 49 * Macros 50 */ 51 52 /* Free a struct if it was allocated */ 53 #define FREE_IF_ALLOC(m) \ 54 do { \ 55 if ((m)) kmem_free((m), sizeof (*(m))); \ 56 _NOTE(CONSTCOND) \ 57 } while (0) 58 59 /* 60 * Macros to simplify the addition of struct fields to an nvlist. 61 * The name of the fields in the nvlist is the same as the name 62 * of the struct field. 63 * 64 * These macros require an int rc and a "done:" return retval label; 65 * they assume that the nvlist is named "nvl". 66 */ 67 #define NVLIST_ADD_FIELD(type, structure, field) \ 68 do { \ 69 rc = nvlist_add_##type(nvl, #field, structure->field); \ 70 if (rc) goto done; \ 71 _NOTE(CONSTCOND) \ 72 } while (0) 73 74 /* use this macro when the array is defined as part of the struct */ 75 #define NVLIST_ADD_ARRAY(type, structure, field) \ 76 do { \ 77 rc = nvlist_add_##type##_array(nvl, #field, \ 78 structure->field, sizeof (structure->field)); \ 79 if (rc) goto done; \ 80 _NOTE(CONSTCOND) \ 81 } while (0) 82 83 /* 84 * use this macro when the array field is a ptr or you need to explictly 85 * call out the size. 86 */ 87 #define NVLIST_ADD_ARRAY_LEN(type, structure, field, len) \ 88 do { \ 89 rc = nvlist_add_##type##_array(nvl, #field, \ 90 structure->field, len); \ 91 if (rc) goto done; \ 92 _NOTE(CONSTCOND) \ 93 } while (0) 94 95 #define NVLIST_ADD_DEVID(structure, field) \ 96 do { \ 97 rc = stmf_ic_scsi_devid_desc_marshal(nvl, #field, \ 98 structure->field); \ 99 if (rc) goto done; \ 100 _NOTE(CONSTCOND) \ 101 } while (0) 102 103 #define NVLIST_ADD_RPORT(structure, field) \ 104 do { \ 105 rc = stmf_ic_remote_port_marshal(nvl, #field, \ 106 structure->field); \ 107 if (rc) goto done; \ 108 _NOTE(CONSTCOND) \ 109 } while (0) 110 111 #define NVLIST_ADD_FIELD_UINT8(structure, field) \ 112 NVLIST_ADD_FIELD(structure, field, uint8) 113 114 /* 115 * Macros to simplify the extraction of struct fields from an nvlist. 116 * The name of the fields in the nvlist is the same as the name 117 * of the struct field. 118 * 119 * Requires an int rc and a "done:" return retval label. 120 * Assumes that the nvlist is named "nvl". 121 * 122 * Sample usage: NVLIST_LOOKUP_FIELD(uint8, structname, fieldname); 123 */ 124 #define NVLIST_LOOKUP_FIELD(type, structure, field) \ 125 do { \ 126 rc = nvlist_lookup_##type(nvl, #field, \ 127 &(structure->field)); \ 128 if (rc) { \ 129 stmf_ic_nvlookup_warn(__func__, #field); \ 130 goto done; \ 131 } \ 132 _NOTE(CONSTCOND) \ 133 } while (0) 134 135 /* 136 * Look up a field which gets stored into a structure bit field. 137 * The type passed is a uint type which can hold the largest value 138 * in the bit field. 139 * 140 * Requires an int rc and a "done:" return retval label. 141 * Assumes that the nvlist is named "nvl". 142 * 143 * Sample usage: NVLIST_LOOKUP_BIT_FIELD(uint8, structname, fieldname); 144 */ 145 #define NVLIST_LOOKUP_BIT_FIELD(type, structure, field) \ 146 do { \ 147 type##_t tmp; \ 148 rc = nvlist_lookup_##type(nvl, #field, &tmp); \ 149 if (rc) { \ 150 stmf_ic_nvlookup_warn(__func__, #field); \ 151 goto done; \ 152 } \ 153 structure->field = tmp; \ 154 _NOTE(CONSTCOND) \ 155 } while (0) 156 157 /* 158 * Look up a boolean field which gets stored into a structure bit field. 159 * 160 * Requires an int rc and a "done:" return retval label. 161 * Assumes that the nvlist is named "nvl". 162 */ 163 #define NVLIST_LOOKUP_BIT_FIELD_BOOLEAN(structure, field) \ 164 do { \ 165 boolean_t tmp; \ 166 rc = nvlist_lookup_boolean_value(nvl, #field, &tmp); \ 167 if (rc) { \ 168 stmf_ic_nvlookup_warn(__func__, #field); \ 169 goto done; \ 170 } \ 171 structure->field = (tmp ? 1 : 0); \ 172 _NOTE(CONSTCOND) \ 173 } while (0) 174 175 /* shorthand for nvlist_lookup_pairs() args */ 176 #define NV_PAIR(type, strct, field) #field, DATA_TYPE_##type, &(strct->field) 177 178 /* number of times to retry the upcall to transmit */ 179 #define STMF_MSG_TRANSMIT_RETRY 3 180 181 /* 182 * How was the message constructed? 183 * 184 * We need to know this when we free the message in order to 185 * determine what to do with pointers in the message: 186 * 187 * - messages which were unmarshaled from an nvlist may point to 188 * memory within that nvlist; this memory should not be freed since 189 * it will be deallocated when we free the nvlist. 190 * 191 * - messages which built using a constructor (alloc) function may 192 * point to memory which was explicitly allocated by the constructor; 193 * it should be freed when the message is freed. 194 * 195 */ 196 typedef enum { 197 STMF_CONSTRUCTOR = 0, 198 STMF_UNMARSHAL 199 } stmf_ic_msg_construction_method_t; 200 201 202 /* 203 * Function prototypes. 204 */ 205 206 /* 207 * Helpers for msg_alloc routines, used when the msg payload is 208 * the same for multiple types of messages. 209 */ 210 static stmf_ic_msg_t *stmf_ic_reg_dereg_lun_msg_alloc( 211 stmf_ic_msg_type_t msg_type, uint8_t *lun_id, 212 char *lu_provider_name, uint16_t cb_arg_len, 213 uint8_t *cb_arg, stmf_ic_msgid_t msgid); 214 215 static stmf_ic_msg_t *stmf_ic_session_create_destroy_msg_alloc( 216 stmf_ic_msg_type_t msg_type, 217 stmf_scsi_session_t *session, 218 stmf_ic_msgid_t msgid); 219 220 static stmf_ic_msg_t *stmf_ic_echo_request_reply_msg_alloc( 221 stmf_ic_msg_type_t msg_type, 222 uint32_t data_len, 223 uint8_t *data, 224 stmf_ic_msgid_t msgid); 225 226 /* 227 * Msg free routines. 228 */ 229 static void stmf_ic_reg_port_msg_free(stmf_ic_reg_port_msg_t *m, 230 stmf_ic_msg_construction_method_t cmethod); 231 static void stmf_ic_dereg_port_msg_free(stmf_ic_dereg_port_msg_t *m, 232 stmf_ic_msg_construction_method_t cmethod); 233 static void stmf_ic_reg_dereg_lun_msg_free(stmf_ic_reg_dereg_lun_msg_t *m, 234 stmf_ic_msg_construction_method_t cmethod); 235 static void stmf_ic_scsi_cmd_msg_free(stmf_ic_scsi_cmd_msg_t *m, 236 stmf_ic_msg_construction_method_t cmethod); 237 static void stmf_ic_scsi_data_msg_free(stmf_ic_scsi_data_msg_t *m, 238 stmf_ic_msg_construction_method_t cmethod); 239 static void stmf_ic_scsi_data_xfer_done_msg_free( 240 stmf_ic_scsi_data_xfer_done_msg_t *m, 241 stmf_ic_msg_construction_method_t cmethod); 242 static void stmf_ic_scsi_status_msg_free(stmf_ic_scsi_status_msg_t *m, 243 stmf_ic_msg_construction_method_t cmethod); 244 static void stmf_ic_r2t_msg_free(stmf_ic_r2t_msg_t *m, 245 stmf_ic_msg_construction_method_t cmethod); 246 static void stmf_ic_status_msg_free(stmf_ic_status_msg_t *m, 247 stmf_ic_msg_construction_method_t cmethod); 248 static void stmf_ic_session_create_destroy_msg_free( 249 stmf_ic_session_create_destroy_msg_t *m, 250 stmf_ic_msg_construction_method_t cmethod); 251 static void stmf_ic_echo_request_reply_msg_free( 252 stmf_ic_echo_request_reply_msg_t *m, 253 stmf_ic_msg_construction_method_t cmethod); 254 255 /* 256 * Marshaling routines. 257 */ 258 static nvlist_t *stmf_ic_msg_marshal(stmf_ic_msg_t *msg); 259 static int stmf_ic_reg_port_msg_marshal(nvlist_t *nvl, void *msg); 260 static int stmf_ic_dereg_port_msg_marshal(nvlist_t *nvl, void *msg); 261 static int stmf_ic_reg_dereg_lun_msg_marshal(nvlist_t *nvl, void *msg); 262 static int stmf_ic_scsi_cmd_msg_marshal(nvlist_t *nvl, void *msg); 263 static int stmf_ic_scsi_data_msg_marshal(nvlist_t *nvl, void *msg); 264 static int stmf_ic_scsi_data_xfer_done_msg_marshal(nvlist_t *nvl, void *msg); 265 static int stmf_ic_scsi_status_msg_marshal(nvlist_t *nvl, void *msg); 266 static int stmf_ic_r2t_msg_marshal(nvlist_t *nvl, void *msg); 267 static int stmf_ic_status_msg_marshal(nvlist_t *nvl, void *msg); 268 static int stmf_ic_session_create_destroy_msg_marshal(nvlist_t *nvl, void *msg); 269 static int stmf_ic_echo_request_reply_msg_marshal(nvlist_t *nvl, void *msg); 270 static int stmf_ic_scsi_devid_desc_marshal(nvlist_t *parent_nvl, 271 char *sdid_name, scsi_devid_desc_t *sdid); 272 static int stmf_ic_remote_port_marshal(nvlist_t *parent_nvl, 273 char *rport_name, stmf_remote_port_t *rport); 274 275 /* 276 * Unmarshaling routines. 277 */ 278 static stmf_ic_msg_t *stmf_ic_msg_unmarshal(nvlist_t *nvl); 279 static void *stmf_ic_reg_port_msg_unmarshal(nvlist_t *nvl); 280 static void *stmf_ic_dereg_port_msg_unmarshal(nvlist_t *nvl); 281 static void *stmf_ic_reg_dereg_lun_msg_unmarshal(nvlist_t *nvl); 282 static void *stmf_ic_scsi_cmd_msg_unmarshal(nvlist_t *nvl); 283 static void *stmf_ic_scsi_data_msg_unmarshal(nvlist_t *nvl); 284 static void *stmf_ic_scsi_data_xfer_done_msg_unmarshal(nvlist_t *nvl); 285 static void *stmf_ic_scsi_status_msg_unmarshal(nvlist_t *nvl); 286 static void *stmf_ic_r2t_msg_unmarshal(nvlist_t *nvl); 287 static void *stmf_ic_status_msg_unmarshal(nvlist_t *nvl); 288 static void *stmf_ic_session_create_destroy_msg_unmarshal(nvlist_t *nvl); 289 static void *stmf_ic_echo_request_reply_msg_unmarshal(nvlist_t *nvl); 290 static scsi_devid_desc_t *stmf_ic_lookup_scsi_devid_desc_and_unmarshal( 291 nvlist_t *nvl, char *field_name); 292 static scsi_devid_desc_t *stmf_ic_scsi_devid_desc_unmarshal( 293 nvlist_t *nvl_devid); 294 static uint8_t *stmf_ic_uint8_array_unmarshal(nvlist_t *nvl, char *field_name, 295 uint64_t len, uint8_t *buf); 296 static char *stmf_ic_string_unmarshal(nvlist_t *nvl, char *field_name); 297 static stmf_remote_port_t *stmf_ic_lookup_remote_port_and_unmarshal( 298 nvlist_t *nvl, char *field_name); 299 static stmf_remote_port_t *stmf_ic_remote_port_unmarshal(nvlist_t *nvl); 300 301 /* 302 * Transmit and recieve routines. 303 */ 304 stmf_ic_msg_status_t stmf_ic_transmit(char *buf, size_t size); 305 306 /* 307 * Utilities. 308 */ 309 static stmf_ic_msg_t *stmf_ic_alloc_msg_header(stmf_ic_msg_type_t msg_type, 310 stmf_ic_msgid_t msgid); 311 static size_t sizeof_scsi_devid_desc(int ident_length); 312 static char *stmf_ic_strdup(char *str); 313 static scsi_devid_desc_t *scsi_devid_desc_dup(scsi_devid_desc_t *did); 314 static stmf_remote_port_t *remote_port_dup(stmf_remote_port_t *rport); 315 static void scsi_devid_desc_free(scsi_devid_desc_t *did); 316 static inline void stmf_ic_nvlookup_warn(const char *func, char *field); 317 318 /* 319 * Send a message out over the interconnect, in the process marshalling 320 * the arguments. 321 * 322 * After being sent, the message is freed. 323 */ 324 stmf_ic_msg_status_t 325 stmf_ic_tx_msg(stmf_ic_msg_t *msg) 326 { 327 size_t size = 0; 328 nvlist_t *nvl = NULL; 329 char *buf = NULL; 330 int err = 0; 331 stmf_ic_msg_status_t status = STMF_IC_MSG_SUCCESS; 332 333 nvl = stmf_ic_msg_marshal(msg); 334 if (!nvl) { 335 cmn_err(CE_WARN, "stmf_ic_tx_msg: marshal failed"); 336 status = STMF_IC_MSG_INTERNAL_ERROR; 337 goto done; 338 } 339 340 err = nvlist_size(nvl, &size, NV_ENCODE_XDR); 341 if (err) { 342 status = STMF_IC_MSG_INTERNAL_ERROR; 343 goto done; 344 } 345 346 buf = kmem_alloc(size, KM_SLEEP); 347 err = nvlist_pack(nvl, &buf, &size, NV_ENCODE_XDR, 0); 348 if (err) { 349 status = STMF_IC_MSG_INTERNAL_ERROR; 350 goto done; 351 } 352 353 /* push the bits out on the wire */ 354 355 status = stmf_ic_transmit(buf, size); 356 357 done: 358 if (nvl) 359 nvlist_free(nvl); 360 361 if (buf) 362 kmem_free(buf, size); 363 364 stmf_ic_msg_free(msg); 365 366 367 return (status); 368 } 369 370 /* 371 * Pass the command to the daemon for transmission to the other node. 372 */ 373 stmf_ic_msg_status_t 374 stmf_ic_transmit(char *buf, size_t size) 375 { 376 int i; 377 int rc; 378 door_arg_t arg; 379 door_handle_t door; 380 uint32_t result; 381 382 mutex_enter(&pppt_global.global_door_lock); 383 if (pppt_global.global_door == NULL) { 384 /* daemon not listening */ 385 mutex_exit(&pppt_global.global_door_lock); 386 return (STMF_IC_MSG_INTERNAL_ERROR); 387 } 388 door = pppt_global.global_door; 389 door_ki_hold(door); 390 mutex_exit(&pppt_global.global_door_lock); 391 392 arg.data_ptr = buf; 393 arg.data_size = size; 394 arg.desc_ptr = NULL; 395 arg.desc_num = 0; 396 arg.rbuf = (char *)&result; 397 arg.rsize = sizeof (result); 398 /* 399 * Retry a few times if there is a shortage of threads to 400 * service the upcall. This shouldn't happen unless a large 401 * number of initiators issue commands at once. 402 */ 403 for (i = 0; i < STMF_MSG_TRANSMIT_RETRY; i++) { 404 rc = door_ki_upcall(door, &arg); 405 if (rc != EAGAIN) 406 break; 407 delay(hz); 408 } 409 door_ki_rele(door); 410 if (rc != 0) { 411 cmn_err(CE_WARN, 412 "stmf_ic_transmit door_ki_upcall failed %d", rc); 413 return (STMF_IC_MSG_INTERNAL_ERROR); 414 } 415 if (result != 0) { 416 /* XXX Just warn for now */ 417 cmn_err(CE_WARN, 418 "stmf_ic_transmit bad result from daemon %d", result); 419 } 420 421 return (STMF_IC_MSG_SUCCESS); 422 } 423 424 /* 425 * This is a low-level upcall which is called when a message has 426 * been received on the interconnect. 427 * 428 * The caller is responsible for freeing the buffer which is passed in. 429 */ 430 /*ARGSUSED*/ 431 void 432 stmf_ic_rx_msg(char *buf, size_t len) 433 { 434 nvlist_t *nvl = NULL; 435 stmf_ic_msg_t *m = NULL; 436 stmf_ic_echo_request_reply_msg_t *icerr; 437 stmf_ic_msg_t *echo_msg; 438 int rc = 0; 439 440 rc = nvlist_unpack(buf, len, &nvl, 0); 441 if (rc) { 442 cmn_err(CE_WARN, "stmf_ic_rx_msg: unpack failed"); 443 return; 444 } 445 446 m = stmf_ic_msg_unmarshal(nvl); 447 if (m == NULL) { 448 cmn_err(CE_WARN, "stmf_ic_rx_msg: unmarshal failed"); 449 nvlist_free(nvl); 450 return; 451 } 452 453 switch (m->icm_msg_type) { 454 455 case STMF_ICM_REGISTER_PROXY_PORT: 456 case STMF_ICM_DEREGISTER_PROXY_PORT: 457 case STMF_ICM_SCSI_CMD: 458 case STMF_ICM_SCSI_DATA_XFER_DONE: 459 case STMF_ICM_SESSION_CREATE: 460 case STMF_ICM_SESSION_DESTROY: 461 /* 462 * These messages are all received by pppt. 463 * Currently, pppt will parse the message for type 464 */ 465 (void) pppt_msg_rx(m); 466 break; 467 468 case STMF_ICM_LUN_ACTIVE: 469 case STMF_ICM_REGISTER_LUN: 470 case STMF_ICM_DEREGISTER_LUN: 471 case STMF_ICM_SCSI_DATA: 472 case STMF_ICM_SCSI_STATUS: 473 /* 474 * These messages are all received by stmf. 475 * Currently, stmf will parse the message for type 476 */ 477 (void) stmf_msg_rx(m); 478 break; 479 480 case STMF_ICM_ECHO_REQUEST: 481 icerr = m->icm_msg; 482 echo_msg = stmf_ic_echo_reply_msg_alloc(icerr->icerr_datalen, 483 icerr->icerr_data, 0); 484 if (echo_msg != NULL) { 485 (void) stmf_ic_tx_msg(echo_msg); 486 } 487 stmf_ic_msg_free(m); 488 break; 489 490 case STMF_ICM_ECHO_REPLY: 491 stmf_ic_msg_free(m); 492 break; 493 494 case STMF_ICM_R2T: 495 /* 496 * XXX currently not supported 497 */ 498 stmf_ic_msg_free(m); 499 break; 500 501 case STMF_ICM_STATUS: 502 (void) stmf_msg_rx(m); 503 break; 504 505 default: 506 ASSERT(0); 507 } 508 } 509 510 /* 511 * IC message allocation routines. 512 */ 513 514 stmf_ic_msg_t * 515 stmf_ic_reg_port_msg_alloc( 516 scsi_devid_desc_t *port_id, 517 uint16_t relative_port_id, 518 uint16_t cb_arg_len, 519 uint8_t *cb_arg, 520 stmf_ic_msgid_t msgid) 521 { 522 stmf_ic_msg_t *icm = NULL; 523 stmf_ic_reg_port_msg_t *icrp = NULL; 524 525 icm = stmf_ic_alloc_msg_header(STMF_ICM_REGISTER_PROXY_PORT, msgid); 526 icrp = (stmf_ic_reg_port_msg_t *)kmem_zalloc(sizeof (*icrp), KM_SLEEP); 527 icm->icm_msg = (void *)icrp; 528 529 icrp->icrp_port_id = scsi_devid_desc_dup(port_id); 530 icrp->icrp_relative_port_id = relative_port_id; 531 532 if (cb_arg_len) { 533 icrp->icrp_cb_arg_len = cb_arg_len; 534 icrp->icrp_cb_arg = cb_arg; 535 } 536 537 return (icm); 538 } 539 540 stmf_ic_msg_t * 541 stmf_ic_dereg_port_msg_alloc( 542 scsi_devid_desc_t *port_id, 543 uint16_t cb_arg_len, 544 uint8_t *cb_arg, 545 stmf_ic_msgid_t msgid) 546 { 547 stmf_ic_msg_t *icm = NULL; 548 stmf_ic_dereg_port_msg_t *icdp = NULL; 549 550 icm = stmf_ic_alloc_msg_header(STMF_ICM_DEREGISTER_PROXY_PORT, msgid); 551 icdp = (stmf_ic_dereg_port_msg_t *)kmem_zalloc(sizeof (*icdp), 552 KM_SLEEP); 553 icm->icm_msg = (void *)icdp; 554 555 icdp->icdp_port_id = scsi_devid_desc_dup(port_id); 556 557 if (cb_arg_len) { 558 icdp->icdp_cb_arg_len = cb_arg_len; 559 icdp->icdp_cb_arg = cb_arg; 560 } 561 562 return (icm); 563 } 564 565 566 stmf_ic_msg_t * 567 stmf_ic_reg_lun_msg_alloc( 568 uint8_t *lun_id, 569 char *lu_provider_name, 570 uint16_t cb_arg_len, 571 uint8_t *cb_arg, 572 stmf_ic_msgid_t msgid) 573 { 574 return (stmf_ic_reg_dereg_lun_msg_alloc(STMF_ICM_REGISTER_LUN, lun_id, 575 lu_provider_name, cb_arg_len, cb_arg, msgid)); 576 } 577 578 stmf_ic_msg_t * 579 stmf_ic_lun_active_msg_alloc( 580 uint8_t *lun_id, 581 char *lu_provider_name, 582 uint16_t cb_arg_len, 583 uint8_t *cb_arg, 584 stmf_ic_msgid_t msgid) 585 { 586 return (stmf_ic_reg_dereg_lun_msg_alloc(STMF_ICM_LUN_ACTIVE, lun_id, 587 lu_provider_name, cb_arg_len, cb_arg, msgid)); 588 } 589 590 stmf_ic_msg_t * 591 stmf_ic_dereg_lun_msg_alloc( 592 uint8_t *lun_id, 593 char *lu_provider_name, 594 uint16_t cb_arg_len, 595 uint8_t *cb_arg, 596 stmf_ic_msgid_t msgid) 597 { 598 return (stmf_ic_reg_dereg_lun_msg_alloc(STMF_ICM_DEREGISTER_LUN, lun_id, 599 lu_provider_name, cb_arg_len, cb_arg, msgid)); 600 } 601 602 /* 603 * Guts of lun register/deregister/active alloc routines. 604 */ 605 static stmf_ic_msg_t * 606 stmf_ic_reg_dereg_lun_msg_alloc( 607 stmf_ic_msg_type_t msg_type, 608 uint8_t *lun_id, 609 char *lu_provider_name, 610 uint16_t cb_arg_len, 611 uint8_t *cb_arg, 612 stmf_ic_msgid_t msgid) 613 { 614 stmf_ic_msg_t *icm = NULL; 615 stmf_ic_reg_dereg_lun_msg_t *icrl = NULL; 616 617 icm = stmf_ic_alloc_msg_header(msg_type, msgid); 618 icrl = (stmf_ic_reg_dereg_lun_msg_t *) 619 kmem_zalloc(sizeof (*icrl), KM_SLEEP); 620 icm->icm_msg = (void *)icrl; 621 622 icrl->icrl_lu_provider_name = stmf_ic_strdup(lu_provider_name); 623 624 bcopy(lun_id, icrl->icrl_lun_id, sizeof (icrl->icrl_lun_id)); 625 626 if (cb_arg_len) { 627 icrl->icrl_cb_arg_len = cb_arg_len; 628 icrl->icrl_cb_arg = cb_arg; 629 } 630 631 return (icm); 632 } 633 634 stmf_ic_msg_t * 635 stmf_ic_scsi_cmd_msg_alloc( 636 stmf_ic_msgid_t task_msgid, 637 scsi_task_t *task, 638 uint32_t immed_data_len, 639 uint8_t *immed_data, 640 stmf_ic_msgid_t msgid) 641 { 642 stmf_ic_msg_t *icm = NULL; 643 stmf_ic_scsi_cmd_msg_t *icsc = NULL; 644 scsi_devid_desc_t *ini_devid = task->task_session->ss_rport_id; 645 scsi_devid_desc_t *tgt_devid = task->task_lport->lport_id; 646 stmf_remote_port_t *rport = task->task_session->ss_rport; 647 648 icm = stmf_ic_alloc_msg_header(STMF_ICM_SCSI_CMD, msgid); 649 icsc = (stmf_ic_scsi_cmd_msg_t *)kmem_zalloc(sizeof (*icsc), KM_SLEEP); 650 icm->icm_msg = (void *)icsc; 651 652 icsc->icsc_task_msgid = task_msgid; 653 icsc->icsc_ini_devid = scsi_devid_desc_dup(ini_devid); 654 icsc->icsc_tgt_devid = scsi_devid_desc_dup(tgt_devid); 655 icsc->icsc_rport = remote_port_dup(rport); 656 icsc->icsc_session_id = task->task_session->ss_session_id; 657 658 if (!task->task_mgmt_function && task->task_lu->lu_id) { 659 bcopy(task->task_lu->lu_id->ident, 660 icsc->icsc_lun_id, sizeof (icsc->icsc_lun_id)); 661 } 662 663 bcopy(task->task_lun_no, icsc->icsc_task_lun_no, 664 sizeof (icsc->icsc_task_lun_no)); 665 666 icsc->icsc_task_expected_xfer_length = task->task_expected_xfer_length; 667 if (task->task_cdb_length) { 668 ASSERT(task->task_mgmt_function == TM_NONE); 669 icsc->icsc_task_cdb_length = task->task_cdb_length; 670 icsc->icsc_task_cdb = 671 (uint8_t *)kmem_zalloc(task->task_cdb_length, KM_SLEEP); 672 bcopy(task->task_cdb, icsc->icsc_task_cdb, 673 task->task_cdb_length); 674 } 675 676 icsc->icsc_task_flags = task->task_flags; 677 icsc->icsc_task_priority = task->task_priority; 678 icsc->icsc_task_mgmt_function = task->task_mgmt_function; 679 680 icsc->icsc_immed_data_len = immed_data_len; 681 icsc->icsc_immed_data = immed_data; 682 683 return (icm); 684 } 685 686 stmf_ic_msg_t * 687 stmf_ic_scsi_data_msg_alloc( 688 stmf_ic_msgid_t task_msgid, 689 uint64_t session_id, 690 uint8_t *lun_id, 691 uint64_t data_len, 692 uint8_t *data, 693 stmf_ic_msgid_t msgid) 694 { 695 stmf_ic_msg_t *icm = NULL; 696 stmf_ic_scsi_data_msg_t *icsd = NULL; 697 698 icm = stmf_ic_alloc_msg_header(STMF_ICM_SCSI_DATA, msgid); 699 icsd = (stmf_ic_scsi_data_msg_t *)kmem_zalloc(sizeof (*icsd), KM_SLEEP); 700 icm->icm_msg = (void *)icsd; 701 702 icsd->icsd_task_msgid = task_msgid; 703 icsd->icsd_session_id = session_id; 704 bcopy(lun_id, icsd->icsd_lun_id, sizeof (icsd->icsd_lun_id)); 705 icsd->icsd_data_len = data_len; 706 icsd->icsd_data = data; 707 708 return (icm); 709 } 710 711 stmf_ic_msg_t * 712 stmf_ic_scsi_data_xfer_done_msg_alloc( 713 stmf_ic_msgid_t task_msgid, 714 uint64_t session_id, 715 stmf_status_t status, 716 stmf_ic_msgid_t msgid) 717 { 718 stmf_ic_msg_t *icm = NULL; 719 stmf_ic_scsi_data_xfer_done_msg_t *icsx = NULL; 720 721 icm = stmf_ic_alloc_msg_header(STMF_ICM_SCSI_DATA_XFER_DONE, msgid); 722 icsx = (stmf_ic_scsi_data_xfer_done_msg_t *)kmem_zalloc( 723 sizeof (*icsx), KM_SLEEP); 724 icm->icm_msg = (void *)icsx; 725 726 icsx->icsx_task_msgid = task_msgid; 727 icsx->icsx_session_id = session_id; 728 icsx->icsx_status = status; 729 730 return (icm); 731 } 732 733 stmf_ic_msg_t * 734 stmf_ic_scsi_status_msg_alloc( 735 stmf_ic_msgid_t task_msgid, 736 uint64_t session_id, 737 uint8_t *lun_id, 738 uint8_t response, 739 uint8_t status, 740 uint8_t flags, 741 uint32_t resid, 742 uint8_t sense_len, 743 uint8_t *sense, 744 stmf_ic_msgid_t msgid) 745 { 746 stmf_ic_msg_t *icm = NULL; 747 stmf_ic_scsi_status_msg_t *icss = NULL; 748 749 icm = stmf_ic_alloc_msg_header(STMF_ICM_SCSI_STATUS, msgid); 750 icss = (stmf_ic_scsi_status_msg_t *)kmem_zalloc(sizeof (*icss), 751 KM_SLEEP); 752 icm->icm_msg = (void *)icss; 753 754 icss->icss_task_msgid = task_msgid; 755 icss->icss_session_id = session_id; 756 bcopy(lun_id, icss->icss_lun_id, sizeof (icss->icss_lun_id)); 757 icss->icss_response = response; 758 icss->icss_status = status; 759 icss->icss_flags = flags; 760 icss->icss_resid = resid; 761 icss->icss_sense_len = sense_len; 762 icss->icss_sense = sense; 763 764 return (icm); 765 } 766 767 stmf_ic_msg_t * 768 stmf_ic_r2t_msg_alloc( 769 stmf_ic_msgid_t task_msgid, 770 uint64_t session_id, 771 uint32_t offset, 772 uint32_t length, 773 stmf_ic_msgid_t msgid) 774 { 775 stmf_ic_msg_t *icm = NULL; 776 stmf_ic_r2t_msg_t *icrt = NULL; 777 778 icm = stmf_ic_alloc_msg_header(STMF_ICM_R2T, msgid); 779 icrt = (stmf_ic_r2t_msg_t *)kmem_zalloc(sizeof (*icrt), KM_SLEEP); 780 icm->icm_msg = (void *)icrt; 781 782 icrt->icrt_task_msgid = task_msgid; 783 icrt->icrt_session_id = session_id; 784 icrt->icrt_offset = offset; 785 icrt->icrt_length = length; 786 787 return (icm); 788 } 789 790 stmf_ic_msg_t * 791 stmf_ic_status_msg_alloc( 792 stmf_status_t status, 793 stmf_ic_msg_type_t msg_type, 794 stmf_ic_msgid_t msgid) 795 { 796 stmf_ic_msg_t *icm = NULL; 797 stmf_ic_status_msg_t *ics = NULL; 798 799 icm = stmf_ic_alloc_msg_header(STMF_ICM_STATUS, msgid); 800 ics = (stmf_ic_status_msg_t *)kmem_zalloc(sizeof (*ics), KM_SLEEP); 801 icm->icm_msg = (void *)ics; 802 803 ics->ics_status = status; 804 ics->ics_msg_type = msg_type; 805 ics->ics_msgid = msgid; /* XXX same as msgid in header */ 806 807 return (icm); 808 } 809 810 stmf_ic_msg_t * 811 stmf_ic_session_create_msg_alloc( 812 stmf_scsi_session_t *session, 813 stmf_ic_msgid_t msgid) 814 { 815 return (stmf_ic_session_create_destroy_msg_alloc( 816 STMF_ICM_SESSION_CREATE, session, msgid)); 817 } 818 819 stmf_ic_msg_t * 820 stmf_ic_session_destroy_msg_alloc( 821 stmf_scsi_session_t *session, 822 stmf_ic_msgid_t msgid) 823 { 824 return (stmf_ic_session_create_destroy_msg_alloc( 825 STMF_ICM_SESSION_DESTROY, session, msgid)); 826 } 827 828 /* 829 * Guts of session create/destroy routines. 830 */ 831 static stmf_ic_msg_t * 832 stmf_ic_session_create_destroy_msg_alloc( 833 stmf_ic_msg_type_t msg_type, 834 stmf_scsi_session_t *session, 835 stmf_ic_msgid_t msgid) 836 { 837 stmf_ic_msg_t *icm = NULL; 838 stmf_ic_session_create_destroy_msg_t *icscd = NULL; 839 scsi_devid_desc_t *ini_devid = session->ss_rport_id; 840 scsi_devid_desc_t *tgt_devid = session->ss_lport->lport_id; 841 842 icm = stmf_ic_alloc_msg_header(msg_type, msgid); 843 icscd = (stmf_ic_session_create_destroy_msg_t *) 844 kmem_zalloc(sizeof (*icscd), KM_SLEEP); 845 icm->icm_msg = (void *)icscd; 846 847 icscd->icscd_session_id = session->ss_session_id; 848 icscd->icscd_ini_devid = scsi_devid_desc_dup(ini_devid); 849 icscd->icscd_tgt_devid = scsi_devid_desc_dup(tgt_devid); 850 icscd->icscd_rport = remote_port_dup(session->ss_rport); 851 852 return (icm); 853 } 854 855 stmf_ic_msg_t * 856 stmf_ic_echo_request_msg_alloc( 857 uint32_t data_len, 858 uint8_t *data, 859 stmf_ic_msgid_t msgid) 860 { 861 return (stmf_ic_echo_request_reply_msg_alloc( 862 STMF_ICM_ECHO_REQUEST, data_len, data, msgid)); 863 } 864 865 stmf_ic_msg_t * 866 stmf_ic_echo_reply_msg_alloc( 867 uint32_t data_len, 868 uint8_t *data, 869 stmf_ic_msgid_t msgid) 870 { 871 return (stmf_ic_echo_request_reply_msg_alloc( 872 STMF_ICM_ECHO_REPLY, data_len, data, msgid)); 873 } 874 875 876 static stmf_ic_msg_t * 877 stmf_ic_echo_request_reply_msg_alloc( 878 stmf_ic_msg_type_t msg_type, 879 uint32_t data_len, 880 uint8_t *data, 881 stmf_ic_msgid_t msgid) 882 { 883 stmf_ic_msg_t *icm = NULL; 884 stmf_ic_echo_request_reply_msg_t *icerr = NULL; 885 886 icm = stmf_ic_alloc_msg_header(msg_type, msgid); 887 icerr = kmem_zalloc(sizeof (*icerr), KM_SLEEP); 888 icm->icm_msg = (void *)icerr; 889 890 icerr->icerr_data = data; 891 icerr->icerr_datalen = data_len; 892 893 return (icm); 894 } 895 896 /* 897 * msg free routines. 898 */ 899 void 900 stmf_ic_msg_free(stmf_ic_msg_t *msg) 901 { 902 stmf_ic_msg_construction_method_t cmethod = 903 (msg->icm_nvlist ? STMF_UNMARSHAL : STMF_CONSTRUCTOR); 904 905 switch (msg->icm_msg_type) { 906 case STMF_ICM_REGISTER_PROXY_PORT: 907 stmf_ic_reg_port_msg_free( 908 (stmf_ic_reg_port_msg_t *)msg->icm_msg, cmethod); 909 break; 910 911 case STMF_ICM_DEREGISTER_PROXY_PORT: 912 stmf_ic_dereg_port_msg_free( 913 (stmf_ic_dereg_port_msg_t *)msg->icm_msg, cmethod); 914 break; 915 916 case STMF_ICM_LUN_ACTIVE: 917 case STMF_ICM_REGISTER_LUN: 918 case STMF_ICM_DEREGISTER_LUN: 919 stmf_ic_reg_dereg_lun_msg_free( 920 (stmf_ic_reg_dereg_lun_msg_t *)msg->icm_msg, cmethod); 921 break; 922 923 case STMF_ICM_SCSI_CMD: 924 stmf_ic_scsi_cmd_msg_free( 925 (stmf_ic_scsi_cmd_msg_t *)msg->icm_msg, cmethod); 926 break; 927 928 case STMF_ICM_SCSI_DATA: 929 stmf_ic_scsi_data_msg_free( 930 (stmf_ic_scsi_data_msg_t *)msg->icm_msg, cmethod); 931 break; 932 933 case STMF_ICM_SCSI_DATA_XFER_DONE: 934 stmf_ic_scsi_data_xfer_done_msg_free( 935 (stmf_ic_scsi_data_xfer_done_msg_t *)msg->icm_msg, cmethod); 936 break; 937 938 case STMF_ICM_SCSI_STATUS: 939 stmf_ic_scsi_status_msg_free( 940 (stmf_ic_scsi_status_msg_t *)msg->icm_msg, cmethod); 941 break; 942 943 case STMF_ICM_R2T: 944 stmf_ic_r2t_msg_free( 945 (stmf_ic_r2t_msg_t *)msg->icm_msg, cmethod); 946 break; 947 948 case STMF_ICM_STATUS: 949 stmf_ic_status_msg_free( 950 (stmf_ic_status_msg_t *)msg->icm_msg, cmethod); 951 break; 952 953 case STMF_ICM_SESSION_CREATE: 954 case STMF_ICM_SESSION_DESTROY: 955 stmf_ic_session_create_destroy_msg_free( 956 (stmf_ic_session_create_destroy_msg_t *)msg->icm_msg, 957 cmethod); 958 break; 959 960 case STMF_ICM_ECHO_REQUEST: 961 case STMF_ICM_ECHO_REPLY: 962 stmf_ic_echo_request_reply_msg_free( 963 (stmf_ic_echo_request_reply_msg_t *)msg->icm_msg, cmethod); 964 break; 965 966 case STMF_ICM_MAX_MSG_TYPE: 967 ASSERT(0); 968 break; 969 970 default: 971 ASSERT(0); 972 } 973 974 if (msg->icm_nvlist) 975 nvlist_free(msg->icm_nvlist); 976 977 kmem_free(msg, sizeof (*msg)); 978 } 979 980 /*ARGSUSED*/ 981 static void 982 stmf_ic_reg_port_msg_free(stmf_ic_reg_port_msg_t *m, 983 stmf_ic_msg_construction_method_t cmethod) 984 { 985 scsi_devid_desc_free(m->icrp_port_id); 986 987 kmem_free(m, sizeof (*m)); 988 } 989 990 991 /*ARGSUSED*/ 992 static void 993 stmf_ic_dereg_port_msg_free(stmf_ic_dereg_port_msg_t *m, 994 stmf_ic_msg_construction_method_t cmethod) 995 { 996 scsi_devid_desc_free(m->icdp_port_id); 997 998 kmem_free(m, sizeof (*m)); 999 } 1000 1001 1002 /* 1003 * Works for both reg_lun_msg and dereg_lun_msg, since the message 1004 * payload is the same. 1005 */ 1006 static void 1007 stmf_ic_reg_dereg_lun_msg_free(stmf_ic_reg_dereg_lun_msg_t *m, 1008 stmf_ic_msg_construction_method_t cmethod) 1009 { 1010 if (cmethod == STMF_CONSTRUCTOR) { 1011 kmem_free(m->icrl_lu_provider_name, 1012 strlen(m->icrl_lu_provider_name) + 1); 1013 } 1014 1015 kmem_free(m, sizeof (*m)); 1016 } 1017 1018 static void 1019 stmf_ic_scsi_cmd_msg_free(stmf_ic_scsi_cmd_msg_t *m, 1020 stmf_ic_msg_construction_method_t cmethod) 1021 { 1022 scsi_devid_desc_free(m->icsc_ini_devid); 1023 scsi_devid_desc_free(m->icsc_tgt_devid); 1024 stmf_remote_port_free(m->icsc_rport); 1025 if ((cmethod == STMF_CONSTRUCTOR) && m->icsc_task_cdb) { 1026 kmem_free(m->icsc_task_cdb, m->icsc_task_cdb_length); 1027 } 1028 1029 kmem_free(m, sizeof (*m)); 1030 1031 } 1032 1033 /*ARGSUSED*/ 1034 static void 1035 stmf_ic_scsi_data_msg_free(stmf_ic_scsi_data_msg_t *m, 1036 stmf_ic_msg_construction_method_t cmethod) 1037 { 1038 kmem_free(m, sizeof (*m)); 1039 } 1040 1041 /*ARGSUSED*/ 1042 static void 1043 stmf_ic_scsi_data_xfer_done_msg_free(stmf_ic_scsi_data_xfer_done_msg_t *m, 1044 stmf_ic_msg_construction_method_t cmethod) 1045 { 1046 kmem_free(m, sizeof (*m)); 1047 } 1048 1049 /*ARGSUSED*/ 1050 static void 1051 stmf_ic_scsi_status_msg_free(stmf_ic_scsi_status_msg_t *m, 1052 stmf_ic_msg_construction_method_t cmethod) 1053 { 1054 kmem_free(m, sizeof (*m)); 1055 } 1056 1057 /*ARGSUSED*/ 1058 static void 1059 stmf_ic_r2t_msg_free(stmf_ic_r2t_msg_t *m, 1060 stmf_ic_msg_construction_method_t cmethod) 1061 { 1062 kmem_free(m, sizeof (*m)); 1063 } 1064 1065 /*ARGSUSED*/ 1066 static void 1067 stmf_ic_status_msg_free(stmf_ic_status_msg_t *m, 1068 stmf_ic_msg_construction_method_t cmethod) 1069 { 1070 kmem_free(m, sizeof (*m)); 1071 } 1072 1073 /* 1074 * Works for both session_create and session_destroy msgs, since the message 1075 * payload is the same. 1076 */ 1077 /*ARGSUSED*/ 1078 static void 1079 stmf_ic_session_create_destroy_msg_free(stmf_ic_session_create_destroy_msg_t *m, 1080 stmf_ic_msg_construction_method_t cmethod) 1081 { 1082 scsi_devid_desc_free(m->icscd_ini_devid); 1083 scsi_devid_desc_free(m->icscd_tgt_devid); 1084 stmf_remote_port_free(m->icscd_rport); 1085 1086 kmem_free(m, sizeof (*m)); 1087 } 1088 1089 /*ARGSUSED*/ 1090 static void 1091 stmf_ic_echo_request_reply_msg_free(stmf_ic_echo_request_reply_msg_t *m, 1092 stmf_ic_msg_construction_method_t cmethod) 1093 { 1094 kmem_free(m, sizeof (*m)); 1095 } 1096 1097 1098 /* 1099 * Marshaling routines. 1100 */ 1101 1102 static nvlist_t * 1103 stmf_ic_msg_marshal(stmf_ic_msg_t *msg) 1104 { 1105 nvlist_t *nvl = NULL; 1106 int rc = 0; 1107 1108 rc = nvlist_alloc(&nvl, NV_UNIQUE_NAME, KM_SLEEP); 1109 if (rc) 1110 goto done; 1111 1112 NVLIST_ADD_FIELD(uint8, msg, icm_msg_type); 1113 NVLIST_ADD_FIELD(uint64, msg, icm_msgid); 1114 1115 switch (msg->icm_msg_type) { 1116 case STMF_ICM_REGISTER_PROXY_PORT: 1117 rc = stmf_ic_reg_port_msg_marshal(nvl, msg->icm_msg); 1118 break; 1119 1120 1121 case STMF_ICM_DEREGISTER_PROXY_PORT: 1122 rc = stmf_ic_dereg_port_msg_marshal(nvl, msg->icm_msg); 1123 break; 1124 1125 case STMF_ICM_LUN_ACTIVE: 1126 case STMF_ICM_REGISTER_LUN: 1127 case STMF_ICM_DEREGISTER_LUN: 1128 rc = stmf_ic_reg_dereg_lun_msg_marshal(nvl, msg->icm_msg); 1129 break; 1130 1131 case STMF_ICM_SCSI_CMD: 1132 rc = stmf_ic_scsi_cmd_msg_marshal(nvl, msg->icm_msg); 1133 break; 1134 1135 case STMF_ICM_SCSI_DATA: 1136 rc = stmf_ic_scsi_data_msg_marshal(nvl, msg->icm_msg); 1137 break; 1138 1139 case STMF_ICM_SCSI_DATA_XFER_DONE: 1140 rc = stmf_ic_scsi_data_xfer_done_msg_marshal(nvl, msg->icm_msg); 1141 break; 1142 1143 case STMF_ICM_SCSI_STATUS: 1144 rc = stmf_ic_scsi_status_msg_marshal(nvl, msg->icm_msg); 1145 break; 1146 1147 case STMF_ICM_R2T: 1148 rc = stmf_ic_r2t_msg_marshal(nvl, msg->icm_msg); 1149 break; 1150 1151 case STMF_ICM_STATUS: 1152 rc = stmf_ic_status_msg_marshal(nvl, msg->icm_msg); 1153 break; 1154 1155 case STMF_ICM_SESSION_CREATE: 1156 case STMF_ICM_SESSION_DESTROY: 1157 rc = stmf_ic_session_create_destroy_msg_marshal(nvl, 1158 msg->icm_msg); 1159 break; 1160 1161 case STMF_ICM_ECHO_REQUEST: 1162 case STMF_ICM_ECHO_REPLY: 1163 rc = stmf_ic_echo_request_reply_msg_marshal(nvl, 1164 msg->icm_msg); 1165 break; 1166 1167 case STMF_ICM_MAX_MSG_TYPE: 1168 ASSERT(0); 1169 break; 1170 1171 default: 1172 ASSERT(0); 1173 } 1174 1175 done: 1176 if (!rc) 1177 return (nvl); 1178 1179 if (nvl) 1180 nvlist_free(nvl); 1181 1182 return (NULL); 1183 } 1184 1185 1186 static int 1187 stmf_ic_reg_port_msg_marshal(nvlist_t *nvl, void *msg) 1188 { 1189 stmf_ic_reg_port_msg_t *m = (stmf_ic_reg_port_msg_t *)msg; 1190 int rc = 0; 1191 1192 NVLIST_ADD_DEVID(m, icrp_port_id); 1193 NVLIST_ADD_FIELD(uint16, m, icrp_relative_port_id); 1194 1195 NVLIST_ADD_FIELD(uint16, m, icrp_cb_arg_len); 1196 /* only add the callback arg if necessary */ 1197 if (m->icrp_cb_arg_len) { 1198 NVLIST_ADD_ARRAY_LEN(uint8, m, icrp_cb_arg, m->icrp_cb_arg_len); 1199 } 1200 1201 done: 1202 return (rc); 1203 } 1204 1205 static int 1206 stmf_ic_dereg_port_msg_marshal(nvlist_t *nvl, void *msg) 1207 { 1208 stmf_ic_dereg_port_msg_t *m = (stmf_ic_dereg_port_msg_t *)msg; 1209 int rc = 0; 1210 1211 NVLIST_ADD_DEVID(m, icdp_port_id); 1212 NVLIST_ADD_FIELD(uint16, m, icdp_cb_arg_len); 1213 1214 /* only add the callback arg if necessary */ 1215 if (m->icdp_cb_arg_len) { 1216 NVLIST_ADD_ARRAY_LEN(uint8, m, icdp_cb_arg, m->icdp_cb_arg_len); 1217 } 1218 1219 done: 1220 return (rc); 1221 } 1222 1223 /* 1224 * Handles STMF_ICM_LUN_ACTIVE, STMF_ICM_REGISTER_LUN and 1225 * STMF_ICM_DEREGISTER_LUN; 1226 * msg payload is the same for all. 1227 */ 1228 static int 1229 stmf_ic_reg_dereg_lun_msg_marshal(nvlist_t *nvl, void *msg) 1230 { 1231 stmf_ic_reg_dereg_lun_msg_t *m = (stmf_ic_reg_dereg_lun_msg_t *)msg; 1232 int rc = 0; 1233 1234 NVLIST_ADD_ARRAY(uint8, m, icrl_lun_id); 1235 NVLIST_ADD_FIELD(string, m, icrl_lu_provider_name); 1236 NVLIST_ADD_FIELD(uint16, m, icrl_cb_arg_len); 1237 1238 /* only add the callback arg if necessary */ 1239 if (m->icrl_cb_arg_len) { 1240 NVLIST_ADD_ARRAY_LEN(uint8, m, icrl_cb_arg, m->icrl_cb_arg_len); 1241 } 1242 1243 done: 1244 return (rc); 1245 } 1246 1247 static int 1248 stmf_ic_scsi_cmd_msg_marshal(nvlist_t *nvl, void *msg) 1249 { 1250 stmf_ic_scsi_cmd_msg_t *m = (stmf_ic_scsi_cmd_msg_t *)msg; 1251 int rc = 0; 1252 1253 NVLIST_ADD_FIELD(uint64, m, icsc_task_msgid); 1254 NVLIST_ADD_DEVID(m, icsc_ini_devid); 1255 NVLIST_ADD_DEVID(m, icsc_tgt_devid); 1256 NVLIST_ADD_RPORT(m, icsc_rport); 1257 NVLIST_ADD_ARRAY(uint8, m, icsc_lun_id); 1258 NVLIST_ADD_FIELD(uint64, m, icsc_session_id); 1259 NVLIST_ADD_ARRAY_LEN(uint8, m, icsc_task_lun_no, 8); 1260 NVLIST_ADD_FIELD(uint32, m, icsc_task_expected_xfer_length); 1261 NVLIST_ADD_FIELD(uint16, m, icsc_task_cdb_length); 1262 /* 1263 * icsc_task_cdb_length may be zero in the case of a task 1264 * management function. 1265 */ 1266 NVLIST_ADD_ARRAY_LEN(uint8, m, icsc_task_cdb, m->icsc_task_cdb_length); 1267 NVLIST_ADD_FIELD(uint8, m, icsc_task_flags); 1268 NVLIST_ADD_FIELD(uint8, m, icsc_task_priority); 1269 NVLIST_ADD_FIELD(uint8, m, icsc_task_mgmt_function); 1270 1271 NVLIST_ADD_FIELD(uint32, m, icsc_immed_data_len); 1272 /* only add immediate data if necessary */ 1273 if (m->icsc_immed_data_len) { 1274 NVLIST_ADD_ARRAY_LEN(uint8, m, icsc_immed_data, 1275 m->icsc_immed_data_len); 1276 } 1277 1278 done: 1279 return (rc); 1280 } 1281 1282 static int 1283 stmf_ic_scsi_data_msg_marshal(nvlist_t *nvl, void *msg) 1284 { 1285 stmf_ic_scsi_data_msg_t *m = (stmf_ic_scsi_data_msg_t *)msg; 1286 int rc = 0; 1287 1288 NVLIST_ADD_FIELD(uint64, m, icsd_task_msgid); 1289 NVLIST_ADD_FIELD(uint64, m, icsd_session_id); 1290 NVLIST_ADD_ARRAY(uint8, m, icsd_lun_id); 1291 NVLIST_ADD_FIELD(uint64, m, icsd_data_len); 1292 NVLIST_ADD_ARRAY_LEN(uint8, m, icsd_data, m->icsd_data_len); 1293 1294 done: 1295 return (rc); 1296 } 1297 1298 static int 1299 stmf_ic_scsi_data_xfer_done_msg_marshal(nvlist_t *nvl, void *msg) 1300 { 1301 stmf_ic_scsi_data_xfer_done_msg_t *m = 1302 (stmf_ic_scsi_data_xfer_done_msg_t *)msg; 1303 int rc = 0; 1304 1305 NVLIST_ADD_FIELD(uint64, m, icsx_task_msgid); 1306 NVLIST_ADD_FIELD(uint64, m, icsx_session_id); 1307 NVLIST_ADD_FIELD(uint64, m, icsx_status); 1308 1309 done: 1310 return (rc); 1311 } 1312 1313 static int 1314 stmf_ic_scsi_status_msg_marshal(nvlist_t *nvl, void *msg) 1315 { 1316 stmf_ic_scsi_status_msg_t *m = (stmf_ic_scsi_status_msg_t *)msg; 1317 int rc = 0; 1318 1319 NVLIST_ADD_FIELD(uint64, m, icss_task_msgid); 1320 NVLIST_ADD_FIELD(uint64, m, icss_session_id); 1321 NVLIST_ADD_ARRAY(uint8, m, icss_lun_id); 1322 NVLIST_ADD_FIELD(uint8, m, icss_response); 1323 NVLIST_ADD_FIELD(uint8, m, icss_status); 1324 NVLIST_ADD_FIELD(uint8, m, icss_flags); 1325 NVLIST_ADD_FIELD(uint32, m, icss_resid); 1326 1327 NVLIST_ADD_FIELD(uint8, m, icss_sense_len); 1328 1329 if (m->icss_sense_len) 1330 NVLIST_ADD_ARRAY_LEN(uint8, m, icss_sense, m->icss_sense_len); 1331 1332 done: 1333 return (rc); 1334 } 1335 1336 static int 1337 stmf_ic_r2t_msg_marshal(nvlist_t *nvl, void *msg) 1338 { 1339 stmf_ic_r2t_msg_t *m = (stmf_ic_r2t_msg_t *)msg; 1340 int rc = 0; 1341 1342 NVLIST_ADD_FIELD(uint64, m, icrt_task_msgid); 1343 NVLIST_ADD_FIELD(uint64, m, icrt_session_id); 1344 NVLIST_ADD_FIELD(uint32, m, icrt_offset); 1345 NVLIST_ADD_FIELD(uint32, m, icrt_length); 1346 1347 done: 1348 return (rc); 1349 } 1350 1351 static int 1352 stmf_ic_status_msg_marshal(nvlist_t *nvl, void *msg) 1353 { 1354 stmf_ic_status_msg_t *m = (stmf_ic_status_msg_t *)msg; 1355 int rc = 0; 1356 1357 NVLIST_ADD_FIELD(uint8, m, ics_msg_type); 1358 NVLIST_ADD_FIELD(uint64, m, ics_msgid); 1359 NVLIST_ADD_FIELD(uint8, m, ics_status); 1360 1361 done: 1362 return (rc); 1363 } 1364 1365 static int 1366 stmf_ic_session_create_destroy_msg_marshal(nvlist_t *nvl, void *msg) 1367 { 1368 stmf_ic_session_create_destroy_msg_t *m = 1369 (stmf_ic_session_create_destroy_msg_t *)msg; 1370 int rc = 0; 1371 1372 NVLIST_ADD_DEVID(m, icscd_ini_devid); 1373 NVLIST_ADD_DEVID(m, icscd_tgt_devid); 1374 NVLIST_ADD_RPORT(m, icscd_rport); 1375 NVLIST_ADD_FIELD(uint64, m, icscd_session_id); 1376 1377 done: 1378 return (rc); 1379 } 1380 1381 static int 1382 stmf_ic_echo_request_reply_msg_marshal(nvlist_t *nvl, void *msg) 1383 { 1384 stmf_ic_echo_request_reply_msg_t *m = msg; 1385 int rc = 0; 1386 1387 NVLIST_ADD_FIELD(uint32, m, icerr_datalen); 1388 if (m->icerr_datalen) 1389 NVLIST_ADD_ARRAY_LEN(uint8, m, icerr_data, m->icerr_datalen); 1390 1391 done: 1392 return (rc); 1393 } 1394 1395 /* 1396 * Allocate a new nvlist representing the scsi_devid_desc and add it 1397 * to the nvlist. 1398 */ 1399 static int 1400 stmf_ic_scsi_devid_desc_marshal(nvlist_t *parent_nvl, 1401 char *sdid_name, 1402 scsi_devid_desc_t *sdid) 1403 { 1404 int rc = 0; 1405 nvlist_t *nvl = NULL; 1406 1407 rc = nvlist_alloc(&nvl, NV_UNIQUE_NAME, KM_SLEEP); 1408 if (rc) 1409 goto done; 1410 1411 NVLIST_ADD_FIELD(uint8, sdid, protocol_id); 1412 NVLIST_ADD_FIELD(uint8, sdid, code_set); 1413 NVLIST_ADD_FIELD(uint8, sdid, piv); 1414 NVLIST_ADD_FIELD(uint8, sdid, association); 1415 NVLIST_ADD_FIELD(uint8, sdid, ident_type); 1416 NVLIST_ADD_FIELD(uint8, sdid, ident_length); 1417 1418 rc = nvlist_add_uint8_array(nvl, "ident", sdid->ident, 1419 sdid->ident_length); 1420 if (rc) 1421 goto done; 1422 1423 rc = nvlist_add_nvlist(parent_nvl, sdid_name, nvl); 1424 done: 1425 if (nvl) { 1426 nvlist_free(nvl); 1427 } 1428 return (rc); 1429 } 1430 1431 /* 1432 * Allocate a new nvlist representing the stmf_remote_port and add it 1433 * to the nvlist. 1434 */ 1435 static int 1436 stmf_ic_remote_port_marshal(nvlist_t *parent_nvl, char *rport_name, 1437 stmf_remote_port_t *rport) { 1438 1439 int rc = 0; 1440 nvlist_t *nvl = NULL; 1441 1442 rc = nvlist_alloc(&nvl, NV_UNIQUE_NAME, KM_SLEEP); 1443 if (rc) 1444 goto done; 1445 1446 NVLIST_ADD_FIELD(uint16, rport, rport_tptid_sz); 1447 rc = nvlist_add_uint8_array(nvl, "rport_tptid", 1448 (uint8_t *)rport->rport_tptid, rport->rport_tptid_sz); 1449 if (rc) 1450 goto done; 1451 1452 rc = nvlist_add_nvlist(parent_nvl, rport_name, nvl); 1453 done: 1454 if (nvl) { 1455 nvlist_free(nvl); 1456 } 1457 return (rc); 1458 } 1459 1460 /* 1461 * Unmarshaling routines. 1462 */ 1463 1464 static stmf_ic_msg_t * 1465 stmf_ic_msg_unmarshal(nvlist_t *nvl) 1466 { 1467 stmf_ic_msg_t *m = kmem_zalloc(sizeof (*m), KM_SLEEP); 1468 uint8_t msg_type; 1469 int rc = 0; 1470 1471 /* 1472 * We'd like to do this: 1473 * 1474 * NVLIST_LOOKUP_FIELD(uint8, m, icm_msg_type); 1475 * 1476 * but the fact that msg type is an enum causes type problems. 1477 */ 1478 rc = nvlist_lookup_uint8(nvl, "icm_msg_type", &msg_type); 1479 if (rc) { 1480 stmf_ic_nvlookup_warn(__func__, "icm_msg_type"); 1481 goto done; 1482 } 1483 1484 m->icm_msg_type = msg_type; 1485 m->icm_nvlist = nvl; 1486 1487 NVLIST_LOOKUP_FIELD(uint64, m, icm_msgid); 1488 1489 switch (m->icm_msg_type) { 1490 1491 case STMF_ICM_REGISTER_PROXY_PORT: 1492 m->icm_msg = stmf_ic_reg_port_msg_unmarshal(nvl); 1493 break; 1494 1495 1496 case STMF_ICM_DEREGISTER_PROXY_PORT: 1497 m->icm_msg = stmf_ic_dereg_port_msg_unmarshal(nvl); 1498 break; 1499 1500 case STMF_ICM_LUN_ACTIVE: 1501 case STMF_ICM_REGISTER_LUN: 1502 case STMF_ICM_DEREGISTER_LUN: 1503 m->icm_msg = stmf_ic_reg_dereg_lun_msg_unmarshal(nvl); 1504 break; 1505 1506 case STMF_ICM_SCSI_CMD: 1507 m->icm_msg = stmf_ic_scsi_cmd_msg_unmarshal(nvl); 1508 break; 1509 1510 case STMF_ICM_SCSI_DATA: 1511 m->icm_msg = stmf_ic_scsi_data_msg_unmarshal(nvl); 1512 break; 1513 1514 case STMF_ICM_SCSI_DATA_XFER_DONE: 1515 m->icm_msg = stmf_ic_scsi_data_xfer_done_msg_unmarshal(nvl); 1516 break; 1517 1518 case STMF_ICM_SCSI_STATUS: 1519 m->icm_msg = stmf_ic_scsi_status_msg_unmarshal(nvl); 1520 break; 1521 1522 case STMF_ICM_R2T: 1523 m->icm_msg = stmf_ic_r2t_msg_unmarshal(nvl); 1524 break; 1525 1526 case STMF_ICM_STATUS: 1527 m->icm_msg = stmf_ic_status_msg_unmarshal(nvl); 1528 break; 1529 1530 case STMF_ICM_SESSION_CREATE: 1531 case STMF_ICM_SESSION_DESTROY: 1532 m->icm_msg = stmf_ic_session_create_destroy_msg_unmarshal(nvl); 1533 break; 1534 1535 case STMF_ICM_ECHO_REQUEST: 1536 case STMF_ICM_ECHO_REPLY: 1537 m->icm_msg = stmf_ic_echo_request_reply_msg_unmarshal(nvl); 1538 break; 1539 1540 case STMF_ICM_MAX_MSG_TYPE: 1541 ASSERT(0); 1542 break; 1543 1544 default: 1545 ASSERT(0); 1546 } 1547 1548 done: 1549 1550 if (!m->icm_msg) { 1551 kmem_free(m, sizeof (*m)); 1552 return (NULL); 1553 } 1554 1555 return (m); 1556 } 1557 1558 static void * 1559 stmf_ic_reg_port_msg_unmarshal(nvlist_t *nvl) 1560 { 1561 nvlist_t *nvl_port_id = NULL; 1562 int rc = 0; 1563 stmf_ic_reg_port_msg_t *m = kmem_zalloc(sizeof (*m), KM_SLEEP); 1564 1565 rc = nvlist_lookup_nvlist(nvl, "icrp_port_id", &nvl_port_id); 1566 if (rc) { 1567 stmf_ic_nvlookup_warn(__func__, "icrp_port_id nvl"); 1568 rc = ENOMEM; /* XXX */ 1569 goto done; 1570 } 1571 1572 m->icrp_port_id = stmf_ic_scsi_devid_desc_unmarshal(nvl_port_id); 1573 if (m->icrp_port_id == NULL) { 1574 stmf_ic_nvlookup_warn(__func__, "icrp_port_id"); 1575 rc = ENOMEM; /* XXX */ 1576 goto done; 1577 } 1578 1579 NVLIST_LOOKUP_FIELD(uint16, m, icrp_relative_port_id); 1580 NVLIST_LOOKUP_FIELD(uint16, m, icrp_cb_arg_len); 1581 1582 if (m->icrp_cb_arg_len) { 1583 m->icrp_cb_arg = stmf_ic_uint8_array_unmarshal(nvl, 1584 "icrp_cb_arg", m->icrp_cb_arg_len, NULL); 1585 if (m->icrp_cb_arg == NULL) { 1586 stmf_ic_nvlookup_warn(__func__, "icrp_cb_arg"); 1587 rc = ENOMEM; /* XXX */ 1588 goto done; 1589 } 1590 } 1591 1592 done: 1593 if (!rc) 1594 return (m); 1595 1596 stmf_ic_reg_port_msg_free(m, STMF_UNMARSHAL); 1597 1598 return (NULL); 1599 } 1600 1601 /* 1602 * XXX largely the same as stmf_ic_reg_port_msg_unmarshal() 1603 * Common stuff should be factored out. Type issues may make this 1604 * painful. 1605 */ 1606 static void * 1607 stmf_ic_dereg_port_msg_unmarshal(nvlist_t *nvl) 1608 { 1609 nvlist_t *nvl_port_id = NULL; 1610 int rc = 0; 1611 stmf_ic_dereg_port_msg_t *m = kmem_zalloc(sizeof (*m), KM_SLEEP); 1612 1613 rc = nvlist_lookup_nvlist(nvl, "icdp_port_id", &nvl_port_id); 1614 if (rc) { 1615 stmf_ic_nvlookup_warn(__func__, "icdp_port_id nvl"); 1616 goto done; 1617 } 1618 1619 m->icdp_port_id = stmf_ic_scsi_devid_desc_unmarshal(nvl_port_id); 1620 if (m->icdp_port_id == NULL) { 1621 stmf_ic_nvlookup_warn(__func__, "icdp_port_id"); 1622 rc = ENOMEM; /* XXX */ 1623 goto done; 1624 } 1625 1626 NVLIST_LOOKUP_FIELD(uint16, m, icdp_cb_arg_len); 1627 1628 if (m->icdp_cb_arg_len) { 1629 m->icdp_cb_arg = stmf_ic_uint8_array_unmarshal(nvl, 1630 "icdp_cb_arg", m->icdp_cb_arg_len, NULL); 1631 if (m->icdp_cb_arg == NULL) { 1632 stmf_ic_nvlookup_warn(__func__, "icdp_cb_arg"); 1633 rc = ENOMEM; /* XXX */ 1634 goto done; 1635 } 1636 } 1637 1638 done: 1639 if (!rc) 1640 return (m); 1641 1642 stmf_ic_dereg_port_msg_free(m, STMF_UNMARSHAL); 1643 1644 return (NULL); 1645 } 1646 1647 static void * 1648 stmf_ic_reg_dereg_lun_msg_unmarshal(nvlist_t *nvl) 1649 { 1650 int rc = 0; 1651 stmf_ic_reg_dereg_lun_msg_t *m = kmem_zalloc(sizeof (*m), KM_SLEEP); 1652 1653 if (! stmf_ic_uint8_array_unmarshal(nvl, "icrl_lun_id", 1654 sizeof (m->icrl_lun_id), m->icrl_lun_id)) { 1655 stmf_ic_nvlookup_warn(__func__, "icrl_lun_id"); 1656 rc = ENOMEM; /* XXX */ 1657 goto done; 1658 } 1659 1660 m->icrl_lu_provider_name = stmf_ic_string_unmarshal(nvl, 1661 "icrl_lu_provider_name"); 1662 1663 if (!m->icrl_lu_provider_name) { 1664 stmf_ic_nvlookup_warn(__func__, "icrl_lu_provider_name"); 1665 rc = ENOMEM; /* XXX */ 1666 goto done; 1667 } 1668 1669 NVLIST_LOOKUP_FIELD(uint16, m, icrl_cb_arg_len); 1670 1671 if (m->icrl_cb_arg_len) { 1672 m->icrl_cb_arg = stmf_ic_uint8_array_unmarshal(nvl, 1673 "icrl_cb_arg", m->icrl_cb_arg_len, NULL); 1674 if (m->icrl_cb_arg == NULL) { 1675 stmf_ic_nvlookup_warn(__func__, "icrl_cb_arg"); 1676 rc = ENOMEM; /* XXX */ 1677 goto done; 1678 } 1679 } 1680 1681 done: 1682 if (!rc) 1683 return (m); 1684 1685 stmf_ic_reg_dereg_lun_msg_free(m, STMF_UNMARSHAL); 1686 1687 return (NULL); 1688 } 1689 1690 static void * 1691 stmf_ic_scsi_cmd_msg_unmarshal(nvlist_t *nvl) 1692 { 1693 int rc = 0; 1694 stmf_ic_scsi_cmd_msg_t *m = kmem_zalloc(sizeof (*m), KM_SLEEP); 1695 1696 if (nvlist_lookup_pairs(nvl, 0, 1697 NV_PAIR(UINT64, m, icsc_task_msgid), 1698 NV_PAIR(UINT64, m, icsc_session_id), 1699 NV_PAIR(UINT32, m, icsc_task_expected_xfer_length), 1700 NV_PAIR(UINT16, m, icsc_task_cdb_length), 1701 NV_PAIR(UINT8, m, icsc_task_flags), 1702 NV_PAIR(UINT8, m, icsc_task_mgmt_function), 1703 NV_PAIR(UINT32, m, icsc_immed_data_len), 1704 NULL) != 0) { 1705 stmf_ic_nvlookup_warn(__func__, "icsc_task_msgid and friends"); 1706 rc = ENOMEM; /* XXX need something better */ 1707 goto done; 1708 } 1709 1710 m->icsc_ini_devid = stmf_ic_lookup_scsi_devid_desc_and_unmarshal( 1711 nvl, "icsc_ini_devid"); 1712 if (m->icsc_ini_devid == NULL) { 1713 stmf_ic_nvlookup_warn(__func__, "icsc_ini_devid"); 1714 rc = ENOMEM; 1715 goto done; 1716 } 1717 1718 m->icsc_tgt_devid = stmf_ic_lookup_scsi_devid_desc_and_unmarshal( 1719 nvl, "icsc_tgt_devid"); 1720 if (m->icsc_tgt_devid == NULL) { 1721 stmf_ic_nvlookup_warn(__func__, "icsc_tgt_devid"); 1722 rc = ENOMEM; 1723 goto done; 1724 } 1725 1726 m->icsc_rport = stmf_ic_lookup_remote_port_and_unmarshal( 1727 nvl, "icsc_rport"); 1728 if (m->icsc_rport == NULL) { 1729 stmf_ic_nvlookup_warn(__func__, "icsc_rport"); 1730 rc = ENOMEM; 1731 goto done; 1732 } 1733 1734 /* icsc_lun_id */ 1735 if (!stmf_ic_uint8_array_unmarshal(nvl, "icsc_lun_id", 1736 sizeof (m->icsc_lun_id), m->icsc_lun_id)) { 1737 stmf_ic_nvlookup_warn(__func__, "icsc_lun_id"); 1738 rc = ENOMEM; 1739 goto done; 1740 } 1741 1742 /* icsc_task_lun_no */ 1743 if (!stmf_ic_uint8_array_unmarshal(nvl, "icsc_task_lun_no", 1744 sizeof (m->icsc_task_lun_no), m->icsc_task_lun_no)) { 1745 stmf_ic_nvlookup_warn(__func__, "icsc_task_lun_no"); 1746 rc = ENOMEM; 1747 goto done; 1748 } 1749 1750 /* icsc_task_cdb */ 1751 if (m->icsc_task_cdb_length) { 1752 m->icsc_task_cdb = stmf_ic_uint8_array_unmarshal(nvl, 1753 "icsc_task_cdb", m->icsc_task_cdb_length, NULL); 1754 if (!m->icsc_task_cdb) { 1755 stmf_ic_nvlookup_warn(__func__, "icsc_task_cdb"); 1756 rc = ENOMEM; 1757 goto done; 1758 } 1759 } 1760 1761 /* immediate data, if there is any */ 1762 if (m->icsc_immed_data_len) { 1763 m->icsc_immed_data = stmf_ic_uint8_array_unmarshal(nvl, 1764 "icsc_immed_data", m->icsc_immed_data_len, NULL); 1765 if (!m->icsc_immed_data) { 1766 stmf_ic_nvlookup_warn(__func__, "icsc_immed_data"); 1767 rc = ENOMEM; 1768 goto done; 1769 } 1770 } 1771 1772 done: 1773 if (!rc) 1774 return (m); 1775 1776 stmf_ic_scsi_cmd_msg_free(m, STMF_UNMARSHAL); 1777 1778 return (NULL); 1779 } 1780 1781 static void * 1782 stmf_ic_scsi_data_msg_unmarshal(nvlist_t *nvl) 1783 { 1784 int rc = 0; 1785 stmf_ic_scsi_data_msg_t *m = kmem_zalloc(sizeof (*m), KM_SLEEP); 1786 1787 if (nvlist_lookup_pairs(nvl, 0, 1788 NV_PAIR(UINT64, m, icsd_task_msgid), 1789 NV_PAIR(UINT64, m, icsd_session_id), 1790 NV_PAIR(UINT64, m, icsd_data_len), 1791 NULL) != 0) { 1792 stmf_ic_nvlookup_warn(__func__, "icsd_task_msgid and friends"); 1793 rc = ENOMEM; /* XXX need something better */ 1794 goto done; 1795 } 1796 1797 if (!stmf_ic_uint8_array_unmarshal(nvl, "icsd_lun_id", 1798 sizeof (m->icsd_lun_id), m->icsd_lun_id)) { 1799 stmf_ic_nvlookup_warn(__func__, "icsd_lun_id"); 1800 rc = ENOMEM; 1801 goto done; 1802 } 1803 1804 m->icsd_data = stmf_ic_uint8_array_unmarshal(nvl, "icsd_data", 1805 m->icsd_data_len, NULL); 1806 if (!m->icsd_data) { 1807 stmf_ic_nvlookup_warn(__func__, "icsd_data"); 1808 rc = ENOMEM; 1809 goto done; 1810 } 1811 1812 done: 1813 if (!rc) 1814 return (m); 1815 1816 stmf_ic_scsi_data_msg_free(m, STMF_UNMARSHAL); 1817 1818 return (NULL); 1819 } 1820 1821 static void * 1822 stmf_ic_scsi_data_xfer_done_msg_unmarshal(nvlist_t *nvl) 1823 { 1824 int rc = 0; 1825 stmf_ic_scsi_data_xfer_done_msg_t *m = 1826 kmem_zalloc(sizeof (*m), KM_SLEEP); 1827 1828 if (nvlist_lookup_pairs(nvl, 0, 1829 NV_PAIR(UINT64, m, icsx_task_msgid), 1830 NV_PAIR(UINT64, m, icsx_session_id), 1831 NV_PAIR(UINT64, m, icsx_status), 1832 NULL) != 0) { 1833 stmf_ic_nvlookup_warn(__func__, "icsx_task_msgid and friends"); 1834 rc = ENOMEM; /* XXX need something better */ 1835 goto done; 1836 } 1837 1838 done: 1839 if (!rc) 1840 return (m); 1841 1842 stmf_ic_scsi_data_xfer_done_msg_free(m, STMF_UNMARSHAL); 1843 1844 return (NULL); 1845 } 1846 1847 static void * 1848 stmf_ic_scsi_status_msg_unmarshal(nvlist_t *nvl) 1849 { 1850 int rc = 0; 1851 stmf_ic_scsi_status_msg_t *m = kmem_zalloc(sizeof (*m), KM_SLEEP); 1852 1853 if (nvlist_lookup_pairs(nvl, 0, 1854 NV_PAIR(UINT64, m, icss_task_msgid), 1855 NV_PAIR(UINT64, m, icss_session_id), 1856 NV_PAIR(UINT8, m, icss_response), 1857 NV_PAIR(UINT8, m, icss_status), 1858 NV_PAIR(UINT8, m, icss_flags), 1859 NV_PAIR(UINT32, m, icss_resid), 1860 NV_PAIR(UINT8, m, icss_sense_len), 1861 NULL) != 0) { 1862 stmf_ic_nvlookup_warn(__func__, "icss_task_msgid and friends"); 1863 rc = ENOMEM; /* XXX need something better */ 1864 goto done; 1865 } 1866 1867 if (!stmf_ic_uint8_array_unmarshal(nvl, "icss_lun_id", 1868 sizeof (m->icss_lun_id), m->icss_lun_id)) { 1869 stmf_ic_nvlookup_warn(__func__, "icss_lun_id"); 1870 rc = ENOMEM; 1871 goto done; 1872 } 1873 1874 if (m->icss_sense_len) { 1875 m->icss_sense = stmf_ic_uint8_array_unmarshal(nvl, "icss_sense", 1876 m->icss_sense_len, NULL); 1877 if (!m->icss_sense) { 1878 stmf_ic_nvlookup_warn(__func__, "icss_sense"); 1879 rc = ENOMEM; 1880 goto done; 1881 } 1882 } 1883 done: 1884 if (!rc) 1885 return (m); 1886 1887 stmf_ic_scsi_status_msg_free(m, STMF_UNMARSHAL); 1888 1889 return (NULL); 1890 } 1891 1892 static void * 1893 stmf_ic_r2t_msg_unmarshal(nvlist_t *nvl) 1894 { 1895 int rc = 0; 1896 stmf_ic_r2t_msg_t *m = kmem_zalloc(sizeof (*m), KM_SLEEP); 1897 1898 if (nvlist_lookup_pairs(nvl, 0, 1899 NV_PAIR(UINT64, m, icrt_task_msgid), 1900 NV_PAIR(UINT64, m, icrt_session_id), 1901 NV_PAIR(UINT32, m, icrt_offset), 1902 NV_PAIR(UINT32, m, icrt_length), 1903 NULL) != 0) { 1904 stmf_ic_nvlookup_warn(__func__, "icrt_task_msgid and friends"); 1905 rc = ENOMEM; /* XXX need something better */ 1906 goto done; 1907 } 1908 1909 done: 1910 if (!rc) 1911 return (m); 1912 1913 stmf_ic_r2t_msg_free(m, STMF_UNMARSHAL); 1914 1915 return (NULL); 1916 } 1917 1918 static void * 1919 stmf_ic_session_create_destroy_msg_unmarshal(nvlist_t *nvl) 1920 { 1921 int rc = 0; 1922 stmf_ic_session_create_destroy_msg_t *m = kmem_zalloc(sizeof (*m), 1923 KM_SLEEP); 1924 1925 if (nvlist_lookup_pairs(nvl, 0, 1926 NV_PAIR(UINT64, m, icscd_session_id), 1927 NULL) != 0) { 1928 stmf_ic_nvlookup_warn(__func__, "icsd_session_id"); 1929 rc = ENOMEM; /* XXX need something better */ 1930 goto done; 1931 } 1932 1933 m->icscd_ini_devid = stmf_ic_lookup_scsi_devid_desc_and_unmarshal( 1934 nvl, "icscd_ini_devid"); 1935 if (m->icscd_ini_devid == NULL) { 1936 stmf_ic_nvlookup_warn(__func__, "icsd_ini_devid"); 1937 rc = ENOMEM; 1938 goto done; 1939 } 1940 1941 m->icscd_tgt_devid = stmf_ic_lookup_scsi_devid_desc_and_unmarshal( 1942 nvl, "icscd_tgt_devid"); 1943 if (m->icscd_tgt_devid == NULL) { 1944 stmf_ic_nvlookup_warn(__func__, "icsd_tgt_devid"); 1945 rc = ENOMEM; 1946 goto done; 1947 } 1948 1949 m->icscd_rport = stmf_ic_lookup_remote_port_and_unmarshal( 1950 nvl, "icscd_rport"); 1951 if (m->icscd_rport == NULL) { 1952 stmf_ic_nvlookup_warn(__func__, "icscd_rport"); 1953 rc = ENOMEM; 1954 goto done; 1955 } 1956 1957 done: 1958 if (!rc) 1959 return (m); 1960 1961 stmf_ic_session_create_destroy_msg_free(m, STMF_UNMARSHAL); 1962 1963 return (NULL); 1964 } 1965 1966 static void * 1967 stmf_ic_echo_request_reply_msg_unmarshal(nvlist_t *nvl) 1968 { 1969 int rc = 0; 1970 stmf_ic_echo_request_reply_msg_t *m = kmem_zalloc(sizeof (*m), 1971 KM_SLEEP); 1972 1973 if (nvlist_lookup_pairs(nvl, 0, 1974 NV_PAIR(UINT32, m, icerr_datalen), 1975 NULL) != 0) { 1976 stmf_ic_nvlookup_warn(__func__, "icerr_datalen"); 1977 rc = ENOMEM; /* XXX need something better */ 1978 goto done; 1979 } 1980 1981 /* immediate data, if there is any */ 1982 if (m->icerr_datalen) { 1983 m->icerr_data = stmf_ic_uint8_array_unmarshal(nvl, 1984 "icerr_data", m->icerr_datalen, NULL); 1985 if (!m->icerr_data) { 1986 stmf_ic_nvlookup_warn(__func__, "icerr_data"); 1987 rc = ENOMEM; 1988 goto done; 1989 } 1990 } 1991 1992 done: 1993 if (!rc) 1994 return (m); 1995 1996 stmf_ic_echo_request_reply_msg_free(m, STMF_UNMARSHAL); 1997 1998 return (NULL); 1999 } 2000 2001 static void * 2002 stmf_ic_status_msg_unmarshal(nvlist_t *nvl) 2003 { 2004 int rc = 0; 2005 stmf_ic_status_msg_t *m = kmem_zalloc(sizeof (*m), KM_SLEEP); 2006 2007 if (nvlist_lookup_pairs(nvl, 0, 2008 NV_PAIR(UINT8, m, ics_msg_type), 2009 NV_PAIR(UINT64, m, ics_msgid), 2010 NV_PAIR(UINT8, m, ics_status), 2011 NULL) != 0) { 2012 stmf_ic_nvlookup_warn(__func__, "ics_msg_type and friends"); 2013 rc = ENOMEM; /* XXX need something better */ 2014 goto done; 2015 } 2016 2017 done: 2018 if (!rc) 2019 return (m); 2020 2021 kmem_free(m, sizeof (*m)); 2022 return (NULL); 2023 } 2024 2025 2026 static scsi_devid_desc_t * 2027 stmf_ic_lookup_scsi_devid_desc_and_unmarshal(nvlist_t *nvl, char *field_name) 2028 { 2029 nvlist_t *nvl_devid = NULL; 2030 scsi_devid_desc_t *did = NULL; 2031 int rc; 2032 2033 rc = nvlist_lookup_nvlist(nvl, field_name, &nvl_devid); 2034 if (rc) { 2035 goto done; 2036 } 2037 2038 did = stmf_ic_scsi_devid_desc_unmarshal(nvl_devid); 2039 2040 done: 2041 return (did); 2042 } 2043 2044 2045 static scsi_devid_desc_t * 2046 stmf_ic_scsi_devid_desc_unmarshal(nvlist_t *nvl) 2047 { 2048 scsi_devid_desc_t *sdid = NULL; 2049 uint8_t ident_length = 0; 2050 size_t sdid_size; 2051 int rc = 0; 2052 2053 /* 2054 * we get the ident_length first, since that's the only 2055 * variable-sized field in the struct. 2056 */ 2057 rc = nvlist_lookup_uint8(nvl, "ident_length", &ident_length); 2058 if (rc) 2059 goto done; 2060 2061 sdid_size = sizeof_scsi_devid_desc(ident_length); 2062 sdid = kmem_zalloc(sdid_size, KM_SLEEP); 2063 2064 NVLIST_LOOKUP_BIT_FIELD(uint8, sdid, protocol_id); 2065 NVLIST_LOOKUP_BIT_FIELD(uint8, sdid, code_set); 2066 NVLIST_LOOKUP_BIT_FIELD(uint8, sdid, piv); 2067 NVLIST_LOOKUP_BIT_FIELD(uint8, sdid, association); 2068 NVLIST_LOOKUP_BIT_FIELD(uint8, sdid, ident_type); 2069 2070 sdid->ident_length = ident_length; 2071 2072 if (!stmf_ic_uint8_array_unmarshal(nvl, "ident", 2073 sdid->ident_length, sdid->ident)) { 2074 rc = ENOMEM; /* XXX */ 2075 goto done; 2076 } 2077 2078 done: 2079 if (!rc) 2080 return (sdid); 2081 2082 kmem_free(sdid, sdid_size); 2083 2084 return (NULL); 2085 } 2086 2087 static stmf_remote_port_t * 2088 stmf_ic_lookup_remote_port_and_unmarshal(nvlist_t *nvl, char *field_name) 2089 { 2090 nvlist_t *nvl_rport = NULL; 2091 2092 if (nvlist_lookup_nvlist(nvl, field_name, &nvl_rport) != 0) 2093 return (NULL); 2094 2095 return (stmf_ic_remote_port_unmarshal(nvl_rport)); 2096 } 2097 2098 static stmf_remote_port_t * 2099 stmf_ic_remote_port_unmarshal(nvlist_t *nvl) 2100 { 2101 stmf_remote_port_t *rport = NULL; 2102 uint16_t rport_tptid_sz = 0; 2103 int rc = 0; 2104 2105 rc = nvlist_lookup_uint16(nvl, "rport_tptid_sz", &rport_tptid_sz); 2106 if (rc || rport_tptid_sz < sizeof (scsi_transport_id_t)) 2107 return (NULL); 2108 2109 rport = stmf_remote_port_alloc(rport_tptid_sz); 2110 if (!stmf_ic_uint8_array_unmarshal(nvl, "rport_tptid", rport_tptid_sz, 2111 (uint8_t *)rport->rport_tptid)) { 2112 stmf_remote_port_free(rport); 2113 rport = NULL; 2114 } 2115 return (rport); 2116 } 2117 2118 /* 2119 * Unmarshal a uint8_t array. 2120 * 2121 * Takes a buf argument: 2122 * 2123 * - if non-null, the array contents are copied into the buf, 2124 * and we return a pointer to the buffer. 2125 * 2126 * - if null, we return a pointer to the unmarshaled data, which 2127 * resides in the nvlist. 2128 * 2129 * Returns NULL on failure. 2130 */ 2131 static uint8_t * 2132 stmf_ic_uint8_array_unmarshal( 2133 nvlist_t *nvl, 2134 char *field_name, 2135 uint64_t len, 2136 uint8_t *buf) /* non-NULL: copy array into buf */ 2137 { 2138 uint8_t *array = NULL; 2139 uint_t actual_len; 2140 int rc = 0; 2141 2142 rc = nvlist_lookup_uint8_array(nvl, field_name, &array, &actual_len); 2143 if (rc) { 2144 return (NULL); 2145 } 2146 2147 if (len != actual_len) { 2148 cmn_err(CE_WARN, 2149 "stmf_ic_uint8_array_unmarshal: wrong len (%d != %d)", 2150 (int)len, actual_len); 2151 return (NULL); 2152 } 2153 2154 if (buf) { 2155 /* preallocated buf, copy in */ 2156 bcopy(array, buf, len); 2157 } else { 2158 /* return a pointer to the underlying array in the nvlist */ 2159 buf = array; 2160 } 2161 2162 return (buf); 2163 } 2164 2165 /* 2166 * Unmarshal a string. 2167 * 2168 * Returns NULL on failure. 2169 */ 2170 static char * 2171 stmf_ic_string_unmarshal( 2172 nvlist_t *nvl, 2173 char *field_name) 2174 { 2175 char *s = NULL; 2176 int rc = 0; 2177 2178 rc = nvlist_lookup_string(nvl, field_name, &s); 2179 if (rc) { 2180 return (NULL); 2181 } 2182 2183 return (s); 2184 } 2185 2186 /* 2187 * Utility routines. 2188 */ 2189 2190 static stmf_ic_msg_t * 2191 stmf_ic_alloc_msg_header( 2192 stmf_ic_msg_type_t msg_type, 2193 stmf_ic_msgid_t msgid) 2194 { 2195 stmf_ic_msg_t *icm; 2196 2197 icm = (stmf_ic_msg_t *)kmem_zalloc(sizeof (*icm), KM_SLEEP); 2198 icm->icm_msg_type = msg_type; 2199 icm->icm_msgid = msgid; 2200 2201 return (icm); 2202 } 2203 2204 static size_t 2205 sizeof_scsi_devid_desc(int ident_length) 2206 { 2207 int num_ident_elems; 2208 size_t size; 2209 2210 ASSERT(ident_length > 0); 2211 2212 /* 2213 * Need to account for the fact that there's 2214 * already a single element in scsi_devid_desc_t. 2215 * 2216 * XXX would really like to have a way to determine the 2217 * sizeof (struct scsi_devid_desc.ident[0]), but 2218 * it's not clear that can be done. 2219 * Thus, this code relies on the knowledge of the type of 2220 * that field. 2221 */ 2222 num_ident_elems = ident_length - 1; 2223 size = sizeof (scsi_devid_desc_t) + 2224 (num_ident_elems * sizeof (uint8_t)); 2225 2226 return (size); 2227 } 2228 2229 2230 /* 2231 * Duplicate the scsi_devid_desc_t. 2232 */ 2233 static scsi_devid_desc_t * 2234 scsi_devid_desc_dup(scsi_devid_desc_t *did) 2235 { 2236 scsi_devid_desc_t *dup; 2237 size_t dup_size; 2238 2239 ASSERT(did->ident_length > 0); 2240 2241 dup_size = sizeof_scsi_devid_desc(did->ident_length); 2242 dup = (scsi_devid_desc_t *)kmem_zalloc(dup_size, KM_SLEEP); 2243 bcopy(did, dup, dup_size); 2244 return (dup); 2245 } 2246 2247 /* 2248 * May be called with a null pointer. 2249 */ 2250 static void 2251 scsi_devid_desc_free(scsi_devid_desc_t *did) 2252 { 2253 if (!did) 2254 return; 2255 2256 kmem_free(did, sizeof_scsi_devid_desc(did->ident_length)); 2257 } 2258 2259 /* 2260 * Duplicate the stmf_remote_port_t. 2261 */ 2262 static stmf_remote_port_t * 2263 remote_port_dup(stmf_remote_port_t *rport) 2264 { 2265 stmf_remote_port_t *dup = NULL; 2266 if (rport) { 2267 dup = stmf_remote_port_alloc(rport->rport_tptid_sz); 2268 bcopy(rport->rport_tptid, dup->rport_tptid, 2269 rport->rport_tptid_sz); 2270 } 2271 return (dup); 2272 } 2273 2274 /* 2275 * Helper functions, returns NULL if no memory. 2276 */ 2277 static char * 2278 stmf_ic_strdup(char *str) 2279 { 2280 char *copy; 2281 2282 ASSERT(str); 2283 2284 copy = kmem_zalloc(strlen(str) + 1, KM_SLEEP); 2285 (void) strcpy(copy, str); 2286 return (copy); 2287 } 2288 2289 static inline void 2290 stmf_ic_nvlookup_warn(const char *func, char *field) 2291 { 2292 cmn_err(CE_WARN, "%s: nvlist lookup of %s failed", func, field); 2293 }