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