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 uint8_t *lun_id = task->task_lu->lu_id->ident; 633 634 icm = stmf_ic_alloc_msg_header(STMF_ICM_SCSI_CMD, msgid); 635 icsc = (stmf_ic_scsi_cmd_msg_t *)kmem_zalloc(sizeof (*icsc), KM_SLEEP); 636 icm->icm_msg = (void *)icsc; 637 638 icsc->icsc_task_msgid = task_msgid; 639 icsc->icsc_ini_devid = scsi_devid_desc_dup(ini_devid); 640 icsc->icsc_tgt_devid = scsi_devid_desc_dup(tgt_devid); 641 icsc->icsc_session_id = task->task_session->ss_session_id; 642 643 bcopy(lun_id, icsc->icsc_lun_id, sizeof (icsc->icsc_lun_id)); 644 645 bcopy(task->task_lun_no, icsc->icsc_task_lun_no, 646 sizeof (icsc->icsc_task_lun_no)); 647 648 icsc->icsc_task_expected_xfer_length = task->task_expected_xfer_length; 649 icsc->icsc_task_cdb_length = task->task_cdb_length; 650 651 icsc->icsc_task_cdb = (uint8_t *)kmem_zalloc(task->task_cdb_length, 652 KM_SLEEP); 653 bcopy(task->task_cdb, icsc->icsc_task_cdb, task->task_cdb_length); 654 655 icsc->icsc_task_flags = task->task_flags; 656 icsc->icsc_task_priority = task->task_priority; 657 icsc->icsc_task_mgmt_function = task->task_mgmt_function; 658 659 icsc->icsc_immed_data_len = immed_data_len; 660 icsc->icsc_immed_data = immed_data; 661 662 return (icm); 663 } 664 665 stmf_ic_msg_t * 666 stmf_ic_scsi_data_msg_alloc( 667 stmf_ic_msgid_t task_msgid, 668 uint64_t session_id, 669 uint8_t *lun_id, 670 uint64_t data_len, 671 uint8_t *data, 672 stmf_ic_msgid_t msgid) 673 { 674 stmf_ic_msg_t *icm = NULL; 675 stmf_ic_scsi_data_msg_t *icsd = NULL; 676 677 icm = stmf_ic_alloc_msg_header(STMF_ICM_SCSI_DATA, msgid); 678 icsd = (stmf_ic_scsi_data_msg_t *)kmem_zalloc(sizeof (*icsd), KM_SLEEP); 679 icm->icm_msg = (void *)icsd; 680 681 icsd->icsd_task_msgid = task_msgid; 682 icsd->icsd_session_id = session_id; 683 bcopy(lun_id, icsd->icsd_lun_id, sizeof (icsd->icsd_lun_id)); 684 icsd->icsd_data_len = data_len; 685 icsd->icsd_data = data; 686 687 return (icm); 688 } 689 690 stmf_ic_msg_t * 691 stmf_ic_scsi_data_xfer_done_msg_alloc( 692 stmf_ic_msgid_t task_msgid, 693 uint64_t session_id, 694 stmf_status_t status, 695 stmf_ic_msgid_t msgid) 696 { 697 stmf_ic_msg_t *icm = NULL; 698 stmf_ic_scsi_data_xfer_done_msg_t *icsx = NULL; 699 700 icm = stmf_ic_alloc_msg_header(STMF_ICM_SCSI_DATA_XFER_DONE, msgid); 701 icsx = (stmf_ic_scsi_data_xfer_done_msg_t *)kmem_zalloc( 702 sizeof (*icsx), KM_SLEEP); 703 icm->icm_msg = (void *)icsx; 704 705 icsx->icsx_task_msgid = task_msgid; 706 icsx->icsx_session_id = session_id; 707 icsx->icsx_status = status; 708 709 return (icm); 710 } 711 712 stmf_ic_msg_t * 713 stmf_ic_scsi_status_msg_alloc( 714 stmf_ic_msgid_t task_msgid, 715 uint64_t session_id, 716 uint8_t *lun_id, 717 uint8_t response, 718 uint8_t status, 719 uint8_t flags, 720 uint32_t resid, 721 uint8_t sense_len, 722 uint8_t *sense, 723 stmf_ic_msgid_t msgid) 724 { 725 stmf_ic_msg_t *icm = NULL; 726 stmf_ic_scsi_status_msg_t *icss = NULL; 727 728 icm = stmf_ic_alloc_msg_header(STMF_ICM_SCSI_STATUS, msgid); 729 icss = (stmf_ic_scsi_status_msg_t *)kmem_zalloc(sizeof (*icss), 730 KM_SLEEP); 731 icm->icm_msg = (void *)icss; 732 733 icss->icss_task_msgid = task_msgid; 734 icss->icss_session_id = session_id; 735 bcopy(lun_id, icss->icss_lun_id, sizeof (icss->icss_lun_id)); 736 icss->icss_response = response; 737 icss->icss_status = status; 738 icss->icss_flags = flags; 739 icss->icss_resid = resid; 740 icss->icss_sense_len = sense_len; 741 icss->icss_sense = sense; 742 743 return (icm); 744 } 745 746 stmf_ic_msg_t * 747 stmf_ic_r2t_msg_alloc( 748 stmf_ic_msgid_t task_msgid, 749 uint64_t session_id, 750 uint32_t offset, 751 uint32_t length, 752 stmf_ic_msgid_t msgid) 753 { 754 stmf_ic_msg_t *icm = NULL; 755 stmf_ic_r2t_msg_t *icrt = NULL; 756 757 icm = stmf_ic_alloc_msg_header(STMF_ICM_R2T, msgid); 758 icrt = (stmf_ic_r2t_msg_t *)kmem_zalloc(sizeof (*icrt), KM_SLEEP); 759 icm->icm_msg = (void *)icrt; 760 761 icrt->icrt_task_msgid = task_msgid; 762 icrt->icrt_session_id = session_id; 763 icrt->icrt_offset = offset; 764 icrt->icrt_length = length; 765 766 return (icm); 767 } 768 769 stmf_ic_msg_t * 770 stmf_ic_status_msg_alloc( 771 stmf_status_t status, 772 stmf_ic_msg_type_t msg_type, 773 stmf_ic_msgid_t msgid) 774 { 775 stmf_ic_msg_t *icm = NULL; 776 stmf_ic_status_msg_t *ics = NULL; 777 778 icm = stmf_ic_alloc_msg_header(STMF_ICM_STATUS, msgid); 779 ics = (stmf_ic_status_msg_t *)kmem_zalloc(sizeof (*ics), KM_SLEEP); 780 icm->icm_msg = (void *)ics; 781 782 ics->ics_status = status; 783 ics->ics_msg_type = msg_type; 784 ics->ics_msgid = msgid; /* XXX same as msgid in header */ 785 786 return (icm); 787 } 788 789 stmf_ic_msg_t * 790 stmf_ic_session_create_msg_alloc( 791 stmf_scsi_session_t *session, 792 stmf_ic_msgid_t msgid) 793 { 794 return (stmf_ic_session_create_destroy_msg_alloc( 795 STMF_ICM_SESSION_CREATE, session, msgid)); 796 } 797 798 stmf_ic_msg_t * 799 stmf_ic_session_destroy_msg_alloc( 800 stmf_scsi_session_t *session, 801 stmf_ic_msgid_t msgid) 802 { 803 return (stmf_ic_session_create_destroy_msg_alloc( 804 STMF_ICM_SESSION_DESTROY, session, msgid)); 805 } 806 807 /* 808 * Guts of session create/destroy routines. 809 */ 810 static stmf_ic_msg_t * 811 stmf_ic_session_create_destroy_msg_alloc( 812 stmf_ic_msg_type_t msg_type, 813 stmf_scsi_session_t *session, 814 stmf_ic_msgid_t msgid) 815 { 816 stmf_ic_msg_t *icm = NULL; 817 stmf_ic_session_create_destroy_msg_t *icscd = NULL; 818 scsi_devid_desc_t *ini_devid = session->ss_rport_id; 819 scsi_devid_desc_t *tgt_devid = session->ss_lport->lport_id; 820 821 icm = stmf_ic_alloc_msg_header(msg_type, msgid); 822 icscd = (stmf_ic_session_create_destroy_msg_t *) 823 kmem_zalloc(sizeof (*icscd), KM_SLEEP); 824 icm->icm_msg = (void *)icscd; 825 826 icscd->icscd_session_id = session->ss_session_id; 827 icscd->icscd_ini_devid = scsi_devid_desc_dup(ini_devid); 828 icscd->icscd_tgt_devid = scsi_devid_desc_dup(tgt_devid); 829 830 return (icm); 831 } 832 833 stmf_ic_msg_t * 834 stmf_ic_echo_request_msg_alloc( 835 uint32_t data_len, 836 uint8_t *data, 837 stmf_ic_msgid_t msgid) 838 { 839 return (stmf_ic_echo_request_reply_msg_alloc( 840 STMF_ICM_ECHO_REQUEST, data_len, data, msgid)); 841 } 842 843 stmf_ic_msg_t * 844 stmf_ic_echo_reply_msg_alloc( 845 uint32_t data_len, 846 uint8_t *data, 847 stmf_ic_msgid_t msgid) 848 { 849 return (stmf_ic_echo_request_reply_msg_alloc( 850 STMF_ICM_ECHO_REPLY, data_len, data, msgid)); 851 } 852 853 854 static stmf_ic_msg_t * 855 stmf_ic_echo_request_reply_msg_alloc( 856 stmf_ic_msg_type_t msg_type, 857 uint32_t data_len, 858 uint8_t *data, 859 stmf_ic_msgid_t msgid) 860 { 861 stmf_ic_msg_t *icm = NULL; 862 stmf_ic_echo_request_reply_msg_t *icerr = NULL; 863 864 icm = stmf_ic_alloc_msg_header(msg_type, msgid); 865 icerr = kmem_zalloc(sizeof (*icerr), KM_SLEEP); 866 icm->icm_msg = (void *)icerr; 867 868 icerr->icerr_data = data; 869 icerr->icerr_datalen = data_len; 870 871 return (icm); 872 } 873 874 /* 875 * msg free routines. 876 */ 877 void 878 stmf_ic_msg_free(stmf_ic_msg_t *msg) 879 { 880 stmf_ic_msg_construction_method_t cmethod = 881 (msg->icm_nvlist ? STMF_UNMARSHAL : STMF_CONSTRUCTOR); 882 883 switch (msg->icm_msg_type) { 884 case STMF_ICM_REGISTER_PROXY_PORT: 885 stmf_ic_reg_port_msg_free( 886 (stmf_ic_reg_port_msg_t *)msg->icm_msg, cmethod); 887 break; 888 889 case STMF_ICM_DEREGISTER_PROXY_PORT: 890 stmf_ic_dereg_port_msg_free( 891 (stmf_ic_dereg_port_msg_t *)msg->icm_msg, cmethod); 892 break; 893 894 case STMF_ICM_LUN_ACTIVE: 895 case STMF_ICM_REGISTER_LUN: 896 case STMF_ICM_DEREGISTER_LUN: 897 stmf_ic_reg_dereg_lun_msg_free( 898 (stmf_ic_reg_dereg_lun_msg_t *)msg->icm_msg, cmethod); 899 break; 900 901 case STMF_ICM_SCSI_CMD: 902 stmf_ic_scsi_cmd_msg_free( 903 (stmf_ic_scsi_cmd_msg_t *)msg->icm_msg, cmethod); 904 break; 905 906 case STMF_ICM_SCSI_DATA: 907 stmf_ic_scsi_data_msg_free( 908 (stmf_ic_scsi_data_msg_t *)msg->icm_msg, cmethod); 909 break; 910 911 case STMF_ICM_SCSI_DATA_XFER_DONE: 912 stmf_ic_scsi_data_xfer_done_msg_free( 913 (stmf_ic_scsi_data_xfer_done_msg_t *)msg->icm_msg, cmethod); 914 break; 915 916 case STMF_ICM_SCSI_STATUS: 917 stmf_ic_scsi_status_msg_free( 918 (stmf_ic_scsi_status_msg_t *)msg->icm_msg, cmethod); 919 break; 920 921 case STMF_ICM_R2T: 922 stmf_ic_r2t_msg_free( 923 (stmf_ic_r2t_msg_t *)msg->icm_msg, cmethod); 924 break; 925 926 case STMF_ICM_STATUS: 927 stmf_ic_status_msg_free( 928 (stmf_ic_status_msg_t *)msg->icm_msg, cmethod); 929 break; 930 931 case STMF_ICM_SESSION_CREATE: 932 case STMF_ICM_SESSION_DESTROY: 933 stmf_ic_session_create_destroy_msg_free( 934 (stmf_ic_session_create_destroy_msg_t *)msg->icm_msg, 935 cmethod); 936 break; 937 938 case STMF_ICM_ECHO_REQUEST: 939 case STMF_ICM_ECHO_REPLY: 940 stmf_ic_echo_request_reply_msg_free( 941 (stmf_ic_echo_request_reply_msg_t *)msg->icm_msg, cmethod); 942 break; 943 944 case STMF_ICM_MAX_MSG_TYPE: 945 ASSERT(0); 946 break; 947 948 default: 949 ASSERT(0); 950 } 951 952 if (msg->icm_nvlist) 953 nvlist_free(msg->icm_nvlist); 954 955 kmem_free(msg, sizeof (*msg)); 956 } 957 958 /*ARGSUSED*/ 959 static void 960 stmf_ic_reg_port_msg_free(stmf_ic_reg_port_msg_t *m, 961 stmf_ic_msg_construction_method_t cmethod) 962 { 963 scsi_devid_desc_free(m->icrp_port_id); 964 965 kmem_free(m, sizeof (*m)); 966 } 967 968 969 /*ARGSUSED*/ 970 static void 971 stmf_ic_dereg_port_msg_free(stmf_ic_dereg_port_msg_t *m, 972 stmf_ic_msg_construction_method_t cmethod) 973 { 974 scsi_devid_desc_free(m->icdp_port_id); 975 976 kmem_free(m, sizeof (*m)); 977 } 978 979 980 /* 981 * Works for both reg_lun_msg and dereg_lun_msg, since the message 982 * payload is the same. 983 */ 984 static void 985 stmf_ic_reg_dereg_lun_msg_free(stmf_ic_reg_dereg_lun_msg_t *m, 986 stmf_ic_msg_construction_method_t cmethod) 987 { 988 if (cmethod == STMF_CONSTRUCTOR) { 989 kmem_free(m->icrl_lu_provider_name, 990 strlen(m->icrl_lu_provider_name) + 1); 991 } 992 993 kmem_free(m, sizeof (*m)); 994 } 995 996 static void 997 stmf_ic_scsi_cmd_msg_free(stmf_ic_scsi_cmd_msg_t *m, 998 stmf_ic_msg_construction_method_t cmethod) 999 { 1000 scsi_devid_desc_free(m->icsc_ini_devid); 1001 scsi_devid_desc_free(m->icsc_tgt_devid); 1002 if (cmethod == STMF_CONSTRUCTOR) { 1003 kmem_free(m->icsc_task_cdb, m->icsc_task_cdb_length); 1004 } 1005 1006 kmem_free(m, sizeof (*m)); 1007 1008 } 1009 1010 /*ARGSUSED*/ 1011 static void 1012 stmf_ic_scsi_data_msg_free(stmf_ic_scsi_data_msg_t *m, 1013 stmf_ic_msg_construction_method_t cmethod) 1014 { 1015 kmem_free(m, sizeof (*m)); 1016 } 1017 1018 /*ARGSUSED*/ 1019 static void 1020 stmf_ic_scsi_data_xfer_done_msg_free(stmf_ic_scsi_data_xfer_done_msg_t *m, 1021 stmf_ic_msg_construction_method_t cmethod) 1022 { 1023 kmem_free(m, sizeof (*m)); 1024 } 1025 1026 /*ARGSUSED*/ 1027 static void 1028 stmf_ic_scsi_status_msg_free(stmf_ic_scsi_status_msg_t *m, 1029 stmf_ic_msg_construction_method_t cmethod) 1030 { 1031 kmem_free(m, sizeof (*m)); 1032 } 1033 1034 /*ARGSUSED*/ 1035 static void 1036 stmf_ic_r2t_msg_free(stmf_ic_r2t_msg_t *m, 1037 stmf_ic_msg_construction_method_t cmethod) 1038 { 1039 kmem_free(m, sizeof (*m)); 1040 } 1041 1042 /*ARGSUSED*/ 1043 static void 1044 stmf_ic_status_msg_free(stmf_ic_status_msg_t *m, 1045 stmf_ic_msg_construction_method_t cmethod) 1046 { 1047 kmem_free(m, sizeof (*m)); 1048 } 1049 1050 /* 1051 * Works for both session_create and session_destroy msgs, since the message 1052 * payload is the same. 1053 */ 1054 /*ARGSUSED*/ 1055 static void 1056 stmf_ic_session_create_destroy_msg_free(stmf_ic_session_create_destroy_msg_t *m, 1057 stmf_ic_msg_construction_method_t cmethod) 1058 { 1059 scsi_devid_desc_free(m->icscd_ini_devid); 1060 scsi_devid_desc_free(m->icscd_tgt_devid); 1061 1062 kmem_free(m, sizeof (*m)); 1063 } 1064 1065 /*ARGSUSED*/ 1066 static void 1067 stmf_ic_echo_request_reply_msg_free(stmf_ic_echo_request_reply_msg_t *m, 1068 stmf_ic_msg_construction_method_t cmethod) 1069 { 1070 kmem_free(m, sizeof (*m)); 1071 } 1072 1073 1074 /* 1075 * Marshaling routines. 1076 */ 1077 1078 static nvlist_t * 1079 stmf_ic_msg_marshal(stmf_ic_msg_t *msg) 1080 { 1081 nvlist_t *nvl = NULL; 1082 int rc = 0; 1083 1084 rc = nvlist_alloc(&nvl, NV_UNIQUE_NAME, KM_SLEEP); 1085 if (rc) 1086 goto done; 1087 1088 NVLIST_ADD_FIELD(uint8, msg, icm_msg_type); 1089 NVLIST_ADD_FIELD(uint64, msg, icm_msgid); 1090 1091 switch (msg->icm_msg_type) { 1092 case STMF_ICM_REGISTER_PROXY_PORT: 1093 rc = stmf_ic_reg_port_msg_marshal(nvl, msg->icm_msg); 1094 break; 1095 1096 1097 case STMF_ICM_DEREGISTER_PROXY_PORT: 1098 rc = stmf_ic_dereg_port_msg_marshal(nvl, msg->icm_msg); 1099 break; 1100 1101 case STMF_ICM_LUN_ACTIVE: 1102 case STMF_ICM_REGISTER_LUN: 1103 case STMF_ICM_DEREGISTER_LUN: 1104 rc = stmf_ic_reg_dereg_lun_msg_marshal(nvl, msg->icm_msg); 1105 break; 1106 1107 case STMF_ICM_SCSI_CMD: 1108 rc = stmf_ic_scsi_cmd_msg_marshal(nvl, msg->icm_msg); 1109 break; 1110 1111 case STMF_ICM_SCSI_DATA: 1112 rc = stmf_ic_scsi_data_msg_marshal(nvl, msg->icm_msg); 1113 break; 1114 1115 case STMF_ICM_SCSI_DATA_XFER_DONE: 1116 rc = stmf_ic_scsi_data_xfer_done_msg_marshal(nvl, msg->icm_msg); 1117 break; 1118 1119 case STMF_ICM_SCSI_STATUS: 1120 rc = stmf_ic_scsi_status_msg_marshal(nvl, msg->icm_msg); 1121 break; 1122 1123 case STMF_ICM_R2T: 1124 rc = stmf_ic_r2t_msg_marshal(nvl, msg->icm_msg); 1125 break; 1126 1127 case STMF_ICM_STATUS: 1128 rc = stmf_ic_status_msg_marshal(nvl, msg->icm_msg); 1129 break; 1130 1131 case STMF_ICM_SESSION_CREATE: 1132 case STMF_ICM_SESSION_DESTROY: 1133 rc = stmf_ic_session_create_destroy_msg_marshal(nvl, 1134 msg->icm_msg); 1135 break; 1136 1137 case STMF_ICM_ECHO_REQUEST: 1138 case STMF_ICM_ECHO_REPLY: 1139 rc = stmf_ic_echo_request_reply_msg_marshal(nvl, 1140 msg->icm_msg); 1141 break; 1142 1143 case STMF_ICM_MAX_MSG_TYPE: 1144 ASSERT(0); 1145 break; 1146 1147 default: 1148 ASSERT(0); 1149 } 1150 1151 done: 1152 if (!rc) 1153 return (nvl); 1154 1155 if (nvl) 1156 nvlist_free(nvl); 1157 1158 return (NULL); 1159 } 1160 1161 1162 static int 1163 stmf_ic_reg_port_msg_marshal(nvlist_t *nvl, void *msg) 1164 { 1165 stmf_ic_reg_port_msg_t *m = (stmf_ic_reg_port_msg_t *)msg; 1166 int rc = 0; 1167 1168 NVLIST_ADD_DEVID(m, icrp_port_id); 1169 NVLIST_ADD_FIELD(uint16, m, icrp_relative_port_id); 1170 1171 NVLIST_ADD_FIELD(uint16, m, icrp_cb_arg_len); 1172 /* only add the callback arg if necessary */ 1173 if (m->icrp_cb_arg_len) { 1174 NVLIST_ADD_ARRAY_LEN(uint8, m, icrp_cb_arg, m->icrp_cb_arg_len); 1175 } 1176 1177 done: 1178 return (rc); 1179 } 1180 1181 static int 1182 stmf_ic_dereg_port_msg_marshal(nvlist_t *nvl, void *msg) 1183 { 1184 stmf_ic_dereg_port_msg_t *m = (stmf_ic_dereg_port_msg_t *)msg; 1185 int rc = 0; 1186 1187 NVLIST_ADD_DEVID(m, icdp_port_id); 1188 NVLIST_ADD_FIELD(uint16, m, icdp_cb_arg_len); 1189 1190 /* only add the callback arg if necessary */ 1191 if (m->icdp_cb_arg_len) { 1192 NVLIST_ADD_ARRAY_LEN(uint8, m, icdp_cb_arg, m->icdp_cb_arg_len); 1193 } 1194 1195 done: 1196 return (rc); 1197 } 1198 1199 /* 1200 * Handles STMF_ICM_LUN_ACTIVE, STMF_ICM_REGISTER_LUN and 1201 * STMF_ICM_DEREGISTER_LUN; 1202 * msg payload is the same for all. 1203 */ 1204 static int 1205 stmf_ic_reg_dereg_lun_msg_marshal(nvlist_t *nvl, void *msg) 1206 { 1207 stmf_ic_reg_dereg_lun_msg_t *m = (stmf_ic_reg_dereg_lun_msg_t *)msg; 1208 int rc = 0; 1209 1210 NVLIST_ADD_ARRAY(uint8, m, icrl_lun_id); 1211 NVLIST_ADD_FIELD(string, m, icrl_lu_provider_name); 1212 NVLIST_ADD_FIELD(uint16, m, icrl_cb_arg_len); 1213 1214 /* only add the callback arg if necessary */ 1215 if (m->icrl_cb_arg_len) { 1216 NVLIST_ADD_ARRAY_LEN(uint8, m, icrl_cb_arg, m->icrl_cb_arg_len); 1217 } 1218 1219 done: 1220 return (rc); 1221 } 1222 1223 static int 1224 stmf_ic_scsi_cmd_msg_marshal(nvlist_t *nvl, void *msg) 1225 { 1226 stmf_ic_scsi_cmd_msg_t *m = (stmf_ic_scsi_cmd_msg_t *)msg; 1227 int rc = 0; 1228 1229 NVLIST_ADD_FIELD(uint64, m, icsc_task_msgid); 1230 NVLIST_ADD_DEVID(m, icsc_ini_devid); 1231 NVLIST_ADD_DEVID(m, icsc_tgt_devid); 1232 NVLIST_ADD_ARRAY(uint8, m, icsc_lun_id); 1233 NVLIST_ADD_FIELD(uint64, m, icsc_session_id); 1234 NVLIST_ADD_ARRAY_LEN(uint8, m, icsc_task_lun_no, 8); 1235 NVLIST_ADD_FIELD(uint32, m, icsc_task_expected_xfer_length); 1236 NVLIST_ADD_FIELD(uint16, m, icsc_task_cdb_length); 1237 NVLIST_ADD_ARRAY_LEN(uint8, m, icsc_task_cdb, m->icsc_task_cdb_length); 1238 NVLIST_ADD_FIELD(uint8, m, icsc_task_flags); 1239 NVLIST_ADD_FIELD(uint8, m, icsc_task_priority); 1240 NVLIST_ADD_FIELD(uint8, m, icsc_task_mgmt_function); 1241 1242 NVLIST_ADD_FIELD(uint32, m, icsc_immed_data_len); 1243 /* only add immediate data if necessary */ 1244 if (m->icsc_immed_data_len) { 1245 NVLIST_ADD_ARRAY_LEN(uint8, m, icsc_immed_data, 1246 m->icsc_immed_data_len); 1247 } 1248 1249 done: 1250 return (rc); 1251 } 1252 1253 static int 1254 stmf_ic_scsi_data_msg_marshal(nvlist_t *nvl, void *msg) 1255 { 1256 stmf_ic_scsi_data_msg_t *m = (stmf_ic_scsi_data_msg_t *)msg; 1257 int rc = 0; 1258 1259 NVLIST_ADD_FIELD(uint64, m, icsd_task_msgid); 1260 NVLIST_ADD_FIELD(uint64, m, icsd_session_id); 1261 NVLIST_ADD_ARRAY(uint8, m, icsd_lun_id); 1262 NVLIST_ADD_FIELD(uint64, m, icsd_data_len); 1263 NVLIST_ADD_ARRAY_LEN(uint8, m, icsd_data, m->icsd_data_len); 1264 1265 done: 1266 return (rc); 1267 } 1268 1269 static int 1270 stmf_ic_scsi_data_xfer_done_msg_marshal(nvlist_t *nvl, void *msg) 1271 { 1272 stmf_ic_scsi_data_xfer_done_msg_t *m = 1273 (stmf_ic_scsi_data_xfer_done_msg_t *)msg; 1274 int rc = 0; 1275 1276 NVLIST_ADD_FIELD(uint64, m, icsx_task_msgid); 1277 NVLIST_ADD_FIELD(uint64, m, icsx_session_id); 1278 NVLIST_ADD_FIELD(uint64, m, icsx_status); 1279 1280 done: 1281 return (rc); 1282 } 1283 1284 static int 1285 stmf_ic_scsi_status_msg_marshal(nvlist_t *nvl, void *msg) 1286 { 1287 stmf_ic_scsi_status_msg_t *m = (stmf_ic_scsi_status_msg_t *)msg; 1288 int rc = 0; 1289 1290 NVLIST_ADD_FIELD(uint64, m, icss_task_msgid); 1291 NVLIST_ADD_FIELD(uint64, m, icss_session_id); 1292 NVLIST_ADD_ARRAY(uint8, m, icss_lun_id); 1293 NVLIST_ADD_FIELD(uint8, m, icss_response); 1294 NVLIST_ADD_FIELD(uint8, m, icss_status); 1295 NVLIST_ADD_FIELD(uint8, m, icss_flags); 1296 NVLIST_ADD_FIELD(uint32, m, icss_resid); 1297 1298 NVLIST_ADD_FIELD(uint8, m, icss_sense_len); 1299 1300 if (m->icss_sense_len) 1301 NVLIST_ADD_ARRAY_LEN(uint8, m, icss_sense, m->icss_sense_len); 1302 1303 done: 1304 return (rc); 1305 } 1306 1307 static int 1308 stmf_ic_r2t_msg_marshal(nvlist_t *nvl, void *msg) 1309 { 1310 stmf_ic_r2t_msg_t *m = (stmf_ic_r2t_msg_t *)msg; 1311 int rc = 0; 1312 1313 NVLIST_ADD_FIELD(uint64, m, icrt_task_msgid); 1314 NVLIST_ADD_FIELD(uint64, m, icrt_session_id); 1315 NVLIST_ADD_FIELD(uint32, m, icrt_offset); 1316 NVLIST_ADD_FIELD(uint32, m, icrt_length); 1317 1318 done: 1319 return (rc); 1320 } 1321 1322 static int 1323 stmf_ic_status_msg_marshal(nvlist_t *nvl, void *msg) 1324 { 1325 stmf_ic_status_msg_t *m = (stmf_ic_status_msg_t *)msg; 1326 int rc = 0; 1327 1328 NVLIST_ADD_FIELD(uint8, m, ics_msg_type); 1329 NVLIST_ADD_FIELD(uint64, m, ics_msgid); 1330 NVLIST_ADD_FIELD(uint8, m, ics_status); 1331 1332 done: 1333 return (rc); 1334 } 1335 1336 static int 1337 stmf_ic_session_create_destroy_msg_marshal(nvlist_t *nvl, void *msg) 1338 { 1339 stmf_ic_session_create_destroy_msg_t *m = 1340 (stmf_ic_session_create_destroy_msg_t *)msg; 1341 int rc = 0; 1342 1343 NVLIST_ADD_DEVID(m, icscd_ini_devid); 1344 NVLIST_ADD_DEVID(m, icscd_tgt_devid); 1345 NVLIST_ADD_FIELD(uint64, m, icscd_session_id); 1346 1347 done: 1348 return (rc); 1349 } 1350 1351 static int 1352 stmf_ic_echo_request_reply_msg_marshal(nvlist_t *nvl, void *msg) 1353 { 1354 stmf_ic_echo_request_reply_msg_t *m = msg; 1355 int rc = 0; 1356 1357 NVLIST_ADD_FIELD(uint32, m, icerr_datalen); 1358 if (m->icerr_datalen) 1359 NVLIST_ADD_ARRAY_LEN(uint8, m, icerr_data, m->icerr_datalen); 1360 1361 done: 1362 return (rc); 1363 } 1364 1365 /* 1366 * Allocate a new nvlist representing the scsi_devid_desc and add it 1367 * to the nvlist. 1368 */ 1369 static int 1370 stmf_ic_scsi_devid_desc_marshal(nvlist_t *parent_nvl, 1371 char *sdid_name, 1372 scsi_devid_desc_t *sdid) 1373 { 1374 int rc = 0; 1375 nvlist_t *nvl = NULL; 1376 1377 rc = nvlist_alloc(&nvl, NV_UNIQUE_NAME, KM_SLEEP); 1378 if (rc) 1379 goto done; 1380 1381 NVLIST_ADD_FIELD(uint8, sdid, protocol_id); 1382 NVLIST_ADD_FIELD(uint8, sdid, code_set); 1383 NVLIST_ADD_FIELD(uint8, sdid, piv); 1384 NVLIST_ADD_FIELD(uint8, sdid, association); 1385 NVLIST_ADD_FIELD(uint8, sdid, ident_type); 1386 NVLIST_ADD_FIELD(uint8, sdid, ident_length); 1387 1388 rc = nvlist_add_uint8_array(nvl, "ident", sdid->ident, 1389 sdid->ident_length); 1390 if (rc) 1391 goto done; 1392 1393 rc = nvlist_add_nvlist(parent_nvl, sdid_name, nvl); 1394 1395 done: 1396 if (nvl) { 1397 nvlist_free(nvl); 1398 } 1399 return (rc); 1400 } 1401 1402 /* 1403 * Unmarshaling routines. 1404 */ 1405 1406 static stmf_ic_msg_t * 1407 stmf_ic_msg_unmarshal(nvlist_t *nvl) 1408 { 1409 stmf_ic_msg_t *m = kmem_zalloc(sizeof (*m), KM_SLEEP); 1410 uint8_t msg_type; 1411 int rc = 0; 1412 1413 /* 1414 * We'd like to do this: 1415 * 1416 * NVLIST_LOOKUP_FIELD(uint8, m, icm_msg_type); 1417 * 1418 * but the fact that msg type is an enum causes type problems. 1419 */ 1420 rc = nvlist_lookup_uint8(nvl, "icm_msg_type", &msg_type); 1421 if (rc) { 1422 stmf_ic_nvlookup_warn(__func__, "icm_msg_type"); 1423 goto done; 1424 } 1425 1426 m->icm_msg_type = msg_type; 1427 m->icm_nvlist = nvl; 1428 1429 NVLIST_LOOKUP_FIELD(uint64, m, icm_msgid); 1430 1431 switch (m->icm_msg_type) { 1432 1433 case STMF_ICM_REGISTER_PROXY_PORT: 1434 m->icm_msg = stmf_ic_reg_port_msg_unmarshal(nvl); 1435 break; 1436 1437 1438 case STMF_ICM_DEREGISTER_PROXY_PORT: 1439 m->icm_msg = stmf_ic_dereg_port_msg_unmarshal(nvl); 1440 break; 1441 1442 case STMF_ICM_LUN_ACTIVE: 1443 case STMF_ICM_REGISTER_LUN: 1444 case STMF_ICM_DEREGISTER_LUN: 1445 m->icm_msg = stmf_ic_reg_dereg_lun_msg_unmarshal(nvl); 1446 break; 1447 1448 case STMF_ICM_SCSI_CMD: 1449 m->icm_msg = stmf_ic_scsi_cmd_msg_unmarshal(nvl); 1450 break; 1451 1452 case STMF_ICM_SCSI_DATA: 1453 m->icm_msg = stmf_ic_scsi_data_msg_unmarshal(nvl); 1454 break; 1455 1456 case STMF_ICM_SCSI_DATA_XFER_DONE: 1457 m->icm_msg = stmf_ic_scsi_data_xfer_done_msg_unmarshal(nvl); 1458 break; 1459 1460 case STMF_ICM_SCSI_STATUS: 1461 m->icm_msg = stmf_ic_scsi_status_msg_unmarshal(nvl); 1462 break; 1463 1464 case STMF_ICM_R2T: 1465 m->icm_msg = stmf_ic_r2t_msg_unmarshal(nvl); 1466 break; 1467 1468 case STMF_ICM_STATUS: 1469 m->icm_msg = stmf_ic_status_msg_unmarshal(nvl); 1470 break; 1471 1472 case STMF_ICM_SESSION_CREATE: 1473 case STMF_ICM_SESSION_DESTROY: 1474 m->icm_msg = stmf_ic_session_create_destroy_msg_unmarshal(nvl); 1475 break; 1476 1477 case STMF_ICM_ECHO_REQUEST: 1478 case STMF_ICM_ECHO_REPLY: 1479 m->icm_msg = stmf_ic_echo_request_reply_msg_unmarshal(nvl); 1480 break; 1481 1482 case STMF_ICM_MAX_MSG_TYPE: 1483 ASSERT(0); 1484 break; 1485 1486 default: 1487 ASSERT(0); 1488 } 1489 1490 done: 1491 1492 if (!m->icm_msg) { 1493 kmem_free(m, sizeof (*m)); 1494 return (NULL); 1495 } 1496 1497 return (m); 1498 } 1499 1500 static void * 1501 stmf_ic_reg_port_msg_unmarshal(nvlist_t *nvl) 1502 { 1503 nvlist_t *nvl_port_id = NULL; 1504 int rc = 0; 1505 stmf_ic_reg_port_msg_t *m = kmem_zalloc(sizeof (*m), KM_SLEEP); 1506 1507 rc = nvlist_lookup_nvlist(nvl, "icrp_port_id", &nvl_port_id); 1508 if (rc) { 1509 stmf_ic_nvlookup_warn(__func__, "icrp_port_id nvl"); 1510 rc = ENOMEM; /* XXX */ 1511 goto done; 1512 } 1513 1514 m->icrp_port_id = stmf_ic_scsi_devid_desc_unmarshal(nvl_port_id); 1515 if (m->icrp_port_id == NULL) { 1516 stmf_ic_nvlookup_warn(__func__, "icrp_port_id"); 1517 rc = ENOMEM; /* XXX */ 1518 goto done; 1519 } 1520 1521 NVLIST_LOOKUP_FIELD(uint16, m, icrp_relative_port_id); 1522 NVLIST_LOOKUP_FIELD(uint16, m, icrp_cb_arg_len); 1523 1524 if (m->icrp_cb_arg_len) { 1525 m->icrp_cb_arg = stmf_ic_uint8_array_unmarshal(nvl, 1526 "icrp_cb_arg", m->icrp_cb_arg_len, NULL); 1527 if (m->icrp_cb_arg == NULL) { 1528 stmf_ic_nvlookup_warn(__func__, "icrp_cb_arg"); 1529 rc = ENOMEM; /* XXX */ 1530 goto done; 1531 } 1532 } 1533 1534 done: 1535 if (!rc) 1536 return (m); 1537 1538 stmf_ic_reg_port_msg_free(m, STMF_UNMARSHAL); 1539 1540 return (NULL); 1541 } 1542 1543 /* 1544 * XXX largely the same as stmf_ic_reg_port_msg_unmarshal() 1545 * Common stuff should be factored out. Type issues may make this 1546 * painful. 1547 */ 1548 static void * 1549 stmf_ic_dereg_port_msg_unmarshal(nvlist_t *nvl) 1550 { 1551 nvlist_t *nvl_port_id = NULL; 1552 int rc = 0; 1553 stmf_ic_dereg_port_msg_t *m = kmem_zalloc(sizeof (*m), KM_SLEEP); 1554 1555 rc = nvlist_lookup_nvlist(nvl, "icdp_port_id", &nvl_port_id); 1556 if (rc) { 1557 stmf_ic_nvlookup_warn(__func__, "icdp_port_id nvl"); 1558 goto done; 1559 } 1560 1561 m->icdp_port_id = stmf_ic_scsi_devid_desc_unmarshal(nvl_port_id); 1562 if (m->icdp_port_id == NULL) { 1563 stmf_ic_nvlookup_warn(__func__, "icdp_port_id"); 1564 rc = ENOMEM; /* XXX */ 1565 goto done; 1566 } 1567 1568 NVLIST_LOOKUP_FIELD(uint16, m, icdp_cb_arg_len); 1569 1570 if (m->icdp_cb_arg_len) { 1571 m->icdp_cb_arg = stmf_ic_uint8_array_unmarshal(nvl, 1572 "icdp_cb_arg", m->icdp_cb_arg_len, NULL); 1573 if (m->icdp_cb_arg == NULL) { 1574 stmf_ic_nvlookup_warn(__func__, "icdp_cb_arg"); 1575 rc = ENOMEM; /* XXX */ 1576 goto done; 1577 } 1578 } 1579 1580 done: 1581 if (!rc) 1582 return (m); 1583 1584 stmf_ic_dereg_port_msg_free(m, STMF_UNMARSHAL); 1585 1586 return (NULL); 1587 } 1588 1589 static void * 1590 stmf_ic_reg_dereg_lun_msg_unmarshal(nvlist_t *nvl) 1591 { 1592 int rc = 0; 1593 stmf_ic_reg_dereg_lun_msg_t *m = kmem_zalloc(sizeof (*m), KM_SLEEP); 1594 1595 if (! stmf_ic_uint8_array_unmarshal(nvl, "icrl_lun_id", 1596 sizeof (m->icrl_lun_id), m->icrl_lun_id)) { 1597 stmf_ic_nvlookup_warn(__func__, "icrl_lun_id"); 1598 rc = ENOMEM; /* XXX */ 1599 goto done; 1600 } 1601 1602 m->icrl_lu_provider_name = stmf_ic_string_unmarshal(nvl, 1603 "icrl_lu_provider_name"); 1604 1605 if (!m->icrl_lu_provider_name) { 1606 stmf_ic_nvlookup_warn(__func__, "icrl_lu_provider_name"); 1607 rc = ENOMEM; /* XXX */ 1608 goto done; 1609 } 1610 1611 NVLIST_LOOKUP_FIELD(uint16, m, icrl_cb_arg_len); 1612 1613 if (m->icrl_cb_arg_len) { 1614 m->icrl_cb_arg = stmf_ic_uint8_array_unmarshal(nvl, 1615 "icrl_cb_arg", m->icrl_cb_arg_len, NULL); 1616 if (m->icrl_cb_arg == NULL) { 1617 stmf_ic_nvlookup_warn(__func__, "icrl_cb_arg"); 1618 rc = ENOMEM; /* XXX */ 1619 goto done; 1620 } 1621 } 1622 1623 done: 1624 if (!rc) 1625 return (m); 1626 1627 stmf_ic_reg_dereg_lun_msg_free(m, STMF_UNMARSHAL); 1628 1629 return (NULL); 1630 } 1631 1632 static void * 1633 stmf_ic_scsi_cmd_msg_unmarshal(nvlist_t *nvl) 1634 { 1635 int rc = 0; 1636 stmf_ic_scsi_cmd_msg_t *m = kmem_zalloc(sizeof (*m), KM_SLEEP); 1637 1638 if (nvlist_lookup_pairs(nvl, 0, 1639 NV_PAIR(UINT64, m, icsc_task_msgid), 1640 NV_PAIR(UINT64, m, icsc_session_id), 1641 NV_PAIR(UINT32, m, icsc_task_expected_xfer_length), 1642 NV_PAIR(UINT16, m, icsc_task_cdb_length), 1643 NV_PAIR(UINT8, m, icsc_task_flags), 1644 NV_PAIR(UINT8, m, icsc_task_mgmt_function), 1645 NV_PAIR(UINT32, m, icsc_immed_data_len), 1646 NULL) != 0) { 1647 stmf_ic_nvlookup_warn(__func__, "icsc_task_msgid and friends"); 1648 rc = ENOMEM; /* XXX need something better */ 1649 goto done; 1650 } 1651 1652 m->icsc_ini_devid = stmf_ic_lookup_scsi_devid_desc_and_unmarshal( 1653 nvl, "icsc_ini_devid"); 1654 if (m->icsc_ini_devid == NULL) { 1655 stmf_ic_nvlookup_warn(__func__, "icsc_ini_devid"); 1656 rc = ENOMEM; 1657 goto done; 1658 } 1659 1660 m->icsc_tgt_devid = stmf_ic_lookup_scsi_devid_desc_and_unmarshal( 1661 nvl, "icsc_tgt_devid"); 1662 if (m->icsc_tgt_devid == NULL) { 1663 stmf_ic_nvlookup_warn(__func__, "icsc_tgt_devid"); 1664 rc = ENOMEM; 1665 goto done; 1666 } 1667 1668 /* icsc_lun_id */ 1669 if (!stmf_ic_uint8_array_unmarshal(nvl, "icsc_lun_id", 1670 sizeof (m->icsc_lun_id), m->icsc_lun_id)) { 1671 stmf_ic_nvlookup_warn(__func__, "icsc_lun_id"); 1672 rc = ENOMEM; 1673 goto done; 1674 } 1675 1676 /* icsc_task_lun_no */ 1677 if (!stmf_ic_uint8_array_unmarshal(nvl, "icsc_task_lun_no", 1678 sizeof (m->icsc_task_lun_no), m->icsc_task_lun_no)) { 1679 stmf_ic_nvlookup_warn(__func__, "icsc_task_lun_no"); 1680 rc = ENOMEM; 1681 goto done; 1682 } 1683 1684 /* icsc_task_cdb */ 1685 m->icsc_task_cdb = stmf_ic_uint8_array_unmarshal(nvl, "icsc_task_cdb", 1686 m->icsc_task_cdb_length, NULL); 1687 if (!m->icsc_task_cdb) { 1688 stmf_ic_nvlookup_warn(__func__, "icsc_task_cdb"); 1689 rc = ENOMEM; 1690 goto done; 1691 } 1692 1693 /* immediate data, if there is any */ 1694 if (m->icsc_immed_data_len) { 1695 m->icsc_immed_data = stmf_ic_uint8_array_unmarshal(nvl, 1696 "icsc_immed_data", m->icsc_immed_data_len, NULL); 1697 if (!m->icsc_immed_data) { 1698 stmf_ic_nvlookup_warn(__func__, "icsc_immed_data"); 1699 rc = ENOMEM; 1700 goto done; 1701 } 1702 } 1703 1704 done: 1705 if (!rc) 1706 return (m); 1707 1708 stmf_ic_scsi_cmd_msg_free(m, STMF_UNMARSHAL); 1709 1710 return (NULL); 1711 } 1712 1713 static void * 1714 stmf_ic_scsi_data_msg_unmarshal(nvlist_t *nvl) 1715 { 1716 int rc = 0; 1717 stmf_ic_scsi_data_msg_t *m = kmem_zalloc(sizeof (*m), KM_SLEEP); 1718 1719 if (nvlist_lookup_pairs(nvl, 0, 1720 NV_PAIR(UINT64, m, icsd_task_msgid), 1721 NV_PAIR(UINT64, m, icsd_session_id), 1722 NV_PAIR(UINT64, m, icsd_data_len), 1723 NULL) != 0) { 1724 stmf_ic_nvlookup_warn(__func__, "icsd_task_msgid and friends"); 1725 rc = ENOMEM; /* XXX need something better */ 1726 goto done; 1727 } 1728 1729 if (!stmf_ic_uint8_array_unmarshal(nvl, "icsd_lun_id", 1730 sizeof (m->icsd_lun_id), m->icsd_lun_id)) { 1731 stmf_ic_nvlookup_warn(__func__, "icsd_lun_id"); 1732 rc = ENOMEM; 1733 goto done; 1734 } 1735 1736 m->icsd_data = stmf_ic_uint8_array_unmarshal(nvl, "icsd_data", 1737 m->icsd_data_len, NULL); 1738 if (!m->icsd_data) { 1739 stmf_ic_nvlookup_warn(__func__, "icsd_data"); 1740 rc = ENOMEM; 1741 goto done; 1742 } 1743 1744 done: 1745 if (!rc) 1746 return (m); 1747 1748 stmf_ic_scsi_data_msg_free(m, STMF_UNMARSHAL); 1749 1750 return (NULL); 1751 } 1752 1753 static void * 1754 stmf_ic_scsi_data_xfer_done_msg_unmarshal(nvlist_t *nvl) 1755 { 1756 int rc = 0; 1757 stmf_ic_scsi_data_xfer_done_msg_t *m = 1758 kmem_zalloc(sizeof (*m), KM_SLEEP); 1759 1760 if (nvlist_lookup_pairs(nvl, 0, 1761 NV_PAIR(UINT64, m, icsx_task_msgid), 1762 NV_PAIR(UINT64, m, icsx_session_id), 1763 NV_PAIR(UINT64, m, icsx_status), 1764 NULL) != 0) { 1765 stmf_ic_nvlookup_warn(__func__, "icsx_task_msgid and friends"); 1766 rc = ENOMEM; /* XXX need something better */ 1767 goto done; 1768 } 1769 1770 done: 1771 if (!rc) 1772 return (m); 1773 1774 stmf_ic_scsi_data_xfer_done_msg_free(m, STMF_UNMARSHAL); 1775 1776 return (NULL); 1777 } 1778 1779 static void * 1780 stmf_ic_scsi_status_msg_unmarshal(nvlist_t *nvl) 1781 { 1782 int rc = 0; 1783 stmf_ic_scsi_status_msg_t *m = kmem_zalloc(sizeof (*m), KM_SLEEP); 1784 1785 if (nvlist_lookup_pairs(nvl, 0, 1786 NV_PAIR(UINT64, m, icss_task_msgid), 1787 NV_PAIR(UINT64, m, icss_session_id), 1788 NV_PAIR(UINT8, m, icss_response), 1789 NV_PAIR(UINT8, m, icss_status), 1790 NV_PAIR(UINT8, m, icss_flags), 1791 NV_PAIR(UINT32, m, icss_resid), 1792 NV_PAIR(UINT8, m, icss_sense_len), 1793 NULL) != 0) { 1794 stmf_ic_nvlookup_warn(__func__, "icss_task_msgid and friends"); 1795 rc = ENOMEM; /* XXX need something better */ 1796 goto done; 1797 } 1798 1799 if (!stmf_ic_uint8_array_unmarshal(nvl, "icss_lun_id", 1800 sizeof (m->icss_lun_id), m->icss_lun_id)) { 1801 stmf_ic_nvlookup_warn(__func__, "icss_lun_id"); 1802 rc = ENOMEM; 1803 goto done; 1804 } 1805 1806 if (m->icss_sense_len) { 1807 m->icss_sense = stmf_ic_uint8_array_unmarshal(nvl, "icss_sense", 1808 m->icss_sense_len, NULL); 1809 if (!m->icss_sense) { 1810 stmf_ic_nvlookup_warn(__func__, "icss_sense"); 1811 rc = ENOMEM; 1812 goto done; 1813 } 1814 } 1815 done: 1816 if (!rc) 1817 return (m); 1818 1819 stmf_ic_scsi_status_msg_free(m, STMF_UNMARSHAL); 1820 1821 return (NULL); 1822 } 1823 1824 static void * 1825 stmf_ic_r2t_msg_unmarshal(nvlist_t *nvl) 1826 { 1827 int rc = 0; 1828 stmf_ic_r2t_msg_t *m = kmem_zalloc(sizeof (*m), KM_SLEEP); 1829 1830 if (nvlist_lookup_pairs(nvl, 0, 1831 NV_PAIR(UINT64, m, icrt_task_msgid), 1832 NV_PAIR(UINT64, m, icrt_session_id), 1833 NV_PAIR(UINT32, m, icrt_offset), 1834 NV_PAIR(UINT32, m, icrt_length), 1835 NULL) != 0) { 1836 stmf_ic_nvlookup_warn(__func__, "icrt_task_msgid and friends"); 1837 rc = ENOMEM; /* XXX need something better */ 1838 goto done; 1839 } 1840 1841 done: 1842 if (!rc) 1843 return (m); 1844 1845 stmf_ic_r2t_msg_free(m, STMF_UNMARSHAL); 1846 1847 return (NULL); 1848 } 1849 1850 static void * 1851 stmf_ic_session_create_destroy_msg_unmarshal(nvlist_t *nvl) 1852 { 1853 int rc = 0; 1854 stmf_ic_session_create_destroy_msg_t *m = kmem_zalloc(sizeof (*m), 1855 KM_SLEEP); 1856 1857 if (nvlist_lookup_pairs(nvl, 0, 1858 NV_PAIR(UINT64, m, icscd_session_id), 1859 NULL) != 0) { 1860 stmf_ic_nvlookup_warn(__func__, "icsd_session_id"); 1861 rc = ENOMEM; /* XXX need something better */ 1862 goto done; 1863 } 1864 1865 m->icscd_ini_devid = stmf_ic_lookup_scsi_devid_desc_and_unmarshal( 1866 nvl, "icscd_ini_devid"); 1867 if (m->icscd_ini_devid == NULL) { 1868 stmf_ic_nvlookup_warn(__func__, "icsd_ini_devid"); 1869 rc = ENOMEM; 1870 goto done; 1871 } 1872 1873 m->icscd_tgt_devid = stmf_ic_lookup_scsi_devid_desc_and_unmarshal( 1874 nvl, "icscd_tgt_devid"); 1875 if (m->icscd_tgt_devid == NULL) { 1876 stmf_ic_nvlookup_warn(__func__, "icsd_tgt_devid"); 1877 rc = ENOMEM; 1878 goto done; 1879 } 1880 1881 done: 1882 if (!rc) 1883 return (m); 1884 1885 stmf_ic_session_create_destroy_msg_free(m, STMF_UNMARSHAL); 1886 1887 return (NULL); 1888 } 1889 1890 static void * 1891 stmf_ic_echo_request_reply_msg_unmarshal(nvlist_t *nvl) 1892 { 1893 int rc = 0; 1894 stmf_ic_echo_request_reply_msg_t *m = kmem_zalloc(sizeof (*m), 1895 KM_SLEEP); 1896 1897 if (nvlist_lookup_pairs(nvl, 0, 1898 NV_PAIR(UINT32, m, icerr_datalen), 1899 NULL) != 0) { 1900 stmf_ic_nvlookup_warn(__func__, "icerr_datalen"); 1901 rc = ENOMEM; /* XXX need something better */ 1902 goto done; 1903 } 1904 1905 /* immediate data, if there is any */ 1906 if (m->icerr_datalen) { 1907 m->icerr_data = stmf_ic_uint8_array_unmarshal(nvl, 1908 "icerr_data", m->icerr_datalen, NULL); 1909 if (!m->icerr_data) { 1910 stmf_ic_nvlookup_warn(__func__, "icerr_data"); 1911 rc = ENOMEM; 1912 goto done; 1913 } 1914 } 1915 1916 done: 1917 if (!rc) 1918 return (m); 1919 1920 stmf_ic_echo_request_reply_msg_free(m, STMF_UNMARSHAL); 1921 1922 return (NULL); 1923 } 1924 1925 static void * 1926 stmf_ic_status_msg_unmarshal(nvlist_t *nvl) 1927 { 1928 int rc = 0; 1929 stmf_ic_status_msg_t *m = kmem_zalloc(sizeof (*m), KM_SLEEP); 1930 1931 if (nvlist_lookup_pairs(nvl, 0, 1932 NV_PAIR(UINT8, m, ics_msg_type), 1933 NV_PAIR(UINT64, m, ics_msgid), 1934 NV_PAIR(UINT8, m, ics_status), 1935 NULL) != 0) { 1936 stmf_ic_nvlookup_warn(__func__, "ics_msg_type and friends"); 1937 rc = ENOMEM; /* XXX need something better */ 1938 goto done; 1939 } 1940 1941 done: 1942 if (!rc) 1943 return (m); 1944 1945 kmem_free(m, sizeof (*m)); 1946 return (NULL); 1947 } 1948 1949 1950 static scsi_devid_desc_t * 1951 stmf_ic_lookup_scsi_devid_desc_and_unmarshal(nvlist_t *nvl, char *field_name) 1952 { 1953 nvlist_t *nvl_devid = NULL; 1954 scsi_devid_desc_t *did = NULL; 1955 int rc; 1956 1957 rc = nvlist_lookup_nvlist(nvl, field_name, &nvl_devid); 1958 if (rc) { 1959 goto done; 1960 } 1961 1962 did = stmf_ic_scsi_devid_desc_unmarshal(nvl_devid); 1963 1964 done: 1965 return (did); 1966 } 1967 1968 1969 static scsi_devid_desc_t * 1970 stmf_ic_scsi_devid_desc_unmarshal(nvlist_t *nvl) 1971 { 1972 scsi_devid_desc_t *sdid = NULL; 1973 uint8_t ident_length = 0; 1974 size_t sdid_size; 1975 int rc = 0; 1976 1977 /* 1978 * we get the ident_length first, since that's the only 1979 * variable-sized field in the struct. 1980 */ 1981 rc = nvlist_lookup_uint8(nvl, "ident_length", &ident_length); 1982 if (rc) 1983 goto done; 1984 1985 sdid_size = sizeof_scsi_devid_desc(ident_length); 1986 sdid = kmem_zalloc(sdid_size, KM_SLEEP); 1987 1988 NVLIST_LOOKUP_BIT_FIELD(uint8, sdid, protocol_id); 1989 NVLIST_LOOKUP_BIT_FIELD(uint8, sdid, code_set); 1990 NVLIST_LOOKUP_BIT_FIELD(uint8, sdid, piv); 1991 NVLIST_LOOKUP_BIT_FIELD(uint8, sdid, association); 1992 NVLIST_LOOKUP_BIT_FIELD(uint8, sdid, ident_type); 1993 1994 sdid->ident_length = ident_length; 1995 1996 if (!stmf_ic_uint8_array_unmarshal(nvl, "ident", 1997 sdid->ident_length, sdid->ident)) { 1998 rc = ENOMEM; /* XXX */ 1999 goto done; 2000 } 2001 2002 done: 2003 if (!rc) 2004 return (sdid); 2005 2006 kmem_free(sdid, sdid_size); 2007 2008 return (NULL); 2009 } 2010 2011 /* 2012 * Unmarshal a uint8_t array. 2013 * 2014 * Takes a buf argument: 2015 * 2016 * - if non-null, the array contents are copied into the buf, 2017 * and we return a pointer to the buffer. 2018 * 2019 * - if null, we return a pointer to the unmarshaled data, which 2020 * resides in the nvlist. 2021 * 2022 * Returns NULL on failure. 2023 */ 2024 static uint8_t * 2025 stmf_ic_uint8_array_unmarshal( 2026 nvlist_t *nvl, 2027 char *field_name, 2028 uint16_t len, 2029 uint8_t *buf) /* non-NULL: copy array into buf */ 2030 { 2031 uint8_t *array = NULL; 2032 uint_t actual_len; 2033 int rc = 0; 2034 2035 rc = nvlist_lookup_uint8_array(nvl, field_name, &array, &actual_len); 2036 if (rc) { 2037 return (NULL); 2038 } 2039 2040 if (len != actual_len) { 2041 cmn_err(CE_WARN, 2042 "stmf_ic_uint8_array_unmarshal: wrong len (%d != %d)", 2043 len, actual_len); 2044 return (NULL); 2045 } 2046 2047 if (buf) { 2048 /* preallocated buf, copy in */ 2049 bcopy(array, buf, len); 2050 } else { 2051 /* return a pointer to the underlying array in the nvlist */ 2052 buf = array; 2053 } 2054 2055 return (buf); 2056 } 2057 2058 /* 2059 * Unmarshal a string. 2060 * 2061 * Returns NULL on failure. 2062 */ 2063 static char * 2064 stmf_ic_string_unmarshal( 2065 nvlist_t *nvl, 2066 char *field_name) 2067 { 2068 char *s = NULL; 2069 int rc = 0; 2070 2071 rc = nvlist_lookup_string(nvl, field_name, &s); 2072 if (rc) { 2073 return (NULL); 2074 } 2075 2076 return (s); 2077 } 2078 2079 /* 2080 * Utility routines. 2081 */ 2082 2083 static stmf_ic_msg_t * 2084 stmf_ic_alloc_msg_header( 2085 stmf_ic_msg_type_t msg_type, 2086 stmf_ic_msgid_t msgid) 2087 { 2088 stmf_ic_msg_t *icm; 2089 2090 icm = (stmf_ic_msg_t *)kmem_zalloc(sizeof (*icm), KM_SLEEP); 2091 icm->icm_msg_type = msg_type; 2092 icm->icm_msgid = msgid; 2093 2094 return (icm); 2095 } 2096 2097 static size_t 2098 sizeof_scsi_devid_desc(int ident_length) 2099 { 2100 int num_ident_elems; 2101 size_t size; 2102 2103 ASSERT(ident_length > 0); 2104 2105 /* 2106 * Need to account for the fact that there's 2107 * already a single element in scsi_devid_desc_t. 2108 * 2109 * XXX would really like to have a way to determine the 2110 * sizeof (struct scsi_devid_desc.ident[0]), but 2111 * it's not clear that can be done. 2112 * Thus, this code relies on the knowledge of the type of 2113 * that field. 2114 */ 2115 num_ident_elems = ident_length - 1; 2116 size = sizeof (scsi_devid_desc_t) + 2117 (num_ident_elems * sizeof (uint8_t)); 2118 2119 return (size); 2120 } 2121 2122 2123 /* 2124 * Duplicate the scsi_devid_desc_t. 2125 */ 2126 static scsi_devid_desc_t * 2127 scsi_devid_desc_dup(scsi_devid_desc_t *did) 2128 { 2129 scsi_devid_desc_t *dup; 2130 size_t dup_size; 2131 2132 ASSERT(did->ident_length > 0); 2133 2134 dup_size = sizeof_scsi_devid_desc(did->ident_length); 2135 dup = (scsi_devid_desc_t *)kmem_zalloc(dup_size, KM_SLEEP); 2136 bcopy(did, dup, dup_size); 2137 return (dup); 2138 } 2139 2140 /* 2141 * May be called with a null pointer. 2142 */ 2143 static void 2144 scsi_devid_desc_free(scsi_devid_desc_t *did) 2145 { 2146 if (!did) 2147 return; 2148 2149 kmem_free(did, sizeof_scsi_devid_desc(did->ident_length)); 2150 } 2151 2152 /* 2153 * Helper functions, returns NULL if no memory. 2154 */ 2155 static char * 2156 stmf_ic_strdup(char *str) 2157 { 2158 char *copy; 2159 2160 ASSERT(str); 2161 2162 copy = kmem_zalloc(strlen(str) + 1, KM_SLEEP); 2163 (void) strcpy(copy, str); 2164 return (copy); 2165 } 2166 2167 static inline void 2168 stmf_ic_nvlookup_warn(const char *func, char *field) 2169 { 2170 cmn_err(CE_WARN, "%s: nvlist lookup of %s failed", func, field); 2171 } 2172