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