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