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 /* 23 * Copyright 2009 Emulex. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 28 #define DEF_ICFG 1 29 30 #include <emlxs.h> 31 #include <emlxs_version.h> 32 33 34 char emlxs_revision[] = EMLXS_REVISION; 35 char emlxs_version[] = EMLXS_VERSION; 36 char emlxs_name[] = EMLXS_NAME; 37 char emlxs_label[] = EMLXS_LABEL; 38 39 /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */ 40 EMLXS_MSG_DEF(EMLXS_SOLARIS_C); 41 42 #ifdef MENLO_SUPPORT 43 static int32_t emlxs_send_menlo(emlxs_port_t *port, emlxs_buf_t *sbp); 44 #endif /* MENLO_SUPPORT */ 45 46 static void emlxs_fca_attach(emlxs_hba_t *hba); 47 static void emlxs_fca_detach(emlxs_hba_t *hba); 48 static void emlxs_drv_banner(emlxs_hba_t *hba); 49 50 static int32_t emlxs_get_props(emlxs_hba_t *hba); 51 static int32_t emlxs_send_fcp_cmd(emlxs_port_t *port, emlxs_buf_t *sbp); 52 static int32_t emlxs_send_fct_status(emlxs_port_t *port, emlxs_buf_t *sbp); 53 static int32_t emlxs_send_fct_abort(emlxs_port_t *port, emlxs_buf_t *sbp); 54 static int32_t emlxs_send_ip(emlxs_port_t *port, emlxs_buf_t *sbp); 55 static int32_t emlxs_send_els(emlxs_port_t *port, emlxs_buf_t *sbp); 56 static int32_t emlxs_send_els_rsp(emlxs_port_t *port, emlxs_buf_t *sbp); 57 static int32_t emlxs_send_ct(emlxs_port_t *port, emlxs_buf_t *sbp); 58 static int32_t emlxs_send_ct_rsp(emlxs_port_t *port, emlxs_buf_t *sbp); 59 static uint32_t emlxs_add_instance(int32_t ddiinst); 60 static void emlxs_iodone(emlxs_buf_t *sbp); 61 static int emlxs_pm_lower_power(dev_info_t *dip); 62 static int emlxs_pm_raise_power(dev_info_t *dip); 63 static void emlxs_driver_remove(dev_info_t *dip, uint32_t init_flag, 64 uint32_t failed); 65 static void emlxs_iodone_server(void *arg1, void *arg2, void *arg3); 66 static uint32_t emlxs_integrity_check(emlxs_hba_t *hba); 67 static uint32_t emlxs_test(emlxs_hba_t *hba, uint32_t test_code, 68 uint32_t args, uint32_t *arg); 69 70 static void emlxs_read_vport_prop(emlxs_hba_t *hba); 71 72 73 74 /* 75 * Driver Entry Routines. 76 */ 77 static int32_t emlxs_detach(dev_info_t *, ddi_detach_cmd_t); 78 static int32_t emlxs_attach(dev_info_t *, ddi_attach_cmd_t); 79 static int32_t emlxs_open(dev_t *, int32_t, int32_t, cred_t *); 80 static int32_t emlxs_close(dev_t, int32_t, int32_t, cred_t *); 81 static int32_t emlxs_ioctl(dev_t, int32_t, intptr_t, int32_t, 82 cred_t *, int32_t *); 83 static int32_t emlxs_info(dev_info_t *, ddi_info_cmd_t, void *, void **); 84 85 86 /* 87 * FC_AL Transport Functions. 88 */ 89 static opaque_t emlxs_bind_port(dev_info_t *, fc_fca_port_info_t *, 90 fc_fca_bind_info_t *); 91 static void emlxs_unbind_port(opaque_t); 92 static void emlxs_initialize_pkt(emlxs_port_t *, emlxs_buf_t *); 93 static int32_t emlxs_get_cap(opaque_t, char *, void *); 94 static int32_t emlxs_set_cap(opaque_t, char *, void *); 95 static int32_t emlxs_get_map(opaque_t, fc_lilpmap_t *); 96 static int32_t emlxs_ub_alloc(opaque_t, uint64_t *, uint32_t, 97 uint32_t *, uint32_t); 98 static int32_t emlxs_ub_free(opaque_t, uint32_t, uint64_t *); 99 100 static opaque_t emlxs_get_device(opaque_t, fc_portid_t); 101 static int32_t emlxs_notify(opaque_t, uint32_t); 102 static void emlxs_ub_els_reject(emlxs_port_t *, fc_unsol_buf_t *); 103 104 /* 105 * Driver Internal Functions. 106 */ 107 108 static void emlxs_poll(emlxs_port_t *, emlxs_buf_t *); 109 static int32_t emlxs_power(dev_info_t *, int32_t, int32_t); 110 #ifdef EMLXS_I386 111 #ifdef S11 112 static int32_t emlxs_quiesce(dev_info_t *); 113 #endif 114 #endif 115 static int32_t emlxs_hba_resume(dev_info_t *); 116 static int32_t emlxs_hba_suspend(dev_info_t *); 117 static int32_t emlxs_hba_detach(dev_info_t *); 118 static int32_t emlxs_hba_attach(dev_info_t *); 119 static void emlxs_lock_destroy(emlxs_hba_t *); 120 static void emlxs_lock_init(emlxs_hba_t *); 121 static ULP_BDE64 *emlxs_pkt_to_bpl(ULP_BDE64 *, fc_packet_t *, 122 uint32_t, uint8_t); 123 124 char *emlxs_pm_components[] = { 125 "NAME=emlxx000", 126 "0=Device D3 State", 127 "1=Device D0 State" 128 }; 129 130 131 /* 132 * Default emlx dma limits 133 */ 134 ddi_dma_lim_t emlxs_dma_lim = { 135 (uint32_t)0, /* dlim_addr_lo */ 136 (uint32_t)0xffffffff, /* dlim_addr_hi */ 137 (uint_t)0x00ffffff, /* dlim_cntr_max */ 138 DEFAULT_BURSTSIZE | BURST32 | BURST64, /* dlim_burstsizes */ 139 1, /* dlim_minxfer */ 140 0x00ffffff /* dlim_dmaspeed */ 141 }; 142 143 /* 144 * Be careful when using these attributes; the defaults listed below are 145 * (almost) the most general case, permitting allocation in almost any 146 * way supported by the LightPulse family. The sole exception is the 147 * alignment specified as requiring memory allocation on a 4-byte boundary; 148 * the Lightpulse can DMA memory on any byte boundary. 149 * 150 * The LightPulse family currently is limited to 16M transfers; 151 * this restriction affects the dma_attr_count_max and dma_attr_maxxfer fields. 152 */ 153 ddi_dma_attr_t emlxs_dma_attr = { 154 DMA_ATTR_V0, /* dma_attr_version */ 155 (uint64_t)0, /* dma_attr_addr_lo */ 156 (uint64_t)0xffffffffffffffff, /* dma_attr_addr_hi */ 157 (uint64_t)0x00ffffff, /* dma_attr_count_max */ 158 1, /* dma_attr_align */ 159 DEFAULT_BURSTSIZE | BURST32 | BURST64, /* dma_attr_burstsizes */ 160 1, /* dma_attr_minxfer */ 161 (uint64_t)0x00ffffff, /* dma_attr_maxxfer */ 162 (uint64_t)0xffffffff, /* dma_attr_seg */ 163 EMLXS_SGLLEN, /* dma_attr_sgllen */ 164 1, /* dma_attr_granular */ 165 0 /* dma_attr_flags */ 166 }; 167 168 ddi_dma_attr_t emlxs_dma_attr_ro = { 169 DMA_ATTR_V0, /* dma_attr_version */ 170 (uint64_t)0, /* dma_attr_addr_lo */ 171 (uint64_t)0xffffffffffffffff, /* dma_attr_addr_hi */ 172 (uint64_t)0x00ffffff, /* dma_attr_count_max */ 173 1, /* dma_attr_align */ 174 DEFAULT_BURSTSIZE | BURST32 | BURST64, /* dma_attr_burstsizes */ 175 1, /* dma_attr_minxfer */ 176 (uint64_t)0x00ffffff, /* dma_attr_maxxfer */ 177 (uint64_t)0xffffffff, /* dma_attr_seg */ 178 EMLXS_SGLLEN, /* dma_attr_sgllen */ 179 1, /* dma_attr_granular */ 180 DDI_DMA_RELAXED_ORDERING /* dma_attr_flags */ 181 }; 182 183 ddi_dma_attr_t emlxs_dma_attr_1sg = { 184 DMA_ATTR_V0, /* dma_attr_version */ 185 (uint64_t)0, /* dma_attr_addr_lo */ 186 (uint64_t)0xffffffffffffffff, /* dma_attr_addr_hi */ 187 (uint64_t)0x00ffffff, /* dma_attr_count_max */ 188 1, /* dma_attr_align */ 189 DEFAULT_BURSTSIZE | BURST32 | BURST64, /* dma_attr_burstsizes */ 190 1, /* dma_attr_minxfer */ 191 (uint64_t)0x00ffffff, /* dma_attr_maxxfer */ 192 (uint64_t)0xffffffff, /* dma_attr_seg */ 193 1, /* dma_attr_sgllen */ 194 1, /* dma_attr_granular */ 195 0 /* dma_attr_flags */ 196 }; 197 198 #if (EMLXS_MODREV >= EMLXS_MODREV3) 199 ddi_dma_attr_t emlxs_dma_attr_fcip_rsp = { 200 DMA_ATTR_V0, /* dma_attr_version */ 201 (uint64_t)0, /* dma_attr_addr_lo */ 202 (uint64_t)0xffffffffffffffff, /* dma_attr_addr_hi */ 203 (uint64_t)0x00ffffff, /* dma_attr_count_max */ 204 1, /* dma_attr_align */ 205 DEFAULT_BURSTSIZE | BURST32 | BURST64, /* dma_attr_burstsizes */ 206 1, /* dma_attr_minxfer */ 207 (uint64_t)0x00ffffff, /* dma_attr_maxxfer */ 208 (uint64_t)0xffffffff, /* dma_attr_seg */ 209 EMLXS_SGLLEN, /* dma_attr_sgllen */ 210 1, /* dma_attr_granular */ 211 0 /* dma_attr_flags */ 212 }; 213 #endif /* >= EMLXS_MODREV3 */ 214 215 /* 216 * DDI access attributes for device 217 */ 218 ddi_device_acc_attr_t emlxs_dev_acc_attr = { 219 DDI_DEVICE_ATTR_V1, /* devacc_attr_version */ 220 DDI_STRUCTURE_LE_ACC, /* PCI is Little Endian */ 221 DDI_STRICTORDER_ACC, /* devacc_attr_dataorder */ 222 DDI_DEFAULT_ACC /* devacc_attr_access */ 223 }; 224 225 /* 226 * DDI access attributes for data 227 */ 228 ddi_device_acc_attr_t emlxs_data_acc_attr = { 229 DDI_DEVICE_ATTR_V1, /* devacc_attr_version */ 230 DDI_NEVERSWAP_ACC, /* don't swap for Data */ 231 DDI_STRICTORDER_ACC, /* devacc_attr_dataorder */ 232 DDI_DEFAULT_ACC /* devacc_attr_access */ 233 }; 234 235 /* 236 * Fill in the FC Transport structure, 237 * as defined in the Fibre Channel Transport Programmming Guide. 238 */ 239 #if (EMLXS_MODREV == EMLXS_MODREV5) 240 static fc_fca_tran_t emlxs_fca_tran = { 241 FCTL_FCA_MODREV_5, /* fca_version, with SUN NPIV support */ 242 MAX_VPORTS, /* fca numerb of ports */ 243 sizeof (emlxs_buf_t), /* fca pkt size */ 244 2048, /* fca cmd max */ 245 &emlxs_dma_lim, /* fca dma limits */ 246 0, /* fca iblock, to be filled in later */ 247 &emlxs_dma_attr, /* fca dma attributes */ 248 &emlxs_dma_attr_1sg, /* fca dma fcp cmd attributes */ 249 &emlxs_dma_attr_1sg, /* fca dma fcp rsp attributes */ 250 &emlxs_dma_attr_ro, /* fca dma fcp data attributes */ 251 &emlxs_dma_attr_1sg, /* fca dma fcip cmd attributes */ 252 &emlxs_dma_attr_fcip_rsp, /* fca dma fcip rsp attributes */ 253 &emlxs_dma_attr_1sg, /* fca dma fcsm cmd attributes */ 254 &emlxs_dma_attr, /* fca dma fcsm rsp attributes */ 255 &emlxs_data_acc_attr, /* fca access atributes */ 256 0, /* fca_num_npivports */ 257 {0, 0, 0, 0, 0, 0, 0, 0}, /* Physical port WWPN */ 258 emlxs_bind_port, 259 emlxs_unbind_port, 260 emlxs_pkt_init, 261 emlxs_pkt_uninit, 262 emlxs_transport, 263 emlxs_get_cap, 264 emlxs_set_cap, 265 emlxs_get_map, 266 emlxs_transport, 267 emlxs_ub_alloc, 268 emlxs_ub_free, 269 emlxs_ub_release, 270 emlxs_pkt_abort, 271 emlxs_reset, 272 emlxs_port_manage, 273 emlxs_get_device, 274 emlxs_notify 275 }; 276 #endif /* EMLXS_MODREV5 */ 277 278 279 #if (EMLXS_MODREV == EMLXS_MODREV4) 280 static fc_fca_tran_t emlxs_fca_tran = { 281 FCTL_FCA_MODREV_4, /* fca_version */ 282 MAX_VPORTS, /* fca numerb of ports */ 283 sizeof (emlxs_buf_t), /* fca pkt size */ 284 2048, /* fca cmd max */ 285 &emlxs_dma_lim, /* fca dma limits */ 286 0, /* fca iblock, to be filled in later */ 287 &emlxs_dma_attr, /* fca dma attributes */ 288 &emlxs_dma_attr_1sg, /* fca dma fcp cmd attributes */ 289 &emlxs_dma_attr_1sg, /* fca dma fcp rsp attributes */ 290 &emlxs_dma_attr_ro, /* fca dma fcp data attributes */ 291 &emlxs_dma_attr_1sg, /* fca dma fcip cmd attributes */ 292 &emlxs_dma_attr_fcip_rsp, /* fca dma fcip rsp attributes */ 293 &emlxs_dma_attr_1sg, /* fca dma fcsm cmd attributes */ 294 &emlxs_dma_attr, /* fca dma fcsm rsp attributes */ 295 &emlxs_data_acc_attr, /* fca access atributes */ 296 emlxs_bind_port, 297 emlxs_unbind_port, 298 emlxs_pkt_init, 299 emlxs_pkt_uninit, 300 emlxs_transport, 301 emlxs_get_cap, 302 emlxs_set_cap, 303 emlxs_get_map, 304 emlxs_transport, 305 emlxs_ub_alloc, 306 emlxs_ub_free, 307 emlxs_ub_release, 308 emlxs_pkt_abort, 309 emlxs_reset, 310 emlxs_port_manage, 311 emlxs_get_device, 312 emlxs_notify 313 }; 314 #endif /* EMLXS_MODEREV4 */ 315 316 317 #if (EMLXS_MODREV == EMLXS_MODREV3) 318 static fc_fca_tran_t emlxs_fca_tran = { 319 FCTL_FCA_MODREV_3, /* fca_version */ 320 MAX_VPORTS, /* fca numerb of ports */ 321 sizeof (emlxs_buf_t), /* fca pkt size */ 322 2048, /* fca cmd max */ 323 &emlxs_dma_lim, /* fca dma limits */ 324 0, /* fca iblock, to be filled in later */ 325 &emlxs_dma_attr, /* fca dma attributes */ 326 &emlxs_dma_attr_1sg, /* fca dma fcp cmd attributes */ 327 &emlxs_dma_attr_1sg, /* fca dma fcp rsp attributes */ 328 &emlxs_dma_attr_ro, /* fca dma fcp data attributes */ 329 &emlxs_dma_attr_1sg, /* fca dma fcip cmd attributes */ 330 &emlxs_dma_attr_fcip_rsp, /* fca dma fcip rsp attributes */ 331 &emlxs_dma_attr_1sg, /* fca dma fcsm cmd attributes */ 332 &emlxs_dma_attr, /* fca dma fcsm rsp attributes */ 333 &emlxs_data_acc_attr, /* fca access atributes */ 334 emlxs_bind_port, 335 emlxs_unbind_port, 336 emlxs_pkt_init, 337 emlxs_pkt_uninit, 338 emlxs_transport, 339 emlxs_get_cap, 340 emlxs_set_cap, 341 emlxs_get_map, 342 emlxs_transport, 343 emlxs_ub_alloc, 344 emlxs_ub_free, 345 emlxs_ub_release, 346 emlxs_pkt_abort, 347 emlxs_reset, 348 emlxs_port_manage, 349 emlxs_get_device, 350 emlxs_notify 351 }; 352 #endif /* EMLXS_MODREV3 */ 353 354 355 #if (EMLXS_MODREV == EMLXS_MODREV2) 356 static fc_fca_tran_t emlxs_fca_tran = { 357 FCTL_FCA_MODREV_2, /* fca_version */ 358 MAX_VPORTS, /* number of ports */ 359 sizeof (emlxs_buf_t), /* pkt size */ 360 2048, /* max cmds */ 361 &emlxs_dma_lim, /* DMA limits */ 362 0, /* iblock, to be filled in later */ 363 &emlxs_dma_attr, /* dma attributes */ 364 &emlxs_data_acc_attr, /* access atributes */ 365 emlxs_bind_port, 366 emlxs_unbind_port, 367 emlxs_pkt_init, 368 emlxs_pkt_uninit, 369 emlxs_transport, 370 emlxs_get_cap, 371 emlxs_set_cap, 372 emlxs_get_map, 373 emlxs_transport, 374 emlxs_ub_alloc, 375 emlxs_ub_free, 376 emlxs_ub_release, 377 emlxs_pkt_abort, 378 emlxs_reset, 379 emlxs_port_manage, 380 emlxs_get_device, 381 emlxs_notify 382 }; 383 #endif /* EMLXS_MODREV2 */ 384 385 /* 386 * This is needed when the module gets loaded by the kernel 387 * so ddi library calls get resolved. 388 */ 389 #ifndef MODSYM_SUPPORT 390 char _depends_on[] = "misc/fctl"; 391 #endif /* MODSYM_SUPPORT */ 392 393 /* 394 * state pointer which the implementation uses as a place to 395 * hang a set of per-driver structures; 396 * 397 */ 398 void *emlxs_soft_state = NULL; 399 400 /* 401 * Driver Global variables. 402 */ 403 int32_t emlxs_scsi_reset_delay = 3000; /* milliseconds */ 404 405 emlxs_device_t emlxs_device; 406 407 uint32_t emlxs_instance[MAX_FC_BRDS]; /* uses emlxs_device.lock */ 408 uint32_t emlxs_instance_count = 0; /* uses emlxs_device.lock */ 409 410 411 /* 412 * Single private "global" lock used to gain access to 413 * the hba_list and/or any other case where we want need to be 414 * single-threaded. 415 */ 416 uint32_t emlxs_diag_state; 417 418 /* 419 * CB ops vector. Used for administration only. 420 */ 421 static struct cb_ops emlxs_cb_ops = { 422 emlxs_open, /* cb_open */ 423 emlxs_close, /* cb_close */ 424 nodev, /* cb_strategy */ 425 nodev, /* cb_print */ 426 nodev, /* cb_dump */ 427 nodev, /* cb_read */ 428 nodev, /* cb_write */ 429 emlxs_ioctl, /* cb_ioctl */ 430 nodev, /* cb_devmap */ 431 nodev, /* cb_mmap */ 432 nodev, /* cb_segmap */ 433 nochpoll, /* cb_chpoll */ 434 ddi_prop_op, /* cb_prop_op */ 435 0, /* cb_stream */ 436 #ifdef _LP64 437 D_64BIT | D_HOTPLUG | D_MP | D_NEW, /* cb_flag */ 438 #else 439 D_HOTPLUG | D_MP | D_NEW, /* cb_flag */ 440 #endif 441 CB_REV, /* rev */ 442 nodev, /* cb_aread */ 443 nodev /* cb_awrite */ 444 }; 445 446 static struct dev_ops emlxs_ops = { 447 DEVO_REV, /* rev */ 448 0, /* refcnt */ 449 emlxs_info, /* getinfo */ 450 nulldev, /* identify */ 451 nulldev, /* probe */ 452 emlxs_attach, /* attach */ 453 emlxs_detach, /* detach */ 454 nodev, /* reset */ 455 &emlxs_cb_ops, /* devo_cb_ops */ 456 NULL, /* devo_bus_ops */ 457 emlxs_power, /* power ops */ 458 #ifdef EMLXS_I386 459 #ifdef S11 460 emlxs_quiesce, /* quiesce */ 461 #endif 462 #endif 463 }; 464 465 #include <sys/modctl.h> 466 extern struct mod_ops mod_driverops; 467 468 #ifdef SAN_DIAG_SUPPORT 469 extern kmutex_t sd_bucket_mutex; 470 extern sd_bucket_info_t sd_bucket; 471 #endif /* SAN_DIAG_SUPPORT */ 472 473 /* 474 * Module linkage information for the kernel. 475 */ 476 static struct modldrv emlxs_modldrv = { 477 &mod_driverops, /* module type - driver */ 478 emlxs_name, /* module name */ 479 &emlxs_ops, /* driver ops */ 480 }; 481 482 483 /* 484 * Driver module linkage structure 485 */ 486 static struct modlinkage emlxs_modlinkage = { 487 MODREV_1, /* ml_rev - must be MODREV_1 */ 488 &emlxs_modldrv, /* ml_linkage */ 489 NULL /* end of driver linkage */ 490 }; 491 492 493 /* We only need to add entries for non-default return codes. */ 494 /* Entries do not need to be in order. */ 495 /* Default: FC_PKT_TRAN_ERROR, FC_REASON_ABORTED, */ 496 /* FC_EXPLN_NONE, FC_ACTION_RETRYABLE */ 497 498 emlxs_xlat_err_t emlxs_iostat_tbl[] = { 499 /* {f/w code, pkt_state, pkt_reason, */ 500 /* pkt_expln, pkt_action} */ 501 502 /* 0x00 - Do not remove */ 503 {IOSTAT_SUCCESS, FC_PKT_SUCCESS, FC_REASON_NONE, 504 FC_EXPLN_NONE, FC_ACTION_RETRYABLE}, 505 506 /* 0x01 - Do not remove */ 507 {IOSTAT_FCP_RSP_ERROR, FC_PKT_SUCCESS, FC_REASON_NONE, 508 FC_EXPLN_NONE, FC_ACTION_RETRYABLE}, 509 510 /* 0x02 */ 511 {IOSTAT_REMOTE_STOP, FC_PKT_REMOTE_STOP, FC_REASON_ABTS, 512 FC_EXPLN_NONE, FC_ACTION_NON_RETRYABLE}, 513 514 /* 515 * This is a default entry. 516 * The real codes are written dynamically in emlxs_els.c 517 */ 518 /* 0x09 */ 519 {IOSTAT_LS_RJT, FC_PKT_LS_RJT, FC_REASON_CMD_UNABLE, 520 FC_EXPLN_NONE, FC_ACTION_RETRYABLE}, 521 522 /* Special error code */ 523 /* 0x10 */ 524 {IOSTAT_DATA_OVERRUN, FC_PKT_TRAN_ERROR, FC_REASON_OVERRUN, 525 FC_EXPLN_NONE, FC_ACTION_RETRYABLE}, 526 527 /* Special error code */ 528 /* 0x11 */ 529 {IOSTAT_DATA_UNDERRUN, FC_PKT_TRAN_ERROR, FC_REASON_ABORTED, 530 FC_EXPLN_NONE, FC_ACTION_RETRYABLE}, 531 532 /* CLASS 2 only */ 533 /* 0x04 */ 534 {IOSTAT_NPORT_RJT, FC_PKT_NPORT_RJT, FC_REASON_PROTOCOL_ERROR, 535 FC_EXPLN_NONE, FC_ACTION_RETRYABLE}, 536 537 /* CLASS 2 only */ 538 /* 0x05 */ 539 {IOSTAT_FABRIC_RJT, FC_PKT_FABRIC_RJT, FC_REASON_PROTOCOL_ERROR, 540 FC_EXPLN_NONE, FC_ACTION_RETRYABLE}, 541 542 /* CLASS 2 only */ 543 /* 0x06 */ 544 {IOSTAT_NPORT_BSY, FC_PKT_NPORT_BSY, FC_REASON_PHYSICAL_BUSY, 545 FC_EXPLN_NONE, FC_ACTION_SEQ_TERM_RETRY}, 546 547 /* CLASS 2 only */ 548 /* 0x07 */ 549 {IOSTAT_FABRIC_BSY, FC_PKT_FABRIC_BSY, FC_REASON_FABRIC_BSY, 550 FC_EXPLN_NONE, FC_ACTION_SEQ_TERM_RETRY}, 551 }; 552 553 #define IOSTAT_MAX (sizeof (emlxs_iostat_tbl)/sizeof (emlxs_xlat_err_t)) 554 555 556 /* We only need to add entries for non-default return codes. */ 557 /* Entries do not need to be in order. */ 558 /* Default: FC_PKT_TRAN_ERROR, FC_REASON_ABORTED, */ 559 /* FC_EXPLN_NONE, FC_ACTION_RETRYABLE} */ 560 561 emlxs_xlat_err_t emlxs_ioerr_tbl[] = { 562 /* {f/w code, pkt_state, pkt_reason, */ 563 /* pkt_expln, pkt_action} */ 564 565 /* 0x01 */ 566 {IOERR_MISSING_CONTINUE, FC_PKT_TRAN_ERROR, FC_REASON_OVERRUN, 567 FC_EXPLN_NONE, FC_ACTION_RETRYABLE}, 568 569 /* 0x02 */ 570 {IOERR_SEQUENCE_TIMEOUT, FC_PKT_TIMEOUT, FC_REASON_SEQ_TIMEOUT, 571 FC_EXPLN_NONE, FC_ACTION_RETRYABLE}, 572 573 /* 0x04 */ 574 {IOERR_INVALID_RPI, FC_PKT_PORT_OFFLINE, FC_REASON_OFFLINE, 575 FC_EXPLN_NONE, FC_ACTION_RETRYABLE}, 576 577 /* 0x05 */ 578 {IOERR_NO_XRI, FC_PKT_LOCAL_RJT, FC_REASON_XCHG_DROPPED, 579 FC_EXPLN_NONE, FC_ACTION_RETRYABLE}, 580 581 /* 0x06 */ 582 {IOERR_ILLEGAL_COMMAND, FC_PKT_LOCAL_RJT, FC_REASON_ILLEGAL_REQ, 583 FC_EXPLN_NONE, FC_ACTION_RETRYABLE}, 584 585 /* 0x07 */ 586 {IOERR_XCHG_DROPPED, FC_PKT_LOCAL_RJT, FC_REASON_XCHG_DROPPED, 587 FC_EXPLN_NONE, FC_ACTION_RETRYABLE}, 588 589 /* 0x08 */ 590 {IOERR_ILLEGAL_FIELD, FC_PKT_LOCAL_RJT, FC_REASON_ILLEGAL_REQ, 591 FC_EXPLN_NONE, FC_ACTION_RETRYABLE}, 592 593 /* 0x0B */ 594 {IOERR_RCV_BUFFER_WAITING, FC_PKT_LOCAL_RJT, FC_REASON_NOMEM, 595 FC_EXPLN_NONE, FC_ACTION_RETRYABLE}, 596 597 /* 0x0D */ 598 {IOERR_TX_DMA_FAILED, FC_PKT_LOCAL_RJT, FC_REASON_DMA_ERROR, 599 FC_EXPLN_NONE, FC_ACTION_RETRYABLE}, 600 601 /* 0x0E */ 602 {IOERR_RX_DMA_FAILED, FC_PKT_LOCAL_RJT, FC_REASON_DMA_ERROR, 603 FC_EXPLN_NONE, FC_ACTION_RETRYABLE}, 604 605 /* 0x0F */ 606 {IOERR_ILLEGAL_FRAME, FC_PKT_LOCAL_RJT, FC_REASON_ILLEGAL_FRAME, 607 FC_EXPLN_NONE, FC_ACTION_RETRYABLE}, 608 609 /* 0x11 */ 610 {IOERR_NO_RESOURCES, FC_PKT_LOCAL_RJT, FC_REASON_NOMEM, 611 FC_EXPLN_NONE, FC_ACTION_RETRYABLE}, 612 613 /* 0x13 */ 614 {IOERR_ILLEGAL_LENGTH, FC_PKT_LOCAL_RJT, FC_REASON_ILLEGAL_LENGTH, 615 FC_EXPLN_NONE, FC_ACTION_RETRYABLE}, 616 617 /* 0x14 */ 618 {IOERR_UNSUPPORTED_FEATURE, FC_PKT_LOCAL_RJT, FC_REASON_UNSUPPORTED, 619 FC_EXPLN_NONE, FC_ACTION_RETRYABLE}, 620 621 /* 0x15 */ 622 {IOERR_ABORT_IN_PROGRESS, FC_PKT_LOCAL_RJT, FC_REASON_ABORTED, 623 FC_EXPLN_NONE, FC_ACTION_RETRYABLE}, 624 625 /* 0x16 */ 626 {IOERR_ABORT_REQUESTED, FC_PKT_LOCAL_RJT, FC_REASON_ABORTED, 627 FC_EXPLN_NONE, FC_ACTION_RETRYABLE}, 628 629 /* 0x17 */ 630 {IOERR_RCV_BUFFER_TIMEOUT, FC_PKT_LOCAL_RJT, FC_REASON_RX_BUF_TIMEOUT, 631 FC_EXPLN_NONE, FC_ACTION_RETRYABLE}, 632 633 /* 0x18 */ 634 {IOERR_LOOP_OPEN_FAILURE, FC_PKT_LOCAL_RJT, FC_REASON_FCAL_OPN_FAIL, 635 FC_EXPLN_NONE, FC_ACTION_RETRYABLE}, 636 637 /* 0x1A */ 638 {IOERR_LINK_DOWN, FC_PKT_PORT_OFFLINE, FC_REASON_OFFLINE, 639 FC_EXPLN_NONE, FC_ACTION_RETRYABLE}, 640 641 /* 0x21 */ 642 {IOERR_BAD_HOST_ADDRESS, FC_PKT_LOCAL_RJT, FC_REASON_BAD_SID, 643 FC_EXPLN_NONE, FC_ACTION_RETRYABLE}, 644 645 /* Occurs at link down */ 646 /* 0x28 */ 647 {IOERR_BUFFER_SHORTAGE, FC_PKT_PORT_OFFLINE, FC_REASON_OFFLINE, 648 FC_EXPLN_NONE, FC_ACTION_RETRYABLE}, 649 650 /* 0xF0 */ 651 {IOERR_ABORT_TIMEOUT, FC_PKT_TIMEOUT, FC_REASON_SEQ_TIMEOUT, 652 FC_EXPLN_NONE, FC_ACTION_RETRYABLE}, 653 }; 654 655 #define IOERR_MAX (sizeof (emlxs_ioerr_tbl)/sizeof (emlxs_xlat_err_t)) 656 657 658 659 emlxs_table_t emlxs_error_table[] = { 660 {IOERR_SUCCESS, "No error."}, 661 {IOERR_MISSING_CONTINUE, "Missing continue."}, 662 {IOERR_SEQUENCE_TIMEOUT, "Sequence timeout."}, 663 {IOERR_INTERNAL_ERROR, "Internal error."}, 664 {IOERR_INVALID_RPI, "Invalid RPI."}, 665 {IOERR_NO_XRI, "No XRI."}, 666 {IOERR_ILLEGAL_COMMAND, "Illegal command."}, 667 {IOERR_XCHG_DROPPED, "Exchange dropped."}, 668 {IOERR_ILLEGAL_FIELD, "Illegal field."}, 669 {IOERR_RCV_BUFFER_WAITING, "RX buffer waiting."}, 670 {IOERR_TX_DMA_FAILED, "TX DMA failed."}, 671 {IOERR_RX_DMA_FAILED, "RX DMA failed."}, 672 {IOERR_ILLEGAL_FRAME, "Illegal frame."}, 673 {IOERR_NO_RESOURCES, "No resources."}, 674 {IOERR_ILLEGAL_LENGTH, "Illegal length."}, 675 {IOERR_UNSUPPORTED_FEATURE, "Unsupported feature."}, 676 {IOERR_ABORT_IN_PROGRESS, "Abort in progess."}, 677 {IOERR_ABORT_REQUESTED, "Abort requested."}, 678 {IOERR_RCV_BUFFER_TIMEOUT, "RX buffer timeout."}, 679 {IOERR_LOOP_OPEN_FAILURE, "Loop open failed."}, 680 {IOERR_RING_RESET, "Ring reset."}, 681 {IOERR_LINK_DOWN, "Link down."}, 682 {IOERR_CORRUPTED_DATA, "Corrupted data."}, 683 {IOERR_CORRUPTED_RPI, "Corrupted RPI."}, 684 {IOERR_OUT_OF_ORDER_DATA, "Out-of-order data."}, 685 {IOERR_OUT_OF_ORDER_ACK, "Out-of-order ack."}, 686 {IOERR_DUP_FRAME, "Duplicate frame."}, 687 {IOERR_LINK_CONTROL_FRAME, "Link control frame."}, 688 {IOERR_BAD_HOST_ADDRESS, "Bad host address."}, 689 {IOERR_RCV_HDRBUF_WAITING, "RX header buffer waiting."}, 690 {IOERR_MISSING_HDR_BUFFER, "Missing header buffer."}, 691 {IOERR_MSEQ_CHAIN_CORRUPTED, "MSEQ chain corrupted."}, 692 {IOERR_ABORTMULT_REQUESTED, "Abort multiple requested."}, 693 {IOERR_BUFFER_SHORTAGE, "Buffer shortage."}, 694 {IOERR_XRIBUF_WAITING, "XRI buffer shortage"}, 695 {IOERR_XRIBUF_MISSING, "XRI buffer missing"}, 696 {IOERR_ROFFSET_INVAL, "Relative offset invalid."}, 697 {IOERR_ROFFSET_MISSING, "Relative offset missing."}, 698 {IOERR_INSUF_BUFFER, "Buffer too small."}, 699 {IOERR_MISSING_SI, "ELS frame missing SI"}, 700 {IOERR_MISSING_ES, "Exhausted burst without ES"}, 701 {IOERR_INCOMP_XFER, "Transfer incomplete."}, 702 {IOERR_ABORT_TIMEOUT, "Abort timeout."} 703 704 }; /* emlxs_error_table */ 705 706 707 emlxs_table_t emlxs_state_table[] = { 708 {IOSTAT_SUCCESS, "Success."}, 709 {IOSTAT_FCP_RSP_ERROR, "FCP response error."}, 710 {IOSTAT_REMOTE_STOP, "Remote stop."}, 711 {IOSTAT_LOCAL_REJECT, "Local reject."}, 712 {IOSTAT_NPORT_RJT, "NPort reject."}, 713 {IOSTAT_FABRIC_RJT, "Fabric reject."}, 714 {IOSTAT_NPORT_BSY, "Nport busy."}, 715 {IOSTAT_FABRIC_BSY, "Fabric busy."}, 716 {IOSTAT_INTERMED_RSP, "Intermediate response."}, 717 {IOSTAT_LS_RJT, "LS reject."}, 718 {IOSTAT_CMD_REJECT, "Cmd reject."}, 719 {IOSTAT_FCP_TGT_LENCHK, "TGT length check."}, 720 {IOSTAT_NEED_BUFF_ENTRY, "Need buffer entry."}, 721 {IOSTAT_DATA_UNDERRUN, "Data underrun."}, 722 {IOSTAT_DATA_OVERRUN, "Data overrun."}, 723 724 }; /* emlxs_state_table */ 725 726 727 #ifdef MENLO_SUPPORT 728 emlxs_table_t emlxs_menlo_cmd_table[] = { 729 {MENLO_CMD_INITIALIZE, "MENLO_INIT"}, 730 {MENLO_CMD_FW_DOWNLOAD, "MENLO_FW_DOWNLOAD"}, 731 {MENLO_CMD_READ_MEMORY, "MENLO_READ_MEM"}, 732 {MENLO_CMD_WRITE_MEMORY, "MENLO_WRITE_MEM"}, 733 {MENLO_CMD_FTE_INSERT, "MENLO_FTE_INSERT"}, 734 {MENLO_CMD_FTE_DELETE, "MENLO_FTE_DELETE"}, 735 736 {MENLO_CMD_GET_INIT, "MENLO_GET_INIT"}, 737 {MENLO_CMD_GET_CONFIG, "MENLO_GET_CONFIG"}, 738 {MENLO_CMD_GET_PORT_STATS, "MENLO_GET_PORT_STATS"}, 739 {MENLO_CMD_GET_LIF_STATS, "MENLO_GET_LIF_STATS"}, 740 {MENLO_CMD_GET_ASIC_STATS, "MENLO_GET_ASIC_STATS"}, 741 {MENLO_CMD_GET_LOG_CONFIG, "MENLO_GET_LOG_CFG"}, 742 {MENLO_CMD_GET_LOG_DATA, "MENLO_GET_LOG_DATA"}, 743 {MENLO_CMD_GET_PANIC_LOG, "MENLO_GET_PANIC_LOG"}, 744 {MENLO_CMD_GET_LB_MODE, "MENLO_GET_LB_MODE"}, 745 746 {MENLO_CMD_SET_PAUSE, "MENLO_SET_PAUSE"}, 747 {MENLO_CMD_SET_FCOE_COS, "MENLO_SET_FCOE_COS"}, 748 {MENLO_CMD_SET_UIF_PORT_TYPE, "MENLO_SET_UIF_TYPE"}, 749 750 {MENLO_CMD_DIAGNOSTICS, "MENLO_DIAGNOSTICS"}, 751 {MENLO_CMD_LOOPBACK, "MENLO_LOOPBACK"}, 752 753 {MENLO_CMD_RESET, "MENLO_RESET"}, 754 {MENLO_CMD_SET_MODE, "MENLO_SET_MODE"} 755 756 }; /* emlxs_menlo_cmd_table */ 757 758 emlxs_table_t emlxs_menlo_rsp_table[] = { 759 {MENLO_RSP_SUCCESS, "SUCCESS"}, 760 {MENLO_ERR_FAILED, "FAILED"}, 761 {MENLO_ERR_INVALID_CMD, "INVALID_CMD"}, 762 {MENLO_ERR_INVALID_CREDIT, "INVALID_CREDIT"}, 763 {MENLO_ERR_INVALID_SIZE, "INVALID_SIZE"}, 764 {MENLO_ERR_INVALID_ADDRESS, "INVALID_ADDRESS"}, 765 {MENLO_ERR_INVALID_CONTEXT, "INVALID_CONTEXT"}, 766 {MENLO_ERR_INVALID_LENGTH, "INVALID_LENGTH"}, 767 {MENLO_ERR_INVALID_TYPE, "INVALID_TYPE"}, 768 {MENLO_ERR_INVALID_DATA, "INVALID_DATA"}, 769 {MENLO_ERR_INVALID_VALUE1, "INVALID_VALUE1"}, 770 {MENLO_ERR_INVALID_VALUE2, "INVALID_VALUE2"}, 771 {MENLO_ERR_INVALID_MASK, "INVALID_MASK"}, 772 {MENLO_ERR_CHECKSUM, "CHECKSUM_ERROR"}, 773 {MENLO_ERR_UNKNOWN_FCID, "UNKNOWN_FCID"}, 774 {MENLO_ERR_UNKNOWN_WWN, "UNKNOWN_WWN"}, 775 {MENLO_ERR_BUSY, "BUSY"}, 776 777 }; /* emlxs_menlo_rsp_table */ 778 779 #endif /* MENLO_SUPPORT */ 780 781 782 emlxs_table_t emlxs_mscmd_table[] = { 783 {SLI_CT_RESPONSE_FS_ACC, "CT_ACC"}, 784 {SLI_CT_RESPONSE_FS_RJT, "CT_RJT"}, 785 {MS_GTIN, "MS_GTIN"}, 786 {MS_GIEL, "MS_GIEL"}, 787 {MS_GIET, "MS_GIET"}, 788 {MS_GDID, "MS_GDID"}, 789 {MS_GMID, "MS_GMID"}, 790 {MS_GFN, "MS_GFN"}, 791 {MS_GIELN, "MS_GIELN"}, 792 {MS_GMAL, "MS_GMAL"}, 793 {MS_GIEIL, "MS_GIEIL"}, 794 {MS_GPL, "MS_GPL"}, 795 {MS_GPT, "MS_GPT"}, 796 {MS_GPPN, "MS_GPPN"}, 797 {MS_GAPNL, "MS_GAPNL"}, 798 {MS_GPS, "MS_GPS"}, 799 {MS_GPSC, "MS_GPSC"}, 800 {MS_GATIN, "MS_GATIN"}, 801 {MS_GSES, "MS_GSES"}, 802 {MS_GPLNL, "MS_GPLNL"}, 803 {MS_GPLT, "MS_GPLT"}, 804 {MS_GPLML, "MS_GPLML"}, 805 {MS_GPAB, "MS_GPAB"}, 806 {MS_GNPL, "MS_GNPL"}, 807 {MS_GPNL, "MS_GPNL"}, 808 {MS_GPFCP, "MS_GPFCP"}, 809 {MS_GPLI, "MS_GPLI"}, 810 {MS_GNID, "MS_GNID"}, 811 {MS_RIELN, "MS_RIELN"}, 812 {MS_RPL, "MS_RPL"}, 813 {MS_RPLN, "MS_RPLN"}, 814 {MS_RPLT, "MS_RPLT"}, 815 {MS_RPLM, "MS_RPLM"}, 816 {MS_RPAB, "MS_RPAB"}, 817 {MS_RPFCP, "MS_RPFCP"}, 818 {MS_RPLI, "MS_RPLI"}, 819 {MS_DPL, "MS_DPL"}, 820 {MS_DPLN, "MS_DPLN"}, 821 {MS_DPLM, "MS_DPLM"}, 822 {MS_DPLML, "MS_DPLML"}, 823 {MS_DPLI, "MS_DPLI"}, 824 {MS_DPAB, "MS_DPAB"}, 825 {MS_DPALL, "MS_DPALL"} 826 827 }; /* emlxs_mscmd_table */ 828 829 830 emlxs_table_t emlxs_ctcmd_table[] = { 831 {SLI_CT_RESPONSE_FS_ACC, "CT_ACC"}, 832 {SLI_CT_RESPONSE_FS_RJT, "CT_RJT"}, 833 {SLI_CTNS_GA_NXT, "GA_NXT"}, 834 {SLI_CTNS_GPN_ID, "GPN_ID"}, 835 {SLI_CTNS_GNN_ID, "GNN_ID"}, 836 {SLI_CTNS_GCS_ID, "GCS_ID"}, 837 {SLI_CTNS_GFT_ID, "GFT_ID"}, 838 {SLI_CTNS_GSPN_ID, "GSPN_ID"}, 839 {SLI_CTNS_GPT_ID, "GPT_ID"}, 840 {SLI_CTNS_GID_PN, "GID_PN"}, 841 {SLI_CTNS_GID_NN, "GID_NN"}, 842 {SLI_CTNS_GIP_NN, "GIP_NN"}, 843 {SLI_CTNS_GIPA_NN, "GIPA_NN"}, 844 {SLI_CTNS_GSNN_NN, "GSNN_NN"}, 845 {SLI_CTNS_GNN_IP, "GNN_IP"}, 846 {SLI_CTNS_GIPA_IP, "GIPA_IP"}, 847 {SLI_CTNS_GID_FT, "GID_FT"}, 848 {SLI_CTNS_GID_PT, "GID_PT"}, 849 {SLI_CTNS_RPN_ID, "RPN_ID"}, 850 {SLI_CTNS_RNN_ID, "RNN_ID"}, 851 {SLI_CTNS_RCS_ID, "RCS_ID"}, 852 {SLI_CTNS_RFT_ID, "RFT_ID"}, 853 {SLI_CTNS_RSPN_ID, "RSPN_ID"}, 854 {SLI_CTNS_RPT_ID, "RPT_ID"}, 855 {SLI_CTNS_RIP_NN, "RIP_NN"}, 856 {SLI_CTNS_RIPA_NN, "RIPA_NN"}, 857 {SLI_CTNS_RSNN_NN, "RSNN_NN"}, 858 {SLI_CTNS_DA_ID, "DA_ID"}, 859 {SLI_CT_LOOPBACK, "LOOPBACK"} /* Driver special */ 860 861 }; /* emlxs_ctcmd_table */ 862 863 864 865 emlxs_table_t emlxs_rmcmd_table[] = { 866 {SLI_CT_RESPONSE_FS_ACC, "CT_ACC"}, 867 {SLI_CT_RESPONSE_FS_RJT, "CT_RJT"}, 868 {CT_OP_GSAT, "RM_GSAT"}, 869 {CT_OP_GHAT, "RM_GHAT"}, 870 {CT_OP_GPAT, "RM_GPAT"}, 871 {CT_OP_GDAT, "RM_GDAT"}, 872 {CT_OP_GPST, "RM_GPST"}, 873 {CT_OP_GDP, "RM_GDP"}, 874 {CT_OP_GDPG, "RM_GDPG"}, 875 {CT_OP_GEPS, "RM_GEPS"}, 876 {CT_OP_GLAT, "RM_GLAT"}, 877 {CT_OP_SSAT, "RM_SSAT"}, 878 {CT_OP_SHAT, "RM_SHAT"}, 879 {CT_OP_SPAT, "RM_SPAT"}, 880 {CT_OP_SDAT, "RM_SDAT"}, 881 {CT_OP_SDP, "RM_SDP"}, 882 {CT_OP_SBBS, "RM_SBBS"}, 883 {CT_OP_RPST, "RM_RPST"}, 884 {CT_OP_VFW, "RM_VFW"}, 885 {CT_OP_DFW, "RM_DFW"}, 886 {CT_OP_RES, "RM_RES"}, 887 {CT_OP_RHD, "RM_RHD"}, 888 {CT_OP_UFW, "RM_UFW"}, 889 {CT_OP_RDP, "RM_RDP"}, 890 {CT_OP_GHDR, "RM_GHDR"}, 891 {CT_OP_CHD, "RM_CHD"}, 892 {CT_OP_SSR, "RM_SSR"}, 893 {CT_OP_RSAT, "RM_RSAT"}, 894 {CT_OP_WSAT, "RM_WSAT"}, 895 {CT_OP_RSAH, "RM_RSAH"}, 896 {CT_OP_WSAH, "RM_WSAH"}, 897 {CT_OP_RACT, "RM_RACT"}, 898 {CT_OP_WACT, "RM_WACT"}, 899 {CT_OP_RKT, "RM_RKT"}, 900 {CT_OP_WKT, "RM_WKT"}, 901 {CT_OP_SSC, "RM_SSC"}, 902 {CT_OP_QHBA, "RM_QHBA"}, 903 {CT_OP_GST, "RM_GST"}, 904 {CT_OP_GFTM, "RM_GFTM"}, 905 {CT_OP_SRL, "RM_SRL"}, 906 {CT_OP_SI, "RM_SI"}, 907 {CT_OP_SRC, "RM_SRC"}, 908 {CT_OP_GPB, "RM_GPB"}, 909 {CT_OP_SPB, "RM_SPB"}, 910 {CT_OP_RPB, "RM_RPB"}, 911 {CT_OP_RAPB, "RM_RAPB"}, 912 {CT_OP_GBC, "RM_GBC"}, 913 {CT_OP_GBS, "RM_GBS"}, 914 {CT_OP_SBS, "RM_SBS"}, 915 {CT_OP_GANI, "RM_GANI"}, 916 {CT_OP_GRV, "RM_GRV"}, 917 {CT_OP_GAPBS, "RM_GAPBS"}, 918 {CT_OP_APBC, "RM_APBC"}, 919 {CT_OP_GDT, "RM_GDT"}, 920 {CT_OP_GDLMI, "RM_GDLMI"}, 921 {CT_OP_GANA, "RM_GANA"}, 922 {CT_OP_GDLV, "RM_GDLV"}, 923 {CT_OP_GWUP, "RM_GWUP"}, 924 {CT_OP_GLM, "RM_GLM"}, 925 {CT_OP_GABS, "RM_GABS"}, 926 {CT_OP_SABS, "RM_SABS"}, 927 {CT_OP_RPR, "RM_RPR"}, 928 {SLI_CT_LOOPBACK, "LOOPBACK"} /* Driver special */ 929 930 }; /* emlxs_rmcmd_table */ 931 932 933 emlxs_table_t emlxs_elscmd_table[] = { 934 {ELS_CMD_ACC, "ACC"}, 935 {ELS_CMD_LS_RJT, "LS_RJT"}, 936 {ELS_CMD_PLOGI, "PLOGI"}, 937 {ELS_CMD_FLOGI, "FLOGI"}, 938 {ELS_CMD_LOGO, "LOGO"}, 939 {ELS_CMD_ABTX, "ABTX"}, 940 {ELS_CMD_RCS, "RCS"}, 941 {ELS_CMD_RES, "RES"}, 942 {ELS_CMD_RSS, "RSS"}, 943 {ELS_CMD_RSI, "RSI"}, 944 {ELS_CMD_ESTS, "ESTS"}, 945 {ELS_CMD_ESTC, "ESTC"}, 946 {ELS_CMD_ADVC, "ADVC"}, 947 {ELS_CMD_RTV, "RTV"}, 948 {ELS_CMD_RLS, "RLS"}, 949 {ELS_CMD_ECHO, "ECHO"}, 950 {ELS_CMD_TEST, "TEST"}, 951 {ELS_CMD_RRQ, "RRQ"}, 952 {ELS_CMD_PRLI, "PRLI"}, 953 {ELS_CMD_PRLO, "PRLO"}, 954 {ELS_CMD_SCN, "SCN"}, 955 {ELS_CMD_TPLS, "TPLS"}, 956 {ELS_CMD_GPRLO, "GPRLO"}, 957 {ELS_CMD_GAID, "GAID"}, 958 {ELS_CMD_FACT, "FACT"}, 959 {ELS_CMD_FDACT, "FDACT"}, 960 {ELS_CMD_NACT, "NACT"}, 961 {ELS_CMD_NDACT, "NDACT"}, 962 {ELS_CMD_QoSR, "QoSR"}, 963 {ELS_CMD_RVCS, "RVCS"}, 964 {ELS_CMD_PDISC, "PDISC"}, 965 {ELS_CMD_FDISC, "FDISC"}, 966 {ELS_CMD_ADISC, "ADISC"}, 967 {ELS_CMD_FARP, "FARP"}, 968 {ELS_CMD_FARPR, "FARPR"}, 969 {ELS_CMD_FAN, "FAN"}, 970 {ELS_CMD_RSCN, "RSCN"}, 971 {ELS_CMD_SCR, "SCR"}, 972 {ELS_CMD_LINIT, "LINIT"}, 973 {ELS_CMD_RNID, "RNID"}, 974 {ELS_CMD_AUTH, "AUTH"} 975 976 }; /* emlxs_elscmd_table */ 977 978 979 /* 980 * 981 * Device Driver Entry Routines 982 * 983 */ 984 985 #ifdef MODSYM_SUPPORT 986 static void emlxs_fca_modclose(); 987 static int emlxs_fca_modopen(); 988 emlxs_modsym_t emlxs_modsym; /* uses emlxs_device.lock */ 989 990 static int 991 emlxs_fca_modopen() 992 { 993 int err; 994 995 if (emlxs_modsym.mod_fctl) { 996 return (0); 997 } 998 999 /* Leadville (fctl) */ 1000 err = 0; 1001 emlxs_modsym.mod_fctl = 1002 ddi_modopen("misc/fctl", KRTLD_MODE_FIRST, &err); 1003 if (!emlxs_modsym.mod_fctl) { 1004 cmn_err(CE_WARN, 1005 "?%s: misc/fctl: ddi_modopen misc/fctl failed: error=%d", 1006 DRIVER_NAME, err); 1007 1008 goto failed; 1009 } 1010 1011 err = 0; 1012 /* Check if the fctl fc_fca_attach is present */ 1013 emlxs_modsym.fc_fca_attach = 1014 (int (*)())ddi_modsym(emlxs_modsym.mod_fctl, "fc_fca_attach", 1015 &err); 1016 if ((void *)emlxs_modsym.fc_fca_attach == NULL) { 1017 cmn_err(CE_WARN, 1018 "?%s: misc/fctl: fc_fca_attach not present", DRIVER_NAME); 1019 goto failed; 1020 } 1021 1022 err = 0; 1023 /* Check if the fctl fc_fca_detach is present */ 1024 emlxs_modsym.fc_fca_detach = 1025 (int (*)())ddi_modsym(emlxs_modsym.mod_fctl, "fc_fca_detach", 1026 &err); 1027 if ((void *)emlxs_modsym.fc_fca_detach == NULL) { 1028 cmn_err(CE_WARN, 1029 "?%s: misc/fctl: fc_fca_detach not present", DRIVER_NAME); 1030 goto failed; 1031 } 1032 1033 err = 0; 1034 /* Check if the fctl fc_fca_init is present */ 1035 emlxs_modsym.fc_fca_init = 1036 (int (*)())ddi_modsym(emlxs_modsym.mod_fctl, "fc_fca_init", &err); 1037 if ((void *)emlxs_modsym.fc_fca_init == NULL) { 1038 cmn_err(CE_WARN, 1039 "?%s: misc/fctl: fc_fca_init not present", DRIVER_NAME); 1040 goto failed; 1041 } 1042 1043 return (0); 1044 1045 failed: 1046 1047 emlxs_fca_modclose(); 1048 1049 return (1); 1050 1051 1052 } /* emlxs_fca_modopen() */ 1053 1054 1055 static void 1056 emlxs_fca_modclose() 1057 { 1058 if (emlxs_modsym.mod_fctl) { 1059 (void) ddi_modclose(emlxs_modsym.mod_fctl); 1060 emlxs_modsym.mod_fctl = 0; 1061 } 1062 1063 emlxs_modsym.fc_fca_attach = NULL; 1064 emlxs_modsym.fc_fca_detach = NULL; 1065 emlxs_modsym.fc_fca_init = NULL; 1066 1067 return; 1068 1069 } /* emlxs_fca_modclose() */ 1070 1071 #endif /* MODSYM_SUPPORT */ 1072 1073 1074 1075 /* 1076 * Global driver initialization, called once when driver is loaded 1077 */ 1078 int 1079 _init(void) 1080 { 1081 int ret; 1082 char buf[64]; 1083 1084 /* 1085 * First init call for this driver, 1086 * so initialize the emlxs_dev_ctl structure. 1087 */ 1088 bzero(&emlxs_device, sizeof (emlxs_device)); 1089 1090 #ifdef MODSYM_SUPPORT 1091 bzero(&emlxs_modsym, sizeof (emlxs_modsym_t)); 1092 #endif /* MODSYM_SUPPORT */ 1093 1094 (void) sprintf(buf, "%s_device mutex", DRIVER_NAME); 1095 mutex_init(&emlxs_device.lock, buf, MUTEX_DRIVER, NULL); 1096 1097 (void) drv_getparm(LBOLT, &emlxs_device.log_timestamp); 1098 emlxs_device.drv_timestamp = ddi_get_time(); 1099 1100 for (ret = 0; ret < MAX_FC_BRDS; ret++) { 1101 emlxs_instance[ret] = (uint32_t)-1; 1102 } 1103 1104 /* 1105 * Provide for one ddiinst of the emlxs_dev_ctl structure 1106 * for each possible board in the system. 1107 */ 1108 if ((ret = ddi_soft_state_init(&emlxs_soft_state, 1109 sizeof (emlxs_hba_t), MAX_FC_BRDS)) != 0) { 1110 cmn_err(CE_WARN, 1111 "?%s: _init: ddi_soft_state_init failed. rval=%x", 1112 DRIVER_NAME, ret); 1113 1114 return (ret); 1115 } 1116 1117 #ifdef MODSYM_SUPPORT 1118 /* Open SFS */ 1119 (void) emlxs_fca_modopen(); 1120 #endif /* MODSYM_SUPPORT */ 1121 1122 /* Setup devops for SFS */ 1123 MODSYM(fc_fca_init)(&emlxs_ops); 1124 1125 if ((ret = mod_install(&emlxs_modlinkage)) != 0) { 1126 (void) ddi_soft_state_fini(&emlxs_soft_state); 1127 #ifdef MODSYM_SUPPORT 1128 /* Close SFS */ 1129 emlxs_fca_modclose(); 1130 #endif /* MODSYM_SUPPORT */ 1131 1132 return (ret); 1133 } 1134 1135 #ifdef SAN_DIAG_SUPPORT 1136 (void) sprintf(buf, "%s_sd_bucket mutex", DRIVER_NAME); 1137 mutex_init(&sd_bucket_mutex, buf, MUTEX_DRIVER, NULL); 1138 #endif /* SAN_DIAG_SUPPORT */ 1139 1140 return (ret); 1141 1142 } /* _init() */ 1143 1144 1145 /* 1146 * Called when driver is unloaded. 1147 */ 1148 int 1149 _fini(void) 1150 { 1151 int ret; 1152 1153 if ((ret = mod_remove(&emlxs_modlinkage)) != 0) { 1154 return (ret); 1155 } 1156 #ifdef MODSYM_SUPPORT 1157 /* Close SFS */ 1158 emlxs_fca_modclose(); 1159 #endif /* MODSYM_SUPPORT */ 1160 1161 /* 1162 * Destroy the soft state structure 1163 */ 1164 (void) ddi_soft_state_fini(&emlxs_soft_state); 1165 1166 /* Destroy the global device lock */ 1167 mutex_destroy(&emlxs_device.lock); 1168 1169 #ifdef SAN_DIAG_SUPPORT 1170 mutex_destroy(&sd_bucket_mutex); 1171 #endif /* SAN_DIAG_SUPPORT */ 1172 1173 return (ret); 1174 1175 } /* _fini() */ 1176 1177 1178 1179 int 1180 _info(struct modinfo *modinfop) 1181 { 1182 1183 return (mod_info(&emlxs_modlinkage, modinfop)); 1184 1185 } /* _info() */ 1186 1187 1188 /* 1189 * Attach an ddiinst of an emlx host adapter. 1190 * Allocate data structures, initialize the adapter and we're ready to fly. 1191 */ 1192 static int 1193 emlxs_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 1194 { 1195 emlxs_hba_t *hba; 1196 int ddiinst; 1197 int emlxinst; 1198 int rval; 1199 1200 switch (cmd) { 1201 case DDI_ATTACH: 1202 /* If successful this will set EMLXS_PM_IN_ATTACH */ 1203 rval = emlxs_hba_attach(dip); 1204 break; 1205 1206 case DDI_PM_RESUME: 1207 /* This will resume the driver */ 1208 rval = emlxs_pm_raise_power(dip); 1209 break; 1210 1211 case DDI_RESUME: 1212 /* This will resume the driver */ 1213 rval = emlxs_hba_resume(dip); 1214 break; 1215 1216 default: 1217 rval = DDI_FAILURE; 1218 } 1219 1220 if (rval == DDI_SUCCESS) { 1221 ddiinst = ddi_get_instance(dip); 1222 emlxinst = emlxs_get_instance(ddiinst); 1223 hba = emlxs_device.hba[emlxinst]; 1224 1225 if ((hba != NULL) && (hba != (emlxs_hba_t *)-1)) { 1226 1227 /* Enable driver dump feature */ 1228 mutex_enter(&EMLXS_PORT_LOCK); 1229 hba->flag |= FC_DUMP_SAFE; 1230 mutex_exit(&EMLXS_PORT_LOCK); 1231 } 1232 } 1233 1234 return (rval); 1235 1236 } /* emlxs_attach() */ 1237 1238 1239 /* 1240 * Detach/prepare driver to unload (see detach(9E)). 1241 */ 1242 static int 1243 emlxs_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 1244 { 1245 emlxs_hba_t *hba; 1246 emlxs_port_t *port; 1247 int ddiinst; 1248 int emlxinst; 1249 int rval; 1250 1251 ddiinst = ddi_get_instance(dip); 1252 emlxinst = emlxs_get_instance(ddiinst); 1253 hba = emlxs_device.hba[emlxinst]; 1254 1255 if (hba == NULL) { 1256 cmn_err(CE_WARN, "?%s: Detach: NULL device.", DRIVER_NAME); 1257 1258 return (DDI_FAILURE); 1259 } 1260 1261 if (hba == (emlxs_hba_t *)-1) { 1262 cmn_err(CE_WARN, "?%s: Detach: Device attach failed.", 1263 DRIVER_NAME); 1264 1265 return (DDI_FAILURE); 1266 } 1267 1268 port = &PPORT; 1269 rval = DDI_SUCCESS; 1270 1271 /* Check driver dump */ 1272 mutex_enter(&EMLXS_PORT_LOCK); 1273 1274 if (hba->flag & FC_DUMP_ACTIVE) { 1275 mutex_exit(&EMLXS_PORT_LOCK); 1276 1277 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_detach_failed_msg, 1278 "emlxs_detach: Driver busy. Driver dump active."); 1279 1280 return (DDI_FAILURE); 1281 } 1282 1283 #ifdef SFCT_SUPPORT 1284 if (port->tgt_mode && ((port->fct_flags & FCT_STATE_PORT_ONLINE) || 1285 (port->fct_flags & FCT_STATE_NOT_ACKED))) { 1286 mutex_exit(&EMLXS_PORT_LOCK); 1287 1288 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_detach_failed_msg, 1289 "emlxs_detach: Driver busy. Target mode active."); 1290 1291 return (DDI_FAILURE); 1292 } 1293 #endif /* SFCT_SUPPORT */ 1294 1295 if (port->ini_mode && (port->flag & EMLXS_PORT_BOUND)) { 1296 mutex_exit(&EMLXS_PORT_LOCK); 1297 1298 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_detach_failed_msg, 1299 "emlxs_detach: Driver busy. Initiator mode active."); 1300 1301 return (DDI_FAILURE); 1302 } 1303 1304 hba->flag &= ~FC_DUMP_SAFE; 1305 1306 mutex_exit(&EMLXS_PORT_LOCK); 1307 1308 switch (cmd) { 1309 case DDI_DETACH: 1310 1311 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_detach_debug_msg, 1312 "DDI_DETACH"); 1313 1314 rval = emlxs_hba_detach(dip); 1315 1316 if (rval != DDI_SUCCESS) { 1317 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_detach_failed_msg, 1318 "Unable to detach."); 1319 } 1320 break; 1321 1322 1323 case DDI_PM_SUSPEND: 1324 1325 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_detach_debug_msg, 1326 "DDI_PM_SUSPEND"); 1327 1328 /* This will suspend the driver */ 1329 rval = emlxs_pm_lower_power(dip); 1330 1331 if (rval != DDI_SUCCESS) { 1332 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_detach_failed_msg, 1333 "Unable to lower power."); 1334 } 1335 1336 break; 1337 1338 1339 case DDI_SUSPEND: 1340 1341 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_detach_debug_msg, 1342 "DDI_SUSPEND"); 1343 1344 /* Suspend the driver */ 1345 rval = emlxs_hba_suspend(dip); 1346 1347 if (rval != DDI_SUCCESS) { 1348 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_detach_failed_msg, 1349 "Unable to suspend driver."); 1350 } 1351 break; 1352 1353 1354 default: 1355 cmn_err(CE_WARN, "?%s: Detach: Unknown cmd received. cmd=%x", 1356 DRIVER_NAME, cmd); 1357 rval = DDI_FAILURE; 1358 } 1359 1360 if (rval == DDI_FAILURE) { 1361 /* Re-Enable driver dump feature */ 1362 mutex_enter(&EMLXS_PORT_LOCK); 1363 hba->flag |= FC_DUMP_SAFE; 1364 mutex_exit(&EMLXS_PORT_LOCK); 1365 } 1366 1367 return (rval); 1368 1369 } /* emlxs_detach() */ 1370 1371 1372 /* EMLXS_PORT_LOCK must be held when calling this */ 1373 extern void 1374 emlxs_port_init(emlxs_port_t *port) 1375 { 1376 emlxs_hba_t *hba = HBA; 1377 1378 /* Initialize the base node */ 1379 bzero((caddr_t)&port->node_base, sizeof (NODELIST)); 1380 port->node_base.nlp_Rpi = 0; 1381 port->node_base.nlp_DID = 0xffffff; 1382 port->node_base.nlp_list_next = NULL; 1383 port->node_base.nlp_list_prev = NULL; 1384 port->node_base.nlp_active = 1; 1385 port->node_base.nlp_base = 1; 1386 port->node_count = 0; 1387 1388 if (!(port->flag & EMLXS_PORT_ENABLE)) { 1389 uint8_t dummy_wwn[8] = 1390 { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; 1391 1392 bcopy((caddr_t)dummy_wwn, (caddr_t)&port->wwnn, 1393 sizeof (NAME_TYPE)); 1394 bcopy((caddr_t)dummy_wwn, (caddr_t)&port->wwpn, 1395 sizeof (NAME_TYPE)); 1396 } 1397 1398 if (!(port->flag & EMLXS_PORT_CONFIG)) { 1399 (void) strncpy((caddr_t)port->snn, (caddr_t)hba->snn, 256); 1400 (void) strncpy((caddr_t)port->spn, (caddr_t)hba->spn, 256); 1401 } 1402 1403 bcopy((caddr_t)&hba->sparam, (caddr_t)&port->sparam, 1404 sizeof (SERV_PARM)); 1405 bcopy((caddr_t)&port->wwnn, (caddr_t)&port->sparam.nodeName, 1406 sizeof (NAME_TYPE)); 1407 bcopy((caddr_t)&port->wwpn, (caddr_t)&port->sparam.portName, 1408 sizeof (NAME_TYPE)); 1409 1410 return; 1411 1412 } /* emlxs_port_init() */ 1413 1414 1415 1416 /* 1417 * emlxs_bind_port 1418 * 1419 * Arguments: 1420 * 1421 * dip: the dev_info pointer for the ddiinst 1422 * port_info: pointer to info handed back to the transport 1423 * bind_info: pointer to info from the transport 1424 * 1425 * Return values: a port handle for this port, NULL for failure 1426 * 1427 */ 1428 static opaque_t 1429 emlxs_bind_port(dev_info_t *dip, fc_fca_port_info_t *port_info, 1430 fc_fca_bind_info_t *bind_info) 1431 { 1432 emlxs_hba_t *hba; 1433 emlxs_port_t *port; 1434 emlxs_port_t *vport; 1435 int ddiinst; 1436 emlxs_vpd_t *vpd; 1437 emlxs_config_t *cfg; 1438 char *dptr; 1439 char buffer[16]; 1440 uint32_t length; 1441 uint32_t len; 1442 char topology[32]; 1443 char linkspeed[32]; 1444 1445 ddiinst = ddi_get_instance(dip); 1446 hba = ddi_get_soft_state(emlxs_soft_state, ddiinst); 1447 port = &PPORT; 1448 1449 ddiinst = hba->ddiinst; 1450 vpd = &VPD; 1451 cfg = &CFG; 1452 1453 mutex_enter(&EMLXS_PORT_LOCK); 1454 1455 if (bind_info->port_num > 0) { 1456 #if (EMLXS_MODREV >= EMLXS_MODREV5) 1457 if (!(hba->flag & FC_NPIV_ENABLED) || 1458 !(bind_info->port_npiv) || 1459 (bind_info->port_num > hba->vpi_max)) 1460 #elif (EMLXS_MODREV >= EMLXS_MODREV3) 1461 if (!(hba->flag & FC_NPIV_ENABLED) || 1462 (bind_info->port_num > hba->vpi_high)) 1463 #endif 1464 { 1465 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 1466 "emlxs_port_bind: Port %d not supported.", 1467 bind_info->port_num); 1468 1469 mutex_exit(&EMLXS_PORT_LOCK); 1470 1471 port_info->pi_error = FC_OUTOFBOUNDS; 1472 return (NULL); 1473 } 1474 } 1475 1476 /* Get true port pointer */ 1477 port = &VPORT(bind_info->port_num); 1478 1479 if (port->tgt_mode) { 1480 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 1481 "emlxs_port_bind: Port %d is in target mode.", 1482 bind_info->port_num); 1483 1484 mutex_exit(&EMLXS_PORT_LOCK); 1485 1486 port_info->pi_error = FC_OUTOFBOUNDS; 1487 return (NULL); 1488 } 1489 1490 if (!port->ini_mode) { 1491 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 1492 "emlxs_port_bind: Port %d is not in initiator mode.", 1493 bind_info->port_num); 1494 1495 mutex_exit(&EMLXS_PORT_LOCK); 1496 1497 port_info->pi_error = FC_OUTOFBOUNDS; 1498 return (NULL); 1499 } 1500 1501 /* Make sure the port is not already bound to the transport */ 1502 if (port->flag & EMLXS_PORT_BOUND) { 1503 1504 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 1505 "emlxs_port_bind: Port %d already bound. flag=%x", 1506 bind_info->port_num, port->flag); 1507 1508 mutex_exit(&EMLXS_PORT_LOCK); 1509 1510 port_info->pi_error = FC_ALREADY; 1511 return (NULL); 1512 } 1513 1514 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 1515 "fca_bind_port: Port %d: port_info=%p bind_info=%p", 1516 bind_info->port_num, port_info, bind_info); 1517 1518 #if (EMLXS_MODREV >= EMLXS_MODREV5) 1519 if (bind_info->port_npiv) { 1520 bcopy((caddr_t)&bind_info->port_nwwn, (caddr_t)&port->wwnn, 1521 sizeof (NAME_TYPE)); 1522 bcopy((caddr_t)&bind_info->port_pwwn, (caddr_t)&port->wwpn, 1523 sizeof (NAME_TYPE)); 1524 if (port->snn[0] == 0) { 1525 (void) strncpy((caddr_t)port->snn, (caddr_t)hba->snn, 1526 256); 1527 } 1528 1529 if (port->spn[0] == 0) { 1530 (void) sprintf((caddr_t)port->spn, "%s VPort-%d", 1531 (caddr_t)hba->spn, port->vpi); 1532 } 1533 port->flag |= (EMLXS_PORT_CONFIG | EMLXS_PORT_ENABLE); 1534 } 1535 #endif /* >= EMLXS_MODREV5 */ 1536 1537 /* 1538 * Restricted login should apply both physical and 1539 * virtual ports. 1540 */ 1541 if (cfg[CFG_VPORT_RESTRICTED].current) { 1542 port->flag |= EMLXS_PORT_RESTRICTED; 1543 } 1544 1545 /* Perform generic port initialization */ 1546 emlxs_port_init(port); 1547 1548 /* Perform SFS specific initialization */ 1549 port->ulp_handle = bind_info->port_handle; 1550 port->ulp_statec_cb = bind_info->port_statec_cb; 1551 port->ulp_unsol_cb = bind_info->port_unsol_cb; 1552 port->ub_count = EMLXS_UB_TOKEN_OFFSET; 1553 port->ub_pool = NULL; 1554 1555 /* Update the port info structure */ 1556 1557 /* Set the topology and state */ 1558 if ((hba->state < FC_LINK_UP) || 1559 ((port->vpi > 0) && (!(port->flag & EMLXS_PORT_ENABLE) || 1560 !(hba->flag & FC_NPIV_SUPPORTED)))) { 1561 port_info->pi_port_state = FC_STATE_OFFLINE; 1562 port_info->pi_topology = FC_TOP_UNKNOWN; 1563 } 1564 #ifdef MENLO_SUPPORT 1565 else if (hba->flag & FC_MENLO_MODE) { 1566 port_info->pi_port_state = FC_STATE_OFFLINE; 1567 port_info->pi_topology = FC_TOP_UNKNOWN; 1568 } 1569 #endif /* MENLO_SUPPORT */ 1570 else { 1571 /* Check for loop topology */ 1572 if (hba->topology == TOPOLOGY_LOOP) { 1573 port_info->pi_port_state = FC_STATE_LOOP; 1574 (void) strcpy(topology, ", loop"); 1575 1576 if (hba->flag & FC_FABRIC_ATTACHED) { 1577 port_info->pi_topology = FC_TOP_PUBLIC_LOOP; 1578 } else { 1579 port_info->pi_topology = FC_TOP_PRIVATE_LOOP; 1580 } 1581 } else { 1582 port_info->pi_topology = FC_TOP_FABRIC; 1583 port_info->pi_port_state = FC_STATE_ONLINE; 1584 (void) strcpy(topology, ", fabric"); 1585 } 1586 1587 /* Set the link speed */ 1588 switch (hba->linkspeed) { 1589 case 0: 1590 (void) strcpy(linkspeed, "Gb"); 1591 port_info->pi_port_state |= FC_STATE_1GBIT_SPEED; 1592 break; 1593 1594 case LA_1GHZ_LINK: 1595 (void) strcpy(linkspeed, "1Gb"); 1596 port_info->pi_port_state |= FC_STATE_1GBIT_SPEED; 1597 break; 1598 case LA_2GHZ_LINK: 1599 (void) strcpy(linkspeed, "2Gb"); 1600 port_info->pi_port_state |= FC_STATE_2GBIT_SPEED; 1601 break; 1602 case LA_4GHZ_LINK: 1603 (void) strcpy(linkspeed, "4Gb"); 1604 port_info->pi_port_state |= FC_STATE_4GBIT_SPEED; 1605 break; 1606 case LA_8GHZ_LINK: 1607 (void) strcpy(linkspeed, "8Gb"); 1608 port_info->pi_port_state |= FC_STATE_8GBIT_SPEED; 1609 break; 1610 case LA_10GHZ_LINK: 1611 (void) strcpy(linkspeed, "10Gb"); 1612 port_info->pi_port_state |= FC_STATE_10GBIT_SPEED; 1613 break; 1614 default: 1615 (void) sprintf(linkspeed, "unknown(0x%x)", 1616 hba->linkspeed); 1617 break; 1618 } 1619 1620 /* Adjusting port context for link up messages */ 1621 vport = port; 1622 port = &PPORT; 1623 if (vport->vpi == 0) { 1624 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_link_up_msg, "%s%s", 1625 linkspeed, topology); 1626 } else if (!(hba->flag & FC_NPIV_LINKUP)) { 1627 hba->flag |= FC_NPIV_LINKUP; 1628 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_npiv_link_up_msg, 1629 "%s%s", linkspeed, topology); 1630 } 1631 port = vport; 1632 1633 } 1634 1635 /* Save initial state */ 1636 port->ulp_statec = port_info->pi_port_state; 1637 1638 /* 1639 * The transport needs a copy of the common service parameters 1640 * for this port. The transport can get any updates through 1641 * the getcap entry point. 1642 */ 1643 bcopy((void *) &port->sparam, 1644 (void *) &port_info->pi_login_params.common_service, 1645 sizeof (SERV_PARM)); 1646 1647 #if (EMLXS_MODREVX == EMLXS_MODREV2X) 1648 /* Swap the service parameters for ULP */ 1649 emlxs_swap_service_params((SERV_PARM *)&port_info->pi_login_params. 1650 common_service); 1651 #endif /* EMLXS_MODREV2X */ 1652 1653 port_info->pi_login_params.common_service.btob_credit = 0xffff; 1654 1655 bcopy((void *) &port->wwnn, 1656 (void *) &port_info->pi_login_params.node_ww_name, 1657 sizeof (NAME_TYPE)); 1658 1659 bcopy((void *) &port->wwpn, 1660 (void *) &port_info->pi_login_params.nport_ww_name, 1661 sizeof (NAME_TYPE)); 1662 1663 /* 1664 * We need to turn off CLASS2 support. 1665 * Otherwise, FC transport will use CLASS2 as default class 1666 * and never try with CLASS3. 1667 */ 1668 #if (EMLXS_MODREV >= EMLXS_MODREV3) 1669 #if (EMLXS_MODREVX >= EMLXS_MODREV3X) 1670 if ((port_info->pi_login_params.class_1.class_opt) & 0x0080) { 1671 port_info->pi_login_params.class_1.class_opt &= ~0x0080; 1672 } 1673 1674 if ((port_info->pi_login_params.class_2.class_opt) & 0x0080) { 1675 port_info->pi_login_params.class_2.class_opt &= ~0x0080; 1676 } 1677 #else /* EMLXS_SPARC or EMLXS_MODREV2X */ 1678 if ((port_info->pi_login_params.class_1.class_opt) & 0x8000) { 1679 port_info->pi_login_params.class_1.class_opt &= ~0x8000; 1680 } 1681 1682 if ((port_info->pi_login_params.class_2.class_opt) & 0x8000) { 1683 port_info->pi_login_params.class_2.class_opt &= ~0x8000; 1684 } 1685 #endif /* >= EMLXS_MODREV3X */ 1686 #endif /* >= EMLXS_MODREV3 */ 1687 1688 1689 #if (EMLXS_MODREV <= EMLXS_MODREV2) 1690 if ((port_info->pi_login_params.class_1.data[0]) & 0x80) { 1691 port_info->pi_login_params.class_1.data[0] &= ~0x80; 1692 } 1693 1694 if ((port_info->pi_login_params.class_2.data[0]) & 0x80) { 1695 port_info->pi_login_params.class_2.data[0] &= ~0x80; 1696 } 1697 #endif /* <= EMLXS_MODREV2 */ 1698 1699 /* Additional parameters */ 1700 port_info->pi_s_id.port_id = port->did; 1701 port_info->pi_s_id.priv_lilp_posit = 0; 1702 port_info->pi_hard_addr.hard_addr = cfg[CFG_ASSIGN_ALPA].current; 1703 1704 /* Initialize the RNID parameters */ 1705 bzero(&port_info->pi_rnid_params, sizeof (port_info->pi_rnid_params)); 1706 1707 (void) sprintf((char *)port_info->pi_rnid_params.params.global_id, 1708 "%01x%01x%02x%02x%02x%02x%02x%02x%02x", hba->wwpn.nameType, 1709 hba->wwpn.IEEEextMsn, hba->wwpn.IEEEextLsb, hba->wwpn.IEEE[0], 1710 hba->wwpn.IEEE[1], hba->wwpn.IEEE[2], hba->wwpn.IEEE[3], 1711 hba->wwpn.IEEE[4], hba->wwpn.IEEE[5]); 1712 1713 port_info->pi_rnid_params.params.unit_type = RNID_HBA; 1714 port_info->pi_rnid_params.params.port_id = port->did; 1715 port_info->pi_rnid_params.params.ip_version = RNID_IPV4; 1716 1717 /* Initialize the port attributes */ 1718 bzero(&port_info->pi_attrs, sizeof (port_info->pi_attrs)); 1719 1720 (void) strcpy(port_info->pi_attrs.manufacturer, "Emulex"); 1721 1722 port_info->pi_rnid_params.status = FC_SUCCESS; 1723 1724 (void) strcpy(port_info->pi_attrs.serial_number, vpd->serial_num); 1725 1726 (void) sprintf(port_info->pi_attrs.firmware_version, "%s (%s)", 1727 vpd->fw_version, vpd->fw_label); 1728 1729 #ifdef EMLXS_I386 1730 (void) sprintf(port_info->pi_attrs.option_rom_version, 1731 "Boot:%s", vpd->boot_version); 1732 #else /* EMLXS_SPARC */ 1733 (void) sprintf(port_info->pi_attrs.option_rom_version, 1734 "Boot:%s Fcode:%s", vpd->boot_version, vpd->fcode_version); 1735 #endif /* EMLXS_I386 */ 1736 1737 1738 (void) sprintf(port_info->pi_attrs.driver_version, "%s (%s)", 1739 emlxs_version, emlxs_revision); 1740 1741 (void) strcpy(port_info->pi_attrs.driver_name, DRIVER_NAME); 1742 1743 port_info->pi_attrs.vendor_specific_id = 1744 ((hba->model_info.device_id << 16) | PCI_VENDOR_ID_EMULEX); 1745 1746 port_info->pi_attrs.supported_cos = LE_SWAP32(FC_NS_CLASS3); 1747 1748 port_info->pi_attrs.max_frame_size = FF_FRAME_SIZE; 1749 1750 #if (EMLXS_MODREV >= EMLXS_MODREV5) 1751 1752 port_info->pi_rnid_params.params.num_attached = 0; 1753 1754 /* 1755 * Copy the serial number string (right most 16 chars) into the right 1756 * justified local buffer 1757 */ 1758 bzero(buffer, sizeof (buffer)); 1759 length = strlen(vpd->serial_num); 1760 len = (length > 16) ? 16 : length; 1761 bcopy(&vpd->serial_num[(length - len)], 1762 &buffer[(sizeof (buffer) - len)], len); 1763 1764 port_info->pi_attrs.hba_fru_details.port_index = vpd->port_index; 1765 1766 #endif /* >= EMLXS_MODREV5 */ 1767 1768 #if ((EMLXS_MODREV == EMLXS_MODREV3) || (EMLX_MODREV == EMLXS_MODREV4)) 1769 1770 port_info->pi_rnid_params.params.num_attached = 0; 1771 1772 if (hba->flag & FC_NPIV_ENABLED) { 1773 uint8_t byte; 1774 uint8_t *wwpn; 1775 uint32_t i; 1776 uint32_t j; 1777 1778 /* Copy the WWPN as a string into the local buffer */ 1779 wwpn = (uint8_t *)&hba->wwpn; 1780 for (i = 0; i < 16; i++) { 1781 byte = *wwpn++; 1782 j = ((byte & 0xf0) >> 4); 1783 if (j <= 9) { 1784 buffer[i] = 1785 (char)((uint8_t)'0' + (uint8_t)j); 1786 } else { 1787 buffer[i] = 1788 (char)((uint8_t)'A' + (uint8_t)(j - 1789 10)); 1790 } 1791 1792 i++; 1793 j = (byte & 0xf); 1794 if (j <= 9) { 1795 buffer[i] = 1796 (char)((uint8_t)'0' + (uint8_t)j); 1797 } else { 1798 buffer[i] = 1799 (char)((uint8_t)'A' + (uint8_t)(j - 1800 10)); 1801 } 1802 } 1803 1804 port_info->pi_attrs.hba_fru_details.port_index = port->vpi; 1805 } else { 1806 /* Copy the serial number string (right most 16 chars) */ 1807 /* into the right justified local buffer */ 1808 bzero(buffer, sizeof (buffer)); 1809 length = strlen(vpd->serial_num); 1810 len = (length > 16) ? 16 : length; 1811 bcopy(&vpd->serial_num[(length - len)], 1812 &buffer[(sizeof (buffer) - len)], len); 1813 1814 port_info->pi_attrs.hba_fru_details.port_index = 1815 vpd->port_index; 1816 } 1817 1818 #endif /* == EMLXS_MODREV3 || EMLXS_MODREV4 */ 1819 1820 #if (EMLXS_MODREV >= EMLXS_MODREV3) 1821 1822 dptr = (char *)&port_info->pi_attrs.hba_fru_details.high; 1823 dptr[0] = buffer[0]; 1824 dptr[1] = buffer[1]; 1825 dptr[2] = buffer[2]; 1826 dptr[3] = buffer[3]; 1827 dptr[4] = buffer[4]; 1828 dptr[5] = buffer[5]; 1829 dptr[6] = buffer[6]; 1830 dptr[7] = buffer[7]; 1831 port_info->pi_attrs.hba_fru_details.high = 1832 LE_SWAP64(port_info->pi_attrs.hba_fru_details.high); 1833 1834 dptr = (char *)&port_info->pi_attrs.hba_fru_details.low; 1835 dptr[0] = buffer[8]; 1836 dptr[1] = buffer[9]; 1837 dptr[2] = buffer[10]; 1838 dptr[3] = buffer[11]; 1839 dptr[4] = buffer[12]; 1840 dptr[5] = buffer[13]; 1841 dptr[6] = buffer[14]; 1842 dptr[7] = buffer[15]; 1843 port_info->pi_attrs.hba_fru_details.low = 1844 LE_SWAP64(port_info->pi_attrs.hba_fru_details.low); 1845 1846 #endif /* >= EMLXS_MODREV3 */ 1847 1848 #if (EMLXS_MODREV >= EMLXS_MODREV4) 1849 (void) strncpy((caddr_t)port_info->pi_attrs.sym_node_name, 1850 (caddr_t)port->snn, FCHBA_SYMB_NAME_LEN); 1851 (void) strncpy((caddr_t)port_info->pi_attrs.sym_port_name, 1852 (caddr_t)port->spn, FCHBA_SYMB_NAME_LEN); 1853 #endif /* >= EMLXS_MODREV4 */ 1854 1855 (void) sprintf(port_info->pi_attrs.hardware_version, "%x", vpd->biuRev); 1856 1857 /* Set the hba speed limit */ 1858 if (vpd->link_speed & LMT_10GB_CAPABLE) { 1859 port_info->pi_attrs.supported_speed |= 1860 FC_HBA_PORTSPEED_10GBIT; 1861 } 1862 if (vpd->link_speed & LMT_8GB_CAPABLE) { 1863 port_info->pi_attrs.supported_speed |= FC_HBA_PORTSPEED_8GBIT; 1864 } 1865 if (vpd->link_speed & LMT_4GB_CAPABLE) { 1866 port_info->pi_attrs.supported_speed |= FC_HBA_PORTSPEED_4GBIT; 1867 } 1868 if (vpd->link_speed & LMT_2GB_CAPABLE) { 1869 port_info->pi_attrs.supported_speed |= FC_HBA_PORTSPEED_2GBIT; 1870 } 1871 if (vpd->link_speed & LMT_1GB_CAPABLE) { 1872 port_info->pi_attrs.supported_speed |= FC_HBA_PORTSPEED_1GBIT; 1873 } 1874 1875 /* Set the hba model info */ 1876 (void) strcpy(port_info->pi_attrs.model, hba->model_info.model); 1877 (void) strcpy(port_info->pi_attrs.model_description, 1878 hba->model_info.model_desc); 1879 1880 1881 /* Log information */ 1882 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 1883 "Bind info: port_num = %d", bind_info->port_num); 1884 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 1885 "Bind info: port_handle = %p", bind_info->port_handle); 1886 1887 #if (EMLXS_MODREV >= EMLXS_MODREV5) 1888 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 1889 "Bind info: port_npiv = %d", bind_info->port_npiv); 1890 #endif /* >= EMLXS_MODREV5 */ 1891 1892 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 1893 "Port info: pi_topology = %x", port_info->pi_topology); 1894 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 1895 "Port info: pi_error = %x", port_info->pi_error); 1896 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 1897 "Port info: pi_port_state = %x", port_info->pi_port_state); 1898 1899 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 1900 "Port info: port_id = %x", port_info->pi_s_id.port_id); 1901 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 1902 "Port info: priv_lilp_posit = %x", 1903 port_info->pi_s_id.priv_lilp_posit); 1904 1905 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 1906 "Port info: hard_addr = %x", 1907 port_info->pi_hard_addr.hard_addr); 1908 1909 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 1910 "Port info: rnid.status = %x", 1911 port_info->pi_rnid_params.status); 1912 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 1913 "Port info: rnid.global_id = %16s", 1914 port_info->pi_rnid_params.params.global_id); 1915 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 1916 "Port info: rnid.unit_type = %x", 1917 port_info->pi_rnid_params.params.unit_type); 1918 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 1919 "Port info: rnid.port_id = %x", 1920 port_info->pi_rnid_params.params.port_id); 1921 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 1922 "Port info: rnid.num_attached = %x", 1923 port_info->pi_rnid_params.params.num_attached); 1924 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 1925 "Port info: rnid.ip_version = %x", 1926 port_info->pi_rnid_params.params.ip_version); 1927 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 1928 "Port info: rnid.udp_port = %x", 1929 port_info->pi_rnid_params.params.udp_port); 1930 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 1931 "Port info: rnid.ip_addr = %16s", 1932 port_info->pi_rnid_params.params.ip_addr); 1933 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 1934 "Port info: rnid.spec_id_resv = %x", 1935 port_info->pi_rnid_params.params.specific_id_resv); 1936 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 1937 "Port info: rnid.topo_flags = %x", 1938 port_info->pi_rnid_params.params.topo_flags); 1939 1940 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 1941 "Port info: manufacturer = %s", 1942 port_info->pi_attrs.manufacturer); 1943 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 1944 "Port info: serial_num = %s", 1945 port_info->pi_attrs.serial_number); 1946 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 1947 "Port info: model = %s", port_info->pi_attrs.model); 1948 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 1949 "Port info: model_description = %s", 1950 port_info->pi_attrs.model_description); 1951 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 1952 "Port info: hardware_version = %s", 1953 port_info->pi_attrs.hardware_version); 1954 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 1955 "Port info: driver_version = %s", 1956 port_info->pi_attrs.driver_version); 1957 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 1958 "Port info: option_rom_version = %s", 1959 port_info->pi_attrs.option_rom_version); 1960 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 1961 "Port info: firmware_version = %s", 1962 port_info->pi_attrs.firmware_version); 1963 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 1964 "Port info: driver_name = %s", 1965 port_info->pi_attrs.driver_name); 1966 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 1967 "Port info: vendor_specific_id = %x", 1968 port_info->pi_attrs.vendor_specific_id); 1969 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 1970 "Port info: supported_cos = %x", 1971 port_info->pi_attrs.supported_cos); 1972 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 1973 "Port info: supported_speed = %x", 1974 port_info->pi_attrs.supported_speed); 1975 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 1976 "Port info: max_frame_size = %x", 1977 port_info->pi_attrs.max_frame_size); 1978 1979 #if (EMLXS_MODREV >= EMLXS_MODREV3) 1980 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 1981 "Port info: fru_port_index = %x", 1982 port_info->pi_attrs.hba_fru_details.port_index); 1983 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 1984 "Port info: fru_high = %llx", 1985 port_info->pi_attrs.hba_fru_details.high); 1986 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 1987 "Port info: fru_low = %llx", 1988 port_info->pi_attrs.hba_fru_details.low); 1989 #endif /* >= EMLXS_MODREV3 */ 1990 1991 #if (EMLXS_MODREV >= EMLXS_MODREV4) 1992 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 1993 "Port info: sym_node_name = %s", 1994 port_info->pi_attrs.sym_node_name); 1995 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 1996 "Port info: sym_port_name = %s", 1997 port_info->pi_attrs.sym_port_name); 1998 #endif /* >= EMLXS_MODREV4 */ 1999 2000 /* Set the bound flag */ 2001 port->flag |= EMLXS_PORT_BOUND; 2002 hba->num_of_ports++; 2003 2004 mutex_exit(&EMLXS_PORT_LOCK); 2005 2006 return ((opaque_t)port); 2007 2008 } /* emlxs_bind_port() */ 2009 2010 2011 static void 2012 emlxs_unbind_port(opaque_t fca_port_handle) 2013 { 2014 emlxs_port_t *port = (emlxs_port_t *)fca_port_handle; 2015 emlxs_hba_t *hba = HBA; 2016 2017 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 2018 "fca_unbind_port: port=%p", port); 2019 2020 /* Destroy & flush all port nodes, if they exist */ 2021 if (port->node_count) { 2022 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 2023 (void) emlxs_sli4_unreg_all_rpi_by_port(port); 2024 } else { 2025 (void) emlxs_mb_unreg_rpi(port, 0xffff, 0, 0, 0); 2026 } 2027 } 2028 2029 #if (EMLXS_MODREV >= EMLXS_MODREV5) 2030 if ((hba->flag & FC_NPIV_ENABLED) && 2031 (port->flag & (EMLXS_PORT_CONFIG | EMLXS_PORT_ENABLE))) { 2032 (void) emlxs_mb_unreg_vpi(port); 2033 } 2034 #endif 2035 2036 mutex_enter(&EMLXS_PORT_LOCK); 2037 2038 if (!(port->flag & EMLXS_PORT_BOUND)) { 2039 mutex_exit(&EMLXS_PORT_LOCK); 2040 return; 2041 } 2042 2043 port->flag &= ~EMLXS_PORT_BOUND; 2044 hba->num_of_ports--; 2045 2046 port->ulp_handle = 0; 2047 port->ulp_statec = FC_STATE_OFFLINE; 2048 port->ulp_statec_cb = NULL; 2049 port->ulp_unsol_cb = NULL; 2050 2051 mutex_exit(&EMLXS_PORT_LOCK); 2052 2053 return; 2054 2055 } /* emlxs_unbind_port() */ 2056 2057 2058 /*ARGSUSED*/ 2059 extern int 2060 emlxs_pkt_init(opaque_t fca_port_handle, fc_packet_t *pkt, int32_t sleep) 2061 { 2062 emlxs_port_t *port = (emlxs_port_t *)fca_port_handle; 2063 emlxs_hba_t *hba = HBA; 2064 emlxs_buf_t *sbp = (emlxs_buf_t *)pkt->pkt_fca_private; 2065 2066 if (!sbp) { 2067 return (FC_FAILURE); 2068 } 2069 bzero((void *)sbp, sizeof (emlxs_buf_t)); 2070 2071 mutex_init(&sbp->mtx, NULL, MUTEX_DRIVER, (void *)hba->intr_arg); 2072 sbp->pkt_flags = 2073 PACKET_VALID | PACKET_ULP_OWNED; 2074 sbp->port = port; 2075 sbp->pkt = pkt; 2076 sbp->iocbq.sbp = sbp; 2077 2078 return (FC_SUCCESS); 2079 2080 } /* emlxs_pkt_init() */ 2081 2082 2083 2084 static void 2085 emlxs_initialize_pkt(emlxs_port_t *port, emlxs_buf_t *sbp) 2086 { 2087 emlxs_hba_t *hba = HBA; 2088 emlxs_config_t *cfg = &CFG; 2089 fc_packet_t *pkt = PRIV2PKT(sbp); 2090 uint32_t *iptr; 2091 2092 mutex_enter(&sbp->mtx); 2093 2094 /* Reinitialize */ 2095 sbp->pkt = pkt; 2096 sbp->port = port; 2097 sbp->bmp = NULL; 2098 sbp->pkt_flags &= (PACKET_VALID | PACKET_ALLOCATED); 2099 sbp->iotag = 0; 2100 sbp->ticks = 0; 2101 sbp->abort_attempts = 0; 2102 sbp->fpkt = NULL; 2103 sbp->flush_count = 0; 2104 sbp->next = NULL; 2105 2106 if (!port->tgt_mode) { 2107 sbp->node = NULL; 2108 sbp->did = 0; 2109 sbp->lun = 0; 2110 sbp->class = 0; 2111 sbp->class = 0; 2112 sbp->channel = NULL; 2113 } 2114 2115 bzero((void *)&sbp->iocbq, sizeof (IOCBQ)); 2116 sbp->iocbq.sbp = sbp; 2117 2118 if ((pkt->pkt_tran_flags & FC_TRAN_NO_INTR) || !pkt->pkt_comp || 2119 ddi_in_panic()) { 2120 sbp->pkt_flags |= PACKET_POLLED; 2121 } 2122 2123 /* Prepare the fc packet */ 2124 pkt->pkt_state = FC_PKT_SUCCESS; 2125 pkt->pkt_reason = 0; 2126 pkt->pkt_action = 0; 2127 pkt->pkt_expln = 0; 2128 pkt->pkt_data_resid = 0; 2129 pkt->pkt_resp_resid = 0; 2130 2131 /* Make sure all pkt's have a proper timeout */ 2132 if (!cfg[CFG_TIMEOUT_ENABLE].current) { 2133 /* This disables all IOCB on chip timeouts */ 2134 pkt->pkt_timeout = 0x80000000; 2135 } else if (pkt->pkt_timeout == 0 || pkt->pkt_timeout == 0xffffffff) { 2136 pkt->pkt_timeout = 60; 2137 } 2138 2139 /* Clear the response buffer */ 2140 if (pkt->pkt_rsplen) { 2141 /* Check for FCP commands */ 2142 if ((pkt->pkt_tran_type == FC_PKT_FCP_READ) || 2143 (pkt->pkt_tran_type == FC_PKT_FCP_WRITE)) { 2144 iptr = (uint32_t *)pkt->pkt_resp; 2145 iptr[2] = 0; 2146 iptr[3] = 0; 2147 } else { 2148 bzero(pkt->pkt_resp, pkt->pkt_rsplen); 2149 } 2150 } 2151 2152 mutex_exit(&sbp->mtx); 2153 2154 return; 2155 2156 } /* emlxs_initialize_pkt() */ 2157 2158 2159 2160 /* 2161 * We may not need this routine 2162 */ 2163 /*ARGSUSED*/ 2164 extern int 2165 emlxs_pkt_uninit(opaque_t fca_port_handle, fc_packet_t *pkt) 2166 { 2167 emlxs_buf_t *sbp = PKT2PRIV(pkt); 2168 2169 if (!sbp) { 2170 return (FC_FAILURE); 2171 } 2172 2173 if (!(sbp->pkt_flags & PACKET_VALID)) { 2174 return (FC_FAILURE); 2175 } 2176 sbp->pkt_flags &= ~PACKET_VALID; 2177 mutex_destroy(&sbp->mtx); 2178 2179 return (FC_SUCCESS); 2180 2181 } /* emlxs_pkt_uninit() */ 2182 2183 2184 static int 2185 emlxs_get_cap(opaque_t fca_port_handle, char *cap, void *ptr) 2186 { 2187 emlxs_port_t *port = (emlxs_port_t *)fca_port_handle; 2188 emlxs_hba_t *hba = HBA; 2189 int32_t rval; 2190 2191 if (!(port->flag & EMLXS_PORT_BOUND)) { 2192 return (FC_CAP_ERROR); 2193 } 2194 2195 if (strcmp(cap, FC_NODE_WWN) == 0) { 2196 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 2197 "fca_get_cap: FC_NODE_WWN"); 2198 2199 bcopy((void *)&hba->wwnn, (void *)ptr, sizeof (NAME_TYPE)); 2200 rval = FC_CAP_FOUND; 2201 2202 } else if (strcmp(cap, FC_LOGIN_PARAMS) == 0) { 2203 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 2204 "fca_get_cap: FC_LOGIN_PARAMS"); 2205 2206 /* 2207 * We need to turn off CLASS2 support. 2208 * Otherwise, FC transport will use CLASS2 as default class 2209 * and never try with CLASS3. 2210 */ 2211 hba->sparam.cls2.classValid = 0; 2212 2213 bcopy((void *)&hba->sparam, (void *)ptr, sizeof (SERV_PARM)); 2214 2215 rval = FC_CAP_FOUND; 2216 2217 } else if (strcmp(cap, FC_CAP_UNSOL_BUF) == 0) { 2218 int32_t *num_bufs; 2219 emlxs_config_t *cfg = &CFG; 2220 2221 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 2222 "fca_get_cap: FC_CAP_UNSOL_BUF (%d)", 2223 cfg[CFG_UB_BUFS].current); 2224 2225 num_bufs = (int32_t *)ptr; 2226 2227 /* We multiply by MAX_VPORTS because ULP uses a */ 2228 /* formula to calculate ub bufs from this */ 2229 *num_bufs = (cfg[CFG_UB_BUFS].current * MAX_VPORTS); 2230 2231 rval = FC_CAP_FOUND; 2232 2233 } else if (strcmp(cap, FC_CAP_PAYLOAD_SIZE) == 0) { 2234 int32_t *size; 2235 2236 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 2237 "fca_get_cap: FC_CAP_PAYLOAD_SIZE"); 2238 2239 size = (int32_t *)ptr; 2240 *size = -1; 2241 rval = FC_CAP_FOUND; 2242 2243 } else if (strcmp(cap, FC_CAP_POST_RESET_BEHAVIOR) == 0) { 2244 fc_reset_action_t *action; 2245 2246 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 2247 "fca_get_cap: FC_CAP_POST_RESET_BEHAVIOR"); 2248 2249 action = (fc_reset_action_t *)ptr; 2250 *action = FC_RESET_RETURN_ALL; 2251 rval = FC_CAP_FOUND; 2252 2253 } else if (strcmp(cap, FC_CAP_NOSTREAM_ON_UNALIGN_BUF) == 0) { 2254 fc_dma_behavior_t *behavior; 2255 2256 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 2257 "fca_get_cap: FC_CAP_NOSTREAM_ON_UNALIGN_BUF"); 2258 2259 behavior = (fc_dma_behavior_t *)ptr; 2260 *behavior = FC_ALLOW_STREAMING; 2261 rval = FC_CAP_FOUND; 2262 2263 } else if (strcmp(cap, FC_CAP_FCP_DMA) == 0) { 2264 fc_fcp_dma_t *fcp_dma; 2265 2266 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 2267 "fca_get_cap: FC_CAP_FCP_DMA"); 2268 2269 fcp_dma = (fc_fcp_dma_t *)ptr; 2270 *fcp_dma = FC_DVMA_SPACE; 2271 rval = FC_CAP_FOUND; 2272 2273 } else { 2274 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 2275 "fca_get_cap: Unknown capability. [%s]", cap); 2276 2277 rval = FC_CAP_ERROR; 2278 2279 } 2280 2281 return (rval); 2282 2283 } /* emlxs_get_cap() */ 2284 2285 2286 2287 static int 2288 emlxs_set_cap(opaque_t fca_port_handle, char *cap, void *ptr) 2289 { 2290 emlxs_port_t *port = (emlxs_port_t *)fca_port_handle; 2291 2292 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 2293 "fca_set_cap: cap=[%s] arg=%p", cap, ptr); 2294 2295 return (FC_CAP_ERROR); 2296 2297 } /* emlxs_set_cap() */ 2298 2299 2300 static opaque_t 2301 emlxs_get_device(opaque_t fca_port_handle, fc_portid_t d_id) 2302 { 2303 emlxs_port_t *port = (emlxs_port_t *)fca_port_handle; 2304 2305 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 2306 "fca_get_device: did=%x", d_id.port_id); 2307 2308 return (NULL); 2309 2310 } /* emlxs_get_device() */ 2311 2312 2313 static int32_t 2314 emlxs_notify(opaque_t fca_port_handle, uint32_t cmd) 2315 { 2316 emlxs_port_t *port = (emlxs_port_t *)fca_port_handle; 2317 2318 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, "fca_notify: cmd=%x", 2319 cmd); 2320 2321 return (FC_SUCCESS); 2322 2323 } /* emlxs_notify */ 2324 2325 2326 2327 static int 2328 emlxs_get_map(opaque_t fca_port_handle, fc_lilpmap_t *mapbuf) 2329 { 2330 emlxs_port_t *port = (emlxs_port_t *)fca_port_handle; 2331 emlxs_hba_t *hba = HBA; 2332 uint32_t lilp_length; 2333 2334 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 2335 "fca_get_map: mapbuf=%p length=%d (%X,%X,%X,%X)", mapbuf, 2336 port->alpa_map[0], port->alpa_map[1], port->alpa_map[2], 2337 port->alpa_map[3], port->alpa_map[4]); 2338 2339 if (!(port->flag & EMLXS_PORT_BOUND)) { 2340 return (FC_NOMAP); 2341 } 2342 2343 if (hba->topology != TOPOLOGY_LOOP) { 2344 return (FC_NOMAP); 2345 } 2346 2347 /* Check if alpa map is available */ 2348 if (port->alpa_map[0] != 0) { 2349 mapbuf->lilp_magic = MAGIC_LILP; 2350 } else { /* No LILP map available */ 2351 2352 /* Set lilp_magic to MAGIC_LISA and this will */ 2353 /* trigger an ALPA scan in ULP */ 2354 mapbuf->lilp_magic = MAGIC_LISA; 2355 } 2356 2357 mapbuf->lilp_myalpa = port->did; 2358 2359 /* The first byte of the alpa_map is the lilp map length */ 2360 /* Add one to include the lilp length byte itself */ 2361 lilp_length = (uint32_t)port->alpa_map[0] + 1; 2362 2363 /* Make sure the max transfer is 128 bytes */ 2364 if (lilp_length > 128) { 2365 lilp_length = 128; 2366 } 2367 2368 /* We start copying from the lilp_length field */ 2369 /* in order to get a word aligned address */ 2370 bcopy((void *)&port->alpa_map, (void *)&mapbuf->lilp_length, 2371 lilp_length); 2372 2373 return (FC_SUCCESS); 2374 2375 } /* emlxs_get_map() */ 2376 2377 2378 2379 extern int 2380 emlxs_transport(opaque_t fca_port_handle, fc_packet_t *pkt) 2381 { 2382 emlxs_port_t *port = (emlxs_port_t *)fca_port_handle; 2383 emlxs_hba_t *hba = HBA; 2384 emlxs_buf_t *sbp; 2385 uint32_t rval; 2386 uint32_t pkt_flags; 2387 2388 /* Make sure adapter is online */ 2389 if (!(hba->flag & FC_ONLINE_MODE)) { 2390 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg, 2391 "Adapter offline."); 2392 2393 return (FC_OFFLINE); 2394 } 2395 2396 /* Validate packet */ 2397 sbp = PKT2PRIV(pkt); 2398 2399 /* Make sure ULP was told that the port was online */ 2400 if ((port->ulp_statec == FC_STATE_OFFLINE) && 2401 !(sbp->pkt_flags & PACKET_ALLOCATED)) { 2402 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, 2403 "Port offline."); 2404 2405 return (FC_OFFLINE); 2406 } 2407 2408 if (sbp->port != port) { 2409 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_error_msg, 2410 "Invalid port handle. sbp=%p port=%p flags=%x", sbp, 2411 sbp->port, sbp->pkt_flags); 2412 return (FC_BADPACKET); 2413 } 2414 2415 if (!(sbp->pkt_flags & (PACKET_VALID | PACKET_ULP_OWNED))) { 2416 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_error_msg, 2417 "Invalid packet flags. sbp=%p port=%p flags=%x", sbp, 2418 sbp->port, sbp->pkt_flags); 2419 return (FC_BADPACKET); 2420 } 2421 #ifdef SFCT_SUPPORT 2422 if (port->tgt_mode && !sbp->fct_cmd && 2423 !(sbp->pkt_flags & PACKET_ALLOCATED)) { 2424 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_error_msg, 2425 "Packet blocked. Target mode."); 2426 return (FC_TRANSPORT_ERROR); 2427 } 2428 #endif /* SFCT_SUPPORT */ 2429 2430 #ifdef IDLE_TIMER 2431 emlxs_pm_busy_component(hba); 2432 #endif /* IDLE_TIMER */ 2433 2434 /* Prepare the packet for transport */ 2435 emlxs_initialize_pkt(port, sbp); 2436 2437 /* Save a copy of the pkt flags. */ 2438 /* We will check the polling flag later */ 2439 pkt_flags = sbp->pkt_flags; 2440 2441 /* Send the packet */ 2442 switch (pkt->pkt_tran_type) { 2443 case FC_PKT_FCP_READ: 2444 case FC_PKT_FCP_WRITE: 2445 rval = emlxs_send_fcp_cmd(port, sbp); 2446 break; 2447 2448 case FC_PKT_IP_WRITE: 2449 case FC_PKT_BROADCAST: 2450 rval = emlxs_send_ip(port, sbp); 2451 break; 2452 2453 case FC_PKT_EXCHANGE: 2454 switch (pkt->pkt_cmd_fhdr.type) { 2455 case FC_TYPE_SCSI_FCP: 2456 rval = emlxs_send_fcp_cmd(port, sbp); 2457 break; 2458 2459 case FC_TYPE_FC_SERVICES: 2460 rval = emlxs_send_ct(port, sbp); 2461 break; 2462 2463 #ifdef MENLO_SUPPORT 2464 case EMLXS_MENLO_TYPE: 2465 rval = emlxs_send_menlo(port, sbp); 2466 break; 2467 #endif /* MENLO_SUPPORT */ 2468 2469 default: 2470 rval = emlxs_send_els(port, sbp); 2471 } 2472 break; 2473 2474 case FC_PKT_OUTBOUND: 2475 switch (pkt->pkt_cmd_fhdr.type) { 2476 #ifdef SFCT_SUPPORT 2477 case FC_TYPE_SCSI_FCP: 2478 rval = emlxs_send_fct_status(port, sbp); 2479 break; 2480 2481 case FC_TYPE_BASIC_LS: 2482 rval = emlxs_send_fct_abort(port, sbp); 2483 break; 2484 #endif /* SFCT_SUPPORT */ 2485 2486 case FC_TYPE_FC_SERVICES: 2487 rval = emlxs_send_ct_rsp(port, sbp); 2488 break; 2489 #ifdef MENLO_SUPPORT 2490 case EMLXS_MENLO_TYPE: 2491 rval = emlxs_send_menlo(port, sbp); 2492 break; 2493 #endif /* MENLO_SUPPORT */ 2494 2495 default: 2496 rval = emlxs_send_els_rsp(port, sbp); 2497 } 2498 break; 2499 2500 default: 2501 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_error_msg, 2502 "Unsupported pkt_tran_type. type=%x", pkt->pkt_tran_type); 2503 rval = FC_TRANSPORT_ERROR; 2504 break; 2505 } 2506 2507 /* Check if send was not successful */ 2508 if (rval != FC_SUCCESS) { 2509 /* Return packet to ULP */ 2510 mutex_enter(&sbp->mtx); 2511 sbp->pkt_flags |= PACKET_ULP_OWNED; 2512 mutex_exit(&sbp->mtx); 2513 2514 return (rval); 2515 } 2516 2517 /* Check if this packet should be polled for completion before */ 2518 /* returning. This check must be done with a saved copy of the */ 2519 /* pkt_flags because the packet itself could already be freed from */ 2520 /* memory if it was not polled. */ 2521 if (pkt_flags & PACKET_POLLED) { 2522 emlxs_poll(port, sbp); 2523 } 2524 2525 return (FC_SUCCESS); 2526 2527 } /* emlxs_transport() */ 2528 2529 2530 2531 static void 2532 emlxs_poll(emlxs_port_t *port, emlxs_buf_t *sbp) 2533 { 2534 emlxs_hba_t *hba = HBA; 2535 fc_packet_t *pkt = PRIV2PKT(sbp); 2536 clock_t timeout; 2537 clock_t time; 2538 uint32_t att_bit; 2539 CHANNEL *cp; 2540 2541 mutex_enter(&EMLXS_PORT_LOCK); 2542 hba->io_poll_count++; 2543 mutex_exit(&EMLXS_PORT_LOCK); 2544 2545 /* Check for panic situation */ 2546 cp = (CHANNEL *)sbp->channel; 2547 2548 if (ddi_in_panic()) { 2549 /* 2550 * In panic situations there will be one thread with 2551 * no interrrupts (hard or soft) and no timers 2552 */ 2553 2554 /* 2555 * We must manually poll everything in this thread 2556 * to keep the driver going. 2557 */ 2558 if (hba->sli_mode == EMLXS_HBA_SLI3_MODE) { 2559 switch (cp->channelno) { 2560 case FC_FCP_RING: 2561 att_bit = HA_R0ATT; 2562 break; 2563 2564 case FC_IP_RING: 2565 att_bit = HA_R1ATT; 2566 break; 2567 2568 case FC_ELS_RING: 2569 att_bit = HA_R2ATT; 2570 break; 2571 2572 case FC_CT_RING: 2573 att_bit = HA_R3ATT; 2574 break; 2575 } 2576 } 2577 2578 /* Keep polling the chip until our IO is completed */ 2579 /* Driver's timer will not function during panics. */ 2580 /* Therefore, timer checks must be performed manually. */ 2581 (void) drv_getparm(LBOLT, &time); 2582 timeout = time + drv_usectohz(1000000); 2583 while (!(sbp->pkt_flags & PACKET_COMPLETED)) { 2584 if (hba->sli_mode == EMLXS_HBA_SLI3_MODE) { 2585 EMLXS_SLI_POLL_INTR(hba, att_bit); 2586 } else { 2587 EMLXS_SLI_POLL_INTR(hba, 0); 2588 } 2589 (void) drv_getparm(LBOLT, &time); 2590 2591 /* Trigger timer checks periodically */ 2592 if (time >= timeout) { 2593 emlxs_timer_checks(hba); 2594 timeout = time + drv_usectohz(1000000); 2595 } 2596 } 2597 } else { 2598 /* Wait for IO completion */ 2599 /* The driver's timer will detect */ 2600 /* any timeout and abort the I/O. */ 2601 mutex_enter(&EMLXS_PKT_LOCK); 2602 while (!(sbp->pkt_flags & PACKET_COMPLETED)) { 2603 cv_wait(&EMLXS_PKT_CV, &EMLXS_PKT_LOCK); 2604 } 2605 mutex_exit(&EMLXS_PKT_LOCK); 2606 } 2607 2608 /* Check for fcp reset pkt */ 2609 if (sbp->pkt_flags & PACKET_FCP_RESET) { 2610 if (sbp->pkt_flags & PACKET_FCP_TGT_RESET) { 2611 /* Flush the IO's on the chipq */ 2612 (void) emlxs_chipq_node_flush(port, 2613 &hba->chan[hba->channel_fcp], 2614 sbp->node, sbp); 2615 } else { 2616 /* Flush the IO's on the chipq for this lun */ 2617 (void) emlxs_chipq_lun_flush(port, 2618 sbp->node, sbp->lun, sbp); 2619 } 2620 2621 if (sbp->flush_count == 0) { 2622 emlxs_node_open(port, sbp->node, hba->channel_fcp); 2623 goto done; 2624 } 2625 2626 /* Set the timeout so the flush has time to complete */ 2627 timeout = emlxs_timeout(hba, 60); 2628 (void) drv_getparm(LBOLT, &time); 2629 while ((time < timeout) && sbp->flush_count > 0) { 2630 delay(drv_usectohz(500000)); 2631 (void) drv_getparm(LBOLT, &time); 2632 } 2633 2634 if (sbp->flush_count == 0) { 2635 emlxs_node_open(port, sbp->node, hba->channel_fcp); 2636 goto done; 2637 } 2638 2639 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_flush_timeout_msg, 2640 "sbp=%p flush_count=%d. Waiting...", sbp, 2641 sbp->flush_count); 2642 2643 /* Let's try this one more time */ 2644 2645 if (sbp->pkt_flags & PACKET_FCP_TGT_RESET) { 2646 /* Flush the IO's on the chipq */ 2647 (void) emlxs_chipq_node_flush(port, 2648 &hba->chan[hba->channel_fcp], 2649 sbp->node, sbp); 2650 } else { 2651 /* Flush the IO's on the chipq for this lun */ 2652 (void) emlxs_chipq_lun_flush(port, 2653 sbp->node, sbp->lun, sbp); 2654 } 2655 2656 /* Reset the timeout so the flush has time to complete */ 2657 timeout = emlxs_timeout(hba, 60); 2658 (void) drv_getparm(LBOLT, &time); 2659 while ((time < timeout) && sbp->flush_count > 0) { 2660 delay(drv_usectohz(500000)); 2661 (void) drv_getparm(LBOLT, &time); 2662 } 2663 2664 if (sbp->flush_count == 0) { 2665 emlxs_node_open(port, sbp->node, hba->channel_fcp); 2666 goto done; 2667 } 2668 2669 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_flush_timeout_msg, 2670 "sbp=%p flush_count=%d. Resetting link.", sbp, 2671 sbp->flush_count); 2672 2673 /* Let's first try to reset the link */ 2674 (void) emlxs_reset(port, FC_FCA_LINK_RESET); 2675 2676 if (sbp->flush_count == 0) { 2677 goto done; 2678 } 2679 2680 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_flush_timeout_msg, 2681 "sbp=%p flush_count=%d. Resetting HBA.", sbp, 2682 sbp->flush_count); 2683 2684 /* If that doesn't work, reset the adapter */ 2685 (void) emlxs_reset(port, FC_FCA_RESET); 2686 2687 if (sbp->flush_count != 0) { 2688 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_flush_timeout_msg, 2689 "sbp=%p flush_count=%d. Giving up.", sbp, 2690 sbp->flush_count); 2691 } 2692 2693 } 2694 /* PACKET_FCP_RESET */ 2695 done: 2696 2697 /* Packet has been declared completed and is now ready to be returned */ 2698 2699 #if (EMLXS_MODREVX == EMLXS_MODREV2X) 2700 emlxs_unswap_pkt(sbp); 2701 #endif /* EMLXS_MODREV2X */ 2702 2703 mutex_enter(&sbp->mtx); 2704 sbp->pkt_flags |= PACKET_ULP_OWNED; 2705 mutex_exit(&sbp->mtx); 2706 2707 mutex_enter(&EMLXS_PORT_LOCK); 2708 hba->io_poll_count--; 2709 mutex_exit(&EMLXS_PORT_LOCK); 2710 2711 /* Make ULP completion callback if required */ 2712 if (pkt->pkt_comp) { 2713 cp->ulpCmplCmd++; 2714 (*pkt->pkt_comp) (pkt); 2715 } 2716 2717 return; 2718 2719 } /* emlxs_poll() */ 2720 2721 2722 static int 2723 emlxs_ub_alloc(opaque_t fca_port_handle, uint64_t tokens[], uint32_t size, 2724 uint32_t *count, uint32_t type) 2725 { 2726 emlxs_port_t *port = (emlxs_port_t *)fca_port_handle; 2727 emlxs_hba_t *hba = HBA; 2728 2729 char *err = NULL; 2730 emlxs_unsol_buf_t *pool; 2731 emlxs_unsol_buf_t *new_pool; 2732 int32_t i; 2733 int result; 2734 uint32_t free_resv; 2735 uint32_t free; 2736 emlxs_config_t *cfg = &CFG; 2737 fc_unsol_buf_t *ubp; 2738 emlxs_ub_priv_t *ub_priv; 2739 int rc; 2740 2741 if (port->tgt_mode) { 2742 if (tokens && count) { 2743 bzero(tokens, (sizeof (uint64_t) * (*count))); 2744 } 2745 return (FC_SUCCESS); 2746 } 2747 2748 if (!(port->flag & EMLXS_PORT_BOUND)) { 2749 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 2750 "ub_alloc failed: Port not bound! size=%x count=%d " 2751 "type=%x", size, *count, type); 2752 2753 return (FC_FAILURE); 2754 } 2755 2756 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 2757 "ub_alloc: size=%x count=%d type=%x", size, *count, type); 2758 2759 if (count && (*count > EMLXS_MAX_UBUFS)) { 2760 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_msg, 2761 "ub_alloc failed: Too many unsolicted buffers requested. " 2762 "count=%x", *count); 2763 2764 return (FC_FAILURE); 2765 2766 } 2767 2768 if (tokens == NULL) { 2769 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_msg, 2770 "ub_alloc failed: Token array is NULL."); 2771 2772 return (FC_FAILURE); 2773 } 2774 2775 /* Clear the token array */ 2776 bzero(tokens, (sizeof (uint64_t) * (*count))); 2777 2778 free_resv = 0; 2779 free = *count; 2780 switch (type) { 2781 case FC_TYPE_BASIC_LS: 2782 err = "BASIC_LS"; 2783 break; 2784 case FC_TYPE_EXTENDED_LS: 2785 err = "EXTENDED_LS"; 2786 free = *count / 2; /* Hold 50% for normal use */ 2787 free_resv = *count - free; /* Reserve 50% for RSCN use */ 2788 break; 2789 case FC_TYPE_IS8802: 2790 err = "IS8802"; 2791 break; 2792 case FC_TYPE_IS8802_SNAP: 2793 err = "IS8802_SNAP"; 2794 2795 if (cfg[CFG_NETWORK_ON].current == 0) { 2796 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_msg, 2797 "ub_alloc failed: IP support is disabled."); 2798 2799 return (FC_FAILURE); 2800 } 2801 break; 2802 case FC_TYPE_SCSI_FCP: 2803 err = "SCSI_FCP"; 2804 break; 2805 case FC_TYPE_SCSI_GPP: 2806 err = "SCSI_GPP"; 2807 break; 2808 case FC_TYPE_HIPP_FP: 2809 err = "HIPP_FP"; 2810 break; 2811 case FC_TYPE_IPI3_MASTER: 2812 err = "IPI3_MASTER"; 2813 break; 2814 case FC_TYPE_IPI3_SLAVE: 2815 err = "IPI3_SLAVE"; 2816 break; 2817 case FC_TYPE_IPI3_PEER: 2818 err = "IPI3_PEER"; 2819 break; 2820 case FC_TYPE_FC_SERVICES: 2821 err = "FC_SERVICES"; 2822 break; 2823 } 2824 2825 mutex_enter(&EMLXS_UB_LOCK); 2826 2827 /* 2828 * Walk through the list of the unsolicited buffers 2829 * for this ddiinst of emlx. 2830 */ 2831 2832 pool = port->ub_pool; 2833 2834 /* 2835 * The emlxs_ub_alloc() can be called more than once with different 2836 * size. We will reject the call if there are 2837 * duplicate size with the same FC-4 type. 2838 */ 2839 while (pool) { 2840 if ((pool->pool_type == type) && 2841 (pool->pool_buf_size == size)) { 2842 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_msg, 2843 "ub_alloc failed: Unsolicited buffer pool for %s " 2844 "of size 0x%x bytes already exists.", err, size); 2845 2846 result = FC_FAILURE; 2847 goto fail; 2848 } 2849 2850 pool = pool->pool_next; 2851 } 2852 2853 mutex_exit(&EMLXS_UB_LOCK); 2854 2855 new_pool = (emlxs_unsol_buf_t *)kmem_zalloc(sizeof (emlxs_unsol_buf_t), 2856 KM_SLEEP); 2857 2858 new_pool->pool_next = NULL; 2859 new_pool->pool_type = type; 2860 new_pool->pool_buf_size = size; 2861 new_pool->pool_nentries = *count; 2862 new_pool->pool_available = new_pool->pool_nentries; 2863 new_pool->pool_free = free; 2864 new_pool->pool_free_resv = free_resv; 2865 new_pool->fc_ubufs = 2866 kmem_zalloc((sizeof (fc_unsol_buf_t) * (*count)), KM_SLEEP); 2867 2868 new_pool->pool_first_token = port->ub_count; 2869 new_pool->pool_last_token = port->ub_count + new_pool->pool_nentries; 2870 2871 for (i = 0; i < new_pool->pool_nentries; i++) { 2872 ubp = (fc_unsol_buf_t *)&new_pool->fc_ubufs[i]; 2873 ubp->ub_port_handle = port->ulp_handle; 2874 ubp->ub_token = (uint64_t)((unsigned long)ubp); 2875 ubp->ub_bufsize = size; 2876 ubp->ub_class = FC_TRAN_CLASS3; 2877 ubp->ub_port_private = NULL; 2878 ubp->ub_fca_private = 2879 (emlxs_ub_priv_t *)kmem_zalloc(sizeof (emlxs_ub_priv_t), 2880 KM_SLEEP); 2881 2882 /* 2883 * Initialize emlxs_ub_priv_t 2884 */ 2885 ub_priv = ubp->ub_fca_private; 2886 ub_priv->ubp = ubp; 2887 ub_priv->port = port; 2888 ub_priv->flags = EMLXS_UB_FREE; 2889 ub_priv->available = 1; 2890 ub_priv->pool = new_pool; 2891 ub_priv->time = 0; 2892 ub_priv->timeout = 0; 2893 ub_priv->token = port->ub_count; 2894 ub_priv->cmd = 0; 2895 2896 /* Allocate the actual buffer */ 2897 ubp->ub_buffer = (caddr_t)kmem_zalloc(size, KM_SLEEP); 2898 2899 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_detail_msg, 2900 "ub_alloc: buffer=%p token=%x size=%x type=%x ", ubp, 2901 ub_priv->token, ubp->ub_bufsize, type); 2902 2903 tokens[i] = (uint64_t)((unsigned long)ubp); 2904 port->ub_count++; 2905 } 2906 2907 mutex_enter(&EMLXS_UB_LOCK); 2908 2909 /* Add the pool to the top of the pool list */ 2910 new_pool->pool_prev = NULL; 2911 new_pool->pool_next = port->ub_pool; 2912 2913 if (port->ub_pool) { 2914 port->ub_pool->pool_prev = new_pool; 2915 } 2916 port->ub_pool = new_pool; 2917 2918 /* Set the post counts */ 2919 if (type == FC_TYPE_IS8802_SNAP) { 2920 MAILBOXQ *mbox; 2921 2922 port->ub_post[hba->channel_ip] += new_pool->pool_nentries; 2923 2924 if ((mbox = (MAILBOXQ *)emlxs_mem_get(hba, 2925 MEM_MBOX, 1))) { 2926 emlxs_mb_config_farp(hba, mbox); 2927 rc = EMLXS_SLI_ISSUE_MBOX_CMD(hba, 2928 mbox, MBX_NOWAIT, 0); 2929 if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) { 2930 (void) emlxs_mem_put(hba, MEM_MBOX, 2931 (uint8_t *)mbox); 2932 } 2933 } 2934 port->flag |= EMLXS_PORT_IP_UP; 2935 } else if (type == FC_TYPE_EXTENDED_LS) { 2936 port->ub_post[hba->channel_els] += new_pool->pool_nentries; 2937 } else if (type == FC_TYPE_FC_SERVICES) { 2938 port->ub_post[hba->channel_ct] += new_pool->pool_nentries; 2939 } 2940 2941 mutex_exit(&EMLXS_UB_LOCK); 2942 2943 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 2944 "%d unsolicited buffers allocated for %s of size 0x%x bytes.", 2945 *count, err, size); 2946 2947 return (FC_SUCCESS); 2948 2949 fail: 2950 2951 /* Clean the pool */ 2952 for (i = 0; tokens[i] != NULL; i++) { 2953 /* Get the buffer object */ 2954 ubp = (fc_unsol_buf_t *)((unsigned long)tokens[i]); 2955 ub_priv = (emlxs_ub_priv_t *)ubp->ub_fca_private; 2956 2957 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_detail_msg, 2958 "ub_alloc failed: Freed buffer=%p token=%x size=%x " 2959 "type=%x ", ubp, ub_priv->token, ubp->ub_bufsize, type); 2960 2961 /* Free the actual buffer */ 2962 kmem_free(ubp->ub_buffer, ubp->ub_bufsize); 2963 2964 /* Free the private area of the buffer object */ 2965 kmem_free(ubp->ub_fca_private, sizeof (emlxs_ub_priv_t)); 2966 2967 tokens[i] = 0; 2968 port->ub_count--; 2969 } 2970 2971 /* Free the array of buffer objects in the pool */ 2972 kmem_free((caddr_t)new_pool->fc_ubufs, 2973 (sizeof (fc_unsol_buf_t) * new_pool->pool_nentries)); 2974 2975 /* Free the pool object */ 2976 kmem_free((caddr_t)new_pool, sizeof (emlxs_unsol_buf_t)); 2977 2978 mutex_exit(&EMLXS_UB_LOCK); 2979 2980 return (result); 2981 2982 } /* emlxs_ub_alloc() */ 2983 2984 2985 static void 2986 emlxs_ub_els_reject(emlxs_port_t *port, fc_unsol_buf_t *ubp) 2987 { 2988 emlxs_hba_t *hba = HBA; 2989 emlxs_ub_priv_t *ub_priv; 2990 fc_packet_t *pkt; 2991 ELS_PKT *els; 2992 uint32_t sid; 2993 2994 ub_priv = (emlxs_ub_priv_t *)ubp->ub_fca_private; 2995 2996 if (hba->state <= FC_LINK_DOWN) { 2997 return; 2998 } 2999 3000 if (!(pkt = emlxs_pkt_alloc(port, sizeof (uint32_t) + 3001 sizeof (LS_RJT), 0, 0, KM_NOSLEEP))) { 3002 return; 3003 } 3004 3005 sid = LE_SWAP24_LO(ubp->ub_frame.s_id); 3006 3007 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_unsol_els_msg, 3008 "%s dropped: sid=%x. Rejecting.", 3009 emlxs_elscmd_xlate(ub_priv->cmd), sid); 3010 3011 pkt->pkt_tran_type = FC_PKT_OUTBOUND; 3012 pkt->pkt_timeout = (2 * hba->fc_ratov); 3013 3014 if ((uint32_t)ubp->ub_class == FC_TRAN_CLASS2) { 3015 pkt->pkt_tran_flags &= ~FC_TRAN_CLASS3; 3016 pkt->pkt_tran_flags |= FC_TRAN_CLASS2; 3017 } 3018 3019 /* Build the fc header */ 3020 pkt->pkt_cmd_fhdr.d_id = ubp->ub_frame.s_id; 3021 pkt->pkt_cmd_fhdr.r_ctl = 3022 R_CTL_EXTENDED_SVC | R_CTL_SOLICITED_CONTROL; 3023 pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did); 3024 pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS; 3025 pkt->pkt_cmd_fhdr.f_ctl = 3026 F_CTL_XCHG_CONTEXT | F_CTL_LAST_SEQ | F_CTL_END_SEQ; 3027 pkt->pkt_cmd_fhdr.seq_id = 0; 3028 pkt->pkt_cmd_fhdr.df_ctl = 0; 3029 pkt->pkt_cmd_fhdr.seq_cnt = 0; 3030 pkt->pkt_cmd_fhdr.ox_id = (ub_priv->cmd >> ELS_CMD_SHIFT) & 0xff; 3031 pkt->pkt_cmd_fhdr.rx_id = ubp->ub_frame.rx_id; 3032 pkt->pkt_cmd_fhdr.ro = 0; 3033 3034 /* Build the command */ 3035 els = (ELS_PKT *) pkt->pkt_cmd; 3036 els->elsCode = 0x01; 3037 els->un.lsRjt.un.b.lsRjtRsvd0 = 0; 3038 els->un.lsRjt.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; 3039 els->un.lsRjt.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE; 3040 els->un.lsRjt.un.b.vendorUnique = 0x02; 3041 3042 /* Send the pkt later in another thread */ 3043 (void) emlxs_pkt_send(pkt, 0); 3044 3045 return; 3046 3047 } /* emlxs_ub_els_reject() */ 3048 3049 extern int 3050 emlxs_ub_release(opaque_t fca_port_handle, uint32_t count, uint64_t tokens[]) 3051 { 3052 emlxs_port_t *port = (emlxs_port_t *)fca_port_handle; 3053 emlxs_hba_t *hba = HBA; 3054 fc_unsol_buf_t *ubp; 3055 emlxs_ub_priv_t *ub_priv; 3056 uint32_t i; 3057 uint32_t time; 3058 emlxs_unsol_buf_t *pool; 3059 3060 if (count == 0) { 3061 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 3062 "ub_release: Nothing to do. count=%d", count); 3063 3064 return (FC_SUCCESS); 3065 } 3066 3067 if (!(port->flag & EMLXS_PORT_BOUND)) { 3068 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 3069 "ub_release failed: Port not bound. count=%d token[0]=%p", 3070 count, tokens[0]); 3071 3072 return (FC_UNBOUND); 3073 } 3074 3075 mutex_enter(&EMLXS_UB_LOCK); 3076 3077 if (!port->ub_pool) { 3078 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 3079 "ub_release failed: No pools! count=%d token[0]=%p", 3080 count, tokens[0]); 3081 3082 mutex_exit(&EMLXS_UB_LOCK); 3083 return (FC_UB_BADTOKEN); 3084 } 3085 3086 for (i = 0; i < count; i++) { 3087 ubp = (fc_unsol_buf_t *)((unsigned long)tokens[i]); 3088 3089 if (!ubp) { 3090 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 3091 "ub_release failed: count=%d tokens[%d]=0", count, 3092 i); 3093 3094 mutex_exit(&EMLXS_UB_LOCK); 3095 return (FC_UB_BADTOKEN); 3096 } 3097 3098 ub_priv = (emlxs_ub_priv_t *)ubp->ub_fca_private; 3099 3100 if (!ub_priv || (ub_priv == (emlxs_ub_priv_t *)DEAD_PTR)) { 3101 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 3102 "ub_release failed: Dead buffer found. ubp=%p", 3103 ubp); 3104 3105 mutex_exit(&EMLXS_UB_LOCK); 3106 return (FC_UB_BADTOKEN); 3107 } 3108 3109 if (ub_priv->flags == EMLXS_UB_FREE) { 3110 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 3111 "ub_release: Buffer already free! ubp=%p token=%x", 3112 ubp, ub_priv->token); 3113 3114 continue; 3115 } 3116 3117 /* Check for dropped els buffer */ 3118 /* ULP will do this sometimes without sending a reply */ 3119 if ((ubp->ub_frame.r_ctl == FC_ELS_REQ) && 3120 !(ub_priv->flags & EMLXS_UB_REPLY)) { 3121 emlxs_ub_els_reject(port, ubp); 3122 } 3123 3124 /* Mark the buffer free */ 3125 ub_priv->flags = EMLXS_UB_FREE; 3126 bzero(ubp->ub_buffer, ubp->ub_bufsize); 3127 3128 time = hba->timer_tics - ub_priv->time; 3129 ub_priv->time = 0; 3130 ub_priv->timeout = 0; 3131 3132 pool = ub_priv->pool; 3133 3134 if (ub_priv->flags & EMLXS_UB_RESV) { 3135 pool->pool_free_resv++; 3136 } else { 3137 pool->pool_free++; 3138 } 3139 3140 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_detail_msg, 3141 "ub_release: ubp=%p token=%x time=%d av=%d (%d,%d,%d,%d)", 3142 ubp, ub_priv->token, time, ub_priv->available, 3143 pool->pool_nentries, pool->pool_available, 3144 pool->pool_free, pool->pool_free_resv); 3145 3146 /* Check if pool can be destroyed now */ 3147 if ((pool->pool_available == 0) && 3148 (pool->pool_free + pool->pool_free_resv == 3149 pool->pool_nentries)) { 3150 emlxs_ub_destroy(port, pool); 3151 } 3152 } 3153 3154 mutex_exit(&EMLXS_UB_LOCK); 3155 3156 return (FC_SUCCESS); 3157 3158 } /* emlxs_ub_release() */ 3159 3160 3161 static int 3162 emlxs_ub_free(opaque_t fca_port_handle, uint32_t count, uint64_t tokens[]) 3163 { 3164 emlxs_port_t *port = (emlxs_port_t *)fca_port_handle; 3165 emlxs_unsol_buf_t *pool; 3166 fc_unsol_buf_t *ubp; 3167 emlxs_ub_priv_t *ub_priv; 3168 uint32_t i; 3169 3170 if (port->tgt_mode) { 3171 return (FC_SUCCESS); 3172 } 3173 3174 if (count == 0) { 3175 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 3176 "ub_free: Nothing to do. count=%d token[0]=%p", count, 3177 tokens[0]); 3178 3179 return (FC_SUCCESS); 3180 } 3181 3182 if (!(port->flag & EMLXS_PORT_BOUND)) { 3183 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 3184 "ub_free: Port not bound. count=%d token[0]=%p", count, 3185 tokens[0]); 3186 3187 return (FC_SUCCESS); 3188 } 3189 3190 mutex_enter(&EMLXS_UB_LOCK); 3191 3192 if (!port->ub_pool) { 3193 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 3194 "ub_free failed: No pools! count=%d token[0]=%p", count, 3195 tokens[0]); 3196 3197 mutex_exit(&EMLXS_UB_LOCK); 3198 return (FC_UB_BADTOKEN); 3199 } 3200 3201 /* Process buffer list */ 3202 for (i = 0; i < count; i++) { 3203 ubp = (fc_unsol_buf_t *)((unsigned long)tokens[i]); 3204 3205 if (!ubp) { 3206 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 3207 "ub_free failed: count=%d tokens[%d]=0", count, 3208 i); 3209 3210 mutex_exit(&EMLXS_UB_LOCK); 3211 return (FC_UB_BADTOKEN); 3212 } 3213 3214 /* Mark buffer unavailable */ 3215 ub_priv = (emlxs_ub_priv_t *)ubp->ub_fca_private; 3216 3217 if (!ub_priv || (ub_priv == (emlxs_ub_priv_t *)DEAD_PTR)) { 3218 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 3219 "ub_free failed: Dead buffer found. ubp=%p", ubp); 3220 3221 mutex_exit(&EMLXS_UB_LOCK); 3222 return (FC_UB_BADTOKEN); 3223 } 3224 3225 ub_priv->available = 0; 3226 3227 /* Mark one less buffer available in the parent pool */ 3228 pool = ub_priv->pool; 3229 3230 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_detail_msg, 3231 "ub_free: ubp=%p token=%x (%d,%d,%d,%d)", ubp, 3232 ub_priv->token, pool->pool_nentries, 3233 pool->pool_available - 1, pool->pool_free, 3234 pool->pool_free_resv); 3235 3236 if (pool->pool_available) { 3237 pool->pool_available--; 3238 3239 /* Check if pool can be destroyed */ 3240 if ((pool->pool_available == 0) && 3241 (pool->pool_free + pool->pool_free_resv == 3242 pool->pool_nentries)) { 3243 emlxs_ub_destroy(port, pool); 3244 } 3245 } 3246 } 3247 3248 mutex_exit(&EMLXS_UB_LOCK); 3249 3250 return (FC_SUCCESS); 3251 3252 } /* emlxs_ub_free() */ 3253 3254 3255 /* EMLXS_UB_LOCK must be held when calling this routine */ 3256 extern void 3257 emlxs_ub_destroy(emlxs_port_t *port, emlxs_unsol_buf_t *pool) 3258 { 3259 emlxs_hba_t *hba = HBA; 3260 emlxs_unsol_buf_t *next; 3261 emlxs_unsol_buf_t *prev; 3262 fc_unsol_buf_t *ubp; 3263 uint32_t i; 3264 3265 /* Remove the pool object from the pool list */ 3266 next = pool->pool_next; 3267 prev = pool->pool_prev; 3268 3269 if (port->ub_pool == pool) { 3270 port->ub_pool = next; 3271 } 3272 3273 if (prev) { 3274 prev->pool_next = next; 3275 } 3276 3277 if (next) { 3278 next->pool_prev = prev; 3279 } 3280 3281 pool->pool_prev = NULL; 3282 pool->pool_next = NULL; 3283 3284 /* Clear the post counts */ 3285 switch (pool->pool_type) { 3286 case FC_TYPE_IS8802_SNAP: 3287 port->ub_post[hba->channel_ip] -= pool->pool_nentries; 3288 break; 3289 3290 case FC_TYPE_EXTENDED_LS: 3291 port->ub_post[hba->channel_els] -= pool->pool_nentries; 3292 break; 3293 3294 case FC_TYPE_FC_SERVICES: 3295 port->ub_post[hba->channel_ct] -= pool->pool_nentries; 3296 break; 3297 } 3298 3299 /* Now free the pool memory */ 3300 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 3301 "ub_destroy: pool=%p type=%d size=%d count=%d", pool, 3302 pool->pool_type, pool->pool_buf_size, pool->pool_nentries); 3303 3304 /* Process the array of buffer objects in the pool */ 3305 for (i = 0; i < pool->pool_nentries; i++) { 3306 /* Get the buffer object */ 3307 ubp = (fc_unsol_buf_t *)&pool->fc_ubufs[i]; 3308 3309 /* Free the memory the buffer object represents */ 3310 kmem_free(ubp->ub_buffer, ubp->ub_bufsize); 3311 3312 /* Free the private area of the buffer object */ 3313 kmem_free(ubp->ub_fca_private, sizeof (emlxs_ub_priv_t)); 3314 } 3315 3316 /* Free the array of buffer objects in the pool */ 3317 kmem_free((caddr_t)pool->fc_ubufs, 3318 (sizeof (fc_unsol_buf_t)*pool->pool_nentries)); 3319 3320 /* Free the pool object */ 3321 kmem_free((caddr_t)pool, sizeof (emlxs_unsol_buf_t)); 3322 3323 return; 3324 3325 } /* emlxs_ub_destroy() */ 3326 3327 3328 /*ARGSUSED*/ 3329 extern int 3330 emlxs_pkt_abort(opaque_t fca_port_handle, fc_packet_t *pkt, int32_t sleep) 3331 { 3332 emlxs_port_t *port = (emlxs_port_t *)fca_port_handle; 3333 emlxs_hba_t *hba = HBA; 3334 emlxs_config_t *cfg = &CFG; 3335 3336 emlxs_buf_t *sbp; 3337 NODELIST *nlp; 3338 NODELIST *prev_nlp; 3339 uint8_t channelno; 3340 CHANNEL *cp; 3341 clock_t timeout; 3342 clock_t time; 3343 int32_t pkt_ret; 3344 IOCBQ *iocbq; 3345 IOCBQ *next; 3346 IOCBQ *prev; 3347 uint32_t found; 3348 uint32_t att_bit; 3349 uint32_t pass = 0; 3350 3351 sbp = (emlxs_buf_t *)pkt->pkt_fca_private; 3352 iocbq = &sbp->iocbq; 3353 nlp = (NODELIST *)sbp->node; 3354 cp = (CHANNEL *)sbp->channel; 3355 channelno = (cp) ? cp->channelno : 0; 3356 3357 if (!(port->flag & EMLXS_PORT_BOUND)) { 3358 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_abort_failed_msg, 3359 "Port not bound."); 3360 return (FC_UNBOUND); 3361 } 3362 3363 if (!(hba->flag & FC_ONLINE_MODE)) { 3364 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_abort_failed_msg, 3365 "Adapter offline."); 3366 return (FC_OFFLINE); 3367 } 3368 3369 /* ULP requires the aborted pkt to be completed */ 3370 /* back to ULP before returning from this call. */ 3371 /* SUN knows of problems with this call so they suggested that we */ 3372 /* always return a FC_FAILURE for this call, until it is worked out. */ 3373 3374 /* Check if pkt is no good */ 3375 if (!(sbp->pkt_flags & PACKET_VALID) || 3376 (sbp->pkt_flags & PACKET_ULP_OWNED)) { 3377 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_abort_failed_msg, 3378 "Bad sbp. flags=%x", sbp->pkt_flags); 3379 return (FC_FAILURE); 3380 } 3381 3382 /* Tag this now */ 3383 /* This will prevent any thread except ours from completing it */ 3384 mutex_enter(&sbp->mtx); 3385 3386 /* Check again if we still own this */ 3387 if (!(sbp->pkt_flags & PACKET_VALID) || 3388 (sbp->pkt_flags & PACKET_ULP_OWNED)) { 3389 mutex_exit(&sbp->mtx); 3390 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_abort_failed_msg, 3391 "Bad sbp. flags=%x", sbp->pkt_flags); 3392 return (FC_FAILURE); 3393 } 3394 3395 /* Check if pkt is a real polled command */ 3396 if (!(sbp->pkt_flags & PACKET_IN_ABORT) && 3397 (sbp->pkt_flags & PACKET_POLLED)) { 3398 mutex_exit(&sbp->mtx); 3399 3400 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_abort_failed_msg, 3401 "Attempting to abort a polled I/O. sbp=%p flags=%x", sbp, 3402 sbp->pkt_flags); 3403 return (FC_FAILURE); 3404 } 3405 3406 sbp->pkt_flags |= PACKET_POLLED; 3407 sbp->pkt_flags |= PACKET_IN_ABORT; 3408 3409 if (sbp->pkt_flags & (PACKET_IN_COMPLETION | PACKET_IN_FLUSH | 3410 PACKET_IN_TIMEOUT)) { 3411 mutex_exit(&sbp->mtx); 3412 3413 /* Do nothing, pkt already on its way out */ 3414 goto done; 3415 } 3416 3417 mutex_exit(&sbp->mtx); 3418 3419 begin: 3420 pass++; 3421 3422 mutex_enter(&EMLXS_TX_CHANNEL_LOCK); 3423 3424 if (sbp->pkt_flags & PACKET_IN_TXQ) { 3425 /* Find it on the queue */ 3426 found = 0; 3427 if (iocbq->flag & IOCB_PRIORITY) { 3428 /* Search the priority queue */ 3429 prev = NULL; 3430 next = (IOCBQ *) nlp->nlp_ptx[channelno].q_first; 3431 3432 while (next) { 3433 if (next == iocbq) { 3434 /* Remove it */ 3435 if (prev) { 3436 prev->next = iocbq->next; 3437 } 3438 3439 if (nlp->nlp_ptx[channelno].q_last == 3440 (void *)iocbq) { 3441 nlp->nlp_ptx[channelno].q_last = 3442 (void *)prev; 3443 } 3444 3445 if (nlp->nlp_ptx[channelno].q_first == 3446 (void *)iocbq) { 3447 nlp->nlp_ptx[channelno]. 3448 q_first = 3449 (void *)iocbq->next; 3450 } 3451 3452 nlp->nlp_ptx[channelno].q_cnt--; 3453 iocbq->next = NULL; 3454 found = 1; 3455 break; 3456 } 3457 3458 prev = next; 3459 next = next->next; 3460 } 3461 } else { 3462 /* Search the normal queue */ 3463 prev = NULL; 3464 next = (IOCBQ *) nlp->nlp_tx[channelno].q_first; 3465 3466 while (next) { 3467 if (next == iocbq) { 3468 /* Remove it */ 3469 if (prev) { 3470 prev->next = iocbq->next; 3471 } 3472 3473 if (nlp->nlp_tx[channelno].q_last == 3474 (void *)iocbq) { 3475 nlp->nlp_tx[channelno].q_last = 3476 (void *)prev; 3477 } 3478 3479 if (nlp->nlp_tx[channelno].q_first == 3480 (void *)iocbq) { 3481 nlp->nlp_tx[channelno].q_first = 3482 (void *)iocbq->next; 3483 } 3484 3485 nlp->nlp_tx[channelno].q_cnt--; 3486 iocbq->next = NULL; 3487 found = 1; 3488 break; 3489 } 3490 3491 prev = next; 3492 next = (IOCBQ *) next->next; 3493 } 3494 } 3495 3496 if (!found) { 3497 mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 3498 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_abort_failed_msg, 3499 "I/O not found in driver. sbp=%p flags=%x", sbp, 3500 sbp->pkt_flags); 3501 goto done; 3502 } 3503 3504 /* Check if node still needs servicing */ 3505 if ((nlp->nlp_ptx[channelno].q_first) || 3506 (nlp->nlp_tx[channelno].q_first && 3507 !(nlp->nlp_flag[channelno] & NLP_CLOSED))) { 3508 3509 /* 3510 * If this is the base node, 3511 * then don't shift the pointers 3512 */ 3513 /* We want to drain the base node before moving on */ 3514 if (!nlp->nlp_base) { 3515 /* Just shift channel queue */ 3516 /* pointers to next node */ 3517 cp->nodeq.q_last = (void *) nlp; 3518 cp->nodeq.q_first = nlp->nlp_next[channelno]; 3519 } 3520 } else { 3521 /* Remove node from channel queue */ 3522 3523 /* If this is the only node on list */ 3524 if (cp->nodeq.q_first == (void *)nlp && 3525 cp->nodeq.q_last == (void *)nlp) { 3526 cp->nodeq.q_last = NULL; 3527 cp->nodeq.q_first = NULL; 3528 cp->nodeq.q_cnt = 0; 3529 } else if (cp->nodeq.q_first == (void *)nlp) { 3530 cp->nodeq.q_first = nlp->nlp_next[channelno]; 3531 ((NODELIST *) cp->nodeq.q_last)-> 3532 nlp_next[channelno] = cp->nodeq.q_first; 3533 cp->nodeq.q_cnt--; 3534 } else { 3535 /* 3536 * This is a little more difficult find the 3537 * previous node in the circular channel queue 3538 */ 3539 prev_nlp = nlp; 3540 while (prev_nlp->nlp_next[channelno] != nlp) { 3541 prev_nlp = prev_nlp-> 3542 nlp_next[channelno]; 3543 } 3544 3545 prev_nlp->nlp_next[channelno] = 3546 nlp->nlp_next[channelno]; 3547 3548 if (cp->nodeq.q_last == (void *)nlp) { 3549 cp->nodeq.q_last = (void *)prev_nlp; 3550 } 3551 cp->nodeq.q_cnt--; 3552 3553 } 3554 3555 /* Clear node */ 3556 nlp->nlp_next[channelno] = NULL; 3557 } 3558 3559 /* Free the ULPIOTAG and the bmp */ 3560 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 3561 hba->fc_table[sbp->iotag] = NULL; 3562 emlxs_sli4_free_xri(hba, sbp, sbp->xp); 3563 } else { 3564 (void) emlxs_unregister_pkt(cp, sbp->iotag, 1); 3565 } 3566 3567 3568 mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 3569 3570 emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 3571 IOERR_ABORT_REQUESTED, 1); 3572 3573 goto done; 3574 } 3575 3576 mutex_exit(&EMLXS_TX_CHANNEL_LOCK); 3577 3578 3579 /* Check the chip queue */ 3580 mutex_enter(&EMLXS_FCTAB_LOCK); 3581 3582 if ((sbp->pkt_flags & PACKET_IN_CHIPQ) && 3583 !(sbp->pkt_flags & PACKET_XRI_CLOSED) && 3584 (sbp == hba->fc_table[sbp->iotag])) { 3585 3586 /* Create the abort IOCB */ 3587 if (hba->state >= FC_LINK_UP) { 3588 iocbq = 3589 emlxs_create_abort_xri_cn(port, sbp->node, 3590 sbp->iotag, cp, sbp->class, ABORT_TYPE_ABTS); 3591 3592 mutex_enter(&sbp->mtx); 3593 sbp->pkt_flags |= PACKET_XRI_CLOSED; 3594 sbp->ticks = 3595 hba->timer_tics + (4 * hba->fc_ratov) + 10; 3596 sbp->abort_attempts++; 3597 mutex_exit(&sbp->mtx); 3598 } else { 3599 iocbq = 3600 emlxs_create_close_xri_cn(port, sbp->node, 3601 sbp->iotag, cp); 3602 3603 mutex_enter(&sbp->mtx); 3604 sbp->pkt_flags |= PACKET_XRI_CLOSED; 3605 sbp->ticks = hba->timer_tics + 30; 3606 sbp->abort_attempts++; 3607 mutex_exit(&sbp->mtx); 3608 } 3609 3610 mutex_exit(&EMLXS_FCTAB_LOCK); 3611 3612 /* Send this iocbq */ 3613 if (iocbq) { 3614 EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, iocbq); 3615 iocbq = NULL; 3616 } 3617 3618 goto done; 3619 } 3620 3621 mutex_exit(&EMLXS_FCTAB_LOCK); 3622 3623 /* Pkt was not on any queues */ 3624 3625 /* Check again if we still own this */ 3626 if (!(sbp->pkt_flags & PACKET_VALID) || 3627 (sbp->pkt_flags & 3628 (PACKET_ULP_OWNED | PACKET_IN_COMPLETION | 3629 PACKET_IN_FLUSH | PACKET_IN_TIMEOUT))) { 3630 goto done; 3631 } 3632 3633 if (!sleep) { 3634 return (FC_FAILURE); 3635 } 3636 3637 /* Apparently the pkt was not found. Let's delay and try again */ 3638 if (pass < 5) { 3639 delay(drv_usectohz(5000000)); /* 5 seconds */ 3640 3641 /* Check again if we still own this */ 3642 if (!(sbp->pkt_flags & PACKET_VALID) || 3643 (sbp->pkt_flags & 3644 (PACKET_ULP_OWNED | PACKET_IN_COMPLETION | 3645 PACKET_IN_FLUSH | PACKET_IN_TIMEOUT))) { 3646 goto done; 3647 } 3648 3649 goto begin; 3650 } 3651 3652 force_it: 3653 3654 /* Force the completion now */ 3655 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 3656 "Abort: Completing an IO thats not outstanding: %x", sbp->iotag); 3657 3658 /* Now complete it */ 3659 emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, IOERR_ABORT_REQUESTED, 3660 1); 3661 3662 done: 3663 3664 /* Now wait for the pkt to complete */ 3665 if (!(sbp->pkt_flags & PACKET_COMPLETED)) { 3666 /* Set thread timeout */ 3667 timeout = emlxs_timeout(hba, 30); 3668 3669 /* Check for panic situation */ 3670 if (ddi_in_panic()) { 3671 3672 /* 3673 * In panic situations there will be one thread with no 3674 * interrrupts (hard or soft) and no timers 3675 */ 3676 3677 /* 3678 * We must manually poll everything in this thread 3679 * to keep the driver going. 3680 */ 3681 3682 cp = (CHANNEL *)sbp->channel; 3683 switch (cp->channelno) { 3684 case FC_FCP_RING: 3685 att_bit = HA_R0ATT; 3686 break; 3687 3688 case FC_IP_RING: 3689 att_bit = HA_R1ATT; 3690 break; 3691 3692 case FC_ELS_RING: 3693 att_bit = HA_R2ATT; 3694 break; 3695 3696 case FC_CT_RING: 3697 att_bit = HA_R3ATT; 3698 break; 3699 } 3700 3701 /* Keep polling the chip until our IO is completed */ 3702 (void) drv_getparm(LBOLT, &time); 3703 while ((time < timeout) && 3704 !(sbp->pkt_flags & PACKET_COMPLETED)) { 3705 EMLXS_SLI_POLL_INTR(hba, att_bit); 3706 (void) drv_getparm(LBOLT, &time); 3707 } 3708 } else { 3709 /* Wait for IO completion or timeout */ 3710 mutex_enter(&EMLXS_PKT_LOCK); 3711 pkt_ret = 0; 3712 while ((pkt_ret != -1) && 3713 !(sbp->pkt_flags & PACKET_COMPLETED)) { 3714 pkt_ret = 3715 cv_timedwait(&EMLXS_PKT_CV, 3716 &EMLXS_PKT_LOCK, timeout); 3717 } 3718 mutex_exit(&EMLXS_PKT_LOCK); 3719 } 3720 3721 /* Check if timeout occured. This is not good. */ 3722 /* Something happened to our IO. */ 3723 if (!(sbp->pkt_flags & PACKET_COMPLETED)) { 3724 /* Force the completion now */ 3725 goto force_it; 3726 } 3727 } 3728 #if (EMLXS_MODREVX == EMLXS_MODREV2X) 3729 emlxs_unswap_pkt(sbp); 3730 #endif /* EMLXS_MODREV2X */ 3731 3732 /* Check again if we still own this */ 3733 if ((sbp->pkt_flags & PACKET_VALID) && 3734 !(sbp->pkt_flags & PACKET_ULP_OWNED)) { 3735 mutex_enter(&sbp->mtx); 3736 if ((sbp->pkt_flags & PACKET_VALID) && 3737 !(sbp->pkt_flags & PACKET_ULP_OWNED)) { 3738 sbp->pkt_flags |= PACKET_ULP_OWNED; 3739 } 3740 mutex_exit(&sbp->mtx); 3741 } 3742 3743 #ifdef ULP_PATCH5 3744 if (cfg[CFG_ENABLE_PATCH].current & ULP_PATCH5) { 3745 return (FC_FAILURE); 3746 } 3747 #endif /* ULP_PATCH5 */ 3748 3749 return (FC_SUCCESS); 3750 3751 } /* emlxs_pkt_abort() */ 3752 3753 3754 static void 3755 emlxs_abort_all(emlxs_hba_t *hba, uint32_t *tx, uint32_t *chip) 3756 { 3757 emlxs_port_t *port = &PPORT; 3758 fc_packet_t *pkt; 3759 emlxs_buf_t *sbp; 3760 uint32_t i; 3761 uint32_t flg; 3762 uint32_t rc; 3763 uint32_t txcnt; 3764 uint32_t chipcnt; 3765 3766 txcnt = 0; 3767 chipcnt = 0; 3768 3769 mutex_enter(&EMLXS_FCTAB_LOCK); 3770 for (i = 0; i < hba->max_iotag; i++) { 3771 sbp = hba->fc_table[i]; 3772 if (sbp == NULL || sbp == STALE_PACKET) { 3773 continue; 3774 } 3775 flg = (sbp->pkt_flags & PACKET_IN_CHIPQ); 3776 pkt = PRIV2PKT(sbp); 3777 mutex_exit(&EMLXS_FCTAB_LOCK); 3778 rc = emlxs_pkt_abort(port, pkt, 0); 3779 if (rc == FC_SUCCESS) { 3780 if (flg) { 3781 chipcnt++; 3782 } else { 3783 txcnt++; 3784 } 3785 } 3786 mutex_enter(&EMLXS_FCTAB_LOCK); 3787 } 3788 mutex_exit(&EMLXS_FCTAB_LOCK); 3789 *tx = txcnt; 3790 *chip = chipcnt; 3791 } /* emlxs_abort_all() */ 3792 3793 3794 extern int32_t 3795 emlxs_reset(opaque_t fca_port_handle, uint32_t cmd) 3796 { 3797 emlxs_port_t *port = (emlxs_port_t *)fca_port_handle; 3798 emlxs_hba_t *hba = HBA; 3799 int rval; 3800 int ret; 3801 clock_t timeout; 3802 3803 if (!(port->flag & EMLXS_PORT_BOUND)) { 3804 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 3805 "fca_reset failed. Port not bound."); 3806 3807 return (FC_UNBOUND); 3808 } 3809 3810 switch (cmd) { 3811 case FC_FCA_LINK_RESET: 3812 3813 if (!(hba->flag & FC_ONLINE_MODE) || 3814 (hba->state <= FC_LINK_DOWN)) { 3815 return (FC_SUCCESS); 3816 } 3817 3818 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 3819 "fca_reset: Resetting Link."); 3820 3821 mutex_enter(&EMLXS_LINKUP_LOCK); 3822 hba->linkup_wait_flag = TRUE; 3823 mutex_exit(&EMLXS_LINKUP_LOCK); 3824 3825 if (emlxs_reset_link(hba, 1, 1)) { 3826 mutex_enter(&EMLXS_LINKUP_LOCK); 3827 hba->linkup_wait_flag = FALSE; 3828 mutex_exit(&EMLXS_LINKUP_LOCK); 3829 3830 return (FC_FAILURE); 3831 } 3832 3833 mutex_enter(&EMLXS_LINKUP_LOCK); 3834 timeout = emlxs_timeout(hba, 60); 3835 ret = 0; 3836 while ((ret != -1) && (hba->linkup_wait_flag == TRUE)) { 3837 ret = 3838 cv_timedwait(&EMLXS_LINKUP_CV, &EMLXS_LINKUP_LOCK, 3839 timeout); 3840 } 3841 3842 hba->linkup_wait_flag = FALSE; 3843 mutex_exit(&EMLXS_LINKUP_LOCK); 3844 3845 if (ret == -1) { 3846 return (FC_FAILURE); 3847 } 3848 3849 return (FC_SUCCESS); 3850 3851 case FC_FCA_CORE: 3852 #ifdef DUMP_SUPPORT 3853 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 3854 "fca_reset: Core dump."); 3855 3856 /* Schedule a USER dump */ 3857 emlxs_dump(hba, EMLXS_USER_DUMP, 0, 0); 3858 3859 /* Wait for dump to complete */ 3860 emlxs_dump_wait(hba); 3861 3862 return (FC_SUCCESS); 3863 #endif /* DUMP_SUPPORT */ 3864 3865 case FC_FCA_RESET: 3866 case FC_FCA_RESET_CORE: 3867 3868 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 3869 "fca_reset: Resetting Adapter."); 3870 3871 rval = FC_SUCCESS; 3872 3873 if (emlxs_offline(hba) == 0) { 3874 (void) emlxs_online(hba); 3875 } else { 3876 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 3877 "fca_reset: Adapter reset failed. Device busy."); 3878 3879 rval = FC_DEVICE_BUSY; 3880 } 3881 3882 return (rval); 3883 3884 default: 3885 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 3886 "fca_reset: Unknown command. cmd=%x", cmd); 3887 3888 break; 3889 } 3890 3891 return (FC_FAILURE); 3892 3893 } /* emlxs_reset() */ 3894 3895 3896 extern int 3897 emlxs_port_manage(opaque_t fca_port_handle, fc_fca_pm_t *pm) 3898 { 3899 emlxs_port_t *port = (emlxs_port_t *)fca_port_handle; 3900 emlxs_hba_t *hba = HBA; 3901 int32_t ret; 3902 emlxs_vpd_t *vpd = &VPD; 3903 3904 3905 ret = FC_SUCCESS; 3906 3907 if (!(port->flag & EMLXS_PORT_BOUND)) { 3908 return (FC_UNBOUND); 3909 } 3910 3911 3912 #ifdef IDLE_TIMER 3913 emlxs_pm_busy_component(hba); 3914 #endif /* IDLE_TIMER */ 3915 3916 switch (pm->pm_cmd_code) { 3917 3918 case FC_PORT_GET_FW_REV: 3919 { 3920 char buffer[128]; 3921 3922 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 3923 "fca_port_manage: FC_PORT_GET_FW_REV"); 3924 3925 (void) sprintf(buffer, "%s %s", hba->model_info.model, 3926 vpd->fw_version); 3927 bzero(pm->pm_data_buf, pm->pm_data_len); 3928 3929 if (pm->pm_data_len < strlen(buffer) + 1) { 3930 ret = FC_NOMEM; 3931 3932 break; 3933 } 3934 3935 (void) strcpy(pm->pm_data_buf, buffer); 3936 break; 3937 } 3938 3939 case FC_PORT_GET_FCODE_REV: 3940 { 3941 char buffer[128]; 3942 3943 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 3944 "fca_port_manage: FC_PORT_GET_FCODE_REV"); 3945 3946 /* Force update here just to be sure */ 3947 emlxs_get_fcode_version(hba); 3948 3949 (void) sprintf(buffer, "%s %s", hba->model_info.model, 3950 vpd->fcode_version); 3951 bzero(pm->pm_data_buf, pm->pm_data_len); 3952 3953 if (pm->pm_data_len < strlen(buffer) + 1) { 3954 ret = FC_NOMEM; 3955 break; 3956 } 3957 3958 (void) strcpy(pm->pm_data_buf, buffer); 3959 break; 3960 } 3961 3962 case FC_PORT_GET_DUMP_SIZE: 3963 { 3964 #ifdef DUMP_SUPPORT 3965 uint32_t dump_size = 0; 3966 3967 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 3968 "fca_port_manage: FC_PORT_GET_DUMP_SIZE"); 3969 3970 if (pm->pm_data_len < sizeof (uint32_t)) { 3971 ret = FC_NOMEM; 3972 break; 3973 } 3974 3975 (void) emlxs_get_dump(hba, NULL, &dump_size); 3976 3977 *((uint32_t *)pm->pm_data_buf) = dump_size; 3978 3979 #else 3980 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 3981 "fca_port_manage: FC_PORT_GET_DUMP_SIZE unsupported."); 3982 3983 #endif /* DUMP_SUPPORT */ 3984 3985 break; 3986 } 3987 3988 case FC_PORT_GET_DUMP: 3989 { 3990 #ifdef DUMP_SUPPORT 3991 uint32_t dump_size = 0; 3992 3993 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 3994 "fca_port_manage: FC_PORT_GET_DUMP"); 3995 3996 (void) emlxs_get_dump(hba, NULL, &dump_size); 3997 3998 if (pm->pm_data_len < dump_size) { 3999 ret = FC_NOMEM; 4000 break; 4001 } 4002 4003 (void) emlxs_get_dump(hba, (uint8_t *)pm->pm_data_buf, 4004 (uint32_t *)&dump_size); 4005 #else 4006 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4007 "fca_port_manage: FC_PORT_GET_DUMP unsupported."); 4008 4009 #endif /* DUMP_SUPPORT */ 4010 4011 break; 4012 } 4013 4014 case FC_PORT_FORCE_DUMP: 4015 { 4016 #ifdef DUMP_SUPPORT 4017 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4018 "fca_port_manage: FC_PORT_FORCE_DUMP"); 4019 4020 /* Schedule a USER dump */ 4021 emlxs_dump(hba, EMLXS_USER_DUMP, 0, 0); 4022 4023 /* Wait for dump to complete */ 4024 emlxs_dump_wait(hba); 4025 #else 4026 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4027 "fca_port_manage: FC_PORT_FORCE_DUMP unsupported."); 4028 4029 #endif /* DUMP_SUPPORT */ 4030 break; 4031 } 4032 4033 case FC_PORT_LINK_STATE: 4034 { 4035 uint32_t *link_state; 4036 4037 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4038 "fca_port_manage: FC_PORT_LINK_STATE"); 4039 4040 if (pm->pm_stat_len != sizeof (*link_state)) { 4041 ret = FC_NOMEM; 4042 break; 4043 } 4044 4045 if (pm->pm_cmd_buf != NULL) { 4046 /* 4047 * Can't look beyond the FCA port. 4048 */ 4049 ret = FC_INVALID_REQUEST; 4050 break; 4051 } 4052 4053 link_state = (uint32_t *)pm->pm_stat_buf; 4054 4055 /* Set the state */ 4056 if (hba->state >= FC_LINK_UP) { 4057 /* Check for loop topology */ 4058 if (hba->topology == TOPOLOGY_LOOP) { 4059 *link_state = FC_STATE_LOOP; 4060 } else { 4061 *link_state = FC_STATE_ONLINE; 4062 } 4063 4064 /* Set the link speed */ 4065 switch (hba->linkspeed) { 4066 case LA_2GHZ_LINK: 4067 *link_state |= FC_STATE_2GBIT_SPEED; 4068 break; 4069 case LA_4GHZ_LINK: 4070 *link_state |= FC_STATE_4GBIT_SPEED; 4071 break; 4072 case LA_8GHZ_LINK: 4073 *link_state |= FC_STATE_8GBIT_SPEED; 4074 break; 4075 case LA_10GHZ_LINK: 4076 *link_state |= FC_STATE_10GBIT_SPEED; 4077 break; 4078 case LA_1GHZ_LINK: 4079 default: 4080 *link_state |= FC_STATE_1GBIT_SPEED; 4081 break; 4082 } 4083 } else { 4084 *link_state = FC_STATE_OFFLINE; 4085 } 4086 4087 break; 4088 } 4089 4090 4091 case FC_PORT_ERR_STATS: 4092 case FC_PORT_RLS: 4093 { 4094 MAILBOXQ *mbq; 4095 MAILBOX *mb; 4096 fc_rls_acc_t *bp; 4097 4098 if (!(hba->flag & FC_ONLINE_MODE)) { 4099 return (FC_OFFLINE); 4100 } 4101 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4102 "fca_port_manage: FC_PORT_RLS / FC_PORT_ERR_STATS"); 4103 4104 if (pm->pm_data_len < sizeof (fc_rls_acc_t)) { 4105 ret = FC_NOMEM; 4106 break; 4107 } 4108 4109 if ((mbq = (MAILBOXQ *)emlxs_mem_get(hba, 4110 MEM_MBOX, 1)) == 0) { 4111 ret = FC_NOMEM; 4112 break; 4113 } 4114 mb = (MAILBOX *)mbq; 4115 4116 emlxs_mb_read_lnk_stat(hba, mbq); 4117 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) 4118 != MBX_SUCCESS) { 4119 ret = FC_PBUSY; 4120 } else { 4121 bp = (fc_rls_acc_t *)pm->pm_data_buf; 4122 4123 bp->rls_link_fail = mb->un.varRdLnk.linkFailureCnt; 4124 bp->rls_sync_loss = mb->un.varRdLnk.lossSyncCnt; 4125 bp->rls_sig_loss = mb->un.varRdLnk.lossSignalCnt; 4126 bp->rls_prim_seq_err = mb->un.varRdLnk.primSeqErrCnt; 4127 bp->rls_invalid_word = 4128 mb->un.varRdLnk.invalidXmitWord; 4129 bp->rls_invalid_crc = mb->un.varRdLnk.crcCnt; 4130 } 4131 4132 (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); 4133 break; 4134 } 4135 4136 case FC_PORT_DOWNLOAD_FW: 4137 if (!(hba->flag & FC_ONLINE_MODE)) { 4138 return (FC_OFFLINE); 4139 } 4140 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4141 "fca_port_manage: FC_PORT_DOWNLOAD_FW"); 4142 ret = emlxs_fw_download(hba, pm->pm_data_buf, 4143 pm->pm_data_len, 1); 4144 break; 4145 4146 case FC_PORT_DOWNLOAD_FCODE: 4147 if (!(hba->flag & FC_ONLINE_MODE)) { 4148 return (FC_OFFLINE); 4149 } 4150 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4151 "fca_port_manage: FC_PORT_DOWNLOAD_FCODE"); 4152 ret = emlxs_fw_download(hba, pm->pm_data_buf, 4153 pm->pm_data_len, 1); 4154 break; 4155 4156 case FC_PORT_DIAG: 4157 { 4158 uint32_t errno = 0; 4159 uint32_t did = 0; 4160 uint32_t pattern = 0; 4161 4162 switch (pm->pm_cmd_flags) { 4163 case EMLXS_DIAG_BIU: 4164 4165 if (!(hba->flag & FC_ONLINE_MODE)) { 4166 return (FC_OFFLINE); 4167 } 4168 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4169 "fca_port_manage: EMLXS_DIAG_BIU"); 4170 4171 if (pm->pm_data_len) { 4172 pattern = *((uint32_t *)pm->pm_data_buf); 4173 } 4174 4175 errno = emlxs_diag_biu_run(hba, pattern); 4176 4177 if (pm->pm_stat_len == sizeof (errno)) { 4178 *(int *)pm->pm_stat_buf = errno; 4179 } 4180 4181 break; 4182 4183 4184 case EMLXS_DIAG_POST: 4185 4186 if (!(hba->flag & FC_ONLINE_MODE)) { 4187 return (FC_OFFLINE); 4188 } 4189 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4190 "fca_port_manage: EMLXS_DIAG_POST"); 4191 4192 errno = emlxs_diag_post_run(hba); 4193 4194 if (pm->pm_stat_len == sizeof (errno)) { 4195 *(int *)pm->pm_stat_buf = errno; 4196 } 4197 4198 break; 4199 4200 4201 case EMLXS_DIAG_ECHO: 4202 4203 if (!(hba->flag & FC_ONLINE_MODE)) { 4204 return (FC_OFFLINE); 4205 } 4206 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4207 "fca_port_manage: EMLXS_DIAG_ECHO"); 4208 4209 if (pm->pm_cmd_len != sizeof (uint32_t)) { 4210 ret = FC_INVALID_REQUEST; 4211 break; 4212 } 4213 4214 did = *((uint32_t *)pm->pm_cmd_buf); 4215 4216 if (pm->pm_data_len) { 4217 pattern = *((uint32_t *)pm->pm_data_buf); 4218 } 4219 4220 errno = emlxs_diag_echo_run(port, did, pattern); 4221 4222 if (pm->pm_stat_len == sizeof (errno)) { 4223 *(int *)pm->pm_stat_buf = errno; 4224 } 4225 4226 break; 4227 4228 4229 case EMLXS_PARM_GET_NUM: 4230 { 4231 uint32_t *num; 4232 emlxs_config_t *cfg; 4233 uint32_t i; 4234 uint32_t count; 4235 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4236 "fca_port_manage: EMLXS_PARM_GET_NUM"); 4237 4238 if (pm->pm_stat_len < sizeof (uint32_t)) { 4239 ret = FC_NOMEM; 4240 break; 4241 } 4242 4243 num = (uint32_t *)pm->pm_stat_buf; 4244 count = 0; 4245 cfg = &CFG; 4246 for (i = 0; i < NUM_CFG_PARAM; i++, cfg++) { 4247 if (!(cfg->flags & PARM_HIDDEN)) { 4248 count++; 4249 } 4250 4251 } 4252 4253 *num = count; 4254 4255 break; 4256 } 4257 4258 case EMLXS_PARM_GET_LIST: 4259 { 4260 emlxs_parm_t *parm; 4261 emlxs_config_t *cfg; 4262 uint32_t i; 4263 uint32_t max_count; 4264 4265 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4266 "fca_port_manage: EMLXS_PARM_GET_LIST"); 4267 4268 if (pm->pm_stat_len < sizeof (emlxs_parm_t)) { 4269 ret = FC_NOMEM; 4270 break; 4271 } 4272 4273 max_count = pm->pm_stat_len / sizeof (emlxs_parm_t); 4274 4275 parm = (emlxs_parm_t *)pm->pm_stat_buf; 4276 cfg = &CFG; 4277 for (i = 0; i < NUM_CFG_PARAM && max_count; i++, 4278 cfg++) { 4279 if (!(cfg->flags & PARM_HIDDEN)) { 4280 (void) strcpy(parm->label, cfg->string); 4281 parm->min = cfg->low; 4282 parm->max = cfg->hi; 4283 parm->def = cfg->def; 4284 parm->current = cfg->current; 4285 parm->flags = cfg->flags; 4286 (void) strcpy(parm->help, cfg->help); 4287 parm++; 4288 max_count--; 4289 } 4290 } 4291 4292 break; 4293 } 4294 4295 case EMLXS_PARM_GET: 4296 { 4297 emlxs_parm_t *parm_in; 4298 emlxs_parm_t *parm_out; 4299 emlxs_config_t *cfg; 4300 uint32_t i; 4301 uint32_t len; 4302 4303 if (pm->pm_cmd_len < sizeof (emlxs_parm_t)) { 4304 EMLXS_MSGF(EMLXS_CONTEXT, 4305 &emlxs_sfs_debug_msg, 4306 "fca_port_manage: EMLXS_PARM_GET. " 4307 "inbuf too small."); 4308 4309 ret = FC_BADCMD; 4310 break; 4311 } 4312 4313 if (pm->pm_stat_len < sizeof (emlxs_parm_t)) { 4314 EMLXS_MSGF(EMLXS_CONTEXT, 4315 &emlxs_sfs_debug_msg, 4316 "fca_port_manage: EMLXS_PARM_GET. " 4317 "outbuf too small"); 4318 4319 ret = FC_BADCMD; 4320 break; 4321 } 4322 4323 parm_in = (emlxs_parm_t *)pm->pm_cmd_buf; 4324 parm_out = (emlxs_parm_t *)pm->pm_stat_buf; 4325 len = strlen(parm_in->label); 4326 cfg = &CFG; 4327 ret = FC_BADOBJECT; 4328 4329 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4330 "fca_port_manage: EMLXS_PARM_GET: %s", 4331 parm_in->label); 4332 4333 for (i = 0; i < NUM_CFG_PARAM; i++, cfg++) { 4334 if (len == strlen(cfg->string) && 4335 (strcmp(parm_in->label, 4336 cfg->string) == 0)) { 4337 (void) strcpy(parm_out->label, 4338 cfg->string); 4339 parm_out->min = cfg->low; 4340 parm_out->max = cfg->hi; 4341 parm_out->def = cfg->def; 4342 parm_out->current = cfg->current; 4343 parm_out->flags = cfg->flags; 4344 (void) strcpy(parm_out->help, 4345 cfg->help); 4346 4347 ret = FC_SUCCESS; 4348 break; 4349 } 4350 } 4351 4352 break; 4353 } 4354 4355 case EMLXS_PARM_SET: 4356 { 4357 emlxs_parm_t *parm_in; 4358 emlxs_parm_t *parm_out; 4359 emlxs_config_t *cfg; 4360 uint32_t i; 4361 uint32_t len; 4362 4363 if (pm->pm_cmd_len < sizeof (emlxs_parm_t)) { 4364 EMLXS_MSGF(EMLXS_CONTEXT, 4365 &emlxs_sfs_debug_msg, 4366 "fca_port_manage: EMLXS_PARM_GET. " 4367 "inbuf too small."); 4368 4369 ret = FC_BADCMD; 4370 break; 4371 } 4372 4373 if (pm->pm_stat_len < sizeof (emlxs_parm_t)) { 4374 EMLXS_MSGF(EMLXS_CONTEXT, 4375 &emlxs_sfs_debug_msg, 4376 "fca_port_manage: EMLXS_PARM_GET. " 4377 "outbuf too small"); 4378 ret = FC_BADCMD; 4379 break; 4380 } 4381 4382 parm_in = (emlxs_parm_t *)pm->pm_cmd_buf; 4383 parm_out = (emlxs_parm_t *)pm->pm_stat_buf; 4384 len = strlen(parm_in->label); 4385 cfg = &CFG; 4386 ret = FC_BADOBJECT; 4387 4388 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4389 "fca_port_manage: EMLXS_PARM_SET: %s=0x%x,%d", 4390 parm_in->label, parm_in->current, 4391 parm_in->current); 4392 4393 for (i = 0; i < NUM_CFG_PARAM; i++, cfg++) { 4394 /* Find matching parameter string */ 4395 if (len == strlen(cfg->string) && 4396 (strcmp(parm_in->label, 4397 cfg->string) == 0)) { 4398 /* Attempt to update parameter */ 4399 if (emlxs_set_parm(hba, i, 4400 parm_in->current) == FC_SUCCESS) { 4401 (void) strcpy(parm_out->label, 4402 cfg->string); 4403 parm_out->min = cfg->low; 4404 parm_out->max = cfg->hi; 4405 parm_out->def = cfg->def; 4406 parm_out->current = 4407 cfg->current; 4408 parm_out->flags = cfg->flags; 4409 (void) strcpy(parm_out->help, 4410 cfg->help); 4411 4412 ret = FC_SUCCESS; 4413 } 4414 4415 break; 4416 } 4417 } 4418 4419 break; 4420 } 4421 4422 case EMLXS_LOG_GET: 4423 { 4424 emlxs_log_req_t *req; 4425 emlxs_log_resp_t *resp; 4426 uint32_t len; 4427 4428 /* Check command size */ 4429 if (pm->pm_cmd_len < sizeof (emlxs_log_req_t)) { 4430 ret = FC_BADCMD; 4431 break; 4432 } 4433 4434 /* Get the request */ 4435 req = (emlxs_log_req_t *)pm->pm_cmd_buf; 4436 4437 /* Calculate the response length from the request */ 4438 len = sizeof (emlxs_log_resp_t) + 4439 (req->count * MAX_LOG_MSG_LENGTH); 4440 4441 /* Check the response buffer length */ 4442 if (pm->pm_stat_len < len) { 4443 ret = FC_BADCMD; 4444 break; 4445 } 4446 4447 /* Get the response pointer */ 4448 resp = (emlxs_log_resp_t *)pm->pm_stat_buf; 4449 4450 /* Get the request log enties */ 4451 (void) emlxs_msg_log_get(hba, req, resp); 4452 4453 ret = FC_SUCCESS; 4454 break; 4455 } 4456 4457 case EMLXS_GET_BOOT_REV: 4458 { 4459 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4460 "fca_port_manage: EMLXS_GET_BOOT_REV"); 4461 4462 if (pm->pm_stat_len < strlen(vpd->boot_version)) { 4463 ret = FC_NOMEM; 4464 break; 4465 } 4466 4467 bzero(pm->pm_stat_buf, pm->pm_stat_len); 4468 (void) sprintf(pm->pm_stat_buf, "%s %s", 4469 hba->model_info.model, vpd->boot_version); 4470 4471 break; 4472 } 4473 4474 case EMLXS_DOWNLOAD_BOOT: 4475 if (!(hba->flag & FC_ONLINE_MODE)) { 4476 return (FC_OFFLINE); 4477 } 4478 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4479 "fca_port_manage: EMLXS_DOWNLOAD_BOOT"); 4480 4481 ret = emlxs_fw_download(hba, pm->pm_data_buf, 4482 pm->pm_data_len, 1); 4483 break; 4484 4485 case EMLXS_DOWNLOAD_CFL: 4486 { 4487 uint32_t *buffer; 4488 uint32_t region; 4489 uint32_t length; 4490 4491 if (!(hba->flag & FC_ONLINE_MODE)) { 4492 return (FC_OFFLINE); 4493 } 4494 4495 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4496 "fca_port_manage: EMLXS_DOWNLOAD_CFL"); 4497 4498 /* Extract the region number from the first word. */ 4499 buffer = (uint32_t *)pm->pm_data_buf; 4500 region = *buffer++; 4501 4502 /* Adjust the image length for the header word */ 4503 length = pm->pm_data_len - 4; 4504 4505 ret = 4506 emlxs_cfl_download(hba, region, (caddr_t)buffer, 4507 length); 4508 break; 4509 } 4510 4511 case EMLXS_VPD_GET: 4512 { 4513 emlxs_vpd_desc_t *vpd_out; 4514 4515 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4516 "fca_port_manage: EMLXS_VPD_GET"); 4517 4518 if (pm->pm_stat_len < sizeof (emlxs_vpd_desc_t)) { 4519 ret = FC_BADCMD; 4520 break; 4521 } 4522 4523 vpd_out = (emlxs_vpd_desc_t *)pm->pm_stat_buf; 4524 bzero(vpd_out, sizeof (emlxs_vpd_desc_t)); 4525 4526 (void) strncpy(vpd_out->id, vpd->id, 4527 sizeof (vpd_out->id)); 4528 (void) strncpy(vpd_out->part_num, vpd->part_num, 4529 sizeof (vpd_out->part_num)); 4530 (void) strncpy(vpd_out->eng_change, vpd->eng_change, 4531 sizeof (vpd_out->eng_change)); 4532 (void) strncpy(vpd_out->manufacturer, vpd->manufacturer, 4533 sizeof (vpd_out->manufacturer)); 4534 (void) strncpy(vpd_out->serial_num, vpd->serial_num, 4535 sizeof (vpd_out->serial_num)); 4536 (void) strncpy(vpd_out->model, vpd->model, 4537 sizeof (vpd_out->model)); 4538 (void) strncpy(vpd_out->model_desc, vpd->model_desc, 4539 sizeof (vpd_out->model_desc)); 4540 (void) strncpy(vpd_out->port_num, vpd->port_num, 4541 sizeof (vpd_out->port_num)); 4542 (void) strncpy(vpd_out->prog_types, vpd->prog_types, 4543 sizeof (vpd_out->prog_types)); 4544 4545 ret = FC_SUCCESS; 4546 4547 break; 4548 } 4549 4550 case EMLXS_GET_FCIO_REV: 4551 { 4552 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4553 "fca_port_manage: EMLXS_GET_FCIO_REV"); 4554 4555 if (pm->pm_stat_len < sizeof (uint32_t)) { 4556 ret = FC_NOMEM; 4557 break; 4558 } 4559 4560 bzero(pm->pm_stat_buf, pm->pm_stat_len); 4561 *(uint32_t *)pm->pm_stat_buf = FCIO_REV; 4562 4563 break; 4564 } 4565 4566 case EMLXS_GET_DFC_REV: 4567 { 4568 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4569 "fca_port_manage: EMLXS_GET_DFC_REV"); 4570 4571 if (pm->pm_stat_len < sizeof (uint32_t)) { 4572 ret = FC_NOMEM; 4573 break; 4574 } 4575 4576 bzero(pm->pm_stat_buf, pm->pm_stat_len); 4577 *(uint32_t *)pm->pm_stat_buf = DFC_REV; 4578 4579 break; 4580 } 4581 4582 case EMLXS_SET_BOOT_STATE: 4583 case EMLXS_SET_BOOT_STATE_old: 4584 { 4585 uint32_t state; 4586 4587 if (!(hba->flag & FC_ONLINE_MODE)) { 4588 return (FC_OFFLINE); 4589 } 4590 if (pm->pm_cmd_len < sizeof (uint32_t)) { 4591 EMLXS_MSGF(EMLXS_CONTEXT, 4592 &emlxs_sfs_debug_msg, 4593 "fca_port_manage: EMLXS_SET_BOOT_STATE"); 4594 ret = FC_BADCMD; 4595 break; 4596 } 4597 4598 state = *(uint32_t *)pm->pm_cmd_buf; 4599 4600 if (state == 0) { 4601 EMLXS_MSGF(EMLXS_CONTEXT, 4602 &emlxs_sfs_debug_msg, 4603 "fca_port_manage: EMLXS_SET_BOOT_STATE: " 4604 "Disable"); 4605 ret = emlxs_boot_code_disable(hba); 4606 } else { 4607 EMLXS_MSGF(EMLXS_CONTEXT, 4608 &emlxs_sfs_debug_msg, 4609 "fca_port_manage: EMLXS_SET_BOOT_STATE: " 4610 "Enable"); 4611 ret = emlxs_boot_code_enable(hba); 4612 } 4613 4614 break; 4615 } 4616 4617 case EMLXS_GET_BOOT_STATE: 4618 case EMLXS_GET_BOOT_STATE_old: 4619 { 4620 if (!(hba->flag & FC_ONLINE_MODE)) { 4621 return (FC_OFFLINE); 4622 } 4623 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4624 "fca_port_manage: EMLXS_GET_BOOT_STATE"); 4625 4626 if (pm->pm_stat_len < sizeof (uint32_t)) { 4627 ret = FC_NOMEM; 4628 break; 4629 } 4630 bzero(pm->pm_stat_buf, pm->pm_stat_len); 4631 4632 ret = emlxs_boot_code_state(hba); 4633 4634 if (ret == FC_SUCCESS) { 4635 *(uint32_t *)pm->pm_stat_buf = 1; 4636 ret = FC_SUCCESS; 4637 } else if (ret == FC_FAILURE) { 4638 ret = FC_SUCCESS; 4639 } 4640 4641 break; 4642 } 4643 4644 case EMLXS_HW_ERROR_TEST: 4645 { 4646 if (!(hba->flag & FC_ONLINE_MODE)) { 4647 return (FC_OFFLINE); 4648 } 4649 4650 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4651 "fca_port_manage: EMLXS_HW_ERROR_TEST"); 4652 4653 /* Trigger a mailbox timeout */ 4654 hba->mbox_timer = hba->timer_tics; 4655 4656 break; 4657 } 4658 4659 case EMLXS_TEST_CODE: 4660 { 4661 uint32_t *cmd; 4662 4663 if (!(hba->flag & FC_ONLINE_MODE)) { 4664 return (FC_OFFLINE); 4665 } 4666 4667 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4668 "fca_port_manage: EMLXS_TEST_CODE"); 4669 4670 if (pm->pm_cmd_len < sizeof (uint32_t)) { 4671 EMLXS_MSGF(EMLXS_CONTEXT, 4672 &emlxs_sfs_debug_msg, 4673 "fca_port_manage: EMLXS_TEST_CODE. " 4674 "inbuf to small."); 4675 4676 ret = FC_BADCMD; 4677 break; 4678 } 4679 4680 cmd = (uint32_t *)pm->pm_cmd_buf; 4681 4682 ret = emlxs_test(hba, cmd[0], 4683 (pm->pm_cmd_len/sizeof (uint32_t)) - 1, &cmd[1]); 4684 4685 break; 4686 } 4687 4688 case EMLXS_BAR_IO: 4689 { 4690 uint32_t *cmd; 4691 uint32_t *datap; 4692 uint32_t offset; 4693 caddr_t addr; 4694 uint32_t i; 4695 uint32_t tx_cnt; 4696 uint32_t chip_cnt; 4697 4698 cmd = (uint32_t *)pm->pm_cmd_buf; 4699 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4700 "fca_port_manage: EMLXS_BAR_IO %x %x %x", 4701 cmd[0], cmd[1], cmd[2]); 4702 4703 offset = cmd[1]; 4704 4705 ret = FC_SUCCESS; 4706 4707 switch (cmd[0]) { 4708 case 2: /* bar1read */ 4709 if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) { 4710 return (FC_BADCMD); 4711 } 4712 4713 /* Registers in this range are invalid */ 4714 if ((offset >= 0x4C00) && (offset < 0x5000)) { 4715 return (FC_BADCMD); 4716 } 4717 if ((offset >= 0x5800) || (offset & 0x3)) { 4718 return (FC_BADCMD); 4719 } 4720 datap = (uint32_t *)pm->pm_stat_buf; 4721 4722 for (i = 0; i < pm->pm_stat_len; 4723 i += sizeof (uint32_t)) { 4724 if ((offset >= 0x4C00) && 4725 (offset < 0x5000)) { 4726 pm->pm_stat_len = i; 4727 break; 4728 } 4729 if (offset >= 0x5800) { 4730 pm->pm_stat_len = i; 4731 break; 4732 } 4733 addr = hba->sli.sli4.bar1_addr + offset; 4734 *datap = READ_BAR1_REG(hba, addr); 4735 datap++; 4736 offset += sizeof (uint32_t); 4737 } 4738 #ifdef FMA_SUPPORT 4739 /* Access handle validation */ 4740 EMLXS_CHK_ACC_HANDLE(hba, 4741 hba->sli.sli4.bar1_acc_handle); 4742 #endif /* FMA_SUPPORT */ 4743 break; 4744 case 3: /* bar2read */ 4745 if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) { 4746 return (FC_BADCMD); 4747 } 4748 if ((offset >= 0x1000) || (offset & 0x3)) { 4749 return (FC_BADCMD); 4750 } 4751 datap = (uint32_t *)pm->pm_stat_buf; 4752 4753 for (i = 0; i < pm->pm_stat_len; 4754 i += sizeof (uint32_t)) { 4755 *datap = READ_BAR2_REG(hba, 4756 hba->sli.sli4.bar2_addr + offset); 4757 datap++; 4758 offset += sizeof (uint32_t); 4759 } 4760 #ifdef FMA_SUPPORT 4761 /* Access handle validation */ 4762 EMLXS_CHK_ACC_HANDLE(hba, 4763 hba->sli.sli4.bar2_acc_handle); 4764 #endif /* FMA_SUPPORT */ 4765 break; 4766 case 4: /* bar1write */ 4767 if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) { 4768 return (FC_BADCMD); 4769 } 4770 WRITE_BAR1_REG(hba, hba->sli.sli4.bar1_addr + 4771 offset, cmd[2]); 4772 #ifdef FMA_SUPPORT 4773 /* Access handle validation */ 4774 EMLXS_CHK_ACC_HANDLE(hba, 4775 hba->sli.sli4.bar1_acc_handle); 4776 #endif /* FMA_SUPPORT */ 4777 break; 4778 case 5: /* bar2write */ 4779 if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) { 4780 return (FC_BADCMD); 4781 } 4782 WRITE_BAR2_REG(hba, hba->sli.sli4.bar2_addr + 4783 offset, cmd[2]); 4784 #ifdef FMA_SUPPORT 4785 /* Access handle validation */ 4786 EMLXS_CHK_ACC_HANDLE(hba, 4787 hba->sli.sli4.bar2_acc_handle); 4788 #endif /* FMA_SUPPORT */ 4789 break; 4790 case 6: /* dumpbsmbox */ 4791 if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) { 4792 return (FC_BADCMD); 4793 } 4794 if (offset != 0) { 4795 return (FC_BADCMD); 4796 } 4797 4798 bcopy((caddr_t)hba->sli.sli4.bootstrapmb.virt, 4799 (caddr_t)pm->pm_stat_buf, 256); 4800 break; 4801 case 7: /* pciread */ 4802 if ((offset >= 0x200) || (offset & 0x3)) { 4803 return (FC_BADCMD); 4804 } 4805 datap = (uint32_t *)pm->pm_stat_buf; 4806 for (i = 0; i < pm->pm_stat_len; 4807 i += sizeof (uint32_t)) { 4808 *datap = ddi_get32(hba->pci_acc_handle, 4809 (uint32_t *)(hba->pci_addr + 4810 offset)); 4811 datap++; 4812 offset += sizeof (uint32_t); 4813 } 4814 #ifdef FMA_SUPPORT 4815 /* Access handle validation */ 4816 EMLXS_CHK_ACC_HANDLE(hba, hba->pci_acc_handle); 4817 #endif /* FMA_SUPPORT */ 4818 break; 4819 case 8: /* abortall */ 4820 if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) { 4821 return (FC_BADCMD); 4822 } 4823 emlxs_abort_all(hba, &tx_cnt, &chip_cnt); 4824 datap = (uint32_t *)pm->pm_stat_buf; 4825 *datap++ = tx_cnt; 4826 *datap = chip_cnt; 4827 break; 4828 default: 4829 ret = FC_BADCMD; 4830 break; 4831 } 4832 break; 4833 } 4834 4835 default: 4836 4837 ret = FC_INVALID_REQUEST; 4838 break; 4839 } 4840 4841 break; 4842 4843 } 4844 4845 case FC_PORT_INITIALIZE: 4846 if (!(hba->flag & FC_ONLINE_MODE)) { 4847 return (FC_OFFLINE); 4848 } 4849 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4850 "fca_port_manage: FC_PORT_INITIALIZE"); 4851 break; 4852 4853 case FC_PORT_LOOPBACK: 4854 if (!(hba->flag & FC_ONLINE_MODE)) { 4855 return (FC_OFFLINE); 4856 } 4857 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4858 "fca_port_manage: FC_PORT_LOOPBACK"); 4859 break; 4860 4861 case FC_PORT_BYPASS: 4862 if (!(hba->flag & FC_ONLINE_MODE)) { 4863 return (FC_OFFLINE); 4864 } 4865 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4866 "fca_port_manage: FC_PORT_BYPASS"); 4867 ret = FC_INVALID_REQUEST; 4868 break; 4869 4870 case FC_PORT_UNBYPASS: 4871 if (!(hba->flag & FC_ONLINE_MODE)) { 4872 return (FC_OFFLINE); 4873 } 4874 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4875 "fca_port_manage: FC_PORT_UNBYPASS"); 4876 ret = FC_INVALID_REQUEST; 4877 break; 4878 4879 case FC_PORT_GET_NODE_ID: 4880 { 4881 fc_rnid_t *rnid; 4882 4883 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4884 "fca_port_manage: FC_PORT_GET_NODE_ID"); 4885 4886 bzero(pm->pm_data_buf, pm->pm_data_len); 4887 4888 if (pm->pm_data_len < sizeof (fc_rnid_t)) { 4889 ret = FC_NOMEM; 4890 break; 4891 } 4892 4893 rnid = (fc_rnid_t *)pm->pm_data_buf; 4894 4895 (void) sprintf((char *)rnid->global_id, 4896 "%01x%01x%02x%02x%02x%02x%02x%02x%02x", 4897 hba->wwpn.nameType, hba->wwpn.IEEEextMsn, 4898 hba->wwpn.IEEEextLsb, hba->wwpn.IEEE[0], 4899 hba->wwpn.IEEE[1], hba->wwpn.IEEE[2], hba->wwpn.IEEE[3], 4900 hba->wwpn.IEEE[4], hba->wwpn.IEEE[5]); 4901 4902 rnid->unit_type = RNID_HBA; 4903 rnid->port_id = port->did; 4904 rnid->ip_version = RNID_IPV4; 4905 4906 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4907 "GET_NODE_ID: wwpn: %s", rnid->global_id); 4908 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4909 "GET_NODE_ID: unit_type: 0x%x", rnid->unit_type); 4910 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4911 "GET_NODE_ID: port_id: 0x%x", rnid->port_id); 4912 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4913 "GET_NODE_ID: num_attach: %d", rnid->num_attached); 4914 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4915 "GET_NODE_ID: ip_version: 0x%x", rnid->ip_version); 4916 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4917 "GET_NODE_ID: udp_port: 0x%x", rnid->udp_port); 4918 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4919 "GET_NODE_ID: ip_addr: %s", rnid->ip_addr); 4920 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4921 "GET_NODE_ID: resv: 0x%x", rnid->specific_id_resv); 4922 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4923 "GET_NODE_ID: topo_flags: 0x%x", rnid->topo_flags); 4924 4925 ret = FC_SUCCESS; 4926 break; 4927 } 4928 4929 case FC_PORT_SET_NODE_ID: 4930 { 4931 fc_rnid_t *rnid; 4932 4933 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4934 "fca_port_manage: FC_PORT_SET_NODE_ID"); 4935 4936 if (pm->pm_data_len < sizeof (fc_rnid_t)) { 4937 ret = FC_NOMEM; 4938 break; 4939 } 4940 4941 rnid = (fc_rnid_t *)pm->pm_data_buf; 4942 4943 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4944 "SET_NODE_ID: wwpn: %s", rnid->global_id); 4945 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4946 "SET_NODE_ID: unit_type: 0x%x", rnid->unit_type); 4947 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4948 "SET_NODE_ID: port_id: 0x%x", rnid->port_id); 4949 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4950 "SET_NODE_ID: num_attach: %d", rnid->num_attached); 4951 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4952 "SET_NODE_ID: ip_version: 0x%x", rnid->ip_version); 4953 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4954 "SET_NODE_ID: udp_port: 0x%x", rnid->udp_port); 4955 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4956 "SET_NODE_ID: ip_addr: %s", rnid->ip_addr); 4957 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4958 "SET_NODE_ID: resv: 0x%x", rnid->specific_id_resv); 4959 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4960 "SET_NODE_ID: topo_flags: 0x%x", rnid->topo_flags); 4961 4962 ret = FC_SUCCESS; 4963 break; 4964 } 4965 4966 #ifdef S11 4967 case FC_PORT_GET_P2P_INFO: 4968 { 4969 fc_fca_p2p_info_t *p2p_info; 4970 NODELIST *ndlp; 4971 4972 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4973 "fca_port_manage: FC_PORT_GET_P2P_INFO"); 4974 4975 bzero(pm->pm_data_buf, pm->pm_data_len); 4976 4977 if (pm->pm_data_len < sizeof (fc_fca_p2p_info_t)) { 4978 ret = FC_NOMEM; 4979 break; 4980 } 4981 4982 p2p_info = (fc_fca_p2p_info_t *)pm->pm_data_buf; 4983 4984 if (hba->state >= FC_LINK_UP) { 4985 if ((hba->topology == TOPOLOGY_PT_PT) && 4986 (hba->flag & FC_PT_TO_PT)) { 4987 p2p_info->fca_d_id = port->did; 4988 p2p_info->d_id = port->rdid; 4989 4990 ndlp = emlxs_node_find_did(port, 4991 port->rdid); 4992 4993 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4994 "FC_PORT_GET_P2P_INFO: fca_d_id: 0x%x, " 4995 "d_id: 0x%x, ndlp: 0x%p", port->did, 4996 port->rdid, ndlp); 4997 if (ndlp) { 4998 bcopy(&ndlp->nlp_portname, 4999 (caddr_t)&p2p_info->pwwn, 5000 sizeof (la_wwn_t)); 5001 bcopy(&ndlp->nlp_nodename, 5002 (caddr_t)&p2p_info->nwwn, 5003 sizeof (la_wwn_t)); 5004 5005 ret = FC_SUCCESS; 5006 break; 5007 5008 } 5009 } 5010 } 5011 5012 ret = FC_FAILURE; 5013 break; 5014 } 5015 #endif 5016 5017 default: 5018 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 5019 "fca_port_manage: code=%x", pm->pm_cmd_code); 5020 ret = FC_INVALID_REQUEST; 5021 break; 5022 5023 } 5024 5025 return (ret); 5026 5027 } /* emlxs_port_manage() */ 5028 5029 5030 /*ARGSUSED*/ 5031 static uint32_t 5032 emlxs_test(emlxs_hba_t *hba, uint32_t test_code, uint32_t args, 5033 uint32_t *arg) 5034 { 5035 uint32_t rval = 0; 5036 emlxs_port_t *port = &PPORT; 5037 5038 switch (test_code) { 5039 #ifdef TEST_SUPPORT 5040 case 1: /* SCSI underrun */ 5041 { 5042 hba->underrun_counter = (args)? arg[0]:1; 5043 break; 5044 } 5045 #endif /* TEST_SUPPORT */ 5046 5047 default: 5048 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 5049 "emlxs_test: Unsupported test code. (0x%x)", test_code); 5050 rval = FC_INVALID_REQUEST; 5051 } 5052 5053 return (rval); 5054 5055 } /* emlxs_test() */ 5056 5057 5058 /* 5059 * Given the device number, return the devinfo pointer or the ddiinst number. 5060 * Note: this routine must be successful on DDI_INFO_DEVT2INSTANCE even 5061 * before attach. 5062 * 5063 * Translate "dev_t" to a pointer to the associated "dev_info_t". 5064 */ 5065 /*ARGSUSED*/ 5066 static int 5067 emlxs_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) 5068 { 5069 emlxs_hba_t *hba; 5070 int32_t ddiinst; 5071 5072 ddiinst = getminor((dev_t)arg); 5073 5074 switch (infocmd) { 5075 case DDI_INFO_DEVT2DEVINFO: 5076 hba = ddi_get_soft_state(emlxs_soft_state, ddiinst); 5077 if (hba) 5078 *result = hba->dip; 5079 else 5080 *result = NULL; 5081 break; 5082 5083 case DDI_INFO_DEVT2INSTANCE: 5084 *result = (void *)((unsigned long)ddiinst); 5085 break; 5086 5087 default: 5088 return (DDI_FAILURE); 5089 } 5090 5091 return (DDI_SUCCESS); 5092 5093 } /* emlxs_info() */ 5094 5095 5096 static int32_t 5097 emlxs_power(dev_info_t *dip, int32_t comp, int32_t level) 5098 { 5099 emlxs_hba_t *hba; 5100 emlxs_port_t *port; 5101 int32_t ddiinst; 5102 int rval = DDI_SUCCESS; 5103 5104 ddiinst = ddi_get_instance(dip); 5105 hba = ddi_get_soft_state(emlxs_soft_state, ddiinst); 5106 port = &PPORT; 5107 5108 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 5109 "fca_power: comp=%x level=%x", comp, level); 5110 5111 if (hba == NULL || comp != EMLXS_PM_ADAPTER) { 5112 return (DDI_FAILURE); 5113 } 5114 5115 mutex_enter(&hba->pm_lock); 5116 5117 /* If we are already at the proper level then return success */ 5118 if (hba->pm_level == level) { 5119 mutex_exit(&hba->pm_lock); 5120 return (DDI_SUCCESS); 5121 } 5122 5123 switch (level) { 5124 case EMLXS_PM_ADAPTER_UP: 5125 5126 /* 5127 * If we are already in emlxs_attach, 5128 * let emlxs_hba_attach take care of things 5129 */ 5130 if (hba->pm_state & EMLXS_PM_IN_ATTACH) { 5131 hba->pm_level = EMLXS_PM_ADAPTER_UP; 5132 break; 5133 } 5134 5135 /* Check if adapter is suspended */ 5136 if (hba->pm_state & EMLXS_PM_SUSPENDED) { 5137 hba->pm_level = EMLXS_PM_ADAPTER_UP; 5138 5139 /* Try to resume the port */ 5140 rval = emlxs_hba_resume(dip); 5141 5142 if (rval != DDI_SUCCESS) { 5143 hba->pm_level = EMLXS_PM_ADAPTER_DOWN; 5144 } 5145 break; 5146 } 5147 5148 /* Set adapter up */ 5149 hba->pm_level = EMLXS_PM_ADAPTER_UP; 5150 break; 5151 5152 case EMLXS_PM_ADAPTER_DOWN: 5153 5154 5155 /* 5156 * If we are already in emlxs_detach, 5157 * let emlxs_hba_detach take care of things 5158 */ 5159 if (hba->pm_state & EMLXS_PM_IN_DETACH) { 5160 hba->pm_level = EMLXS_PM_ADAPTER_DOWN; 5161 break; 5162 } 5163 5164 /* Check if adapter is not suspended */ 5165 if (!(hba->pm_state & EMLXS_PM_SUSPENDED)) { 5166 hba->pm_level = EMLXS_PM_ADAPTER_DOWN; 5167 5168 /* Try to suspend the port */ 5169 rval = emlxs_hba_suspend(dip); 5170 5171 if (rval != DDI_SUCCESS) { 5172 hba->pm_level = EMLXS_PM_ADAPTER_UP; 5173 } 5174 5175 break; 5176 } 5177 5178 /* Set adapter down */ 5179 hba->pm_level = EMLXS_PM_ADAPTER_DOWN; 5180 break; 5181 5182 default: 5183 rval = DDI_FAILURE; 5184 break; 5185 5186 } 5187 5188 mutex_exit(&hba->pm_lock); 5189 5190 return (rval); 5191 5192 } /* emlxs_power() */ 5193 5194 5195 #ifdef EMLXS_I386 5196 #ifdef S11 5197 /* 5198 * quiesce(9E) entry point. 5199 * 5200 * This function is called when the system is single-thread at hight PIL 5201 * with preemption disabled. Therefore, this function must not be blocked. 5202 * 5203 * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure. 5204 * DDI_FAILURE indicates an error condition and should almost never happen. 5205 */ 5206 static int 5207 emlxs_quiesce(dev_info_t *dip) 5208 { 5209 emlxs_hba_t *hba; 5210 emlxs_port_t *port; 5211 int32_t ddiinst; 5212 int rval = DDI_SUCCESS; 5213 5214 ddiinst = ddi_get_instance(dip); 5215 hba = ddi_get_soft_state(emlxs_soft_state, ddiinst); 5216 port = &PPORT; 5217 5218 if (hba == NULL || port == NULL) { 5219 return (DDI_FAILURE); 5220 } 5221 5222 /* The fourth arg 1 indicates the call is from quiesce */ 5223 if (EMLXS_SLI_HBA_RESET(hba, 1, 1, 1) == 0) { 5224 return (rval); 5225 } else { 5226 return (DDI_FAILURE); 5227 } 5228 5229 } /* emlxs_quiesce */ 5230 #endif 5231 #endif /* EMLXS_I386 */ 5232 5233 5234 static int 5235 emlxs_open(dev_t *dev_p, int32_t flag, int32_t otype, cred_t *cred_p) 5236 { 5237 emlxs_hba_t *hba; 5238 emlxs_port_t *port; 5239 int ddiinst; 5240 5241 ddiinst = getminor(*dev_p); 5242 hba = ddi_get_soft_state(emlxs_soft_state, ddiinst); 5243 5244 if (hba == NULL) { 5245 return (ENXIO); 5246 } 5247 5248 port = &PPORT; 5249 5250 if (hba->pm_state & EMLXS_PM_SUSPENDED) { 5251 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ioctl_detail_msg, 5252 "open failed: Driver suspended."); 5253 return (ENXIO); 5254 } 5255 5256 if (otype != OTYP_CHR) { 5257 return (EINVAL); 5258 } 5259 5260 if (drv_priv(cred_p)) { 5261 return (EPERM); 5262 } 5263 5264 mutex_enter(&EMLXS_IOCTL_LOCK); 5265 5266 if (hba->ioctl_flags & EMLXS_OPEN_EXCLUSIVE) { 5267 mutex_exit(&EMLXS_IOCTL_LOCK); 5268 return (EBUSY); 5269 } 5270 5271 if (flag & FEXCL) { 5272 if (hba->ioctl_flags & EMLXS_OPEN) { 5273 mutex_exit(&EMLXS_IOCTL_LOCK); 5274 return (EBUSY); 5275 } 5276 5277 hba->ioctl_flags |= EMLXS_OPEN_EXCLUSIVE; 5278 } 5279 5280 hba->ioctl_flags |= EMLXS_OPEN; 5281 5282 mutex_exit(&EMLXS_IOCTL_LOCK); 5283 5284 return (0); 5285 5286 } /* emlxs_open() */ 5287 5288 5289 /*ARGSUSED*/ 5290 static int 5291 emlxs_close(dev_t dev, int32_t flag, int32_t otype, cred_t *cred_p) 5292 { 5293 emlxs_hba_t *hba; 5294 int ddiinst; 5295 5296 ddiinst = getminor(dev); 5297 hba = ddi_get_soft_state(emlxs_soft_state, ddiinst); 5298 5299 if (hba == NULL) { 5300 return (ENXIO); 5301 } 5302 5303 if (otype != OTYP_CHR) { 5304 return (EINVAL); 5305 } 5306 5307 mutex_enter(&EMLXS_IOCTL_LOCK); 5308 5309 if (!(hba->ioctl_flags & EMLXS_OPEN)) { 5310 mutex_exit(&EMLXS_IOCTL_LOCK); 5311 return (ENODEV); 5312 } 5313 5314 hba->ioctl_flags &= ~EMLXS_OPEN; 5315 hba->ioctl_flags &= ~EMLXS_OPEN_EXCLUSIVE; 5316 5317 mutex_exit(&EMLXS_IOCTL_LOCK); 5318 5319 return (0); 5320 5321 } /* emlxs_close() */ 5322 5323 5324 /*ARGSUSED*/ 5325 static int 5326 emlxs_ioctl(dev_t dev, int32_t cmd, intptr_t arg, int32_t mode, 5327 cred_t *cred_p, int32_t *rval_p) 5328 { 5329 emlxs_hba_t *hba; 5330 emlxs_port_t *port; 5331 int rval = 0; /* return code */ 5332 int ddiinst; 5333 5334 ddiinst = getminor(dev); 5335 hba = ddi_get_soft_state(emlxs_soft_state, ddiinst); 5336 5337 if (hba == NULL) { 5338 return (ENXIO); 5339 } 5340 5341 port = &PPORT; 5342 5343 if (hba->pm_state & EMLXS_PM_SUSPENDED) { 5344 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ioctl_detail_msg, 5345 "ioctl failed: Driver suspended."); 5346 5347 return (ENXIO); 5348 } 5349 5350 mutex_enter(&EMLXS_IOCTL_LOCK); 5351 if (!(hba->ioctl_flags & EMLXS_OPEN)) { 5352 mutex_exit(&EMLXS_IOCTL_LOCK); 5353 return (ENXIO); 5354 } 5355 mutex_exit(&EMLXS_IOCTL_LOCK); 5356 5357 #ifdef IDLE_TIMER 5358 emlxs_pm_busy_component(hba); 5359 #endif /* IDLE_TIMER */ 5360 5361 switch (cmd) { 5362 case EMLXS_DFC_COMMAND: 5363 rval = emlxs_dfc_manage(hba, (void *)arg, mode); 5364 break; 5365 5366 default: 5367 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ioctl_detail_msg, 5368 "ioctl: Invalid command received. cmd=%x", cmd); 5369 rval = EINVAL; 5370 } 5371 5372 done: 5373 return (rval); 5374 5375 } /* emlxs_ioctl() */ 5376 5377 5378 5379 /* 5380 * 5381 * Device Driver Common Routines 5382 * 5383 */ 5384 5385 /* emlxs_pm_lock must be held for this call */ 5386 static int 5387 emlxs_hba_resume(dev_info_t *dip) 5388 { 5389 emlxs_hba_t *hba; 5390 emlxs_port_t *port; 5391 int ddiinst; 5392 5393 ddiinst = ddi_get_instance(dip); 5394 hba = ddi_get_soft_state(emlxs_soft_state, ddiinst); 5395 port = &PPORT; 5396 5397 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_resume_msg, NULL); 5398 5399 if (!(hba->pm_state & EMLXS_PM_SUSPENDED)) { 5400 return (DDI_SUCCESS); 5401 } 5402 5403 hba->pm_state &= ~EMLXS_PM_SUSPENDED; 5404 5405 /* Take the adapter online */ 5406 if (emlxs_power_up(hba)) { 5407 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_resume_failed_msg, 5408 "Unable to take adapter online."); 5409 5410 hba->pm_state |= EMLXS_PM_SUSPENDED; 5411 5412 return (DDI_FAILURE); 5413 } 5414 5415 return (DDI_SUCCESS); 5416 5417 } /* emlxs_hba_resume() */ 5418 5419 5420 /* emlxs_pm_lock must be held for this call */ 5421 static int 5422 emlxs_hba_suspend(dev_info_t *dip) 5423 { 5424 emlxs_hba_t *hba; 5425 emlxs_port_t *port; 5426 int ddiinst; 5427 5428 ddiinst = ddi_get_instance(dip); 5429 hba = ddi_get_soft_state(emlxs_soft_state, ddiinst); 5430 port = &PPORT; 5431 5432 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_suspend_msg, NULL); 5433 5434 if (hba->pm_state & EMLXS_PM_SUSPENDED) { 5435 return (DDI_SUCCESS); 5436 } 5437 5438 hba->pm_state |= EMLXS_PM_SUSPENDED; 5439 5440 /* Take the adapter offline */ 5441 if (emlxs_power_down(hba)) { 5442 hba->pm_state &= ~EMLXS_PM_SUSPENDED; 5443 5444 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_suspend_failed_msg, 5445 "Unable to take adapter offline."); 5446 5447 return (DDI_FAILURE); 5448 } 5449 5450 return (DDI_SUCCESS); 5451 5452 } /* emlxs_hba_suspend() */ 5453 5454 5455 5456 static void 5457 emlxs_lock_init(emlxs_hba_t *hba) 5458 { 5459 emlxs_port_t *port = &PPORT; 5460 int32_t ddiinst; 5461 char buf[64]; 5462 uint32_t i; 5463 5464 ddiinst = hba->ddiinst; 5465 5466 /* Initialize the power management */ 5467 (void) sprintf(buf, "%s%d_pm_lock mutex", DRIVER_NAME, ddiinst); 5468 mutex_init(&hba->pm_lock, buf, MUTEX_DRIVER, (void *)hba->intr_arg); 5469 5470 (void) sprintf(buf, "%s%d_adap_lock mutex", DRIVER_NAME, ddiinst); 5471 mutex_init(&EMLXS_TIMER_LOCK, buf, MUTEX_DRIVER, 5472 (void *)hba->intr_arg); 5473 5474 (void) sprintf(buf, "%s%d_adap_lock cv", DRIVER_NAME, ddiinst); 5475 cv_init(&hba->timer_lock_cv, buf, CV_DRIVER, NULL); 5476 5477 (void) sprintf(buf, "%s%d_port_lock mutex", DRIVER_NAME, ddiinst); 5478 mutex_init(&EMLXS_PORT_LOCK, buf, MUTEX_DRIVER, 5479 (void *)hba->intr_arg); 5480 5481 (void) sprintf(buf, "%s%d_mbox_lock mutex", DRIVER_NAME, ddiinst); 5482 mutex_init(&EMLXS_MBOX_LOCK, buf, MUTEX_DRIVER, 5483 (void *)hba->intr_arg); 5484 5485 (void) sprintf(buf, "%s%d_mbox_lock cv", DRIVER_NAME, ddiinst); 5486 cv_init(&EMLXS_MBOX_CV, buf, CV_DRIVER, NULL); 5487 5488 (void) sprintf(buf, "%s%d_linkup_lock mutex", DRIVER_NAME, ddiinst); 5489 mutex_init(&EMLXS_LINKUP_LOCK, buf, MUTEX_DRIVER, 5490 (void *)hba->intr_arg); 5491 5492 (void) sprintf(buf, "%s%d_linkup_lock cv", DRIVER_NAME, ddiinst); 5493 cv_init(&EMLXS_LINKUP_CV, buf, CV_DRIVER, NULL); 5494 5495 (void) sprintf(buf, "%s%d_ring_tx_lock mutex", DRIVER_NAME, ddiinst); 5496 mutex_init(&EMLXS_TX_CHANNEL_LOCK, buf, MUTEX_DRIVER, 5497 (void *)hba->intr_arg); 5498 5499 for (i = 0; i < MAX_RINGS; i++) { 5500 (void) sprintf(buf, "%s%d_cmd_ring%d_lock mutex", DRIVER_NAME, 5501 ddiinst, i); 5502 mutex_init(&EMLXS_CMD_RING_LOCK(i), buf, MUTEX_DRIVER, 5503 (void *)hba->intr_arg); 5504 } 5505 5506 (void) sprintf(buf, "%s%d_fctab_lock mutex", DRIVER_NAME, ddiinst); 5507 mutex_init(&EMLXS_FCTAB_LOCK, buf, MUTEX_DRIVER, 5508 (void *)hba->intr_arg); 5509 5510 (void) sprintf(buf, "%s%d_memget_lock mutex", DRIVER_NAME, ddiinst); 5511 mutex_init(&EMLXS_MEMGET_LOCK, buf, MUTEX_DRIVER, 5512 (void *)hba->intr_arg); 5513 5514 (void) sprintf(buf, "%s%d_memput_lock mutex", DRIVER_NAME, ddiinst); 5515 mutex_init(&EMLXS_MEMPUT_LOCK, buf, MUTEX_DRIVER, 5516 (void *)hba->intr_arg); 5517 5518 (void) sprintf(buf, "%s%d_ioctl_lock mutex", DRIVER_NAME, ddiinst); 5519 mutex_init(&EMLXS_IOCTL_LOCK, buf, MUTEX_DRIVER, 5520 (void *)hba->intr_arg); 5521 5522 #ifdef DUMP_SUPPORT 5523 (void) sprintf(buf, "%s%d_dump mutex", DRIVER_NAME, ddiinst); 5524 mutex_init(&EMLXS_DUMP_LOCK, buf, MUTEX_DRIVER, 5525 (void *)hba->intr_arg); 5526 #endif /* DUMP_SUPPORT */ 5527 5528 /* Create per port locks */ 5529 for (i = 0; i < MAX_VPORTS; i++) { 5530 port = &VPORT(i); 5531 5532 rw_init(&port->node_rwlock, NULL, RW_DRIVER, NULL); 5533 5534 if (i == 0) { 5535 (void) sprintf(buf, "%s%d_pkt_lock mutex", DRIVER_NAME, 5536 ddiinst); 5537 mutex_init(&EMLXS_PKT_LOCK, buf, MUTEX_DRIVER, 5538 (void *)hba->intr_arg); 5539 5540 (void) sprintf(buf, "%s%d_pkt_lock cv", DRIVER_NAME, 5541 ddiinst); 5542 cv_init(&EMLXS_PKT_CV, buf, CV_DRIVER, NULL); 5543 5544 (void) sprintf(buf, "%s%d_ub_lock mutex", DRIVER_NAME, 5545 ddiinst); 5546 mutex_init(&EMLXS_UB_LOCK, buf, MUTEX_DRIVER, 5547 (void *)hba->intr_arg); 5548 } else { 5549 (void) sprintf(buf, "%s%d.%d_pkt_lock mutex", 5550 DRIVER_NAME, ddiinst, port->vpi); 5551 mutex_init(&EMLXS_PKT_LOCK, buf, MUTEX_DRIVER, 5552 (void *)hba->intr_arg); 5553 5554 (void) sprintf(buf, "%s%d.%d_pkt_lock cv", DRIVER_NAME, 5555 ddiinst, port->vpi); 5556 cv_init(&EMLXS_PKT_CV, buf, CV_DRIVER, NULL); 5557 5558 (void) sprintf(buf, "%s%d.%d_ub_lock mutex", 5559 DRIVER_NAME, ddiinst, port->vpi); 5560 mutex_init(&EMLXS_UB_LOCK, buf, MUTEX_DRIVER, 5561 (void *)hba->intr_arg); 5562 } 5563 } 5564 5565 return; 5566 5567 } /* emlxs_lock_init() */ 5568 5569 5570 5571 static void 5572 emlxs_lock_destroy(emlxs_hba_t *hba) 5573 { 5574 emlxs_port_t *port = &PPORT; 5575 uint32_t i; 5576 5577 mutex_destroy(&EMLXS_TIMER_LOCK); 5578 cv_destroy(&hba->timer_lock_cv); 5579 5580 mutex_destroy(&EMLXS_PORT_LOCK); 5581 5582 cv_destroy(&EMLXS_MBOX_CV); 5583 cv_destroy(&EMLXS_LINKUP_CV); 5584 5585 mutex_destroy(&EMLXS_LINKUP_LOCK); 5586 mutex_destroy(&EMLXS_MBOX_LOCK); 5587 5588 mutex_destroy(&EMLXS_TX_CHANNEL_LOCK); 5589 5590 for (i = 0; i < MAX_RINGS; i++) { 5591 mutex_destroy(&EMLXS_CMD_RING_LOCK(i)); 5592 } 5593 5594 mutex_destroy(&EMLXS_FCTAB_LOCK); 5595 mutex_destroy(&EMLXS_MEMGET_LOCK); 5596 mutex_destroy(&EMLXS_MEMPUT_LOCK); 5597 mutex_destroy(&EMLXS_IOCTL_LOCK); 5598 mutex_destroy(&hba->pm_lock); 5599 5600 #ifdef DUMP_SUPPORT 5601 mutex_destroy(&EMLXS_DUMP_LOCK); 5602 #endif /* DUMP_SUPPORT */ 5603 5604 /* Destroy per port locks */ 5605 for (i = 0; i < MAX_VPORTS; i++) { 5606 port = &VPORT(i); 5607 rw_destroy(&port->node_rwlock); 5608 mutex_destroy(&EMLXS_PKT_LOCK); 5609 cv_destroy(&EMLXS_PKT_CV); 5610 mutex_destroy(&EMLXS_UB_LOCK); 5611 } 5612 5613 return; 5614 5615 } /* emlxs_lock_destroy() */ 5616 5617 5618 /* init_flag values */ 5619 #define ATTACH_SOFT_STATE 0x00000001 5620 #define ATTACH_FCA_TRAN 0x00000002 5621 #define ATTACH_HBA 0x00000004 5622 #define ATTACH_LOG 0x00000008 5623 #define ATTACH_MAP_BUS 0x00000010 5624 #define ATTACH_INTR_INIT 0x00000020 5625 #define ATTACH_PROP 0x00000040 5626 #define ATTACH_LOCK 0x00000080 5627 #define ATTACH_THREAD 0x00000100 5628 #define ATTACH_INTR_ADD 0x00000200 5629 #define ATTACH_ONLINE 0x00000400 5630 #define ATTACH_NODE 0x00000800 5631 #define ATTACH_FCT 0x00001000 5632 #define ATTACH_FCA 0x00002000 5633 #define ATTACH_KSTAT 0x00004000 5634 #define ATTACH_DHCHAP 0x00008000 5635 #define ATTACH_FM 0x00010000 5636 #define ATTACH_MAP_SLI 0x00020000 5637 #define ATTACH_SPAWN 0x00040000 5638 #define ATTACH_EVENTS 0x00080000 5639 5640 static void 5641 emlxs_driver_remove(dev_info_t *dip, uint32_t init_flag, uint32_t failed) 5642 { 5643 emlxs_hba_t *hba = NULL; 5644 int ddiinst; 5645 5646 ddiinst = ddi_get_instance(dip); 5647 5648 if (init_flag & ATTACH_HBA) { 5649 hba = ddi_get_soft_state(emlxs_soft_state, ddiinst); 5650 5651 if (init_flag & ATTACH_SPAWN) { 5652 emlxs_thread_spawn_destroy(hba); 5653 } 5654 5655 if (init_flag & ATTACH_ONLINE) { 5656 (void) emlxs_offline(hba); 5657 } 5658 5659 if (init_flag & ATTACH_INTR_ADD) { 5660 (void) EMLXS_INTR_REMOVE(hba); 5661 } 5662 #ifdef SFCT_SUPPORT 5663 if (init_flag & ATTACH_FCT) { 5664 emlxs_fct_detach(hba); 5665 emlxs_fct_modclose(); 5666 } 5667 #endif /* SFCT_SUPPORT */ 5668 5669 #ifdef DHCHAP_SUPPORT 5670 if (init_flag & ATTACH_DHCHAP) { 5671 emlxs_dhc_detach(hba); 5672 } 5673 #endif /* DHCHAP_SUPPORT */ 5674 5675 if (init_flag & ATTACH_KSTAT) { 5676 kstat_delete(hba->kstat); 5677 } 5678 5679 if (init_flag & ATTACH_FCA) { 5680 emlxs_fca_detach(hba); 5681 } 5682 5683 if (init_flag & ATTACH_NODE) { 5684 (void) ddi_remove_minor_node(hba->dip, "devctl"); 5685 } 5686 5687 if (init_flag & ATTACH_THREAD) { 5688 emlxs_thread_destroy(&hba->iodone_thread); 5689 } 5690 5691 if (init_flag & ATTACH_PROP) { 5692 (void) ddi_prop_remove_all(hba->dip); 5693 } 5694 5695 if (init_flag & ATTACH_LOCK) { 5696 emlxs_lock_destroy(hba); 5697 } 5698 5699 if (init_flag & ATTACH_INTR_INIT) { 5700 (void) EMLXS_INTR_UNINIT(hba); 5701 } 5702 5703 if (init_flag & ATTACH_MAP_BUS) { 5704 emlxs_unmap_bus(hba); 5705 } 5706 5707 if (init_flag & ATTACH_MAP_SLI) { 5708 EMLXS_SLI_UNMAP_HDW(hba); 5709 } 5710 5711 #ifdef FMA_SUPPORT 5712 if (init_flag & ATTACH_FM) { 5713 emlxs_fm_fini(hba); 5714 } 5715 #endif /* FMA_SUPPORT */ 5716 5717 if (init_flag & ATTACH_EVENTS) { 5718 (void) emlxs_event_queue_destroy(hba); 5719 } 5720 5721 if (init_flag & ATTACH_LOG) { 5722 (void) emlxs_msg_log_destroy(hba); 5723 } 5724 5725 if (init_flag & ATTACH_FCA_TRAN) { 5726 (void) ddi_set_driver_private(hba->dip, NULL); 5727 kmem_free(hba->fca_tran, sizeof (fc_fca_tran_t)); 5728 hba->fca_tran = NULL; 5729 } 5730 5731 if (init_flag & ATTACH_HBA) { 5732 emlxs_device.log[hba->emlxinst] = 0; 5733 emlxs_device.hba[hba->emlxinst] = 5734 (emlxs_hba_t *)((unsigned long)((failed) ? -1 : 0)); 5735 #ifdef DUMP_SUPPORT 5736 emlxs_device.dump_txtfile[hba->emlxinst] = 0; 5737 emlxs_device.dump_dmpfile[hba->emlxinst] = 0; 5738 emlxs_device.dump_ceefile[hba->emlxinst] = 0; 5739 #endif /* DUMP_SUPPORT */ 5740 5741 } 5742 } 5743 5744 if (init_flag & ATTACH_SOFT_STATE) { 5745 (void) ddi_soft_state_free(emlxs_soft_state, ddiinst); 5746 } 5747 5748 return; 5749 5750 } /* emlxs_driver_remove() */ 5751 5752 5753 5754 /* This determines which ports will be initiator mode */ 5755 static void 5756 emlxs_fca_init(emlxs_hba_t *hba) 5757 { 5758 emlxs_port_t *port = &PPORT; 5759 emlxs_port_t *vport; 5760 uint32_t i; 5761 5762 if (!hba->ini_mode) { 5763 return; 5764 } 5765 /* Check if SFS present */ 5766 if (((void *)MODSYM(fc_fca_init) == NULL) || 5767 ((void *)MODSYM(fc_fca_attach) == NULL)) { 5768 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 5769 "SFS not present. Initiator mode disabled."); 5770 goto failed; 5771 } 5772 5773 /* Check if our SFS driver interface matches the current SFS stack */ 5774 if (MODSYM(fc_fca_attach) (hba->dip, hba->fca_tran) != DDI_SUCCESS) { 5775 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 5776 "SFS/FCA version mismatch. FCA=0x%x", 5777 hba->fca_tran->fca_version); 5778 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 5779 "SFS present. Initiator mode disabled."); 5780 5781 goto failed; 5782 } 5783 5784 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 5785 "SFS present. Initiator mode enabled."); 5786 5787 return; 5788 5789 failed: 5790 5791 hba->ini_mode = 0; 5792 for (i = 0; i < MAX_VPORTS; i++) { 5793 vport = &VPORT(i); 5794 vport->ini_mode = 0; 5795 } 5796 5797 return; 5798 5799 } /* emlxs_fca_init() */ 5800 5801 5802 /* This determines which ports will be initiator or target mode */ 5803 static void 5804 emlxs_set_mode(emlxs_hba_t *hba) 5805 { 5806 emlxs_port_t *port = &PPORT; 5807 emlxs_port_t *vport; 5808 uint32_t i; 5809 uint32_t tgt_mode = 0; 5810 5811 #ifdef SFCT_SUPPORT 5812 emlxs_config_t *cfg; 5813 5814 cfg = &hba->config[CFG_TARGET_MODE]; 5815 tgt_mode = cfg->current; 5816 5817 if (tgt_mode) { 5818 if (emlxs_fct_modopen() != 0) { 5819 tgt_mode = 0; 5820 } 5821 } 5822 5823 port->fct_flags = 0; 5824 #endif /* SFCT_SUPPORT */ 5825 5826 /* Initialize physical port */ 5827 if (tgt_mode) { 5828 hba->tgt_mode = 1; 5829 hba->ini_mode = 0; 5830 5831 port->tgt_mode = 1; 5832 port->ini_mode = 0; 5833 } else { 5834 hba->tgt_mode = 0; 5835 hba->ini_mode = 1; 5836 5837 port->tgt_mode = 0; 5838 port->ini_mode = 1; 5839 } 5840 5841 /* Initialize virtual ports */ 5842 /* Virtual ports take on the mode of the parent physical port */ 5843 for (i = 1; i < MAX_VPORTS; i++) { 5844 vport = &VPORT(i); 5845 5846 #ifdef SFCT_SUPPORT 5847 vport->fct_flags = 0; 5848 #endif /* SFCT_SUPPORT */ 5849 5850 vport->ini_mode = port->ini_mode; 5851 vport->tgt_mode = port->tgt_mode; 5852 } 5853 5854 /* Check if initiator mode is requested */ 5855 if (hba->ini_mode) { 5856 emlxs_fca_init(hba); 5857 } else { 5858 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 5859 "Initiator mode not enabled."); 5860 } 5861 5862 #ifdef SFCT_SUPPORT 5863 /* Check if target mode is requested */ 5864 if (hba->tgt_mode) { 5865 emlxs_fct_init(hba); 5866 } else { 5867 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 5868 "Target mode not enabled."); 5869 } 5870 #endif /* SFCT_SUPPORT */ 5871 5872 return; 5873 5874 } /* emlxs_set_mode() */ 5875 5876 5877 5878 static void 5879 emlxs_fca_attach(emlxs_hba_t *hba) 5880 { 5881 /* Update our transport structure */ 5882 hba->fca_tran->fca_iblock = (ddi_iblock_cookie_t *)&hba->intr_arg; 5883 hba->fca_tran->fca_cmd_max = hba->io_throttle; 5884 5885 #if (EMLXS_MODREV >= EMLXS_MODREV5) 5886 bcopy((caddr_t)&hba->wwpn, (caddr_t)&hba->fca_tran->fca_perm_pwwn, 5887 sizeof (NAME_TYPE)); 5888 #endif /* >= EMLXS_MODREV5 */ 5889 5890 return; 5891 5892 } /* emlxs_fca_attach() */ 5893 5894 5895 static void 5896 emlxs_fca_detach(emlxs_hba_t *hba) 5897 { 5898 uint32_t i; 5899 emlxs_port_t *vport; 5900 5901 if (hba->ini_mode) { 5902 if ((void *)MODSYM(fc_fca_detach) != NULL) { 5903 MODSYM(fc_fca_detach)(hba->dip); 5904 } 5905 5906 hba->ini_mode = 0; 5907 5908 for (i = 0; i < MAX_VPORTS; i++) { 5909 vport = &VPORT(i); 5910 vport->ini_mode = 0; 5911 } 5912 } 5913 5914 return; 5915 5916 } /* emlxs_fca_detach() */ 5917 5918 5919 5920 static void 5921 emlxs_drv_banner(emlxs_hba_t *hba) 5922 { 5923 emlxs_port_t *port = &PPORT; 5924 uint32_t i; 5925 char sli_mode[16]; 5926 char msi_mode[16]; 5927 char npiv_mode[16]; 5928 emlxs_vpd_t *vpd = &VPD; 5929 emlxs_config_t *cfg = &CFG; 5930 uint8_t *wwpn; 5931 uint8_t *wwnn; 5932 5933 /* Display firmware library one time */ 5934 if (emlxs_instance_count == 1) { 5935 emlxs_fw_show(hba); 5936 } 5937 5938 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_msg, "%s (%s)", emlxs_label, 5939 emlxs_revision); 5940 5941 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_msg, 5942 "%s Dev_id:%x Sub_id:%x Id:%d", hba->model_info.model, 5943 hba->model_info.device_id, hba->model_info.ssdid, 5944 hba->model_info.id); 5945 5946 #ifdef EMLXS_I386 5947 5948 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_msg, 5949 "Firmware:%s (%s) Boot:%s", vpd->fw_version, vpd->fw_label, 5950 vpd->boot_version); 5951 5952 #else /* EMLXS_SPARC */ 5953 5954 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_msg, 5955 "Firmware:%s (%s) Boot:%s Fcode:%s", vpd->fw_version, 5956 vpd->fw_label, vpd->boot_version, vpd->fcode_version); 5957 5958 #endif /* EMLXS_I386 */ 5959 5960 if (hba->sli_mode > 3) { 5961 (void) sprintf(sli_mode, "SLI:%d(%s)", hba->sli_mode, 5962 ((hba->flag & FC_FIP_SUPPORTED) ? "FIP" : "nonFIP")); 5963 } else { 5964 (void) sprintf(sli_mode, "SLI:%d", hba->sli_mode); 5965 } 5966 5967 (void) strcpy(msi_mode, " INTX:1"); 5968 5969 #ifdef MSI_SUPPORT 5970 if (hba->intr_flags & EMLXS_MSI_ENABLED) { 5971 switch (hba->intr_type) { 5972 case DDI_INTR_TYPE_FIXED: 5973 (void) strcpy(msi_mode, " MSI:0"); 5974 break; 5975 5976 case DDI_INTR_TYPE_MSI: 5977 (void) sprintf(msi_mode, " MSI:%d", hba->intr_count); 5978 break; 5979 5980 case DDI_INTR_TYPE_MSIX: 5981 (void) sprintf(msi_mode, " MSIX:%d", hba->intr_count); 5982 break; 5983 } 5984 } 5985 #endif 5986 5987 (void) strcpy(npiv_mode, ""); 5988 5989 if (hba->flag & FC_NPIV_ENABLED) { 5990 (void) sprintf(npiv_mode, " NPIV:%d", hba->vpi_max+1); 5991 } else { 5992 (void) strcpy(npiv_mode, " NPIV:0"); 5993 } 5994 5995 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_msg, "%s%s%s%s%s", 5996 sli_mode, msi_mode, npiv_mode, 5997 ((hba->ini_mode)? " FCA":""), ((hba->tgt_mode)? " FCT":"")); 5998 5999 wwpn = (uint8_t *)&hba->wwpn; 6000 wwnn = (uint8_t *)&hba->wwnn; 6001 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_msg, 6002 "WWPN:%02X%02X%02X%02X%02X%02X%02X%02X " 6003 "WWNN:%02X%02X%02X%02X%02X%02X%02X%02X", 6004 wwpn[0], wwpn[1], wwpn[2], wwpn[3], wwpn[4], wwpn[5], wwpn[6], 6005 wwpn[7], wwnn[0], wwnn[1], wwnn[2], wwnn[3], wwnn[4], wwnn[5], 6006 wwnn[6], wwnn[7]); 6007 6008 for (i = 0; i < MAX_VPORTS; i++) { 6009 port = &VPORT(i); 6010 6011 if (!(port->flag & EMLXS_PORT_CONFIG)) { 6012 continue; 6013 } 6014 6015 wwpn = (uint8_t *)&port->wwpn; 6016 wwnn = (uint8_t *)&port->wwnn; 6017 6018 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_msg, 6019 "WWPN:%02X%02X%02X%02X%02X%02X%02X%02X " 6020 "WWNN:%02X%02X%02X%02X%02X%02X%02X%02X", 6021 wwpn[0], wwpn[1], wwpn[2], wwpn[3], wwpn[4], wwpn[5], 6022 wwpn[6], wwpn[7], wwnn[0], wwnn[1], wwnn[2], wwnn[3], 6023 wwnn[4], wwnn[5], wwnn[6], wwnn[7]); 6024 } 6025 port = &PPORT; 6026 6027 /* 6028 * No dependency for Restricted login parameter. 6029 */ 6030 if ((cfg[CFG_VPORT_RESTRICTED].current) && (port->ini_mode)) { 6031 port->flag |= EMLXS_PORT_RESTRICTED; 6032 } else { 6033 port->flag &= ~EMLXS_PORT_RESTRICTED; 6034 } 6035 6036 /* 6037 * Announce the device: ddi_report_dev() prints a banner at boot time, 6038 * announcing the device pointed to by dip. 6039 */ 6040 (void) ddi_report_dev(hba->dip); 6041 6042 return; 6043 6044 } /* emlxs_drv_banner() */ 6045 6046 6047 extern void 6048 emlxs_get_fcode_version(emlxs_hba_t *hba) 6049 { 6050 emlxs_vpd_t *vpd = &VPD; 6051 char *prop_str; 6052 int status; 6053 6054 /* Setup fcode version property */ 6055 prop_str = NULL; 6056 status = 6057 ddi_prop_lookup_string(DDI_DEV_T_ANY, (dev_info_t *)hba->dip, 0, 6058 "fcode-version", (char **)&prop_str); 6059 6060 if (status == DDI_PROP_SUCCESS) { 6061 bcopy(prop_str, vpd->fcode_version, strlen(prop_str)); 6062 (void) ddi_prop_free((void *)prop_str); 6063 } else { 6064 (void) strcpy(vpd->fcode_version, "none"); 6065 } 6066 6067 return; 6068 6069 } /* emlxs_get_fcode_version() */ 6070 6071 6072 static int 6073 emlxs_hba_attach(dev_info_t *dip) 6074 { 6075 emlxs_hba_t *hba; 6076 emlxs_port_t *port; 6077 emlxs_config_t *cfg; 6078 char *prop_str; 6079 int ddiinst; 6080 int32_t emlxinst; 6081 int status; 6082 uint32_t rval; 6083 uint32_t init_flag = 0; 6084 char local_pm_components[32]; 6085 #ifdef EMLXS_I386 6086 uint32_t i; 6087 #endif /* EMLXS_I386 */ 6088 6089 ddiinst = ddi_get_instance(dip); 6090 emlxinst = emlxs_add_instance(ddiinst); 6091 6092 if (emlxinst >= MAX_FC_BRDS) { 6093 cmn_err(CE_WARN, 6094 "?%s: fca_hba_attach failed. Too many driver ddiinsts. " 6095 "inst=%x", DRIVER_NAME, ddiinst); 6096 return (DDI_FAILURE); 6097 } 6098 6099 if (emlxs_device.hba[emlxinst] == (emlxs_hba_t *)-1) { 6100 return (DDI_FAILURE); 6101 } 6102 6103 if (emlxs_device.hba[emlxinst]) { 6104 return (DDI_SUCCESS); 6105 } 6106 6107 /* An adapter can accidentally be plugged into a slave-only PCI slot */ 6108 if (ddi_slaveonly(dip) == DDI_SUCCESS) { 6109 cmn_err(CE_WARN, 6110 "?%s%d: fca_hba_attach failed. Device in slave-only slot.", 6111 DRIVER_NAME, ddiinst); 6112 return (DDI_FAILURE); 6113 } 6114 6115 /* Allocate emlxs_dev_ctl structure. */ 6116 if (ddi_soft_state_zalloc(emlxs_soft_state, ddiinst) != DDI_SUCCESS) { 6117 cmn_err(CE_WARN, 6118 "?%s%d: fca_hba_attach failed. Unable to allocate soft " 6119 "state.", DRIVER_NAME, ddiinst); 6120 return (DDI_FAILURE); 6121 } 6122 init_flag |= ATTACH_SOFT_STATE; 6123 6124 if ((hba = (emlxs_hba_t *)ddi_get_soft_state(emlxs_soft_state, 6125 ddiinst)) == NULL) { 6126 cmn_err(CE_WARN, 6127 "?%s%d: fca_hba_attach failed. Unable to get soft state.", 6128 DRIVER_NAME, ddiinst); 6129 goto failed; 6130 } 6131 bzero((char *)hba, sizeof (emlxs_hba_t)); 6132 6133 emlxs_device.hba[emlxinst] = hba; 6134 emlxs_device.log[emlxinst] = &hba->log; 6135 6136 #ifdef DUMP_SUPPORT 6137 emlxs_device.dump_txtfile[emlxinst] = &hba->dump_txtfile; 6138 emlxs_device.dump_dmpfile[emlxinst] = &hba->dump_dmpfile; 6139 emlxs_device.dump_ceefile[emlxinst] = &hba->dump_ceefile; 6140 #endif /* DUMP_SUPPORT */ 6141 6142 hba->dip = dip; 6143 hba->emlxinst = emlxinst; 6144 hba->ddiinst = ddiinst; 6145 hba->ini_mode = 0; 6146 hba->tgt_mode = 0; 6147 6148 init_flag |= ATTACH_HBA; 6149 6150 /* Enable the physical port on this HBA */ 6151 port = &PPORT; 6152 port->hba = hba; 6153 port->vpi = 0; 6154 port->flag |= EMLXS_PORT_ENABLE; 6155 6156 /* Allocate a transport structure */ 6157 hba->fca_tran = 6158 (fc_fca_tran_t *)kmem_zalloc(sizeof (fc_fca_tran_t), KM_NOSLEEP); 6159 if (hba->fca_tran == NULL) { 6160 cmn_err(CE_WARN, 6161 "?%s%d: fca_hba_attach failed. Unable to allocate fca_tran " 6162 "memory.", DRIVER_NAME, ddiinst); 6163 goto failed; 6164 } 6165 bcopy((caddr_t)&emlxs_fca_tran, (caddr_t)hba->fca_tran, 6166 sizeof (fc_fca_tran_t)); 6167 6168 /* Set the transport structure pointer in our dip */ 6169 /* SFS may panic if we are in target only mode */ 6170 /* We will update the transport structure later */ 6171 (void) ddi_set_driver_private(dip, (caddr_t)&emlxs_fca_tran); 6172 init_flag |= ATTACH_FCA_TRAN; 6173 6174 /* Perform driver integrity check */ 6175 rval = emlxs_integrity_check(hba); 6176 if (rval) { 6177 cmn_err(CE_WARN, 6178 "?%s%d: fca_hba_attach failed. Driver integrity check " 6179 "failed. %d error(s) found.", DRIVER_NAME, ddiinst, rval); 6180 goto failed; 6181 } 6182 6183 cfg = &CFG; 6184 6185 bcopy((uint8_t *)&emlxs_cfg, (uint8_t *)cfg, sizeof (emlxs_cfg)); 6186 #ifdef MSI_SUPPORT 6187 if ((void *)&ddi_intr_get_supported_types != NULL) { 6188 hba->intr_flags |= EMLXS_MSI_ENABLED; 6189 } 6190 #endif /* MSI_SUPPORT */ 6191 6192 6193 /* Create the msg log file */ 6194 if (emlxs_msg_log_create(hba) == 0) { 6195 cmn_err(CE_WARN, 6196 "?%s%d: fca_hba_attach failed. Unable to create message " 6197 "log", DRIVER_NAME, ddiinst); 6198 goto failed; 6199 6200 } 6201 init_flag |= ATTACH_LOG; 6202 6203 /* We can begin to use EMLXS_MSGF from this point on */ 6204 6205 /* Create the event queue */ 6206 if (emlxs_event_queue_create(hba) == 0) { 6207 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg, 6208 "Unable to create event queue"); 6209 6210 goto failed; 6211 6212 } 6213 init_flag |= ATTACH_EVENTS; 6214 6215 /* 6216 * Find the I/O bus type If it is not a SBUS card, 6217 * then it is a PCI card. Default is PCI_FC (0). 6218 */ 6219 prop_str = NULL; 6220 status = ddi_prop_lookup_string(DDI_DEV_T_ANY, 6221 (dev_info_t *)dip, 0, "name", (char **)&prop_str); 6222 6223 if (status == DDI_PROP_SUCCESS) { 6224 if (strncmp(prop_str, "lpfs", 4) == 0) { 6225 hba->bus_type = SBUS_FC; 6226 } 6227 6228 (void) ddi_prop_free((void *)prop_str); 6229 } 6230 6231 /* 6232 * Copy DDS from the config method and update configuration parameters 6233 */ 6234 (void) emlxs_get_props(hba); 6235 6236 #ifdef FMA_SUPPORT 6237 hba->fm_caps = cfg[CFG_FM_CAPS].current; 6238 6239 emlxs_fm_init(hba); 6240 6241 init_flag |= ATTACH_FM; 6242 #endif /* FMA_SUPPORT */ 6243 6244 if (emlxs_map_bus(hba)) { 6245 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg, 6246 "Unable to map memory"); 6247 goto failed; 6248 6249 } 6250 init_flag |= ATTACH_MAP_BUS; 6251 6252 /* Attempt to identify the adapter */ 6253 rval = emlxs_init_adapter_info(hba); 6254 6255 if (rval == 0) { 6256 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg, 6257 "Unable to get adapter info. Id:%d Device id:0x%x " 6258 "Model:%s", hba->model_info.id, 6259 hba->model_info.device_id, hba->model_info.model); 6260 goto failed; 6261 } 6262 6263 /* Check if adapter is not supported */ 6264 if (hba->model_info.flags & EMLXS_NOT_SUPPORTED) { 6265 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg, 6266 "Unsupported adapter found. Id:%d Device id:0x%x " 6267 "SSDID:0x%x Model:%s", hba->model_info.id, 6268 hba->model_info.device_id, 6269 hba->model_info.ssdid, hba->model_info.model); 6270 goto failed; 6271 } 6272 if (hba->model_info.sli_mask & EMLXS_SLI4_MASK) { 6273 hba->sli.sli4.mem_sgl_size = MEM_SGL_SIZE; 6274 #ifdef EMLXS_I386 6275 i = cfg[CFG_MAX_XFER_SIZE].current; 6276 /* Update SGL size based on max_xfer_size */ 6277 if (i > 516096) { 6278 /* 516096 = (((2048 / 16) - 2) * 4096) */ 6279 hba->sli.sli4.mem_sgl_size = 4096; 6280 } else if (i > 253953) { 6281 /* 253953 = (((1024 / 16) - 2) * 4096) */ 6282 hba->sli.sli4.mem_sgl_size = 2048; 6283 } else { 6284 hba->sli.sli4.mem_sgl_size = 1024; 6285 } 6286 i = SGL_TO_SGLLEN(hba->sli.sli4.mem_sgl_size); 6287 #endif /* EMLXS_I386 */ 6288 } else { 6289 hba->sli.sli3.mem_bpl_size = MEM_BPL_SIZE; 6290 #ifdef EMLXS_I386 6291 i = cfg[CFG_MAX_XFER_SIZE].current; 6292 /* Update BPL size based on max_xfer_size */ 6293 if (i > 688128) { 6294 /* 688128 = (((2048 / 12) - 2) * 4096) */ 6295 hba->sli.sli3.mem_bpl_size = 4096; 6296 } else if (i > 339968) { 6297 /* 339968 = (((1024 / 12) - 2) * 4096) */ 6298 hba->sli.sli3.mem_bpl_size = 2048; 6299 } else { 6300 hba->sli.sli3.mem_bpl_size = 1024; 6301 } 6302 i = BPL_TO_SGLLEN(hba->sli.sli3.mem_bpl_size); 6303 #endif /* EMLXS_I386 */ 6304 } 6305 6306 #ifdef EMLXS_I386 6307 /* Update dma_attr_sgllen based on BPL size */ 6308 emlxs_dma_attr.dma_attr_sgllen = i; 6309 emlxs_dma_attr_ro.dma_attr_sgllen = i; 6310 emlxs_dma_attr_fcip_rsp.dma_attr_sgllen = i; 6311 #endif /* EMLXS_I386 */ 6312 6313 if (EMLXS_SLI_MAP_HDW(hba)) { 6314 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg, 6315 "Unable to map memory"); 6316 goto failed; 6317 6318 } 6319 init_flag |= ATTACH_MAP_SLI; 6320 6321 /* Initialize the interrupts. But don't add them yet */ 6322 status = EMLXS_INTR_INIT(hba, 0); 6323 if (status != DDI_SUCCESS) { 6324 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg, 6325 "Unable to initalize interrupt(s)."); 6326 goto failed; 6327 6328 } 6329 init_flag |= ATTACH_INTR_INIT; 6330 6331 /* Initialize LOCKs */ 6332 emlxs_lock_init(hba); 6333 init_flag |= ATTACH_LOCK; 6334 6335 /* Initialize the power management */ 6336 mutex_enter(&hba->pm_lock); 6337 hba->pm_state = EMLXS_PM_IN_ATTACH; 6338 hba->pm_level = EMLXS_PM_ADAPTER_DOWN; 6339 hba->pm_busy = 0; 6340 #ifdef IDLE_TIMER 6341 hba->pm_active = 1; 6342 hba->pm_idle_timer = 0; 6343 #endif /* IDLE_TIMER */ 6344 mutex_exit(&hba->pm_lock); 6345 6346 /* Set the pm component name */ 6347 (void) sprintf(local_pm_components, "NAME=%s%d", DRIVER_NAME, 6348 ddiinst); 6349 emlxs_pm_components[0] = local_pm_components; 6350 6351 /* Check if power management support is enabled */ 6352 if (cfg[CFG_PM_SUPPORT].current) { 6353 if (ddi_prop_update_string_array(DDI_DEV_T_NONE, dip, 6354 "pm-components", emlxs_pm_components, 6355 sizeof (emlxs_pm_components) / 6356 sizeof (emlxs_pm_components[0])) != 6357 DDI_PROP_SUCCESS) { 6358 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg, 6359 "Unable to create pm components."); 6360 goto failed; 6361 } 6362 } 6363 6364 /* Needed for suspend and resume support */ 6365 (void) ddi_prop_update_string(DDI_DEV_T_NONE, dip, "pm-hardware-state", 6366 "needs-suspend-resume"); 6367 init_flag |= ATTACH_PROP; 6368 6369 emlxs_thread_spawn_create(hba); 6370 init_flag |= ATTACH_SPAWN; 6371 6372 emlxs_thread_create(hba, &hba->iodone_thread); 6373 6374 init_flag |= ATTACH_THREAD; 6375 6376 /* Setup initiator / target ports */ 6377 emlxs_set_mode(hba); 6378 6379 /* If driver did not attach to either stack, */ 6380 /* then driver attach failed */ 6381 if (!hba->tgt_mode && !hba->ini_mode) { 6382 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg, 6383 "Driver interfaces not enabled."); 6384 goto failed; 6385 } 6386 6387 /* 6388 * Initialize HBA 6389 */ 6390 6391 /* Set initial state */ 6392 mutex_enter(&EMLXS_PORT_LOCK); 6393 emlxs_diag_state = DDI_OFFDI; 6394 hba->flag |= FC_OFFLINE_MODE; 6395 hba->flag &= ~(FC_ONLINE_MODE | FC_ONLINING_MODE | FC_OFFLINING_MODE); 6396 mutex_exit(&EMLXS_PORT_LOCK); 6397 6398 if (status = emlxs_online(hba)) { 6399 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg, 6400 "Unable to initialize adapter."); 6401 goto failed; 6402 } 6403 init_flag |= ATTACH_ONLINE; 6404 6405 /* This is to ensure that the model property is properly set */ 6406 (void) ddi_prop_update_string(DDI_DEV_T_NONE, dip, "model", 6407 hba->model_info.model); 6408 6409 /* Create the device node. */ 6410 if (ddi_create_minor_node(dip, "devctl", S_IFCHR, ddiinst, NULL, 0) == 6411 DDI_FAILURE) { 6412 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg, 6413 "Unable to create device node."); 6414 goto failed; 6415 } 6416 init_flag |= ATTACH_NODE; 6417 6418 /* Attach initiator now */ 6419 /* This must come after emlxs_online() */ 6420 emlxs_fca_attach(hba); 6421 init_flag |= ATTACH_FCA; 6422 6423 /* Initialize kstat information */ 6424 hba->kstat = kstat_create(DRIVER_NAME, 6425 ddiinst, "statistics", "controller", 6426 KSTAT_TYPE_RAW, sizeof (emlxs_stats_t), 6427 KSTAT_FLAG_VIRTUAL); 6428 6429 if (hba->kstat == NULL) { 6430 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 6431 "kstat_create failed."); 6432 } else { 6433 hba->kstat->ks_data = (void *)&hba->stats; 6434 kstat_install(hba->kstat); 6435 init_flag |= ATTACH_KSTAT; 6436 } 6437 6438 #if (EMLXS_MODREV >= EMLXS_MODREV3) && (EMLXS_MODREV <= EMLXS_MODREV4) 6439 /* Setup virtual port properties */ 6440 emlxs_read_vport_prop(hba); 6441 #endif /* EMLXS_MODREV3 || EMLXS_MODREV4 */ 6442 6443 6444 #ifdef DHCHAP_SUPPORT 6445 emlxs_dhc_attach(hba); 6446 init_flag |= ATTACH_DHCHAP; 6447 #endif /* DHCHAP_SUPPORT */ 6448 6449 /* Display the driver banner now */ 6450 emlxs_drv_banner(hba); 6451 6452 /* Raise the power level */ 6453 6454 /* 6455 * This will not execute emlxs_hba_resume because 6456 * EMLXS_PM_IN_ATTACH is set 6457 */ 6458 if (emlxs_pm_raise_power(dip) != DDI_SUCCESS) { 6459 /* Set power up anyway. This should not happen! */ 6460 mutex_enter(&hba->pm_lock); 6461 hba->pm_level = EMLXS_PM_ADAPTER_UP; 6462 hba->pm_state &= ~EMLXS_PM_IN_ATTACH; 6463 mutex_exit(&hba->pm_lock); 6464 } else { 6465 mutex_enter(&hba->pm_lock); 6466 hba->pm_state &= ~EMLXS_PM_IN_ATTACH; 6467 mutex_exit(&hba->pm_lock); 6468 } 6469 6470 #ifdef SFCT_SUPPORT 6471 /* Do this last */ 6472 emlxs_fct_attach(hba); 6473 init_flag |= ATTACH_FCT; 6474 #endif /* SFCT_SUPPORT */ 6475 6476 return (DDI_SUCCESS); 6477 6478 failed: 6479 6480 emlxs_driver_remove(dip, init_flag, 1); 6481 6482 return (DDI_FAILURE); 6483 6484 } /* emlxs_hba_attach() */ 6485 6486 6487 static int 6488 emlxs_hba_detach(dev_info_t *dip) 6489 { 6490 emlxs_hba_t *hba; 6491 emlxs_port_t *port; 6492 int ddiinst; 6493 int count; 6494 uint32_t init_flag = (uint32_t)-1; 6495 6496 ddiinst = ddi_get_instance(dip); 6497 hba = ddi_get_soft_state(emlxs_soft_state, ddiinst); 6498 port = &PPORT; 6499 6500 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_detach_debug_msg, NULL); 6501 6502 mutex_enter(&hba->pm_lock); 6503 hba->pm_state |= EMLXS_PM_IN_DETACH; 6504 mutex_exit(&hba->pm_lock); 6505 6506 /* Lower the power level */ 6507 /* 6508 * This will not suspend the driver since the 6509 * EMLXS_PM_IN_DETACH has been set 6510 */ 6511 if (emlxs_pm_lower_power(dip) != DDI_SUCCESS) { 6512 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_detach_failed_msg, 6513 "Unable to lower power."); 6514 6515 mutex_enter(&hba->pm_lock); 6516 hba->pm_state &= ~EMLXS_PM_IN_DETACH; 6517 mutex_exit(&hba->pm_lock); 6518 6519 return (DDI_FAILURE); 6520 } 6521 6522 /* Take the adapter offline first, if not already */ 6523 if (emlxs_offline(hba) != 0) { 6524 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_detach_failed_msg, 6525 "Unable to take adapter offline."); 6526 6527 mutex_enter(&hba->pm_lock); 6528 hba->pm_state &= ~EMLXS_PM_IN_DETACH; 6529 mutex_exit(&hba->pm_lock); 6530 6531 (void) emlxs_pm_raise_power(dip); 6532 6533 return (DDI_FAILURE); 6534 } 6535 /* Check ub buffer pools */ 6536 if (port->ub_pool) { 6537 mutex_enter(&EMLXS_UB_LOCK); 6538 6539 /* Wait up to 10 seconds for all ub pools to be freed */ 6540 count = 10 * 2; 6541 while (port->ub_pool && count) { 6542 mutex_exit(&EMLXS_UB_LOCK); 6543 delay(drv_usectohz(500000)); /* half second wait */ 6544 count--; 6545 mutex_enter(&EMLXS_UB_LOCK); 6546 } 6547 6548 if (port->ub_pool) { 6549 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 6550 "fca_unbind_port: Unsolicited buffers still " 6551 "active. port=%p. Destroying...", port); 6552 6553 /* Destroy all pools */ 6554 while (port->ub_pool) { 6555 emlxs_ub_destroy(port, port->ub_pool); 6556 } 6557 } 6558 6559 mutex_exit(&EMLXS_UB_LOCK); 6560 } 6561 init_flag &= ~ATTACH_ONLINE; 6562 6563 /* Remove the driver instance */ 6564 emlxs_driver_remove(dip, init_flag, 0); 6565 6566 return (DDI_SUCCESS); 6567 6568 } /* emlxs_hba_detach() */ 6569 6570 6571 extern int 6572 emlxs_map_bus(emlxs_hba_t *hba) 6573 { 6574 emlxs_port_t *port = &PPORT; 6575 dev_info_t *dip; 6576 ddi_device_acc_attr_t dev_attr; 6577 int status; 6578 6579 dip = (dev_info_t *)hba->dip; 6580 dev_attr = emlxs_dev_acc_attr; 6581 6582 if (hba->bus_type == SBUS_FC) { 6583 if (hba->pci_acc_handle == 0) { 6584 status = ddi_regs_map_setup(dip, 6585 SBUS_DFLY_PCI_CFG_RINDEX, 6586 (caddr_t *)&hba->pci_addr, 6587 0, 0, &emlxs_dev_acc_attr, &hba->pci_acc_handle); 6588 if (status != DDI_SUCCESS) { 6589 EMLXS_MSGF(EMLXS_CONTEXT, 6590 &emlxs_attach_failed_msg, 6591 "(SBUS) ddi_regs_map_setup PCI failed. " 6592 "status=%x", status); 6593 goto failed; 6594 } 6595 } 6596 6597 if (hba->sbus_pci_handle == 0) { 6598 status = ddi_regs_map_setup(dip, 6599 SBUS_TITAN_PCI_CFG_RINDEX, 6600 (caddr_t *)&hba->sbus_pci_addr, 6601 0, 0, &dev_attr, &hba->sbus_pci_handle); 6602 if (status != DDI_SUCCESS) { 6603 EMLXS_MSGF(EMLXS_CONTEXT, 6604 &emlxs_attach_failed_msg, 6605 "(SBUS) ddi_regs_map_setup TITAN PCI " 6606 "failed. status=%x", status); 6607 goto failed; 6608 } 6609 } 6610 6611 } else { /* ****** PCI ****** */ 6612 6613 if (hba->pci_acc_handle == 0) { 6614 status = ddi_regs_map_setup(dip, 6615 PCI_CFG_RINDEX, 6616 (caddr_t *)&hba->pci_addr, 6617 0, 0, &emlxs_dev_acc_attr, &hba->pci_acc_handle); 6618 if (status != DDI_SUCCESS) { 6619 EMLXS_MSGF(EMLXS_CONTEXT, 6620 &emlxs_attach_failed_msg, 6621 "(PCI) ddi_regs_map_setup PCI failed. " 6622 "status=%x", status); 6623 goto failed; 6624 } 6625 } 6626 #ifdef EMLXS_I386 6627 /* Setting up PCI configure space */ 6628 (void) ddi_put16(hba->pci_acc_handle, 6629 (uint16_t *)(hba->pci_addr + PCI_COMMAND_REGISTER), 6630 CMD_CFG_VALUE | CMD_IO_ENBL); 6631 6632 #ifdef FMA_SUPPORT 6633 if (emlxs_fm_check_acc_handle(hba, hba->pci_acc_handle) 6634 != DDI_FM_OK) { 6635 EMLXS_MSGF(EMLXS_CONTEXT, 6636 &emlxs_invalid_access_handle_msg, NULL); 6637 goto failed; 6638 } 6639 #endif /* FMA_SUPPORT */ 6640 6641 #endif /* EMLXS_I386 */ 6642 6643 } 6644 return (0); 6645 6646 failed: 6647 6648 emlxs_unmap_bus(hba); 6649 return (ENOMEM); 6650 6651 } /* emlxs_map_bus() */ 6652 6653 6654 extern void 6655 emlxs_unmap_bus(emlxs_hba_t *hba) 6656 { 6657 if (hba->pci_acc_handle) { 6658 (void) ddi_regs_map_free(&hba->pci_acc_handle); 6659 hba->pci_acc_handle = 0; 6660 } 6661 6662 if (hba->sbus_pci_handle) { 6663 (void) ddi_regs_map_free(&hba->sbus_pci_handle); 6664 hba->sbus_pci_handle = 0; 6665 } 6666 6667 return; 6668 6669 } /* emlxs_unmap_bus() */ 6670 6671 6672 static int 6673 emlxs_get_props(emlxs_hba_t *hba) 6674 { 6675 emlxs_config_t *cfg; 6676 uint32_t i; 6677 char string[256]; 6678 uint32_t new_value; 6679 6680 /* Initialize each parameter */ 6681 for (i = 0; i < NUM_CFG_PARAM; i++) { 6682 cfg = &hba->config[i]; 6683 6684 /* Ensure strings are terminated */ 6685 cfg->string[(EMLXS_CFG_STR_SIZE-1)] = 0; 6686 cfg->help[(EMLXS_CFG_HELP_SIZE-1)] = 0; 6687 6688 /* Set the current value to the default value */ 6689 new_value = cfg->def; 6690 6691 /* First check for the global setting */ 6692 new_value = (uint32_t)ddi_prop_get_int(DDI_DEV_T_ANY, 6693 (void *)hba->dip, DDI_PROP_DONTPASS, 6694 cfg->string, new_value); 6695 6696 /* Now check for the per adapter ddiinst setting */ 6697 (void) sprintf(string, "%s%d-%s", DRIVER_NAME, hba->ddiinst, 6698 cfg->string); 6699 6700 new_value = (uint32_t)ddi_prop_get_int(DDI_DEV_T_ANY, 6701 (void *)hba->dip, DDI_PROP_DONTPASS, string, new_value); 6702 6703 /* Now check the parameter */ 6704 cfg->current = emlxs_check_parm(hba, i, new_value); 6705 } 6706 6707 return (0); 6708 6709 } /* emlxs_get_props() */ 6710 6711 6712 extern uint32_t 6713 emlxs_check_parm(emlxs_hba_t *hba, uint32_t index, uint32_t new_value) 6714 { 6715 emlxs_port_t *port = &PPORT; 6716 uint32_t i; 6717 emlxs_config_t *cfg; 6718 emlxs_vpd_t *vpd = &VPD; 6719 6720 if (index > NUM_CFG_PARAM) { 6721 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 6722 "emlxs_check_parm failed. Invalid index = %d", index); 6723 6724 return (new_value); 6725 } 6726 6727 cfg = &hba->config[index]; 6728 6729 if (new_value > cfg->hi) { 6730 new_value = cfg->def; 6731 } else if (new_value < cfg->low) { 6732 new_value = cfg->def; 6733 } 6734 6735 /* Perform additional checks */ 6736 switch (index) { 6737 case CFG_NPIV_ENABLE: 6738 if (hba->tgt_mode) { 6739 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 6740 "enable-npiv: Not supported in target mode. " 6741 "Disabling."); 6742 6743 new_value = 0; 6744 } 6745 break; 6746 6747 #ifdef DHCHAP_SUPPORT 6748 case CFG_AUTH_ENABLE: 6749 if (hba->tgt_mode) { 6750 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 6751 "enable-auth: Not supported in target mode. " 6752 "Disabling."); 6753 6754 new_value = 0; 6755 } 6756 break; 6757 #endif /* DHCHAP_SUPPORT */ 6758 6759 case CFG_NUM_NODES: 6760 switch (new_value) { 6761 case 1: 6762 case 2: 6763 /* Must have at least 3 if not 0 */ 6764 return (3); 6765 6766 default: 6767 break; 6768 } 6769 break; 6770 6771 case CFG_LINK_SPEED: 6772 if (vpd->link_speed) { 6773 switch (new_value) { 6774 case 0: 6775 break; 6776 6777 case 1: 6778 if (!(vpd->link_speed & LMT_1GB_CAPABLE)) { 6779 new_value = 0; 6780 6781 EMLXS_MSGF(EMLXS_CONTEXT, 6782 &emlxs_init_msg, 6783 "link-speed: 1Gb not supported " 6784 "by adapter. Switching to auto " 6785 "detect."); 6786 } 6787 break; 6788 6789 case 2: 6790 if (!(vpd->link_speed & LMT_2GB_CAPABLE)) { 6791 new_value = 0; 6792 6793 EMLXS_MSGF(EMLXS_CONTEXT, 6794 &emlxs_init_msg, 6795 "link-speed: 2Gb not supported " 6796 "by adapter. Switching to auto " 6797 "detect."); 6798 } 6799 break; 6800 case 4: 6801 if (!(vpd->link_speed & LMT_4GB_CAPABLE)) { 6802 new_value = 0; 6803 6804 EMLXS_MSGF(EMLXS_CONTEXT, 6805 &emlxs_init_msg, 6806 "link-speed: 4Gb not supported " 6807 "by adapter. Switching to auto " 6808 "detect."); 6809 } 6810 break; 6811 6812 case 8: 6813 if (!(vpd->link_speed & LMT_8GB_CAPABLE)) { 6814 new_value = 0; 6815 6816 EMLXS_MSGF(EMLXS_CONTEXT, 6817 &emlxs_init_msg, 6818 "link-speed: 8Gb not supported " 6819 "by adapter. Switching to auto " 6820 "detect."); 6821 } 6822 break; 6823 6824 case 10: 6825 if (!(vpd->link_speed & LMT_10GB_CAPABLE)) { 6826 new_value = 0; 6827 6828 EMLXS_MSGF(EMLXS_CONTEXT, 6829 &emlxs_init_msg, 6830 "link-speed: 10Gb not supported " 6831 "by adapter. Switching to auto " 6832 "detect."); 6833 } 6834 break; 6835 6836 default: 6837 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 6838 "link-speed: Invalid value=%d provided. " 6839 "Switching to auto detect.", 6840 new_value); 6841 6842 new_value = 0; 6843 } 6844 } else { /* Perform basic validity check */ 6845 6846 /* Perform additional check on link speed */ 6847 switch (new_value) { 6848 case 0: 6849 case 1: 6850 case 2: 6851 case 4: 6852 case 8: 6853 case 10: 6854 /* link-speed is a valid choice */ 6855 break; 6856 6857 default: 6858 new_value = cfg->def; 6859 } 6860 } 6861 break; 6862 6863 case CFG_TOPOLOGY: 6864 /* Perform additional check on topology */ 6865 switch (new_value) { 6866 case 0: 6867 case 2: 6868 case 4: 6869 case 6: 6870 /* topology is a valid choice */ 6871 break; 6872 6873 default: 6874 return (cfg->def); 6875 } 6876 break; 6877 6878 #ifdef DHCHAP_SUPPORT 6879 case CFG_AUTH_TYPE: 6880 { 6881 uint32_t shift; 6882 uint32_t mask; 6883 6884 /* Perform additional check on auth type */ 6885 shift = 12; 6886 mask = 0xF000; 6887 for (i = 0; i < 4; i++) { 6888 if (((new_value & mask) >> shift) > DFC_AUTH_TYPE_MAX) { 6889 return (cfg->def); 6890 } 6891 6892 shift -= 4; 6893 mask >>= 4; 6894 } 6895 break; 6896 } 6897 6898 case CFG_AUTH_HASH: 6899 { 6900 uint32_t shift; 6901 uint32_t mask; 6902 6903 /* Perform additional check on auth hash */ 6904 shift = 12; 6905 mask = 0xF000; 6906 for (i = 0; i < 4; i++) { 6907 if (((new_value & mask) >> shift) > DFC_AUTH_HASH_MAX) { 6908 return (cfg->def); 6909 } 6910 6911 shift -= 4; 6912 mask >>= 4; 6913 } 6914 break; 6915 } 6916 6917 case CFG_AUTH_GROUP: 6918 { 6919 uint32_t shift; 6920 uint32_t mask; 6921 6922 /* Perform additional check on auth group */ 6923 shift = 28; 6924 mask = 0xF0000000; 6925 for (i = 0; i < 8; i++) { 6926 if (((new_value & mask) >> shift) > 6927 DFC_AUTH_GROUP_MAX) { 6928 return (cfg->def); 6929 } 6930 6931 shift -= 4; 6932 mask >>= 4; 6933 } 6934 break; 6935 } 6936 6937 case CFG_AUTH_INTERVAL: 6938 if (new_value < 10) { 6939 return (10); 6940 } 6941 break; 6942 6943 6944 #endif /* DHCHAP_SUPPORT */ 6945 6946 } /* switch */ 6947 6948 return (new_value); 6949 6950 } /* emlxs_check_parm() */ 6951 6952 6953 extern uint32_t 6954 emlxs_set_parm(emlxs_hba_t *hba, uint32_t index, uint32_t new_value) 6955 { 6956 emlxs_port_t *port = &PPORT; 6957 emlxs_port_t *vport; 6958 uint32_t vpi; 6959 emlxs_config_t *cfg; 6960 uint32_t old_value; 6961 6962 if (index > NUM_CFG_PARAM) { 6963 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 6964 "emlxs_set_parm failed. Invalid index = %d", index); 6965 6966 return ((uint32_t)FC_FAILURE); 6967 } 6968 6969 cfg = &hba->config[index]; 6970 6971 if (!(cfg->flags & PARM_DYNAMIC)) { 6972 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 6973 "emlxs_set_parm failed. %s is not dynamic.", cfg->string); 6974 6975 return ((uint32_t)FC_FAILURE); 6976 } 6977 6978 /* Check new value */ 6979 old_value = new_value; 6980 new_value = emlxs_check_parm(hba, index, new_value); 6981 6982 if (old_value != new_value) { 6983 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 6984 "emlxs_set_parm: %s invalid. 0x%x --> 0x%x", 6985 cfg->string, old_value, new_value); 6986 } 6987 6988 /* Return now if no actual change */ 6989 if (new_value == cfg->current) { 6990 return (FC_SUCCESS); 6991 } 6992 6993 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 6994 "emlxs_set_parm: %s changing. 0x%x --> 0x%x", 6995 cfg->string, cfg->current, new_value); 6996 6997 old_value = cfg->current; 6998 cfg->current = new_value; 6999 7000 /* React to change if needed */ 7001 switch (index) { 7002 7003 case CFG_PCI_MAX_READ: 7004 /* Update MXR */ 7005 emlxs_pcix_mxr_update(hba, 1); 7006 break; 7007 7008 case CFG_SLI_MODE: 7009 /* Check SLI mode */ 7010 if ((hba->sli_mode == 3) && (new_value == 2)) { 7011 /* All vports must be disabled first */ 7012 for (vpi = 1; vpi < MAX_VPORTS; vpi++) { 7013 vport = &VPORT(vpi); 7014 7015 if (vport->flag & EMLXS_PORT_ENABLE) { 7016 /* Reset current value */ 7017 cfg->current = old_value; 7018 7019 EMLXS_MSGF(EMLXS_CONTEXT, 7020 &emlxs_sfs_debug_msg, 7021 "emlxs_set_parm failed. %s: vpi=%d " 7022 "still enabled. Value restored to " 7023 "0x%x.", cfg->string, vpi, 7024 old_value); 7025 7026 return (2); 7027 } 7028 } 7029 } 7030 break; 7031 7032 case CFG_NPIV_ENABLE: 7033 /* Check if NPIV is being disabled */ 7034 if ((old_value == 1) && (new_value == 0)) { 7035 /* All vports must be disabled first */ 7036 for (vpi = 1; vpi < MAX_VPORTS; vpi++) { 7037 vport = &VPORT(vpi); 7038 7039 if (vport->flag & EMLXS_PORT_ENABLE) { 7040 /* Reset current value */ 7041 cfg->current = old_value; 7042 7043 EMLXS_MSGF(EMLXS_CONTEXT, 7044 &emlxs_sfs_debug_msg, 7045 "emlxs_set_parm failed. %s: vpi=%d " 7046 "still enabled. Value restored to " 7047 "0x%x.", cfg->string, vpi, 7048 old_value); 7049 7050 return (2); 7051 } 7052 } 7053 } 7054 7055 /* Trigger adapter reset */ 7056 /* (void) emlxs_reset(port, FC_FCA_RESET); */ 7057 7058 break; 7059 7060 7061 case CFG_VPORT_RESTRICTED: 7062 for (vpi = 0; vpi < MAX_VPORTS; vpi++) { 7063 vport = &VPORT(vpi); 7064 7065 if (!(vport->flag & EMLXS_PORT_CONFIG)) { 7066 continue; 7067 } 7068 7069 if (vport->options & EMLXS_OPT_RESTRICT_MASK) { 7070 continue; 7071 } 7072 7073 if (new_value) { 7074 vport->flag |= EMLXS_PORT_RESTRICTED; 7075 } else { 7076 vport->flag &= ~EMLXS_PORT_RESTRICTED; 7077 } 7078 } 7079 7080 break; 7081 7082 #ifdef DHCHAP_SUPPORT 7083 case CFG_AUTH_ENABLE: 7084 (void) emlxs_reset(port, FC_FCA_LINK_RESET); 7085 break; 7086 7087 case CFG_AUTH_TMO: 7088 hba->auth_cfg.authentication_timeout = cfg->current; 7089 break; 7090 7091 case CFG_AUTH_MODE: 7092 hba->auth_cfg.authentication_mode = cfg->current; 7093 break; 7094 7095 case CFG_AUTH_BIDIR: 7096 hba->auth_cfg.bidirectional = cfg->current; 7097 break; 7098 7099 case CFG_AUTH_TYPE: 7100 hba->auth_cfg.authentication_type_priority[0] = 7101 (cfg->current & 0xF000) >> 12; 7102 hba->auth_cfg.authentication_type_priority[1] = 7103 (cfg->current & 0x0F00) >> 8; 7104 hba->auth_cfg.authentication_type_priority[2] = 7105 (cfg->current & 0x00F0) >> 4; 7106 hba->auth_cfg.authentication_type_priority[3] = 7107 (cfg->current & 0x000F); 7108 break; 7109 7110 case CFG_AUTH_HASH: 7111 hba->auth_cfg.hash_priority[0] = 7112 (cfg->current & 0xF000) >> 12; 7113 hba->auth_cfg.hash_priority[1] = (cfg->current & 0x0F00)>>8; 7114 hba->auth_cfg.hash_priority[2] = (cfg->current & 0x00F0)>>4; 7115 hba->auth_cfg.hash_priority[3] = (cfg->current & 0x000F); 7116 break; 7117 7118 case CFG_AUTH_GROUP: 7119 hba->auth_cfg.dh_group_priority[0] = 7120 (cfg->current & 0xF0000000) >> 28; 7121 hba->auth_cfg.dh_group_priority[1] = 7122 (cfg->current & 0x0F000000) >> 24; 7123 hba->auth_cfg.dh_group_priority[2] = 7124 (cfg->current & 0x00F00000) >> 20; 7125 hba->auth_cfg.dh_group_priority[3] = 7126 (cfg->current & 0x000F0000) >> 16; 7127 hba->auth_cfg.dh_group_priority[4] = 7128 (cfg->current & 0x0000F000) >> 12; 7129 hba->auth_cfg.dh_group_priority[5] = 7130 (cfg->current & 0x00000F00) >> 8; 7131 hba->auth_cfg.dh_group_priority[6] = 7132 (cfg->current & 0x000000F0) >> 4; 7133 hba->auth_cfg.dh_group_priority[7] = 7134 (cfg->current & 0x0000000F); 7135 break; 7136 7137 case CFG_AUTH_INTERVAL: 7138 hba->auth_cfg.reauthenticate_time_interval = cfg->current; 7139 break; 7140 #endif /* DHCHAP_SUPPORT */ 7141 7142 } 7143 7144 return (FC_SUCCESS); 7145 7146 } /* emlxs_set_parm() */ 7147 7148 7149 /* 7150 * emlxs_mem_alloc OS specific routine for memory allocation / mapping 7151 * 7152 * The buf_info->flags field describes the memory operation requested. 7153 * 7154 * FC_MBUF_PHYSONLY set requests a supplied virtual address be mapped for DMA 7155 * Virtual address is supplied in buf_info->virt 7156 * DMA mapping flag is in buf_info->align 7157 * (DMA_READ_ONLY, DMA_WRITE_ONLY, DMA_READ_WRITE) 7158 * The mapped physical address is returned buf_info->phys 7159 * 7160 * FC_MBUF_PHYSONLY cleared requests memory be allocated for driver use and 7161 * if FC_MBUF_DMA is set the memory is also mapped for DMA 7162 * The byte alignment of the memory request is supplied in buf_info->align 7163 * The byte size of the memory request is supplied in buf_info->size 7164 * The virtual address is returned buf_info->virt 7165 * The mapped physical address is returned buf_info->phys (for FC_MBUF_DMA) 7166 */ 7167 extern uint8_t * 7168 emlxs_mem_alloc(emlxs_hba_t *hba, MBUF_INFO *buf_info) 7169 { 7170 emlxs_port_t *port = &PPORT; 7171 ddi_dma_attr_t dma_attr; 7172 ddi_device_acc_attr_t dev_attr; 7173 uint_t cookie_count; 7174 size_t dma_reallen; 7175 ddi_dma_cookie_t dma_cookie; 7176 uint_t dma_flag; 7177 int status; 7178 7179 dma_attr = emlxs_dma_attr_1sg; 7180 dev_attr = emlxs_data_acc_attr; 7181 7182 if (buf_info->flags & FC_MBUF_SNGLSG) { 7183 dma_attr.dma_attr_sgllen = 1; 7184 } 7185 7186 if (buf_info->flags & FC_MBUF_DMA32) { 7187 dma_attr.dma_attr_addr_hi = (uint64_t)0xffffffff; 7188 } 7189 7190 if (buf_info->flags & FC_MBUF_PHYSONLY) { 7191 7192 if (buf_info->virt == 0) { 7193 goto done; 7194 } 7195 7196 /* 7197 * Allocate the DMA handle for this DMA object 7198 */ 7199 status = ddi_dma_alloc_handle((void *)hba->dip, 7200 &dma_attr, DDI_DMA_DONTWAIT, 7201 NULL, (ddi_dma_handle_t *)&buf_info->dma_handle); 7202 if (status != DDI_SUCCESS) { 7203 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg, 7204 "ddi_dma_alloc_handle failed: size=%x align=%x " 7205 "flags=%x", buf_info->size, buf_info->align, 7206 buf_info->flags); 7207 7208 buf_info->phys = 0; 7209 buf_info->dma_handle = 0; 7210 goto done; 7211 } 7212 7213 switch (buf_info->align) { 7214 case DMA_READ_WRITE: 7215 dma_flag = (DDI_DMA_RDWR | DDI_DMA_CONSISTENT); 7216 break; 7217 case DMA_READ_ONLY: 7218 dma_flag = (DDI_DMA_READ | DDI_DMA_CONSISTENT); 7219 break; 7220 case DMA_WRITE_ONLY: 7221 dma_flag = (DDI_DMA_WRITE | DDI_DMA_CONSISTENT); 7222 break; 7223 } 7224 7225 /* Map this page of memory */ 7226 status = ddi_dma_addr_bind_handle( 7227 (ddi_dma_handle_t)buf_info->dma_handle, NULL, 7228 (caddr_t)buf_info->virt, (size_t)buf_info->size, 7229 dma_flag, DDI_DMA_DONTWAIT, NULL, &dma_cookie, 7230 &cookie_count); 7231 7232 if (status != DDI_DMA_MAPPED || (cookie_count > 1)) { 7233 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg, 7234 "ddi_dma_addr_bind_handle failed: status=%x " 7235 "count=%x flags=%x", status, cookie_count, 7236 buf_info->flags); 7237 7238 (void) ddi_dma_free_handle( 7239 (ddi_dma_handle_t *)&buf_info->dma_handle); 7240 buf_info->phys = 0; 7241 buf_info->dma_handle = 0; 7242 goto done; 7243 } 7244 7245 if (hba->bus_type == SBUS_FC) { 7246 7247 int32_t burstsizes_limit = 0xff; 7248 int32_t ret_burst; 7249 7250 ret_burst = ddi_dma_burstsizes( 7251 buf_info->dma_handle) & burstsizes_limit; 7252 if (ddi_dma_set_sbus64(buf_info->dma_handle, 7253 ret_burst) == DDI_FAILURE) { 7254 EMLXS_MSGF(EMLXS_CONTEXT, 7255 &emlxs_mem_alloc_failed_msg, 7256 "ddi_dma_set_sbus64 failed."); 7257 } 7258 } 7259 7260 /* Save Physical address */ 7261 buf_info->phys = dma_cookie.dmac_laddress; 7262 7263 /* 7264 * Just to be sure, let's add this 7265 */ 7266 EMLXS_MPDATA_SYNC((ddi_dma_handle_t)buf_info->dma_handle, 7267 (off_t)0, (size_t)buf_info->size, DDI_DMA_SYNC_FORDEV); 7268 7269 } else if (buf_info->flags & (FC_MBUF_DMA|FC_MBUF_DMA32)) { 7270 7271 dma_attr.dma_attr_align = buf_info->align; 7272 7273 /* 7274 * Allocate the DMA handle for this DMA object 7275 */ 7276 status = ddi_dma_alloc_handle((void *)hba->dip, &dma_attr, 7277 DDI_DMA_DONTWAIT, NULL, 7278 (ddi_dma_handle_t *)&buf_info->dma_handle); 7279 if (status != DDI_SUCCESS) { 7280 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg, 7281 "ddi_dma_alloc_handle failed: size=%x align=%x " 7282 "flags=%x", buf_info->size, buf_info->align, 7283 buf_info->flags); 7284 7285 buf_info->virt = 0; 7286 buf_info->phys = 0; 7287 buf_info->data_handle = 0; 7288 buf_info->dma_handle = 0; 7289 goto done; 7290 } 7291 7292 status = ddi_dma_mem_alloc( 7293 (ddi_dma_handle_t)buf_info->dma_handle, 7294 (size_t)buf_info->size, &dev_attr, DDI_DMA_CONSISTENT, 7295 DDI_DMA_DONTWAIT, NULL, (caddr_t *)&buf_info->virt, 7296 &dma_reallen, (ddi_acc_handle_t *)&buf_info->data_handle); 7297 7298 if ((status != DDI_SUCCESS) || (buf_info->size > dma_reallen)) { 7299 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg, 7300 "ddi_dma_mem_alloc failed: size=%x align=%x " 7301 "flags=%x", buf_info->size, buf_info->align, 7302 buf_info->flags); 7303 7304 (void) ddi_dma_free_handle( 7305 (ddi_dma_handle_t *)&buf_info->dma_handle); 7306 7307 buf_info->virt = 0; 7308 buf_info->phys = 0; 7309 buf_info->data_handle = 0; 7310 buf_info->dma_handle = 0; 7311 goto done; 7312 } 7313 7314 /* Map this page of memory */ 7315 status = ddi_dma_addr_bind_handle( 7316 (ddi_dma_handle_t)buf_info->dma_handle, NULL, 7317 (caddr_t)buf_info->virt, (size_t)buf_info->size, 7318 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, NULL, 7319 &dma_cookie, &cookie_count); 7320 7321 if (status != DDI_DMA_MAPPED || (cookie_count > 1)) { 7322 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg, 7323 "ddi_dma_addr_bind_handle failed: status=%x " 7324 "count=%d size=%x align=%x flags=%x", status, 7325 cookie_count, buf_info->size, buf_info->align, 7326 buf_info->flags); 7327 7328 (void) ddi_dma_mem_free( 7329 (ddi_acc_handle_t *)&buf_info->data_handle); 7330 (void) ddi_dma_free_handle( 7331 (ddi_dma_handle_t *)&buf_info->dma_handle); 7332 7333 buf_info->virt = 0; 7334 buf_info->phys = 0; 7335 buf_info->dma_handle = 0; 7336 buf_info->data_handle = 0; 7337 goto done; 7338 } 7339 7340 if (hba->bus_type == SBUS_FC) { 7341 int32_t burstsizes_limit = 0xff; 7342 int32_t ret_burst; 7343 7344 ret_burst = 7345 ddi_dma_burstsizes(buf_info-> 7346 dma_handle) & burstsizes_limit; 7347 if (ddi_dma_set_sbus64(buf_info->dma_handle, 7348 ret_burst) == DDI_FAILURE) { 7349 EMLXS_MSGF(EMLXS_CONTEXT, 7350 &emlxs_mem_alloc_failed_msg, 7351 "ddi_dma_set_sbus64 failed."); 7352 } 7353 } 7354 7355 /* Save Physical address */ 7356 buf_info->phys = dma_cookie.dmac_laddress; 7357 7358 /* Just to be sure, let's add this */ 7359 EMLXS_MPDATA_SYNC((ddi_dma_handle_t)buf_info->dma_handle, 7360 (off_t)0, (size_t)buf_info->size, DDI_DMA_SYNC_FORDEV); 7361 7362 } else { /* allocate virtual memory */ 7363 7364 buf_info->virt = 7365 (uint32_t *)kmem_zalloc((size_t)buf_info->size, 7366 KM_NOSLEEP); 7367 buf_info->phys = 0; 7368 buf_info->data_handle = 0; 7369 buf_info->dma_handle = 0; 7370 7371 if (buf_info->virt == (uint32_t *)0) { 7372 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_mem_alloc_failed_msg, 7373 "size=%x flags=%x", buf_info->size, 7374 buf_info->flags); 7375 } 7376 7377 } 7378 7379 done: 7380 7381 return ((uint8_t *)buf_info->virt); 7382 7383 } /* emlxs_mem_alloc() */ 7384 7385 7386 7387 /* 7388 * emlxs_mem_free: 7389 * 7390 * OS specific routine for memory de-allocation / unmapping 7391 * 7392 * The buf_info->flags field describes the memory operation requested. 7393 * 7394 * FC_MBUF_PHYSONLY set requests a supplied virtual address be unmapped 7395 * for DMA, but not freed. The mapped physical address to be unmapped is in 7396 * buf_info->phys 7397 * 7398 * FC_MBUF_PHYSONLY cleared requests memory be freed and unmapped for DMA only 7399 * if FC_MBUF_DMA is set. The mapped physical address to be unmapped is in 7400 * buf_info->phys. The virtual address to be freed is in buf_info->virt 7401 */ 7402 /*ARGSUSED*/ 7403 extern void 7404 emlxs_mem_free(emlxs_hba_t *hba, MBUF_INFO *buf_info) 7405 { 7406 if (buf_info->flags & FC_MBUF_PHYSONLY) { 7407 7408 if (buf_info->dma_handle) { 7409 (void) ddi_dma_unbind_handle(buf_info->dma_handle); 7410 (void) ddi_dma_free_handle( 7411 (ddi_dma_handle_t *)&buf_info->dma_handle); 7412 buf_info->dma_handle = NULL; 7413 } 7414 7415 } else if (buf_info->flags & (FC_MBUF_DMA|FC_MBUF_DMA32)) { 7416 7417 if (buf_info->dma_handle) { 7418 (void) ddi_dma_unbind_handle(buf_info->dma_handle); 7419 (void) ddi_dma_mem_free( 7420 (ddi_acc_handle_t *)&buf_info->data_handle); 7421 (void) ddi_dma_free_handle( 7422 (ddi_dma_handle_t *)&buf_info->dma_handle); 7423 buf_info->dma_handle = NULL; 7424 buf_info->data_handle = NULL; 7425 } 7426 7427 } else { /* allocate virtual memory */ 7428 7429 if (buf_info->virt) { 7430 kmem_free(buf_info->virt, (size_t)buf_info->size); 7431 buf_info->virt = NULL; 7432 } 7433 } 7434 7435 } /* emlxs_mem_free() */ 7436 7437 7438 /* 7439 * A channel has a association with a msi id. 7440 * One msi id could be associated with multiple channels. 7441 */ 7442 static int 7443 emlxs_next_chan(emlxs_hba_t *hba, int msi_id) 7444 { 7445 emlxs_config_t *cfg = &CFG; 7446 EQ_DESC_t *eqp; 7447 int chan; 7448 int num_wq; 7449 7450 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 7451 /* For SLI4 round robin all WQs associated with the msi_id */ 7452 eqp = &hba->sli.sli4.eq[msi_id]; 7453 num_wq = cfg[CFG_NUM_WQ].current; 7454 7455 mutex_enter(&eqp->lastwq_lock); 7456 chan = eqp->lastwq; 7457 eqp->lastwq++; 7458 if (eqp->lastwq >= ((msi_id + 1) * num_wq)) { 7459 eqp->lastwq -= num_wq; 7460 } 7461 mutex_exit(&eqp->lastwq_lock); 7462 7463 } else { 7464 chan = hba->channel_fcp; 7465 } 7466 return (chan); 7467 } 7468 7469 7470 static int 7471 emlxs_select_fcp_channel(emlxs_hba_t *hba, NODELIST *ndlp, int reset) 7472 { 7473 int channel; 7474 7475 7476 /* IO to FCP2 device or a device reset always use fcp channel */ 7477 if ((ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) || reset) { 7478 return (hba->channel_fcp); 7479 } 7480 7481 channel = emlxs_next_chan(hba, 0); 7482 7483 7484 /* If channel is closed, then try fcp channel */ 7485 if (ndlp->nlp_flag[channel] & NLP_CLOSED) { 7486 channel = hba->channel_fcp; 7487 } 7488 return (channel); 7489 7490 } 7491 7492 static int32_t 7493 emlxs_fast_target_reset(emlxs_port_t *port, emlxs_buf_t *sbp, NODELIST *ndlp) 7494 { 7495 emlxs_hba_t *hba = HBA; 7496 fc_packet_t *pkt; 7497 emlxs_config_t *cfg; 7498 MAILBOXQ *mbq; 7499 MAILBOX *mb; 7500 uint32_t rc; 7501 7502 /* 7503 * This routine provides a alternative target reset provessing 7504 * method. Instead of sending an actual target reset to the 7505 * NPort, we will first unreg the login to that NPort. This 7506 * will cause all the outstanding IOs the quickly complete with 7507 * a NO RPI local error. Next we will force the ULP to relogin 7508 * to the NPort by sending an RSCN (for that NPort) to the 7509 * upper layer. This method should result in a fast target 7510 * reset, as far as IOs completing; however, since an actual 7511 * target reset is not sent to the NPort, it is not 100% 7512 * compatable. Things like reservations will not be broken. 7513 * By default this option is DISABLED, and its only enabled thru 7514 * a hidden configuration parameter (fast-tgt-reset). 7515 */ 7516 rc = FC_TRAN_BUSY; 7517 pkt = PRIV2PKT(sbp); 7518 cfg = &CFG; 7519 7520 if ((mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) { 7521 /* issue the mbox cmd to the sli */ 7522 mb = (MAILBOX *) mbq->mbox; 7523 bzero((void *) mb, MAILBOX_CMD_BSIZE); 7524 mb->un.varUnregLogin.rpi = (uint16_t)ndlp->nlp_Rpi; 7525 #ifdef SLI3_SUPPORT 7526 mb->un.varUnregLogin.vpi = port->vpi; 7527 #endif /* SLI3_SUPPORT */ 7528 mb->mbxCommand = MBX_UNREG_LOGIN; 7529 mb->mbxOwner = OWN_HOST; 7530 7531 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, 7532 "Fast Target Reset: unreg rpi=x%x tmr %d", ndlp->nlp_Rpi, 7533 cfg[CFG_FAST_TGT_RESET_TMR].current); 7534 7535 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) 7536 == MBX_SUCCESS) { 7537 7538 ndlp->nlp_Rpi = 0; 7539 7540 mutex_enter(&sbp->mtx); 7541 sbp->node = (void *)ndlp; 7542 sbp->did = ndlp->nlp_DID; 7543 mutex_exit(&sbp->mtx); 7544 7545 if (pkt->pkt_rsplen) { 7546 bzero((uint8_t *)pkt->pkt_resp, 7547 pkt->pkt_rsplen); 7548 } 7549 if (cfg[CFG_FAST_TGT_RESET_TMR].current) { 7550 ndlp->nlp_force_rscn = hba->timer_tics + 7551 cfg[CFG_FAST_TGT_RESET_TMR].current; 7552 } 7553 7554 emlxs_pkt_complete(sbp, IOSTAT_SUCCESS, 0, 0); 7555 } 7556 7557 (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); 7558 rc = FC_SUCCESS; 7559 } 7560 return (rc); 7561 } 7562 7563 static int32_t 7564 emlxs_send_fcp_cmd(emlxs_port_t *port, emlxs_buf_t *sbp) 7565 { 7566 emlxs_hba_t *hba = HBA; 7567 fc_packet_t *pkt; 7568 emlxs_config_t *cfg; 7569 IOCBQ *iocbq; 7570 IOCB *iocb; 7571 CHANNEL *cp; 7572 NODELIST *ndlp; 7573 char *cmd; 7574 uint16_t lun; 7575 FCP_CMND *fcp_cmd; 7576 uint32_t did; 7577 uint32_t reset = 0; 7578 int channel; 7579 int32_t rval; 7580 7581 pkt = PRIV2PKT(sbp); 7582 did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id); 7583 7584 /* Find target node object */ 7585 ndlp = emlxs_node_find_did(port, did); 7586 7587 if (!ndlp || !ndlp->nlp_active) { 7588 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg, 7589 "Node not found. did=%x", did); 7590 7591 return (FC_BADPACKET); 7592 } 7593 7594 /* When the fcp channel is closed we stop accepting any FCP cmd */ 7595 if (ndlp->nlp_flag[hba->channel_fcp] & NLP_CLOSED) { 7596 return (FC_TRAN_BUSY); 7597 } 7598 7599 /* Snoop for target or lun reset first */ 7600 /* We always use FCP channel to send out target/lun reset fcp cmds */ 7601 /* interrupt affinity only applies to non tgt lun reset fcp cmd */ 7602 7603 cmd = (char *)pkt->pkt_cmd; 7604 lun = *((uint16_t *)cmd); 7605 lun = LE_SWAP16(lun); 7606 7607 iocbq = &sbp->iocbq; 7608 iocb = &iocbq->iocb; 7609 iocbq->node = (void *) ndlp; 7610 7611 /* Check for target reset */ 7612 if (cmd[10] & 0x20) { 7613 /* prepare iocb */ 7614 if ((rval = EMLXS_SLI_PREP_FCP_IOCB(port, sbp, 7615 hba->channel_fcp)) != FC_SUCCESS) { 7616 7617 if (rval == 0xff) { 7618 emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 7619 0, 1); 7620 rval = FC_SUCCESS; 7621 } 7622 7623 return (rval); 7624 } 7625 7626 mutex_enter(&sbp->mtx); 7627 sbp->pkt_flags |= PACKET_FCP_TGT_RESET; 7628 sbp->pkt_flags |= PACKET_POLLED; 7629 mutex_exit(&sbp->mtx); 7630 7631 #ifdef SAN_DIAG_SUPPORT 7632 emlxs_log_sd_scsi_event(port, SD_SCSI_SUBCATEGORY_TGTRESET, 7633 (HBA_WWN *)&ndlp->nlp_portname, -1); 7634 #endif /* SAN_DIAG_SUPPORT */ 7635 7636 iocbq->flag |= IOCB_PRIORITY; 7637 7638 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, 7639 "Target Reset: did=%x", did); 7640 7641 cfg = &CFG; 7642 if (cfg[CFG_FAST_TGT_RESET].current) { 7643 if (emlxs_fast_target_reset(port, sbp, ndlp) == 7644 FC_SUCCESS) { 7645 return (FC_SUCCESS); 7646 } 7647 } 7648 7649 /* Close the node for any further normal IO */ 7650 emlxs_node_close(port, ndlp, hba->channel_fcp, 7651 pkt->pkt_timeout); 7652 7653 /* Flush the IO's on the tx queues */ 7654 (void) emlxs_tx_node_flush(port, ndlp, 7655 &hba->chan[hba->channel_fcp], 0, sbp); 7656 7657 /* This is the target reset fcp cmd */ 7658 reset = 1; 7659 } 7660 7661 /* Check for lun reset */ 7662 else if (cmd[10] & 0x10) { 7663 /* prepare iocb */ 7664 if ((rval = EMLXS_SLI_PREP_FCP_IOCB(port, sbp, 7665 hba->channel_fcp)) != FC_SUCCESS) { 7666 7667 if (rval == 0xff) { 7668 emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 7669 0, 1); 7670 rval = FC_SUCCESS; 7671 } 7672 7673 return (rval); 7674 } 7675 7676 mutex_enter(&sbp->mtx); 7677 sbp->pkt_flags |= PACKET_FCP_LUN_RESET; 7678 sbp->pkt_flags |= PACKET_POLLED; 7679 mutex_exit(&sbp->mtx); 7680 7681 #ifdef SAN_DIAG_SUPPORT 7682 emlxs_log_sd_scsi_event(port, SD_SCSI_SUBCATEGORY_LUNRESET, 7683 (HBA_WWN *)&ndlp->nlp_portname, lun); 7684 #endif /* SAN_DIAG_SUPPORT */ 7685 7686 iocbq->flag |= IOCB_PRIORITY; 7687 7688 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, 7689 "LUN Reset: did=%x LUN=%02x02x", did, cmd[0], cmd[1]); 7690 7691 /* Flush the IO's on the tx queues for this lun */ 7692 (void) emlxs_tx_lun_flush(port, ndlp, lun, sbp); 7693 7694 /* This is the lun reset fcp cmd */ 7695 reset = 1; 7696 } 7697 7698 channel = emlxs_select_fcp_channel(hba, ndlp, reset); 7699 7700 #ifdef SAN_DIAG_SUPPORT 7701 sbp->sd_start_time = gethrtime(); 7702 #endif /* SAN_DIAG_SUPPORT */ 7703 7704 #if (EMLXS_MODREVX == EMLXS_MODREV2X) 7705 emlxs_swap_fcp_pkt(sbp); 7706 #endif /* EMLXS_MODREV2X */ 7707 7708 fcp_cmd = (FCP_CMND *) pkt->pkt_cmd; 7709 7710 if (fcp_cmd->fcpCntl1 == FCP_QTYPE_UNTAGGED) { 7711 fcp_cmd->fcpCntl1 = FCP_QTYPE_SIMPLE; 7712 } 7713 7714 if (reset == 0) { 7715 /* 7716 * tgt lun reset fcp cmd has been prepared 7717 * separately in the beginning 7718 */ 7719 if ((rval = EMLXS_SLI_PREP_FCP_IOCB(port, sbp, 7720 channel)) != FC_SUCCESS) { 7721 7722 if (rval == 0xff) { 7723 emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 7724 0, 1); 7725 rval = FC_SUCCESS; 7726 } 7727 7728 return (rval); 7729 } 7730 } 7731 7732 cp = &hba->chan[channel]; 7733 cp->ulpSendCmd++; 7734 7735 /* Initalize sbp */ 7736 mutex_enter(&sbp->mtx); 7737 sbp->ticks = hba->timer_tics + pkt->pkt_timeout + 7738 ((pkt->pkt_timeout > 0xff) ? 0 : 10); 7739 sbp->node = (void *)ndlp; 7740 sbp->lun = lun; 7741 sbp->class = iocb->ULPCLASS; 7742 sbp->did = ndlp->nlp_DID; 7743 mutex_exit(&sbp->mtx); 7744 7745 if (pkt->pkt_cmdlen) { 7746 EMLXS_MPDATA_SYNC(pkt->pkt_cmd_dma, 0, pkt->pkt_cmdlen, 7747 DDI_DMA_SYNC_FORDEV); 7748 } 7749 7750 if (pkt->pkt_datalen && pkt->pkt_tran_type == FC_PKT_FCP_WRITE) { 7751 EMLXS_MPDATA_SYNC(pkt->pkt_data_dma, 0, pkt->pkt_datalen, 7752 DDI_DMA_SYNC_FORDEV); 7753 } 7754 7755 HBASTATS.FcpIssued++; 7756 7757 EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, iocbq); 7758 return (FC_SUCCESS); 7759 7760 } /* emlxs_send_fcp_cmd() */ 7761 7762 7763 7764 7765 #ifdef SFCT_SUPPORT 7766 static int32_t 7767 emlxs_send_fct_status(emlxs_port_t *port, emlxs_buf_t *sbp) 7768 { 7769 emlxs_hba_t *hba = HBA; 7770 fc_packet_t *pkt; 7771 IOCBQ *iocbq; 7772 IOCB *iocb; 7773 NODELIST *ndlp; 7774 CHANNEL *cp; 7775 uint16_t iotag; 7776 uint32_t did; 7777 ddi_dma_cookie_t *cp_cmd; 7778 7779 pkt = PRIV2PKT(sbp); 7780 7781 did = sbp->did; 7782 ndlp = sbp->node; 7783 7784 iocbq = &sbp->iocbq; 7785 iocb = &iocbq->iocb; 7786 7787 /* Make sure node is still active */ 7788 if (!ndlp->nlp_active) { 7789 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg, 7790 "*Node not found. did=%x", did); 7791 7792 return (FC_BADPACKET); 7793 } 7794 7795 /* If gate is closed */ 7796 if (ndlp->nlp_flag[hba->channel_fcp] & NLP_CLOSED) { 7797 return (FC_TRAN_BUSY); 7798 } 7799 7800 /* Get the iotag by registering the packet */ 7801 iotag = emlxs_register_pkt(sbp->channel, sbp); 7802 7803 if (!iotag) { 7804 /* No more command slots available, retry later */ 7805 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, 7806 "*Adapter Busy. Unable to allocate iotag: did=0x%x", did); 7807 7808 return (FC_TRAN_BUSY); 7809 } 7810 7811 /* Point of no return */ 7812 7813 cp = sbp->channel; 7814 cp->ulpSendCmd++; 7815 7816 #if (EMLXS_MODREV >= EMLXS_MODREV3) 7817 cp_cmd = pkt->pkt_cmd_cookie; 7818 #else 7819 cp_cmd = &pkt->pkt_cmd_cookie; 7820 #endif /* >= EMLXS_MODREV3 */ 7821 7822 iocb->un.fcpt64.bdl.addrHigh = PADDR_HI(cp_cmd->dmac_laddress); 7823 iocb->un.fcpt64.bdl.addrLow = PADDR_LO(cp_cmd->dmac_laddress); 7824 iocb->un.fcpt64.bdl.bdeSize = pkt->pkt_cmdlen; 7825 iocb->un.fcpt64.bdl.bdeFlags = 0; 7826 7827 if (hba->sli_mode < 3) { 7828 iocb->ULPBDECOUNT = 1; 7829 iocb->ULPLE = 1; 7830 } else { /* SLI3 */ 7831 7832 iocb->ULPBDECOUNT = 0; 7833 iocb->ULPLE = 0; 7834 iocb->unsli3.ext_iocb.ebde_count = 0; 7835 } 7836 7837 /* Initalize iocbq */ 7838 iocbq->port = (void *)port; 7839 iocbq->node = (void *)ndlp; 7840 iocbq->channel = (void *)cp; 7841 7842 /* Initalize iocb */ 7843 iocb->ULPCONTEXT = (uint16_t)pkt->pkt_cmd_fhdr.rx_id; 7844 iocb->ULPIOTAG = iotag; 7845 iocb->ULPRSVDBYTE = 7846 ((pkt->pkt_timeout > 0xff) ? 0 : pkt->pkt_timeout); 7847 iocb->ULPOWNER = OWN_CHIP; 7848 iocb->ULPCLASS = sbp->class; 7849 iocb->ULPCOMMAND = CMD_FCP_TRSP64_CX; 7850 7851 /* Set the pkt timer */ 7852 sbp->ticks = hba->timer_tics + pkt->pkt_timeout + 7853 ((pkt->pkt_timeout > 0xff) ? 0 : 10); 7854 7855 if (pkt->pkt_cmdlen) { 7856 EMLXS_MPDATA_SYNC(pkt->pkt_cmd_dma, 0, pkt->pkt_cmdlen, 7857 DDI_DMA_SYNC_FORDEV); 7858 } 7859 7860 HBASTATS.FcpIssued++; 7861 7862 EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, iocbq); 7863 7864 return (FC_SUCCESS); 7865 7866 } /* emlxs_send_fct_status() */ 7867 7868 7869 static int32_t 7870 emlxs_send_fct_abort(emlxs_port_t *port, emlxs_buf_t *sbp) 7871 { 7872 emlxs_hba_t *hba = HBA; 7873 fc_packet_t *pkt; 7874 IOCBQ *iocbq; 7875 IOCB *iocb; 7876 NODELIST *ndlp; 7877 uint16_t iotag; 7878 uint32_t did; 7879 7880 pkt = PRIV2PKT(sbp); 7881 7882 did = sbp->did; 7883 ndlp = sbp->node; 7884 7885 7886 iocbq = &sbp->iocbq; 7887 iocb = &iocbq->iocb; 7888 7889 /* Make sure node is still active */ 7890 if ((ndlp == NULL) || (!ndlp->nlp_active)) { 7891 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg, 7892 "*Node not found. did=%x", did); 7893 7894 return (FC_BADPACKET); 7895 } 7896 7897 /* If gate is closed */ 7898 if (ndlp->nlp_flag[hba->channel_fcp] & NLP_CLOSED) { 7899 return (FC_TRAN_BUSY); 7900 } 7901 7902 /* Get the iotag by registering the packet */ 7903 iotag = emlxs_register_pkt(sbp->channel, sbp); 7904 7905 if (!iotag) { 7906 /* No more command slots available, retry later */ 7907 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, 7908 "*Adapter Busy. Unable to allocate iotag: did=0x%x", did); 7909 7910 return (FC_TRAN_BUSY); 7911 } 7912 7913 /* Point of no return */ 7914 iocbq->port = (void *)port; 7915 iocbq->node = (void *)ndlp; 7916 iocbq->channel = (void *)sbp->channel; 7917 ((CHANNEL *)sbp->channel)->ulpSendCmd++; 7918 7919 /* 7920 * Don't give the abort priority, we want the IOCB 7921 * we are aborting to be processed first. 7922 */ 7923 iocbq->flag |= IOCB_SPECIAL; 7924 7925 iocb->ULPCONTEXT = pkt->pkt_cmd_fhdr.rx_id; 7926 iocb->ULPIOTAG = iotag; 7927 iocb->ULPLE = 1; 7928 iocb->ULPCLASS = sbp->class; 7929 iocb->ULPOWNER = OWN_CHIP; 7930 7931 if (hba->state >= FC_LINK_UP) { 7932 /* Create the abort IOCB */ 7933 iocb->un.acxri.abortType = ABORT_TYPE_ABTS; 7934 iocb->ULPCOMMAND = CMD_ABORT_XRI_CX; 7935 7936 } else { 7937 /* Create the close IOCB */ 7938 iocb->ULPCOMMAND = CMD_CLOSE_XRI_CX; 7939 7940 } 7941 7942 iocb->ULPRSVDBYTE = 7943 ((pkt->pkt_timeout > 0xff) ? 0 : pkt->pkt_timeout); 7944 /* Set the pkt timer */ 7945 sbp->ticks = hba->timer_tics + pkt->pkt_timeout + 7946 ((pkt->pkt_timeout > 0xff) ? 0 : 10); 7947 7948 EMLXS_SLI_ISSUE_IOCB_CMD(hba, sbp->channel, iocbq); 7949 7950 return (FC_SUCCESS); 7951 7952 } /* emlxs_send_fct_abort() */ 7953 7954 #endif /* SFCT_SUPPORT */ 7955 7956 7957 static int32_t 7958 emlxs_send_ip(emlxs_port_t *port, emlxs_buf_t *sbp) 7959 { 7960 emlxs_hba_t *hba = HBA; 7961 fc_packet_t *pkt; 7962 IOCBQ *iocbq; 7963 IOCB *iocb; 7964 CHANNEL *cp; 7965 uint32_t i; 7966 NODELIST *ndlp; 7967 uint32_t did; 7968 int32_t rval; 7969 7970 pkt = PRIV2PKT(sbp); 7971 cp = &hba->chan[hba->channel_ip]; 7972 did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id); 7973 7974 /* Check if node exists */ 7975 /* Broadcast did is always a success */ 7976 ndlp = emlxs_node_find_did(port, did); 7977 7978 if (!ndlp || !ndlp->nlp_active) { 7979 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg, 7980 "Node not found. did=0x%x", did); 7981 7982 return (FC_BADPACKET); 7983 } 7984 7985 /* Check if gate is temporarily closed */ 7986 if (ndlp->nlp_flag[hba->channel_ip] & NLP_CLOSED) { 7987 return (FC_TRAN_BUSY); 7988 } 7989 7990 /* Check if an exchange has been created */ 7991 if ((ndlp->nlp_Xri == 0) && (did != BCAST_DID)) { 7992 /* No exchange. Try creating one */ 7993 (void) emlxs_create_xri(port, cp, ndlp); 7994 7995 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, 7996 "Adapter Busy. Exchange not found. did=0x%x", did); 7997 7998 return (FC_TRAN_BUSY); 7999 } 8000 8001 /* ULP PATCH: pkt_cmdlen was found to be set to zero */ 8002 /* on BROADCAST commands */ 8003 if (pkt->pkt_cmdlen == 0) { 8004 /* Set the pkt_cmdlen to the cookie size */ 8005 #if (EMLXS_MODREV >= EMLXS_MODREV3) 8006 for (i = 0; i < pkt->pkt_cmd_cookie_cnt; i++) { 8007 pkt->pkt_cmdlen += pkt->pkt_cmd_cookie[i].dmac_size; 8008 } 8009 #else 8010 pkt->pkt_cmdlen = pkt->pkt_cmd_cookie.dmac_size; 8011 #endif /* >= EMLXS_MODREV3 */ 8012 8013 } 8014 8015 iocbq = &sbp->iocbq; 8016 iocb = &iocbq->iocb; 8017 8018 iocbq->node = (void *)ndlp; 8019 if ((rval = EMLXS_SLI_PREP_IP_IOCB(port, sbp)) != FC_SUCCESS) { 8020 8021 if (rval == 0xff) { 8022 emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 0, 1); 8023 rval = FC_SUCCESS; 8024 } 8025 8026 return (rval); 8027 } 8028 8029 cp->ulpSendCmd++; 8030 8031 /* Initalize sbp */ 8032 mutex_enter(&sbp->mtx); 8033 sbp->ticks = hba->timer_tics + pkt->pkt_timeout + 8034 ((pkt->pkt_timeout > 0xff) ? 0 : 10); 8035 sbp->node = (void *)ndlp; 8036 sbp->lun = 0; 8037 sbp->class = iocb->ULPCLASS; 8038 sbp->did = did; 8039 mutex_exit(&sbp->mtx); 8040 8041 if (pkt->pkt_cmdlen) { 8042 EMLXS_MPDATA_SYNC(pkt->pkt_cmd_dma, 0, pkt->pkt_cmdlen, 8043 DDI_DMA_SYNC_FORDEV); 8044 } 8045 8046 EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, iocbq); 8047 8048 return (FC_SUCCESS); 8049 8050 } /* emlxs_send_ip() */ 8051 8052 8053 static int32_t 8054 emlxs_send_els(emlxs_port_t *port, emlxs_buf_t *sbp) 8055 { 8056 emlxs_hba_t *hba = HBA; 8057 emlxs_port_t *vport; 8058 fc_packet_t *pkt; 8059 IOCBQ *iocbq; 8060 CHANNEL *cp; 8061 uint32_t cmd; 8062 int i; 8063 ELS_PKT *els_pkt; 8064 NODELIST *ndlp; 8065 uint32_t did; 8066 char fcsp_msg[32]; 8067 int rc; 8068 int32_t rval; 8069 8070 fcsp_msg[0] = 0; 8071 pkt = PRIV2PKT(sbp); 8072 els_pkt = (ELS_PKT *)pkt->pkt_cmd; 8073 did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id); 8074 8075 iocbq = &sbp->iocbq; 8076 8077 #if (EMLXS_MODREVX == EMLXS_MODREV2X) 8078 emlxs_swap_els_pkt(sbp); 8079 #endif /* EMLXS_MODREV2X */ 8080 8081 cmd = *((uint32_t *)pkt->pkt_cmd); 8082 cmd &= ELS_CMD_MASK; 8083 8084 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 8085 "Send ELS cmd: %x", cmd); 8086 8087 /* Point of no return, except for ADISC & PLOGI */ 8088 8089 /* Check node */ 8090 switch (cmd) { 8091 case ELS_CMD_FLOGI: 8092 if (port->vpi > 0) { 8093 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 8094 if (!(port->flag & EMLXS_PORT_INIT_VPI_CMPL)) { 8095 (void) emlxs_mb_init_vpi(port); 8096 if (!(port->flag & 8097 EMLXS_PORT_INIT_VPI_CMPL)) { 8098 pkt->pkt_state = 8099 FC_PKT_LOCAL_RJT; 8100 8101 #if (EMLXS_MODREVX == EMLXS_MODREV2X) 8102 emlxs_unswap_pkt(sbp); 8103 #endif /* EMLXS_MODREV2X */ 8104 8105 return (FC_FAILURE); 8106 } 8107 } 8108 } 8109 cmd = ELS_CMD_FDISC; 8110 *((uint32_t *)pkt->pkt_cmd) = cmd; 8111 } 8112 ndlp = NULL; 8113 8114 if (hba->flag & FC_NPIV_DELAY_REQUIRED) { 8115 sbp->pkt_flags |= PACKET_DELAY_REQUIRED; 8116 } 8117 8118 /* We will process these cmds at the bottom of this routine */ 8119 break; 8120 8121 case ELS_CMD_PLOGI: 8122 /* Make sure we don't log into ourself */ 8123 for (i = 0; i < MAX_VPORTS; i++) { 8124 vport = &VPORT(i); 8125 8126 if (!(vport->flag & EMLXS_PORT_BOUND)) { 8127 continue; 8128 } 8129 8130 if (did == vport->did) { 8131 pkt->pkt_state = FC_PKT_NPORT_RJT; 8132 8133 #if (EMLXS_MODREVX == EMLXS_MODREV2X) 8134 emlxs_unswap_pkt(sbp); 8135 #endif /* EMLXS_MODREV2X */ 8136 8137 return (FC_FAILURE); 8138 } 8139 } 8140 8141 ndlp = NULL; 8142 8143 /* Check if this is the first PLOGI */ 8144 /* after a PT_TO_PT connection */ 8145 if ((hba->flag & FC_PT_TO_PT) && (port->did == 0)) { 8146 MAILBOXQ *mbox; 8147 8148 /* ULP bug fix */ 8149 if (pkt->pkt_cmd_fhdr.s_id == 0) { 8150 pkt->pkt_cmd_fhdr.s_id = 8151 pkt->pkt_cmd_fhdr.d_id - FP_DEFAULT_DID + 8152 FP_DEFAULT_SID; 8153 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_els_send_msg, 8154 "PLOGI: P2P Fix. sid=0-->%x did=%x", 8155 pkt->pkt_cmd_fhdr.s_id, 8156 pkt->pkt_cmd_fhdr.d_id); 8157 } 8158 8159 mutex_enter(&EMLXS_PORT_LOCK); 8160 port->did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.s_id); 8161 mutex_exit(&EMLXS_PORT_LOCK); 8162 8163 /* Update our service parms */ 8164 if ((mbox = (MAILBOXQ *)emlxs_mem_get(hba, 8165 MEM_MBOX, 1))) { 8166 emlxs_mb_config_link(hba, mbox); 8167 8168 rc = EMLXS_SLI_ISSUE_MBOX_CMD(hba, 8169 mbox, MBX_NOWAIT, 0); 8170 if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) { 8171 (void) emlxs_mem_put(hba, MEM_MBOX, 8172 (uint8_t *)mbox); 8173 } 8174 8175 } 8176 } 8177 8178 /* We will process these cmds at the bottom of this routine */ 8179 break; 8180 8181 default: 8182 ndlp = emlxs_node_find_did(port, did); 8183 8184 /* If an ADISC is being sent and we have no node, */ 8185 /* then we must fail the ADISC now */ 8186 if (!ndlp && (cmd == ELS_CMD_ADISC) && !port->tgt_mode) { 8187 8188 /* Build the LS_RJT response */ 8189 els_pkt = (ELS_PKT *)pkt->pkt_resp; 8190 els_pkt->elsCode = 0x01; 8191 els_pkt->un.lsRjt.un.b.lsRjtRsvd0 = 0; 8192 els_pkt->un.lsRjt.un.b.lsRjtRsnCode = 8193 LSRJT_LOGICAL_ERR; 8194 els_pkt->un.lsRjt.un.b.lsRjtRsnCodeExp = 8195 LSEXP_NOTHING_MORE; 8196 els_pkt->un.lsRjt.un.b.vendorUnique = 0x03; 8197 8198 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_msg, 8199 "ADISC Rejected. Node not found. did=0x%x", did); 8200 8201 if (sbp->channel == NULL) { 8202 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 8203 sbp->channel = 8204 &hba->chan[hba->channel_els]; 8205 } else { 8206 sbp->channel = 8207 &hba->chan[FC_ELS_RING]; 8208 } 8209 } 8210 8211 /* Return this as rejected by the target */ 8212 emlxs_pkt_complete(sbp, IOSTAT_LS_RJT, 0, 1); 8213 8214 return (FC_SUCCESS); 8215 } 8216 } 8217 8218 /* DID == BCAST_DID is special case to indicate that */ 8219 /* RPI is being passed in seq_id field */ 8220 /* This is used by emlxs_send_logo() for target mode */ 8221 8222 /* Initalize iocbq */ 8223 iocbq->node = (void *)ndlp; 8224 if ((rval = EMLXS_SLI_PREP_ELS_IOCB(port, sbp)) != FC_SUCCESS) { 8225 8226 if (rval == 0xff) { 8227 emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 0, 1); 8228 rval = FC_SUCCESS; 8229 } 8230 8231 return (rval); 8232 } 8233 8234 cp = &hba->chan[hba->channel_els]; 8235 cp->ulpSendCmd++; 8236 8237 /* Check cmd */ 8238 switch (cmd) { 8239 case ELS_CMD_PRLI: 8240 { 8241 /* 8242 * if our firmware version is 3.20 or later, 8243 * set the following bits for FC-TAPE support. 8244 */ 8245 8246 if (port->ini_mode && hba->vpd.feaLevelHigh >= 0x02) { 8247 els_pkt->un.prli.ConfmComplAllowed = 1; 8248 els_pkt->un.prli.Retry = 1; 8249 els_pkt->un.prli.TaskRetryIdReq = 1; 8250 } else { 8251 els_pkt->un.prli.ConfmComplAllowed = 0; 8252 els_pkt->un.prli.Retry = 0; 8253 els_pkt->un.prli.TaskRetryIdReq = 0; 8254 } 8255 8256 break; 8257 } 8258 8259 /* This is a patch for the ULP stack. */ 8260 8261 /* 8262 * ULP only reads our service paramters once during bind_port, 8263 * but the service parameters change due to topology. 8264 */ 8265 case ELS_CMD_FLOGI: 8266 case ELS_CMD_FDISC: 8267 case ELS_CMD_PLOGI: 8268 case ELS_CMD_PDISC: 8269 { 8270 /* Copy latest service parameters to payload */ 8271 bcopy((void *) &port->sparam, 8272 (void *)&els_pkt->un.logi, sizeof (SERV_PARM)); 8273 8274 if ((hba->flag & FC_NPIV_ENABLED) && 8275 (hba->flag & FC_NPIV_SUPPORTED) && 8276 (cmd == ELS_CMD_PLOGI)) { 8277 SERV_PARM *sp; 8278 emlxs_vvl_fmt_t *vvl; 8279 8280 sp = (SERV_PARM *)&els_pkt->un.logi; 8281 sp->VALID_VENDOR_VERSION = 1; 8282 vvl = (emlxs_vvl_fmt_t *)&sp->vendorVersion[0]; 8283 vvl->un0.w0.oui = 0x0000C9; 8284 vvl->un0.word0 = LE_SWAP32(vvl->un0.word0); 8285 vvl->un1.w1.vport = (port->vpi > 0) ? 1 : 0; 8286 vvl->un1.word1 = LE_SWAP32(vvl->un1.word1); 8287 } 8288 8289 #ifdef DHCHAP_SUPPORT 8290 emlxs_dhc_init_sp(port, did, 8291 (SERV_PARM *)&els_pkt->un.logi, (char **)&fcsp_msg); 8292 #endif /* DHCHAP_SUPPORT */ 8293 8294 break; 8295 } 8296 8297 } 8298 8299 /* Initialize the sbp */ 8300 mutex_enter(&sbp->mtx); 8301 sbp->ticks = hba->timer_tics + pkt->pkt_timeout + 8302 ((pkt->pkt_timeout > 0xff) ? 0 : 10); 8303 sbp->node = (void *)ndlp; 8304 sbp->lun = 0; 8305 sbp->did = did; 8306 mutex_exit(&sbp->mtx); 8307 8308 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_els_send_msg, "%s: sid=%x did=%x %s", 8309 emlxs_elscmd_xlate(cmd), port->did, did, fcsp_msg); 8310 8311 if (pkt->pkt_cmdlen) { 8312 EMLXS_MPDATA_SYNC(pkt->pkt_cmd_dma, 0, pkt->pkt_cmdlen, 8313 DDI_DMA_SYNC_FORDEV); 8314 } 8315 8316 /* Check node */ 8317 switch (cmd) { 8318 case ELS_CMD_FLOGI: 8319 if (port->ini_mode) { 8320 /* Make sure fabric node is destroyed */ 8321 /* It should already have been destroyed at link down */ 8322 /* Unregister the fabric did and attempt a deferred */ 8323 /* iocb send */ 8324 if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) { 8325 if (emlxs_mb_unreg_did(port, FABRIC_DID, NULL, 8326 NULL, iocbq) == 0) { 8327 /* Deferring iocb tx until */ 8328 /* completion of unreg */ 8329 return (FC_SUCCESS); 8330 } 8331 } 8332 } 8333 break; 8334 8335 case ELS_CMD_PLOGI: 8336 8337 ndlp = emlxs_node_find_did(port, did); 8338 8339 if (ndlp && ndlp->nlp_active) { 8340 /* Close the node for any further normal IO */ 8341 emlxs_node_close(port, ndlp, hba->channel_fcp, 8342 pkt->pkt_timeout + 10); 8343 emlxs_node_close(port, ndlp, hba->channel_ip, 8344 pkt->pkt_timeout + 10); 8345 8346 /* Flush tx queues */ 8347 (void) emlxs_tx_node_flush(port, ndlp, 0, 0, 0); 8348 8349 /* Flush chip queues */ 8350 (void) emlxs_chipq_node_flush(port, 0, ndlp, 0); 8351 } 8352 8353 break; 8354 8355 case ELS_CMD_PRLI: 8356 8357 ndlp = emlxs_node_find_did(port, did); 8358 8359 if (ndlp && ndlp->nlp_active) { 8360 /* 8361 * Close the node for any further FCP IO; 8362 * Flush all outstanding I/O only if 8363 * "Establish Image Pair" bit is set. 8364 */ 8365 emlxs_node_close(port, ndlp, hba->channel_fcp, 8366 pkt->pkt_timeout + 10); 8367 8368 if (els_pkt->un.prli.estabImagePair) { 8369 /* Flush tx queues */ 8370 (void) emlxs_tx_node_flush(port, ndlp, 8371 &hba->chan[hba->channel_fcp], 0, 0); 8372 8373 /* Flush chip queues */ 8374 (void) emlxs_chipq_node_flush(port, 8375 &hba->chan[hba->channel_fcp], ndlp, 0); 8376 } 8377 } 8378 8379 break; 8380 8381 } 8382 8383 HBASTATS.ElsCmdIssued++; 8384 8385 EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, iocbq); 8386 8387 return (FC_SUCCESS); 8388 8389 } /* emlxs_send_els() */ 8390 8391 8392 8393 8394 static int32_t 8395 emlxs_send_els_rsp(emlxs_port_t *port, emlxs_buf_t *sbp) 8396 { 8397 emlxs_hba_t *hba = HBA; 8398 emlxs_config_t *cfg = &CFG; 8399 fc_packet_t *pkt; 8400 IOCBQ *iocbq; 8401 IOCB *iocb; 8402 NODELIST *ndlp; 8403 CHANNEL *cp; 8404 int i; 8405 uint32_t cmd; 8406 uint32_t ucmd; 8407 ELS_PKT *els_pkt; 8408 fc_unsol_buf_t *ubp; 8409 emlxs_ub_priv_t *ub_priv; 8410 uint32_t did; 8411 char fcsp_msg[32]; 8412 uint8_t *ub_buffer; 8413 int32_t rval; 8414 8415 fcsp_msg[0] = 0; 8416 pkt = PRIV2PKT(sbp); 8417 els_pkt = (ELS_PKT *)pkt->pkt_cmd; 8418 did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id); 8419 8420 iocbq = &sbp->iocbq; 8421 iocb = &iocbq->iocb; 8422 8423 /* Acquire the unsolicited command this pkt is replying to */ 8424 if (pkt->pkt_cmd_fhdr.ox_id < EMLXS_UB_TOKEN_OFFSET) { 8425 /* This is for auto replies when no ub's are used */ 8426 ucmd = pkt->pkt_cmd_fhdr.ox_id << ELS_CMD_SHIFT; 8427 ubp = NULL; 8428 ub_priv = NULL; 8429 ub_buffer = NULL; 8430 8431 #ifdef SFCT_SUPPORT 8432 if (sbp->fct_cmd) { 8433 fct_els_t *els = 8434 (fct_els_t *)sbp->fct_cmd->cmd_specific; 8435 ub_buffer = (uint8_t *)els->els_req_payload; 8436 } 8437 #endif /* SFCT_SUPPORT */ 8438 8439 } else { 8440 /* Find the ub buffer that goes with this reply */ 8441 if (!(ubp = emlxs_ub_find(port, pkt->pkt_cmd_fhdr.ox_id))) { 8442 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_error_msg, 8443 "ELS reply: Invalid oxid=%x", 8444 pkt->pkt_cmd_fhdr.ox_id); 8445 return (FC_BADPACKET); 8446 } 8447 8448 ub_buffer = (uint8_t *)ubp->ub_buffer; 8449 ub_priv = ubp->ub_fca_private; 8450 ucmd = ub_priv->cmd; 8451 8452 ub_priv->flags |= EMLXS_UB_REPLY; 8453 8454 /* Reset oxid to ELS command */ 8455 /* We do this because the ub is only valid */ 8456 /* until we return from this thread */ 8457 pkt->pkt_cmd_fhdr.ox_id = (ucmd >> ELS_CMD_SHIFT) & 0xff; 8458 } 8459 8460 /* Save the result */ 8461 sbp->ucmd = ucmd; 8462 8463 if (sbp->channel == NULL) { 8464 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 8465 sbp->channel = &hba->chan[hba->channel_els]; 8466 } else { 8467 sbp->channel = &hba->chan[FC_ELS_RING]; 8468 } 8469 } 8470 8471 /* Check for interceptions */ 8472 switch (ucmd) { 8473 8474 #ifdef ULP_PATCH2 8475 case ELS_CMD_LOGO: 8476 if (!(cfg[CFG_ENABLE_PATCH].current & ULP_PATCH2)) { 8477 break; 8478 } 8479 8480 /* Check if this was generated by ULP and not us */ 8481 if (!(sbp->pkt_flags & PACKET_ALLOCATED)) { 8482 8483 /* 8484 * Since we replied to this already, 8485 * we won't need to send this now 8486 */ 8487 emlxs_pkt_complete(sbp, IOSTAT_SUCCESS, 0, 1); 8488 8489 return (FC_SUCCESS); 8490 } 8491 8492 break; 8493 #endif /* ULP_PATCH2 */ 8494 8495 #ifdef ULP_PATCH3 8496 case ELS_CMD_PRLI: 8497 if (!(cfg[CFG_ENABLE_PATCH].current & ULP_PATCH3)) { 8498 break; 8499 } 8500 8501 /* Check if this was generated by ULP and not us */ 8502 if (!(sbp->pkt_flags & PACKET_ALLOCATED)) { 8503 8504 /* 8505 * Since we replied to this already, 8506 * we won't need to send this now 8507 */ 8508 emlxs_pkt_complete(sbp, IOSTAT_SUCCESS, 0, 1); 8509 8510 return (FC_SUCCESS); 8511 } 8512 8513 break; 8514 #endif /* ULP_PATCH3 */ 8515 8516 8517 #ifdef ULP_PATCH4 8518 case ELS_CMD_PRLO: 8519 if (!(cfg[CFG_ENABLE_PATCH].current & ULP_PATCH4)) { 8520 break; 8521 } 8522 8523 /* Check if this was generated by ULP and not us */ 8524 if (!(sbp->pkt_flags & PACKET_ALLOCATED)) { 8525 /* 8526 * Since we replied to this already, 8527 * we won't need to send this now 8528 */ 8529 emlxs_pkt_complete(sbp, IOSTAT_SUCCESS, 0, 1); 8530 8531 return (FC_SUCCESS); 8532 } 8533 8534 break; 8535 #endif /* ULP_PATCH4 */ 8536 8537 #ifdef ULP_PATCH6 8538 case ELS_CMD_RSCN: 8539 if (!(cfg[CFG_ENABLE_PATCH].current & ULP_PATCH6)) { 8540 break; 8541 } 8542 8543 /* Check if this RSCN was generated by us */ 8544 if (ub_priv && (ub_priv->flags & EMLXS_UB_INTERCEPT)) { 8545 cmd = *((uint32_t *)pkt->pkt_cmd); 8546 cmd = LE_SWAP32(cmd); 8547 cmd &= ELS_CMD_MASK; 8548 8549 /* 8550 * If ULP is accepting this, 8551 * then close affected node 8552 */ 8553 if (port->ini_mode && ub_buffer && cmd 8554 == ELS_CMD_ACC) { 8555 fc_rscn_t *rscn; 8556 uint32_t count; 8557 uint32_t *lp; 8558 8559 /* 8560 * Only the Leadville code path will 8561 * come thru here. The RSCN data is NOT 8562 * swapped properly for the Comstar code 8563 * path. 8564 */ 8565 lp = (uint32_t *)ub_buffer; 8566 rscn = (fc_rscn_t *)lp++; 8567 count = 8568 ((rscn->rscn_payload_len - 4) / 4); 8569 8570 /* Close affected ports */ 8571 for (i = 0; i < count; i++, lp++) { 8572 (void) emlxs_port_offline(port, 8573 *lp); 8574 } 8575 } 8576 8577 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_els_reply_msg, 8578 "RSCN %s: did=%x oxid=%x rxid=%x. " 8579 "Intercepted.", emlxs_elscmd_xlate(cmd), 8580 did, pkt->pkt_cmd_fhdr.ox_id, 8581 pkt->pkt_cmd_fhdr.rx_id); 8582 8583 /* 8584 * Since we generated this RSCN, 8585 * we won't need to send this reply 8586 */ 8587 emlxs_pkt_complete(sbp, IOSTAT_SUCCESS, 0, 1); 8588 8589 return (FC_SUCCESS); 8590 } 8591 8592 break; 8593 #endif /* ULP_PATCH6 */ 8594 8595 case ELS_CMD_PLOGI: 8596 /* Check if this PLOGI was generated by us */ 8597 if (ub_priv && (ub_priv->flags & EMLXS_UB_INTERCEPT)) { 8598 cmd = *((uint32_t *)pkt->pkt_cmd); 8599 cmd = LE_SWAP32(cmd); 8600 cmd &= ELS_CMD_MASK; 8601 8602 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_els_reply_msg, 8603 "PLOGI %s: did=%x oxid=%x rxid=%x. " 8604 "Intercepted.", emlxs_elscmd_xlate(cmd), 8605 did, pkt->pkt_cmd_fhdr.ox_id, 8606 pkt->pkt_cmd_fhdr.rx_id); 8607 8608 /* 8609 * Since we generated this PLOGI, 8610 * we won't need to send this reply 8611 */ 8612 emlxs_pkt_complete(sbp, IOSTAT_SUCCESS, 0, 1); 8613 8614 return (FC_SUCCESS); 8615 } 8616 8617 break; 8618 } 8619 8620 #if (EMLXS_MODREVX == EMLXS_MODREV2X) 8621 emlxs_swap_els_pkt(sbp); 8622 #endif /* EMLXS_MODREV2X */ 8623 8624 8625 cmd = *((uint32_t *)pkt->pkt_cmd); 8626 cmd &= ELS_CMD_MASK; 8627 8628 /* Check if modifications are needed */ 8629 switch (ucmd) { 8630 case (ELS_CMD_PRLI): 8631 8632 if (cmd == ELS_CMD_ACC) { 8633 /* This is a patch for the ULP stack. */ 8634 /* ULP does not keep track of FCP2 support */ 8635 8636 if (port->ini_mode && hba->vpd.feaLevelHigh >= 0x02) { 8637 els_pkt->un.prli.ConfmComplAllowed = 1; 8638 els_pkt->un.prli.Retry = 1; 8639 els_pkt->un.prli.TaskRetryIdReq = 1; 8640 } else { 8641 els_pkt->un.prli.ConfmComplAllowed = 0; 8642 els_pkt->un.prli.Retry = 0; 8643 els_pkt->un.prli.TaskRetryIdReq = 0; 8644 } 8645 } 8646 8647 break; 8648 8649 case ELS_CMD_FLOGI: 8650 case ELS_CMD_PLOGI: 8651 case ELS_CMD_FDISC: 8652 case ELS_CMD_PDISC: 8653 8654 if (cmd == ELS_CMD_ACC) { 8655 /* This is a patch for the ULP stack. */ 8656 8657 /* 8658 * ULP only reads our service parameters 8659 * once during bind_port, but the service 8660 * parameters change due to topology. 8661 */ 8662 8663 /* Copy latest service parameters to payload */ 8664 bcopy((void *)&port->sparam, 8665 (void *)&els_pkt->un.logi, sizeof (SERV_PARM)); 8666 8667 #ifdef DHCHAP_SUPPORT 8668 emlxs_dhc_init_sp(port, did, 8669 (SERV_PARM *)&els_pkt->un.logi, (char **)&fcsp_msg); 8670 #endif /* DHCHAP_SUPPORT */ 8671 8672 } 8673 8674 break; 8675 8676 } 8677 8678 /* Initalize iocbq */ 8679 iocbq->node = (void *)NULL; 8680 if ((rval = EMLXS_SLI_PREP_ELS_IOCB(port, sbp)) != FC_SUCCESS) { 8681 8682 if (rval == 0xff) { 8683 emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 0, 1); 8684 rval = FC_SUCCESS; 8685 } 8686 8687 return (rval); 8688 } 8689 8690 cp = &hba->chan[hba->channel_els]; 8691 cp->ulpSendCmd++; 8692 8693 /* Initalize sbp */ 8694 mutex_enter(&sbp->mtx); 8695 sbp->ticks = hba->timer_tics + pkt->pkt_timeout + 8696 ((pkt->pkt_timeout > 0xff) ? 0 : 10); 8697 sbp->node = (void *) NULL; 8698 sbp->lun = 0; 8699 sbp->class = iocb->ULPCLASS; 8700 sbp->did = did; 8701 mutex_exit(&sbp->mtx); 8702 8703 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_els_reply_msg, 8704 "%s %s: did=%x oxid=%x rxid=%x %s", emlxs_elscmd_xlate(ucmd), 8705 emlxs_elscmd_xlate(cmd), did, pkt->pkt_cmd_fhdr.ox_id, 8706 pkt->pkt_cmd_fhdr.rx_id, fcsp_msg); 8707 8708 /* Process nodes */ 8709 switch (ucmd) { 8710 case ELS_CMD_RSCN: 8711 { 8712 if (port->ini_mode && ub_buffer && cmd == ELS_CMD_ACC) { 8713 fc_rscn_t *rscn; 8714 uint32_t count; 8715 uint32_t *lp = NULL; 8716 8717 /* 8718 * Only the Leadville code path will come thru 8719 * here. The RSCN data is NOT swapped properly 8720 * for the Comstar code path. 8721 */ 8722 lp = (uint32_t *)ub_buffer; 8723 rscn = (fc_rscn_t *)lp++; 8724 count = ((rscn->rscn_payload_len - 4) / 4); 8725 8726 /* Close affected ports */ 8727 for (i = 0; i < count; i++, lp++) { 8728 (void) emlxs_port_offline(port, *lp); 8729 } 8730 } 8731 break; 8732 } 8733 case ELS_CMD_PLOGI: 8734 8735 if (cmd == ELS_CMD_ACC) { 8736 ndlp = emlxs_node_find_did(port, did); 8737 8738 if (ndlp && ndlp->nlp_active) { 8739 /* Close the node for any further normal IO */ 8740 emlxs_node_close(port, ndlp, hba->channel_fcp, 8741 pkt->pkt_timeout + 10); 8742 emlxs_node_close(port, ndlp, hba->channel_ip, 8743 pkt->pkt_timeout + 10); 8744 8745 /* Flush tx queue */ 8746 (void) emlxs_tx_node_flush(port, ndlp, 0, 0, 0); 8747 8748 /* Flush chip queue */ 8749 (void) emlxs_chipq_node_flush(port, 0, ndlp, 0); 8750 } 8751 } 8752 8753 break; 8754 8755 case ELS_CMD_PRLI: 8756 8757 if (cmd == ELS_CMD_ACC) { 8758 ndlp = emlxs_node_find_did(port, did); 8759 8760 if (ndlp && ndlp->nlp_active) { 8761 /* Close the node for any further normal IO */ 8762 emlxs_node_close(port, ndlp, hba->channel_fcp, 8763 pkt->pkt_timeout + 10); 8764 8765 /* Flush tx queues */ 8766 (void) emlxs_tx_node_flush(port, ndlp, 8767 &hba->chan[hba->channel_fcp], 0, 0); 8768 8769 /* Flush chip queues */ 8770 (void) emlxs_chipq_node_flush(port, 8771 &hba->chan[hba->channel_fcp], ndlp, 0); 8772 } 8773 } 8774 8775 break; 8776 8777 case ELS_CMD_PRLO: 8778 8779 if (cmd == ELS_CMD_ACC) { 8780 ndlp = emlxs_node_find_did(port, did); 8781 8782 if (ndlp && ndlp->nlp_active) { 8783 /* Close the node for any further normal IO */ 8784 emlxs_node_close(port, ndlp, 8785 hba->channel_fcp, 60); 8786 8787 /* Flush tx queues */ 8788 (void) emlxs_tx_node_flush(port, ndlp, 8789 &hba->chan[hba->channel_fcp], 0, 0); 8790 8791 /* Flush chip queues */ 8792 (void) emlxs_chipq_node_flush(port, 8793 &hba->chan[hba->channel_fcp], ndlp, 0); 8794 } 8795 } 8796 8797 break; 8798 8799 case ELS_CMD_LOGO: 8800 8801 if (cmd == ELS_CMD_ACC) { 8802 ndlp = emlxs_node_find_did(port, did); 8803 8804 if (ndlp && ndlp->nlp_active) { 8805 /* Close the node for any further normal IO */ 8806 emlxs_node_close(port, ndlp, 8807 hba->channel_fcp, 60); 8808 emlxs_node_close(port, ndlp, 8809 hba->channel_ip, 60); 8810 8811 /* Flush tx queues */ 8812 (void) emlxs_tx_node_flush(port, ndlp, 0, 0, 0); 8813 8814 /* Flush chip queues */ 8815 (void) emlxs_chipq_node_flush(port, 0, ndlp, 0); 8816 } 8817 } 8818 8819 break; 8820 } 8821 8822 if (pkt->pkt_cmdlen) { 8823 EMLXS_MPDATA_SYNC(pkt->pkt_cmd_dma, 0, pkt->pkt_cmdlen, 8824 DDI_DMA_SYNC_FORDEV); 8825 } 8826 8827 HBASTATS.ElsRspIssued++; 8828 8829 EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, iocbq); 8830 8831 return (FC_SUCCESS); 8832 8833 } /* emlxs_send_els_rsp() */ 8834 8835 8836 #ifdef MENLO_SUPPORT 8837 static int32_t 8838 emlxs_send_menlo(emlxs_port_t *port, emlxs_buf_t *sbp) 8839 { 8840 emlxs_hba_t *hba = HBA; 8841 fc_packet_t *pkt; 8842 IOCBQ *iocbq; 8843 IOCB *iocb; 8844 CHANNEL *cp; 8845 NODELIST *ndlp; 8846 uint32_t did; 8847 uint32_t *lp; 8848 int32_t rval; 8849 8850 pkt = PRIV2PKT(sbp); 8851 did = EMLXS_MENLO_DID; 8852 lp = (uint32_t *)pkt->pkt_cmd; 8853 8854 iocbq = &sbp->iocbq; 8855 iocb = &iocbq->iocb; 8856 8857 ndlp = emlxs_node_find_did(port, did); 8858 8859 if (!ndlp || !ndlp->nlp_active) { 8860 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg, 8861 "Node not found. did=0x%x", did); 8862 8863 return (FC_BADPACKET); 8864 } 8865 8866 iocbq->node = (void *) ndlp; 8867 if ((rval = EMLXS_SLI_PREP_CT_IOCB(port, sbp)) != FC_SUCCESS) { 8868 8869 if (rval == 0xff) { 8870 emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 0, 1); 8871 rval = FC_SUCCESS; 8872 } 8873 8874 return (rval); 8875 } 8876 8877 cp = &hba->chan[hba->channel_ct]; 8878 cp->ulpSendCmd++; 8879 8880 if (pkt->pkt_tran_type == FC_PKT_EXCHANGE) { 8881 /* Cmd phase */ 8882 8883 /* Initalize iocb */ 8884 iocb->un.genreq64.param = pkt->pkt_cmd_fhdr.d_id; 8885 iocb->ULPCONTEXT = 0; 8886 iocb->ULPPU = 3; 8887 8888 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ct_send_msg, 8889 "%s: [%08x,%08x,%08x,%08x]", 8890 emlxs_menlo_cmd_xlate(BE_SWAP32(lp[0])), BE_SWAP32(lp[1]), 8891 BE_SWAP32(lp[2]), BE_SWAP32(lp[3]), BE_SWAP32(lp[4])); 8892 8893 } else { /* FC_PKT_OUTBOUND */ 8894 8895 /* MENLO_CMD_FW_DOWNLOAD Data Phase */ 8896 iocb->ULPCOMMAND = CMD_GEN_REQUEST64_CX; 8897 8898 /* Initalize iocb */ 8899 iocb->un.genreq64.param = 0; 8900 iocb->ULPCONTEXT = pkt->pkt_cmd_fhdr.rx_id; 8901 iocb->ULPPU = 1; 8902 8903 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ct_send_msg, 8904 "%s: Data: rxid=0x%x size=%d", 8905 emlxs_menlo_cmd_xlate(MENLO_CMD_FW_DOWNLOAD), 8906 pkt->pkt_cmd_fhdr.rx_id, pkt->pkt_cmdlen); 8907 } 8908 8909 /* Initalize sbp */ 8910 mutex_enter(&sbp->mtx); 8911 sbp->ticks = hba->timer_tics + pkt->pkt_timeout + 8912 ((pkt->pkt_timeout > 0xff) ? 0 : 10); 8913 sbp->node = (void *) ndlp; 8914 sbp->lun = 0; 8915 sbp->class = iocb->ULPCLASS; 8916 sbp->did = did; 8917 mutex_exit(&sbp->mtx); 8918 8919 EMLXS_MPDATA_SYNC(pkt->pkt_cmd_dma, 0, pkt->pkt_cmdlen, 8920 DDI_DMA_SYNC_FORDEV); 8921 8922 HBASTATS.CtCmdIssued++; 8923 8924 EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, iocbq); 8925 8926 return (FC_SUCCESS); 8927 8928 } /* emlxs_send_menlo() */ 8929 #endif /* MENLO_SUPPORT */ 8930 8931 8932 static int32_t 8933 emlxs_send_ct(emlxs_port_t *port, emlxs_buf_t *sbp) 8934 { 8935 emlxs_hba_t *hba = HBA; 8936 fc_packet_t *pkt; 8937 IOCBQ *iocbq; 8938 IOCB *iocb; 8939 NODELIST *ndlp; 8940 uint32_t did; 8941 CHANNEL *cp; 8942 int32_t rval; 8943 8944 pkt = PRIV2PKT(sbp); 8945 did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id); 8946 8947 iocbq = &sbp->iocbq; 8948 iocb = &iocbq->iocb; 8949 8950 ndlp = emlxs_node_find_did(port, did); 8951 8952 if (!ndlp || !ndlp->nlp_active) { 8953 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_trans_failed_msg, 8954 "Node not found. did=0x%x", did); 8955 8956 return (FC_BADPACKET); 8957 } 8958 8959 #if (EMLXS_MODREVX == EMLXS_MODREV2X) 8960 emlxs_swap_ct_pkt(sbp); 8961 #endif /* EMLXS_MODREV2X */ 8962 8963 iocbq->node = (void *)ndlp; 8964 if ((rval = EMLXS_SLI_PREP_CT_IOCB(port, sbp)) != FC_SUCCESS) { 8965 8966 if (rval == 0xff) { 8967 emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 0, 1); 8968 rval = FC_SUCCESS; 8969 } 8970 8971 return (rval); 8972 } 8973 8974 cp = &hba->chan[hba->channel_ct]; 8975 cp->ulpSendCmd++; 8976 8977 /* Initalize sbp */ 8978 mutex_enter(&sbp->mtx); 8979 sbp->ticks = hba->timer_tics + pkt->pkt_timeout + 8980 ((pkt->pkt_timeout > 0xff) ? 0 : 10); 8981 sbp->node = (void *)ndlp; 8982 sbp->lun = 0; 8983 sbp->class = iocb->ULPCLASS; 8984 sbp->did = did; 8985 mutex_exit(&sbp->mtx); 8986 8987 if (did == NAMESERVER_DID) { 8988 SLI_CT_REQUEST *CtCmd; 8989 uint32_t *lp0; 8990 8991 CtCmd = (SLI_CT_REQUEST *)pkt->pkt_cmd; 8992 lp0 = (uint32_t *)pkt->pkt_cmd; 8993 8994 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ct_send_msg, 8995 "%s: did=%x [%08x,%08x]", 8996 emlxs_ctcmd_xlate( 8997 LE_SWAP16(CtCmd->CommandResponse.bits.CmdRsp)), 8998 did, LE_SWAP32(lp0[4]), LE_SWAP32(lp0[5])); 8999 9000 if (hba->flag & FC_NPIV_DELAY_REQUIRED) { 9001 sbp->pkt_flags |= PACKET_DELAY_REQUIRED; 9002 } 9003 9004 } else if (did == FDMI_DID) { 9005 SLI_CT_REQUEST *CtCmd; 9006 uint32_t *lp0; 9007 9008 CtCmd = (SLI_CT_REQUEST *)pkt->pkt_cmd; 9009 lp0 = (uint32_t *)pkt->pkt_cmd; 9010 9011 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ct_send_msg, 9012 "%s: did=%x [%08x,%08x]", 9013 emlxs_mscmd_xlate( 9014 LE_SWAP16(CtCmd->CommandResponse.bits.CmdRsp)), 9015 did, LE_SWAP32(lp0[4]), LE_SWAP32(lp0[5])); 9016 } else { 9017 SLI_CT_REQUEST *CtCmd; 9018 uint32_t *lp0; 9019 9020 CtCmd = (SLI_CT_REQUEST *)pkt->pkt_cmd; 9021 lp0 = (uint32_t *)pkt->pkt_cmd; 9022 9023 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ct_send_msg, 9024 "%s: did=%x [%08x,%08x]", 9025 emlxs_rmcmd_xlate( 9026 LE_SWAP16(CtCmd->CommandResponse.bits.CmdRsp)), 9027 did, LE_SWAP32(lp0[4]), LE_SWAP32(lp0[5])); 9028 } 9029 9030 if (pkt->pkt_cmdlen) { 9031 EMLXS_MPDATA_SYNC(pkt->pkt_cmd_dma, 0, pkt->pkt_cmdlen, 9032 DDI_DMA_SYNC_FORDEV); 9033 } 9034 9035 HBASTATS.CtCmdIssued++; 9036 9037 EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, iocbq); 9038 9039 return (FC_SUCCESS); 9040 9041 } /* emlxs_send_ct() */ 9042 9043 9044 static int32_t 9045 emlxs_send_ct_rsp(emlxs_port_t *port, emlxs_buf_t *sbp) 9046 { 9047 emlxs_hba_t *hba = HBA; 9048 fc_packet_t *pkt; 9049 CHANNEL *cp; 9050 IOCBQ *iocbq; 9051 IOCB *iocb; 9052 uint32_t *cmd; 9053 SLI_CT_REQUEST *CtCmd; 9054 int32_t rval; 9055 9056 pkt = PRIV2PKT(sbp); 9057 CtCmd = (SLI_CT_REQUEST *)pkt->pkt_cmd; 9058 cmd = (uint32_t *)pkt->pkt_cmd; 9059 9060 iocbq = &sbp->iocbq; 9061 iocb = &iocbq->iocb; 9062 9063 #if (EMLXS_MODREVX == EMLXS_MODREV2X) 9064 emlxs_swap_ct_pkt(sbp); 9065 #endif /* EMLXS_MODREV2X */ 9066 9067 if ((rval = EMLXS_SLI_PREP_CT_IOCB(port, sbp)) != FC_SUCCESS) { 9068 9069 if (rval == 0xff) { 9070 emlxs_pkt_complete(sbp, IOSTAT_LOCAL_REJECT, 0, 1); 9071 rval = FC_SUCCESS; 9072 } 9073 9074 return (rval); 9075 } 9076 9077 cp = &hba->chan[hba->channel_ct]; 9078 cp->ulpSendCmd++; 9079 9080 /* Initalize sbp */ 9081 mutex_enter(&sbp->mtx); 9082 sbp->ticks = hba->timer_tics + pkt->pkt_timeout + 9083 ((pkt->pkt_timeout > 0xff) ? 0 : 10); 9084 sbp->node = NULL; 9085 sbp->lun = 0; 9086 sbp->class = iocb->ULPCLASS; 9087 mutex_exit(&sbp->mtx); 9088 9089 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_ct_reply_msg, 9090 "%s: Rsn=%x Exp=%x [%08x,%08x] rxid=%x ", 9091 emlxs_rmcmd_xlate(LE_SWAP16( 9092 CtCmd->CommandResponse.bits.CmdRsp)), 9093 CtCmd->ReasonCode, CtCmd->Explanation, 9094 LE_SWAP32(cmd[4]), LE_SWAP32(cmd[5]), 9095 pkt->pkt_cmd_fhdr.rx_id); 9096 9097 if (pkt->pkt_cmdlen) { 9098 EMLXS_MPDATA_SYNC(pkt->pkt_cmd_dma, 0, pkt->pkt_cmdlen, 9099 DDI_DMA_SYNC_FORDEV); 9100 } 9101 9102 HBASTATS.CtRspIssued++; 9103 9104 EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, iocbq); 9105 9106 return (FC_SUCCESS); 9107 9108 } /* emlxs_send_ct_rsp() */ 9109 9110 9111 /* 9112 * emlxs_get_instance() 9113 * Given a ddi ddiinst, return a Fibre Channel (emlx) ddiinst. 9114 */ 9115 extern uint32_t 9116 emlxs_get_instance(int32_t ddiinst) 9117 { 9118 uint32_t i; 9119 uint32_t inst; 9120 9121 mutex_enter(&emlxs_device.lock); 9122 9123 inst = MAX_FC_BRDS; 9124 for (i = 0; i < emlxs_instance_count; i++) { 9125 if (emlxs_instance[i] == ddiinst) { 9126 inst = i; 9127 break; 9128 } 9129 } 9130 9131 mutex_exit(&emlxs_device.lock); 9132 9133 return (inst); 9134 9135 } /* emlxs_get_instance() */ 9136 9137 9138 /* 9139 * emlxs_add_instance() 9140 * Given a ddi ddiinst, create a Fibre Channel (emlx) ddiinst. 9141 * emlx ddiinsts are the order that emlxs_attach gets called, starting at 0. 9142 */ 9143 static uint32_t 9144 emlxs_add_instance(int32_t ddiinst) 9145 { 9146 uint32_t i; 9147 9148 mutex_enter(&emlxs_device.lock); 9149 9150 /* First see if the ddiinst already exists */ 9151 for (i = 0; i < emlxs_instance_count; i++) { 9152 if (emlxs_instance[i] == ddiinst) { 9153 break; 9154 } 9155 } 9156 9157 /* If it doesn't already exist, add it */ 9158 if (i >= emlxs_instance_count) { 9159 if ((i = emlxs_instance_count) < MAX_FC_BRDS) { 9160 emlxs_instance[i] = ddiinst; 9161 emlxs_instance_count++; 9162 emlxs_device.hba_count = emlxs_instance_count; 9163 } 9164 } 9165 9166 mutex_exit(&emlxs_device.lock); 9167 9168 return (i); 9169 9170 } /* emlxs_add_instance() */ 9171 9172 9173 /*ARGSUSED*/ 9174 extern void 9175 emlxs_pkt_complete(emlxs_buf_t *sbp, uint32_t iostat, uint8_t localstat, 9176 uint32_t doneq) 9177 { 9178 emlxs_hba_t *hba; 9179 emlxs_port_t *port; 9180 emlxs_buf_t *fpkt; 9181 9182 port = sbp->port; 9183 9184 if (!port) { 9185 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_completion_error_msg, 9186 "NULL port found. sbp=%p flags=%x", sbp, sbp->pkt_flags); 9187 9188 return; 9189 } 9190 9191 hba = HBA; 9192 9193 mutex_enter(&sbp->mtx); 9194 9195 /* Check for error conditions */ 9196 if (sbp->pkt_flags & (PACKET_ULP_OWNED | PACKET_COMPLETED | 9197 PACKET_IN_DONEQ | PACKET_IN_COMPLETION | 9198 PACKET_IN_TXQ | PACKET_IN_CHIPQ)) { 9199 if (sbp->pkt_flags & PACKET_ULP_OWNED) { 9200 EMLXS_MSGF(EMLXS_CONTEXT, 9201 &emlxs_pkt_completion_error_msg, 9202 "Packet already returned. sbp=%p flags=%x", sbp, 9203 sbp->pkt_flags); 9204 } 9205 9206 else if (sbp->pkt_flags & PACKET_COMPLETED) { 9207 EMLXS_MSGF(EMLXS_CONTEXT, 9208 &emlxs_pkt_completion_error_msg, 9209 "Packet already completed. sbp=%p flags=%x", sbp, 9210 sbp->pkt_flags); 9211 } 9212 9213 else if (sbp->pkt_flags & PACKET_IN_DONEQ) { 9214 EMLXS_MSGF(EMLXS_CONTEXT, 9215 &emlxs_pkt_completion_error_msg, 9216 "Pkt already on done queue. sbp=%p flags=%x", sbp, 9217 sbp->pkt_flags); 9218 } 9219 9220 else if (sbp->pkt_flags & PACKET_IN_COMPLETION) { 9221 EMLXS_MSGF(EMLXS_CONTEXT, 9222 &emlxs_pkt_completion_error_msg, 9223 "Packet already in completion. sbp=%p flags=%x", 9224 sbp, sbp->pkt_flags); 9225 } 9226 9227 else if (sbp->pkt_flags & PACKET_IN_CHIPQ) { 9228 EMLXS_MSGF(EMLXS_CONTEXT, 9229 &emlxs_pkt_completion_error_msg, 9230 "Packet still on chip queue. sbp=%p flags=%x", 9231 sbp, sbp->pkt_flags); 9232 } 9233 9234 else if (sbp->pkt_flags & PACKET_IN_TXQ) { 9235 EMLXS_MSGF(EMLXS_CONTEXT, 9236 &emlxs_pkt_completion_error_msg, 9237 "Packet still on tx queue. sbp=%p flags=%x", sbp, 9238 sbp->pkt_flags); 9239 } 9240 9241 mutex_exit(&sbp->mtx); 9242 return; 9243 } 9244 9245 /* Packet is now in completion */ 9246 sbp->pkt_flags |= PACKET_IN_COMPLETION; 9247 9248 /* Set the state if not already set */ 9249 if (!(sbp->pkt_flags & PACKET_STATE_VALID)) { 9250 emlxs_set_pkt_state(sbp, iostat, localstat, 0); 9251 } 9252 9253 /* Check for parent flush packet */ 9254 /* If pkt has a parent flush packet then adjust its count now */ 9255 fpkt = sbp->fpkt; 9256 if (fpkt) { 9257 /* 9258 * We will try to NULL sbp->fpkt inside the 9259 * fpkt's mutex if possible 9260 */ 9261 9262 if (!(fpkt->pkt_flags & PACKET_ULP_OWNED)) { 9263 mutex_enter(&fpkt->mtx); 9264 if (fpkt->flush_count) { 9265 fpkt->flush_count--; 9266 } 9267 sbp->fpkt = NULL; 9268 mutex_exit(&fpkt->mtx); 9269 } else { /* fpkt has been returned already */ 9270 9271 sbp->fpkt = NULL; 9272 } 9273 } 9274 9275 /* If pkt is polled, then wake up sleeping thread */ 9276 if (sbp->pkt_flags & PACKET_POLLED) { 9277 /* Don't set the PACKET_ULP_OWNED flag here */ 9278 /* because the polling thread will do it */ 9279 sbp->pkt_flags |= PACKET_COMPLETED; 9280 mutex_exit(&sbp->mtx); 9281 9282 /* Wake up sleeping thread */ 9283 mutex_enter(&EMLXS_PKT_LOCK); 9284 cv_broadcast(&EMLXS_PKT_CV); 9285 mutex_exit(&EMLXS_PKT_LOCK); 9286 } 9287 9288 /* If packet was generated by our driver, */ 9289 /* then complete it immediately */ 9290 else if (sbp->pkt_flags & PACKET_ALLOCATED) { 9291 mutex_exit(&sbp->mtx); 9292 9293 emlxs_iodone(sbp); 9294 } 9295 9296 /* Put the pkt on the done queue for callback */ 9297 /* completion in another thread */ 9298 else { 9299 sbp->pkt_flags |= PACKET_IN_DONEQ; 9300 sbp->next = NULL; 9301 mutex_exit(&sbp->mtx); 9302 9303 /* Put pkt on doneq, so I/O's will be completed in order */ 9304 mutex_enter(&EMLXS_PORT_LOCK); 9305 if (hba->iodone_tail == NULL) { 9306 hba->iodone_list = sbp; 9307 hba->iodone_count = 1; 9308 } else { 9309 hba->iodone_tail->next = sbp; 9310 hba->iodone_count++; 9311 } 9312 hba->iodone_tail = sbp; 9313 mutex_exit(&EMLXS_PORT_LOCK); 9314 9315 /* Trigger a thread to service the doneq */ 9316 emlxs_thread_trigger1(&hba->iodone_thread, 9317 emlxs_iodone_server); 9318 } 9319 9320 return; 9321 9322 } /* emlxs_pkt_complete() */ 9323 9324 9325 #ifdef SAN_DIAG_SUPPORT 9326 /* 9327 * This routine is called with EMLXS_PORT_LOCK held so we can just increment 9328 * normally. Don't have to use atomic operations. 9329 */ 9330 extern void 9331 emlxs_update_sd_bucket(emlxs_buf_t *sbp) 9332 { 9333 emlxs_port_t *vport; 9334 fc_packet_t *pkt; 9335 uint32_t did; 9336 hrtime_t t; 9337 hrtime_t delta_time; 9338 int i; 9339 NODELIST *ndlp; 9340 9341 vport = sbp->port; 9342 9343 if ((sd_bucket.search_type == 0) || 9344 (vport->sd_io_latency_state != SD_COLLECTING)) 9345 return; 9346 9347 /* Compute the iolatency time in microseconds */ 9348 t = gethrtime(); 9349 delta_time = t - sbp->sd_start_time; 9350 pkt = PRIV2PKT(sbp); 9351 did = LE_SWAP24_LO(pkt->pkt_cmd_fhdr.d_id); 9352 ndlp = emlxs_node_find_did(vport, did); 9353 9354 if (ndlp) { 9355 if (delta_time >= 9356 sd_bucket.values[SD_IO_LATENCY_MAX_BUCKETS - 1]) 9357 ndlp->sd_dev_bucket[SD_IO_LATENCY_MAX_BUCKETS - 1]. 9358 count++; 9359 else if (delta_time <= sd_bucket.values[0]) 9360 ndlp->sd_dev_bucket[0].count++; 9361 else { 9362 for (i = 1; i < SD_IO_LATENCY_MAX_BUCKETS; i++) { 9363 if ((delta_time > sd_bucket.values[i-1]) && 9364 (delta_time <= sd_bucket.values[i])) { 9365 ndlp->sd_dev_bucket[i].count++; 9366 break; 9367 } 9368 } 9369 } 9370 } 9371 } 9372 #endif /* SAN_DIAG_SUPPORT */ 9373 9374 /*ARGSUSED*/ 9375 static void 9376 emlxs_iodone_server(void *arg1, void *arg2, void *arg3) 9377 { 9378 emlxs_hba_t *hba = (emlxs_hba_t *)arg1; 9379 emlxs_buf_t *sbp; 9380 9381 mutex_enter(&EMLXS_PORT_LOCK); 9382 9383 /* Remove one pkt from the doneq head and complete it */ 9384 while ((sbp = hba->iodone_list) != NULL) { 9385 if ((hba->iodone_list = sbp->next) == NULL) { 9386 hba->iodone_tail = NULL; 9387 hba->iodone_count = 0; 9388 } else { 9389 hba->iodone_count--; 9390 } 9391 9392 mutex_exit(&EMLXS_PORT_LOCK); 9393 9394 /* Prepare the pkt for completion */ 9395 mutex_enter(&sbp->mtx); 9396 sbp->next = NULL; 9397 sbp->pkt_flags &= ~PACKET_IN_DONEQ; 9398 mutex_exit(&sbp->mtx); 9399 9400 /* Complete the IO now */ 9401 emlxs_iodone(sbp); 9402 9403 /* Reacquire lock and check if more work is to be done */ 9404 mutex_enter(&EMLXS_PORT_LOCK); 9405 } 9406 9407 mutex_exit(&EMLXS_PORT_LOCK); 9408 9409 return; 9410 9411 } /* End emlxs_iodone_server */ 9412 9413 9414 static void 9415 emlxs_iodone(emlxs_buf_t *sbp) 9416 { 9417 fc_packet_t *pkt; 9418 CHANNEL *cp; 9419 9420 pkt = PRIV2PKT(sbp); 9421 9422 /* Check one more time that the pkt has not already been returned */ 9423 if (sbp->pkt_flags & PACKET_ULP_OWNED) { 9424 return; 9425 } 9426 cp = (CHANNEL *)sbp->channel; 9427 9428 #if (EMLXS_MODREVX == EMLXS_MODREV2X) 9429 emlxs_unswap_pkt(sbp); 9430 #endif /* EMLXS_MODREV2X */ 9431 9432 mutex_enter(&sbp->mtx); 9433 sbp->pkt_flags |= (PACKET_COMPLETED | PACKET_ULP_OWNED); 9434 mutex_exit(&sbp->mtx); 9435 9436 if (pkt->pkt_comp) { 9437 cp->ulpCmplCmd++; 9438 (*pkt->pkt_comp) (pkt); 9439 } 9440 9441 return; 9442 9443 } /* emlxs_iodone() */ 9444 9445 9446 9447 extern fc_unsol_buf_t * 9448 emlxs_ub_find(emlxs_port_t *port, uint32_t token) 9449 { 9450 emlxs_unsol_buf_t *pool; 9451 fc_unsol_buf_t *ubp; 9452 emlxs_ub_priv_t *ub_priv; 9453 9454 /* Check if this is a valid ub token */ 9455 if (token < EMLXS_UB_TOKEN_OFFSET) { 9456 return (NULL); 9457 } 9458 9459 mutex_enter(&EMLXS_UB_LOCK); 9460 9461 pool = port->ub_pool; 9462 while (pool) { 9463 /* Find a pool with the proper token range */ 9464 if (token >= pool->pool_first_token && 9465 token <= pool->pool_last_token) { 9466 ubp = (fc_unsol_buf_t *)&pool->fc_ubufs[(token - 9467 pool->pool_first_token)]; 9468 ub_priv = ubp->ub_fca_private; 9469 9470 if (ub_priv->token != token) { 9471 EMLXS_MSGF(EMLXS_CONTEXT, 9472 &emlxs_sfs_debug_msg, 9473 "ub_find: Invalid token=%x", ubp, token, 9474 ub_priv->token); 9475 9476 ubp = NULL; 9477 } 9478 9479 else if (!(ub_priv->flags & EMLXS_UB_IN_USE)) { 9480 EMLXS_MSGF(EMLXS_CONTEXT, 9481 &emlxs_sfs_debug_msg, 9482 "ub_find: Buffer not in use. buffer=%p " 9483 "token=%x", ubp, token); 9484 9485 ubp = NULL; 9486 } 9487 9488 mutex_exit(&EMLXS_UB_LOCK); 9489 9490 return (ubp); 9491 } 9492 9493 pool = pool->pool_next; 9494 } 9495 9496 mutex_exit(&EMLXS_UB_LOCK); 9497 9498 return (NULL); 9499 9500 } /* emlxs_ub_find() */ 9501 9502 9503 9504 extern fc_unsol_buf_t * 9505 emlxs_ub_get(emlxs_port_t *port, uint32_t size, uint32_t type, 9506 uint32_t reserve) 9507 { 9508 emlxs_hba_t *hba = HBA; 9509 emlxs_unsol_buf_t *pool; 9510 fc_unsol_buf_t *ubp; 9511 emlxs_ub_priv_t *ub_priv; 9512 uint32_t i; 9513 uint32_t resv_flag; 9514 uint32_t pool_free; 9515 uint32_t pool_free_resv; 9516 9517 mutex_enter(&EMLXS_UB_LOCK); 9518 9519 pool = port->ub_pool; 9520 while (pool) { 9521 /* Find a pool of the appropriate type and size */ 9522 if ((pool->pool_available == 0) || 9523 (pool->pool_type != type) || 9524 (pool->pool_buf_size < size)) { 9525 goto next_pool; 9526 } 9527 9528 9529 /* Adjust free counts based on availablity */ 9530 /* The free reserve count gets first priority */ 9531 pool_free_resv = 9532 min(pool->pool_free_resv, pool->pool_available); 9533 pool_free = 9534 min(pool->pool_free, 9535 (pool->pool_available - pool_free_resv)); 9536 9537 /* Initialize reserve flag */ 9538 resv_flag = reserve; 9539 9540 if (resv_flag) { 9541 if (pool_free_resv == 0) { 9542 if (pool_free == 0) { 9543 goto next_pool; 9544 } 9545 resv_flag = 0; 9546 } 9547 } else if (pool_free == 0) { 9548 goto next_pool; 9549 } 9550 9551 /* Find next available free buffer in this pool */ 9552 for (i = 0; i < pool->pool_nentries; i++) { 9553 ubp = (fc_unsol_buf_t *)&pool->fc_ubufs[i]; 9554 ub_priv = ubp->ub_fca_private; 9555 9556 if (!ub_priv->available || 9557 ub_priv->flags != EMLXS_UB_FREE) { 9558 continue; 9559 } 9560 9561 ub_priv->time = hba->timer_tics; 9562 9563 /* Timeout in 5 minutes */ 9564 ub_priv->timeout = (5 * 60); 9565 9566 ub_priv->flags = EMLXS_UB_IN_USE; 9567 9568 /* Alloc the buffer from the pool */ 9569 if (resv_flag) { 9570 ub_priv->flags |= EMLXS_UB_RESV; 9571 pool->pool_free_resv--; 9572 } else { 9573 pool->pool_free--; 9574 } 9575 9576 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_detail_msg, 9577 "ub_get: ubp=%p token=%x (%d,%d,%d,%d)", ubp, 9578 ub_priv->token, pool->pool_nentries, 9579 pool->pool_available, pool->pool_free, 9580 pool->pool_free_resv); 9581 9582 mutex_exit(&EMLXS_UB_LOCK); 9583 9584 return (ubp); 9585 } 9586 next_pool: 9587 9588 pool = pool->pool_next; 9589 } 9590 9591 mutex_exit(&EMLXS_UB_LOCK); 9592 9593 return (NULL); 9594 9595 } /* emlxs_ub_get() */ 9596 9597 9598 9599 extern void 9600 emlxs_set_pkt_state(emlxs_buf_t *sbp, uint32_t iostat, uint8_t localstat, 9601 uint32_t lock) 9602 { 9603 fc_packet_t *pkt; 9604 fcp_rsp_t *fcp_rsp; 9605 uint32_t i; 9606 emlxs_xlat_err_t *tptr; 9607 emlxs_xlat_err_t *entry; 9608 9609 9610 pkt = PRIV2PKT(sbp); 9611 9612 if (lock) { 9613 mutex_enter(&sbp->mtx); 9614 } 9615 9616 if (!(sbp->pkt_flags & PACKET_STATE_VALID)) { 9617 sbp->pkt_flags |= PACKET_STATE_VALID; 9618 9619 /* Perform table lookup */ 9620 entry = NULL; 9621 if (iostat != IOSTAT_LOCAL_REJECT) { 9622 tptr = emlxs_iostat_tbl; 9623 for (i = 0; i < IOSTAT_MAX; i++, tptr++) { 9624 if (iostat == tptr->emlxs_status) { 9625 entry = tptr; 9626 break; 9627 } 9628 } 9629 } else { /* iostate == IOSTAT_LOCAL_REJECT */ 9630 9631 tptr = emlxs_ioerr_tbl; 9632 for (i = 0; i < IOERR_MAX; i++, tptr++) { 9633 if (localstat == tptr->emlxs_status) { 9634 entry = tptr; 9635 break; 9636 } 9637 } 9638 } 9639 9640 if (entry) { 9641 pkt->pkt_state = entry->pkt_state; 9642 pkt->pkt_reason = entry->pkt_reason; 9643 pkt->pkt_expln = entry->pkt_expln; 9644 pkt->pkt_action = entry->pkt_action; 9645 } else { 9646 /* Set defaults */ 9647 pkt->pkt_state = FC_PKT_TRAN_ERROR; 9648 pkt->pkt_reason = FC_REASON_ABORTED; 9649 pkt->pkt_expln = FC_EXPLN_NONE; 9650 pkt->pkt_action = FC_ACTION_RETRYABLE; 9651 } 9652 9653 9654 /* Set the residual counts and response frame */ 9655 /* Check if response frame was received from the chip */ 9656 /* If so, then the residual counts will already be set */ 9657 if (!(sbp->pkt_flags & (PACKET_FCP_RSP_VALID | 9658 PACKET_CT_RSP_VALID | PACKET_ELS_RSP_VALID))) { 9659 /* We have to create the response frame */ 9660 if (iostat == IOSTAT_SUCCESS) { 9661 pkt->pkt_resp_resid = 0; 9662 pkt->pkt_data_resid = 0; 9663 9664 if ((pkt->pkt_cmd_fhdr.type == 9665 FC_TYPE_SCSI_FCP) && pkt->pkt_rsplen && 9666 pkt->pkt_resp) { 9667 fcp_rsp = (fcp_rsp_t *)pkt->pkt_resp; 9668 9669 fcp_rsp->fcp_u.fcp_status. 9670 rsp_len_set = 1; 9671 fcp_rsp->fcp_response_len = 8; 9672 } 9673 } else { 9674 /* Otherwise assume no data */ 9675 /* and no response received */ 9676 pkt->pkt_data_resid = pkt->pkt_datalen; 9677 pkt->pkt_resp_resid = pkt->pkt_rsplen; 9678 } 9679 } 9680 } 9681 9682 if (lock) { 9683 mutex_exit(&sbp->mtx); 9684 } 9685 9686 return; 9687 9688 } /* emlxs_set_pkt_state() */ 9689 9690 9691 #if (EMLXS_MODREVX == EMLXS_MODREV2X) 9692 9693 extern void 9694 emlxs_swap_service_params(SERV_PARM *sp) 9695 { 9696 uint16_t *p; 9697 int size; 9698 int i; 9699 9700 size = (sizeof (CSP) - 4) / 2; 9701 p = (uint16_t *)&sp->cmn; 9702 for (i = 0; i < size; i++) { 9703 p[i] = LE_SWAP16(p[i]); 9704 } 9705 sp->cmn.e_d_tov = LE_SWAP32(sp->cmn.e_d_tov); 9706 9707 size = sizeof (CLASS_PARMS) / 2; 9708 p = (uint16_t *)&sp->cls1; 9709 for (i = 0; i < size; i++, p++) { 9710 *p = LE_SWAP16(*p); 9711 } 9712 9713 size = sizeof (CLASS_PARMS) / 2; 9714 p = (uint16_t *)&sp->cls2; 9715 for (i = 0; i < size; i++, p++) { 9716 *p = LE_SWAP16(*p); 9717 } 9718 9719 size = sizeof (CLASS_PARMS) / 2; 9720 p = (uint16_t *)&sp->cls3; 9721 for (i = 0; i < size; i++, p++) { 9722 *p = LE_SWAP16(*p); 9723 } 9724 9725 size = sizeof (CLASS_PARMS) / 2; 9726 p = (uint16_t *)&sp->cls4; 9727 for (i = 0; i < size; i++, p++) { 9728 *p = LE_SWAP16(*p); 9729 } 9730 9731 return; 9732 9733 } /* emlxs_swap_service_params() */ 9734 9735 extern void 9736 emlxs_unswap_pkt(emlxs_buf_t *sbp) 9737 { 9738 if (sbp->pkt_flags & PACKET_FCP_SWAPPED) { 9739 emlxs_swap_fcp_pkt(sbp); 9740 } 9741 9742 else if (sbp->pkt_flags & PACKET_ELS_SWAPPED) { 9743 emlxs_swap_els_pkt(sbp); 9744 } 9745 9746 else if (sbp->pkt_flags & PACKET_CT_SWAPPED) { 9747 emlxs_swap_ct_pkt(sbp); 9748 } 9749 9750 } /* emlxs_unswap_pkt() */ 9751 9752 9753 extern void 9754 emlxs_swap_fcp_pkt(emlxs_buf_t *sbp) 9755 { 9756 fc_packet_t *pkt; 9757 FCP_CMND *cmd; 9758 fcp_rsp_t *rsp; 9759 uint16_t *lunp; 9760 uint32_t i; 9761 9762 mutex_enter(&sbp->mtx); 9763 9764 if (sbp->pkt_flags & PACKET_ALLOCATED) { 9765 mutex_exit(&sbp->mtx); 9766 return; 9767 } 9768 9769 if (sbp->pkt_flags & PACKET_FCP_SWAPPED) { 9770 sbp->pkt_flags &= ~PACKET_FCP_SWAPPED; 9771 } else { 9772 sbp->pkt_flags |= PACKET_FCP_SWAPPED; 9773 } 9774 9775 mutex_exit(&sbp->mtx); 9776 9777 pkt = PRIV2PKT(sbp); 9778 9779 cmd = (FCP_CMND *)pkt->pkt_cmd; 9780 rsp = (pkt->pkt_rsplen && 9781 (sbp->pkt_flags & PACKET_FCP_RSP_VALID)) ? 9782 (fcp_rsp_t *)pkt->pkt_resp : NULL; 9783 9784 /* The size of data buffer needs to be swapped. */ 9785 cmd->fcpDl = LE_SWAP32(cmd->fcpDl); 9786 9787 /* 9788 * Swap first 2 words of FCP CMND payload. 9789 */ 9790 lunp = (uint16_t *)&cmd->fcpLunMsl; 9791 for (i = 0; i < 4; i++) { 9792 lunp[i] = LE_SWAP16(lunp[i]); 9793 } 9794 9795 if (rsp) { 9796 rsp->fcp_resid = LE_SWAP32(rsp->fcp_resid); 9797 rsp->fcp_sense_len = LE_SWAP32(rsp->fcp_sense_len); 9798 rsp->fcp_response_len = LE_SWAP32(rsp->fcp_response_len); 9799 } 9800 9801 return; 9802 9803 } /* emlxs_swap_fcp_pkt() */ 9804 9805 9806 extern void 9807 emlxs_swap_els_pkt(emlxs_buf_t *sbp) 9808 { 9809 fc_packet_t *pkt; 9810 uint32_t *cmd; 9811 uint32_t *rsp; 9812 uint32_t command; 9813 uint16_t *c; 9814 uint32_t i; 9815 uint32_t swapped; 9816 9817 mutex_enter(&sbp->mtx); 9818 9819 if (sbp->pkt_flags & PACKET_ALLOCATED) { 9820 mutex_exit(&sbp->mtx); 9821 return; 9822 } 9823 9824 if (sbp->pkt_flags & PACKET_ELS_SWAPPED) { 9825 sbp->pkt_flags &= ~PACKET_ELS_SWAPPED; 9826 swapped = 1; 9827 } else { 9828 sbp->pkt_flags |= PACKET_ELS_SWAPPED; 9829 swapped = 0; 9830 } 9831 9832 mutex_exit(&sbp->mtx); 9833 9834 pkt = PRIV2PKT(sbp); 9835 9836 cmd = (uint32_t *)pkt->pkt_cmd; 9837 rsp = (pkt->pkt_rsplen && 9838 (sbp->pkt_flags & PACKET_ELS_RSP_VALID)) ? 9839 (uint32_t *)pkt->pkt_resp : NULL; 9840 9841 if (!swapped) { 9842 cmd[0] = LE_SWAP32(cmd[0]); 9843 command = cmd[0] & ELS_CMD_MASK; 9844 } else { 9845 command = cmd[0] & ELS_CMD_MASK; 9846 cmd[0] = LE_SWAP32(cmd[0]); 9847 } 9848 9849 if (rsp) { 9850 rsp[0] = LE_SWAP32(rsp[0]); 9851 } 9852 9853 switch (command) { 9854 case ELS_CMD_ACC: 9855 if (sbp->ucmd == ELS_CMD_ADISC) { 9856 /* Hard address of originator */ 9857 cmd[1] = LE_SWAP32(cmd[1]); 9858 9859 /* N_Port ID of originator */ 9860 cmd[6] = LE_SWAP32(cmd[6]); 9861 } 9862 break; 9863 9864 case ELS_CMD_PLOGI: 9865 case ELS_CMD_FLOGI: 9866 case ELS_CMD_FDISC: 9867 if (rsp) { 9868 emlxs_swap_service_params((SERV_PARM *) & rsp[1]); 9869 } 9870 break; 9871 9872 case ELS_CMD_RLS: 9873 cmd[1] = LE_SWAP32(cmd[1]); 9874 9875 if (rsp) { 9876 for (i = 0; i < 6; i++) { 9877 rsp[1 + i] = LE_SWAP32(rsp[1 + i]); 9878 } 9879 } 9880 break; 9881 9882 case ELS_CMD_ADISC: 9883 cmd[1] = LE_SWAP32(cmd[1]); /* Hard address of originator */ 9884 cmd[6] = LE_SWAP32(cmd[6]); /* N_Port ID of originator */ 9885 break; 9886 9887 case ELS_CMD_PRLI: 9888 c = (uint16_t *)&cmd[1]; 9889 c[1] = LE_SWAP16(c[1]); 9890 9891 cmd[4] = LE_SWAP32(cmd[4]); 9892 9893 if (rsp) { 9894 rsp[4] = LE_SWAP32(rsp[4]); 9895 } 9896 break; 9897 9898 case ELS_CMD_SCR: 9899 cmd[1] = LE_SWAP32(cmd[1]); 9900 break; 9901 9902 case ELS_CMD_LINIT: 9903 if (rsp) { 9904 rsp[1] = LE_SWAP32(rsp[1]); 9905 } 9906 break; 9907 9908 default: 9909 break; 9910 } 9911 9912 return; 9913 9914 } /* emlxs_swap_els_pkt() */ 9915 9916 9917 extern void 9918 emlxs_swap_ct_pkt(emlxs_buf_t *sbp) 9919 { 9920 fc_packet_t *pkt; 9921 uint32_t *cmd; 9922 uint32_t *rsp; 9923 uint32_t command; 9924 uint32_t i; 9925 uint32_t swapped; 9926 9927 mutex_enter(&sbp->mtx); 9928 9929 if (sbp->pkt_flags & PACKET_ALLOCATED) { 9930 mutex_exit(&sbp->mtx); 9931 return; 9932 } 9933 9934 if (sbp->pkt_flags & PACKET_CT_SWAPPED) { 9935 sbp->pkt_flags &= ~PACKET_CT_SWAPPED; 9936 swapped = 1; 9937 } else { 9938 sbp->pkt_flags |= PACKET_CT_SWAPPED; 9939 swapped = 0; 9940 } 9941 9942 mutex_exit(&sbp->mtx); 9943 9944 pkt = PRIV2PKT(sbp); 9945 9946 cmd = (uint32_t *)pkt->pkt_cmd; 9947 rsp = (pkt->pkt_rsplen && 9948 (sbp->pkt_flags & PACKET_CT_RSP_VALID)) ? 9949 (uint32_t *)pkt->pkt_resp : NULL; 9950 9951 if (!swapped) { 9952 cmd[0] = 0x01000000; 9953 command = cmd[2]; 9954 } 9955 9956 cmd[0] = LE_SWAP32(cmd[0]); 9957 cmd[1] = LE_SWAP32(cmd[1]); 9958 cmd[2] = LE_SWAP32(cmd[2]); 9959 cmd[3] = LE_SWAP32(cmd[3]); 9960 9961 if (swapped) { 9962 command = cmd[2]; 9963 } 9964 9965 switch ((command >> 16)) { 9966 case SLI_CTNS_GA_NXT: 9967 cmd[4] = LE_SWAP32(cmd[4]); 9968 break; 9969 9970 case SLI_CTNS_GPN_ID: 9971 case SLI_CTNS_GNN_ID: 9972 case SLI_CTNS_RPN_ID: 9973 case SLI_CTNS_RNN_ID: 9974 case SLI_CTNS_RSPN_ID: 9975 cmd[4] = LE_SWAP32(cmd[4]); 9976 break; 9977 9978 case SLI_CTNS_RCS_ID: 9979 case SLI_CTNS_RPT_ID: 9980 cmd[4] = LE_SWAP32(cmd[4]); 9981 cmd[5] = LE_SWAP32(cmd[5]); 9982 break; 9983 9984 case SLI_CTNS_RFT_ID: 9985 cmd[4] = LE_SWAP32(cmd[4]); 9986 9987 /* Swap FC4 types */ 9988 for (i = 0; i < 8; i++) { 9989 cmd[5 + i] = LE_SWAP32(cmd[5 + i]); 9990 } 9991 break; 9992 9993 case SLI_CTNS_GFT_ID: 9994 if (rsp) { 9995 /* Swap FC4 types */ 9996 for (i = 0; i < 8; i++) { 9997 rsp[4 + i] = LE_SWAP32(rsp[4 + i]); 9998 } 9999 } 10000 break; 10001 10002 case SLI_CTNS_GCS_ID: 10003 case SLI_CTNS_GSPN_ID: 10004 case SLI_CTNS_GSNN_NN: 10005 case SLI_CTNS_GIP_NN: 10006 case SLI_CTNS_GIPA_NN: 10007 10008 case SLI_CTNS_GPT_ID: 10009 case SLI_CTNS_GID_NN: 10010 case SLI_CTNS_GNN_IP: 10011 case SLI_CTNS_GIPA_IP: 10012 case SLI_CTNS_GID_FT: 10013 case SLI_CTNS_GID_PT: 10014 case SLI_CTNS_GID_PN: 10015 case SLI_CTNS_RIP_NN: 10016 case SLI_CTNS_RIPA_NN: 10017 case SLI_CTNS_RSNN_NN: 10018 case SLI_CTNS_DA_ID: 10019 case SLI_CT_RESPONSE_FS_RJT: 10020 case SLI_CT_RESPONSE_FS_ACC: 10021 10022 default: 10023 break; 10024 } 10025 return; 10026 10027 } /* emlxs_swap_ct_pkt() */ 10028 10029 10030 extern void 10031 emlxs_swap_els_ub(fc_unsol_buf_t *ubp) 10032 { 10033 emlxs_ub_priv_t *ub_priv; 10034 fc_rscn_t *rscn; 10035 uint32_t count; 10036 uint32_t i; 10037 uint32_t *lp; 10038 la_els_logi_t *logi; 10039 10040 ub_priv = ubp->ub_fca_private; 10041 10042 switch (ub_priv->cmd) { 10043 case ELS_CMD_RSCN: 10044 rscn = (fc_rscn_t *)ubp->ub_buffer; 10045 10046 rscn->rscn_payload_len = LE_SWAP16(rscn->rscn_payload_len); 10047 10048 count = ((rscn->rscn_payload_len - 4) / 4); 10049 lp = (uint32_t *)ubp->ub_buffer + 1; 10050 for (i = 0; i < count; i++, lp++) { 10051 *lp = LE_SWAP32(*lp); 10052 } 10053 10054 break; 10055 10056 case ELS_CMD_FLOGI: 10057 case ELS_CMD_PLOGI: 10058 case ELS_CMD_FDISC: 10059 case ELS_CMD_PDISC: 10060 logi = (la_els_logi_t *)ubp->ub_buffer; 10061 emlxs_swap_service_params( 10062 (SERV_PARM *)&logi->common_service); 10063 break; 10064 10065 /* ULP handles this */ 10066 case ELS_CMD_LOGO: 10067 case ELS_CMD_PRLI: 10068 case ELS_CMD_PRLO: 10069 case ELS_CMD_ADISC: 10070 default: 10071 break; 10072 } 10073 10074 return; 10075 10076 } /* emlxs_swap_els_ub() */ 10077 10078 10079 #endif /* EMLXS_MODREV2X */ 10080 10081 10082 extern char * 10083 emlxs_elscmd_xlate(uint32_t elscmd) 10084 { 10085 static char buffer[32]; 10086 uint32_t i; 10087 uint32_t count; 10088 10089 count = sizeof (emlxs_elscmd_table) / sizeof (emlxs_table_t); 10090 for (i = 0; i < count; i++) { 10091 if (elscmd == emlxs_elscmd_table[i].code) { 10092 return (emlxs_elscmd_table[i].string); 10093 } 10094 } 10095 10096 (void) sprintf(buffer, "ELS=0x%x", elscmd); 10097 return (buffer); 10098 10099 } /* emlxs_elscmd_xlate() */ 10100 10101 10102 extern char * 10103 emlxs_ctcmd_xlate(uint32_t ctcmd) 10104 { 10105 static char buffer[32]; 10106 uint32_t i; 10107 uint32_t count; 10108 10109 count = sizeof (emlxs_ctcmd_table) / sizeof (emlxs_table_t); 10110 for (i = 0; i < count; i++) { 10111 if (ctcmd == emlxs_ctcmd_table[i].code) { 10112 return (emlxs_ctcmd_table[i].string); 10113 } 10114 } 10115 10116 (void) sprintf(buffer, "cmd=0x%x", ctcmd); 10117 return (buffer); 10118 10119 } /* emlxs_ctcmd_xlate() */ 10120 10121 10122 #ifdef MENLO_SUPPORT 10123 extern char * 10124 emlxs_menlo_cmd_xlate(uint32_t cmd) 10125 { 10126 static char buffer[32]; 10127 uint32_t i; 10128 uint32_t count; 10129 10130 count = sizeof (emlxs_menlo_cmd_table) / sizeof (emlxs_table_t); 10131 for (i = 0; i < count; i++) { 10132 if (cmd == emlxs_menlo_cmd_table[i].code) { 10133 return (emlxs_menlo_cmd_table[i].string); 10134 } 10135 } 10136 10137 (void) sprintf(buffer, "Cmd=0x%x", cmd); 10138 return (buffer); 10139 10140 } /* emlxs_menlo_cmd_xlate() */ 10141 10142 extern char * 10143 emlxs_menlo_rsp_xlate(uint32_t rsp) 10144 { 10145 static char buffer[32]; 10146 uint32_t i; 10147 uint32_t count; 10148 10149 count = sizeof (emlxs_menlo_rsp_table) / sizeof (emlxs_table_t); 10150 for (i = 0; i < count; i++) { 10151 if (rsp == emlxs_menlo_rsp_table[i].code) { 10152 return (emlxs_menlo_rsp_table[i].string); 10153 } 10154 } 10155 10156 (void) sprintf(buffer, "Rsp=0x%x", rsp); 10157 return (buffer); 10158 10159 } /* emlxs_menlo_rsp_xlate() */ 10160 10161 #endif /* MENLO_SUPPORT */ 10162 10163 10164 extern char * 10165 emlxs_rmcmd_xlate(uint32_t rmcmd) 10166 { 10167 static char buffer[32]; 10168 uint32_t i; 10169 uint32_t count; 10170 10171 count = sizeof (emlxs_rmcmd_table) / sizeof (emlxs_table_t); 10172 for (i = 0; i < count; i++) { 10173 if (rmcmd == emlxs_rmcmd_table[i].code) { 10174 return (emlxs_rmcmd_table[i].string); 10175 } 10176 } 10177 10178 (void) sprintf(buffer, "RM=0x%x", rmcmd); 10179 return (buffer); 10180 10181 } /* emlxs_rmcmd_xlate() */ 10182 10183 10184 10185 extern char * 10186 emlxs_mscmd_xlate(uint16_t mscmd) 10187 { 10188 static char buffer[32]; 10189 uint32_t i; 10190 uint32_t count; 10191 10192 count = sizeof (emlxs_mscmd_table) / sizeof (emlxs_table_t); 10193 for (i = 0; i < count; i++) { 10194 if (mscmd == emlxs_mscmd_table[i].code) { 10195 return (emlxs_mscmd_table[i].string); 10196 } 10197 } 10198 10199 (void) sprintf(buffer, "Cmd=0x%x", mscmd); 10200 return (buffer); 10201 10202 } /* emlxs_mscmd_xlate() */ 10203 10204 10205 extern char * 10206 emlxs_state_xlate(uint8_t state) 10207 { 10208 static char buffer[32]; 10209 uint32_t i; 10210 uint32_t count; 10211 10212 count = sizeof (emlxs_state_table) / sizeof (emlxs_table_t); 10213 for (i = 0; i < count; i++) { 10214 if (state == emlxs_state_table[i].code) { 10215 return (emlxs_state_table[i].string); 10216 } 10217 } 10218 10219 (void) sprintf(buffer, "State=0x%x", state); 10220 return (buffer); 10221 10222 } /* emlxs_state_xlate() */ 10223 10224 10225 extern char * 10226 emlxs_error_xlate(uint8_t errno) 10227 { 10228 static char buffer[32]; 10229 uint32_t i; 10230 uint32_t count; 10231 10232 count = sizeof (emlxs_error_table) / sizeof (emlxs_table_t); 10233 for (i = 0; i < count; i++) { 10234 if (errno == emlxs_error_table[i].code) { 10235 return (emlxs_error_table[i].string); 10236 } 10237 } 10238 10239 (void) sprintf(buffer, "Errno=0x%x", errno); 10240 return (buffer); 10241 10242 } /* emlxs_error_xlate() */ 10243 10244 10245 static int 10246 emlxs_pm_lower_power(dev_info_t *dip) 10247 { 10248 int ddiinst; 10249 int emlxinst; 10250 emlxs_config_t *cfg; 10251 int32_t rval; 10252 emlxs_hba_t *hba; 10253 10254 ddiinst = ddi_get_instance(dip); 10255 emlxinst = emlxs_get_instance(ddiinst); 10256 hba = emlxs_device.hba[emlxinst]; 10257 cfg = &CFG; 10258 10259 rval = DDI_SUCCESS; 10260 10261 /* Lower the power level */ 10262 if (cfg[CFG_PM_SUPPORT].current) { 10263 rval = 10264 pm_lower_power(dip, EMLXS_PM_ADAPTER, 10265 EMLXS_PM_ADAPTER_DOWN); 10266 } else { 10267 /* We do not have kernel support of power management enabled */ 10268 /* therefore, call our power management routine directly */ 10269 rval = 10270 emlxs_power(dip, EMLXS_PM_ADAPTER, EMLXS_PM_ADAPTER_DOWN); 10271 } 10272 10273 return (rval); 10274 10275 } /* emlxs_pm_lower_power() */ 10276 10277 10278 static int 10279 emlxs_pm_raise_power(dev_info_t *dip) 10280 { 10281 int ddiinst; 10282 int emlxinst; 10283 emlxs_config_t *cfg; 10284 int32_t rval; 10285 emlxs_hba_t *hba; 10286 10287 ddiinst = ddi_get_instance(dip); 10288 emlxinst = emlxs_get_instance(ddiinst); 10289 hba = emlxs_device.hba[emlxinst]; 10290 cfg = &CFG; 10291 10292 /* Raise the power level */ 10293 if (cfg[CFG_PM_SUPPORT].current) { 10294 rval = 10295 pm_raise_power(dip, EMLXS_PM_ADAPTER, 10296 EMLXS_PM_ADAPTER_UP); 10297 } else { 10298 /* We do not have kernel support of power management enabled */ 10299 /* therefore, call our power management routine directly */ 10300 rval = 10301 emlxs_power(dip, EMLXS_PM_ADAPTER, EMLXS_PM_ADAPTER_UP); 10302 } 10303 10304 return (rval); 10305 10306 } /* emlxs_pm_raise_power() */ 10307 10308 10309 #ifdef IDLE_TIMER 10310 10311 extern int 10312 emlxs_pm_busy_component(emlxs_hba_t *hba) 10313 { 10314 emlxs_config_t *cfg = &CFG; 10315 int rval; 10316 10317 hba->pm_active = 1; 10318 10319 if (hba->pm_busy) { 10320 return (DDI_SUCCESS); 10321 } 10322 10323 mutex_enter(&hba->pm_lock); 10324 10325 if (hba->pm_busy) { 10326 mutex_exit(&hba->pm_lock); 10327 return (DDI_SUCCESS); 10328 } 10329 hba->pm_busy = 1; 10330 10331 mutex_exit(&hba->pm_lock); 10332 10333 /* Attempt to notify system that we are busy */ 10334 if (cfg[CFG_PM_SUPPORT].current) { 10335 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 10336 "pm_busy_component."); 10337 10338 rval = pm_busy_component(dip, EMLXS_PM_ADAPTER); 10339 10340 if (rval != DDI_SUCCESS) { 10341 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 10342 "pm_busy_component failed. ret=%d", rval); 10343 10344 /* If this attempt failed then clear our flags */ 10345 mutex_enter(&hba->pm_lock); 10346 hba->pm_busy = 0; 10347 mutex_exit(&hba->pm_lock); 10348 10349 return (rval); 10350 } 10351 } 10352 10353 return (DDI_SUCCESS); 10354 10355 } /* emlxs_pm_busy_component() */ 10356 10357 10358 extern int 10359 emlxs_pm_idle_component(emlxs_hba_t *hba) 10360 { 10361 emlxs_config_t *cfg = &CFG; 10362 int rval; 10363 10364 if (!hba->pm_busy) { 10365 return (DDI_SUCCESS); 10366 } 10367 10368 mutex_enter(&hba->pm_lock); 10369 10370 if (!hba->pm_busy) { 10371 mutex_exit(&hba->pm_lock); 10372 return (DDI_SUCCESS); 10373 } 10374 hba->pm_busy = 0; 10375 10376 mutex_exit(&hba->pm_lock); 10377 10378 if (cfg[CFG_PM_SUPPORT].current) { 10379 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 10380 "pm_idle_component."); 10381 10382 rval = pm_idle_component(dip, EMLXS_PM_ADAPTER); 10383 10384 if (rval != DDI_SUCCESS) { 10385 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 10386 "pm_idle_component failed. ret=%d", rval); 10387 10388 /* If this attempt failed then */ 10389 /* reset our flags for another attempt */ 10390 mutex_enter(&hba->pm_lock); 10391 hba->pm_busy = 1; 10392 mutex_exit(&hba->pm_lock); 10393 10394 return (rval); 10395 } 10396 } 10397 10398 return (DDI_SUCCESS); 10399 10400 } /* emlxs_pm_idle_component() */ 10401 10402 10403 extern void 10404 emlxs_pm_idle_timer(emlxs_hba_t *hba) 10405 { 10406 emlxs_config_t *cfg = &CFG; 10407 10408 if (hba->pm_active) { 10409 /* Clear active flag and reset idle timer */ 10410 mutex_enter(&hba->pm_lock); 10411 hba->pm_active = 0; 10412 hba->pm_idle_timer = 10413 hba->timer_tics + cfg[CFG_PM_IDLE].current; 10414 mutex_exit(&hba->pm_lock); 10415 } 10416 10417 /* Check for idle timeout */ 10418 else if (hba->timer_tics >= hba->pm_idle_timer) { 10419 if (emlxs_pm_idle_component(hba) == DDI_SUCCESS) { 10420 mutex_enter(&hba->pm_lock); 10421 hba->pm_idle_timer = 10422 hba->timer_tics + cfg[CFG_PM_IDLE].current; 10423 mutex_exit(&hba->pm_lock); 10424 } 10425 } 10426 10427 return; 10428 10429 } /* emlxs_pm_idle_timer() */ 10430 10431 #endif /* IDLE_TIMER */ 10432 10433 10434 static void 10435 emlxs_read_vport_prop(emlxs_hba_t *hba) 10436 { 10437 emlxs_port_t *port = &PPORT; 10438 emlxs_config_t *cfg = &CFG; 10439 char **arrayp; 10440 uint8_t *s; 10441 uint8_t *np; 10442 NAME_TYPE pwwpn; 10443 NAME_TYPE wwnn; 10444 NAME_TYPE wwpn; 10445 uint32_t vpi; 10446 uint32_t cnt; 10447 uint32_t rval; 10448 uint32_t i; 10449 uint32_t j; 10450 uint32_t c1; 10451 uint32_t sum; 10452 uint32_t errors; 10453 char buffer[64]; 10454 10455 /* Check for the per adapter vport setting */ 10456 (void) sprintf(buffer, "%s%d-vport", DRIVER_NAME, hba->ddiinst); 10457 cnt = 0; 10458 arrayp = NULL; 10459 rval = 10460 ddi_prop_lookup_string_array(DDI_DEV_T_ANY, hba->dip, 10461 (DDI_PROP_DONTPASS), buffer, &arrayp, &cnt); 10462 10463 if ((rval != DDI_PROP_SUCCESS) || !cnt || !arrayp) { 10464 /* Check for the global vport setting */ 10465 cnt = 0; 10466 arrayp = NULL; 10467 rval = 10468 ddi_prop_lookup_string_array(DDI_DEV_T_ANY, hba->dip, 10469 (DDI_PROP_DONTPASS), "vport", &arrayp, &cnt); 10470 } 10471 10472 if ((rval != DDI_PROP_SUCCESS) || !cnt || !arrayp) { 10473 return; 10474 } 10475 10476 for (i = 0; i < cnt; i++) { 10477 errors = 0; 10478 s = (uint8_t *)arrayp[i]; 10479 10480 if (!s) { 10481 break; 10482 } 10483 10484 np = (uint8_t *)&pwwpn; 10485 for (j = 0; j < sizeof (NAME_TYPE); j++) { 10486 c1 = *s++; 10487 if ((c1 >= '0') && (c1 <= '9')) { 10488 sum = ((c1 - '0') << 4); 10489 } else if ((c1 >= 'a') && (c1 <= 'f')) { 10490 sum = ((c1 - 'a' + 10) << 4); 10491 } else if ((c1 >= 'A') && (c1 <= 'F')) { 10492 sum = ((c1 - 'A' + 10) << 4); 10493 } else { 10494 EMLXS_MSGF(EMLXS_CONTEXT, 10495 &emlxs_attach_debug_msg, 10496 "Config error: Invalid PWWPN found. " 10497 "entry=%d byte=%d hi_nibble=%c", 10498 i, j, c1); 10499 errors++; 10500 } 10501 10502 c1 = *s++; 10503 if ((c1 >= '0') && (c1 <= '9')) { 10504 sum |= (c1 - '0'); 10505 } else if ((c1 >= 'a') && (c1 <= 'f')) { 10506 sum |= (c1 - 'a' + 10); 10507 } else if ((c1 >= 'A') && (c1 <= 'F')) { 10508 sum |= (c1 - 'A' + 10); 10509 } else { 10510 EMLXS_MSGF(EMLXS_CONTEXT, 10511 &emlxs_attach_debug_msg, 10512 "Config error: Invalid PWWPN found. " 10513 "entry=%d byte=%d lo_nibble=%c", 10514 i, j, c1); 10515 errors++; 10516 } 10517 10518 *np++ = sum; 10519 } 10520 10521 if (*s++ != ':') { 10522 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 10523 "Config error: Invalid delimiter after PWWPN. " 10524 "entry=%d", i); 10525 goto out; 10526 } 10527 10528 np = (uint8_t *)&wwnn; 10529 for (j = 0; j < sizeof (NAME_TYPE); j++) { 10530 c1 = *s++; 10531 if ((c1 >= '0') && (c1 <= '9')) { 10532 sum = ((c1 - '0') << 4); 10533 } else if ((c1 >= 'a') && (c1 <= 'f')) { 10534 sum = ((c1 - 'a' + 10) << 4); 10535 } else if ((c1 >= 'A') && (c1 <= 'F')) { 10536 sum = ((c1 - 'A' + 10) << 4); 10537 } else { 10538 EMLXS_MSGF(EMLXS_CONTEXT, 10539 &emlxs_attach_debug_msg, 10540 "Config error: Invalid WWNN found. " 10541 "entry=%d byte=%d hi_nibble=%c", 10542 i, j, c1); 10543 errors++; 10544 } 10545 10546 c1 = *s++; 10547 if ((c1 >= '0') && (c1 <= '9')) { 10548 sum |= (c1 - '0'); 10549 } else if ((c1 >= 'a') && (c1 <= 'f')) { 10550 sum |= (c1 - 'a' + 10); 10551 } else if ((c1 >= 'A') && (c1 <= 'F')) { 10552 sum |= (c1 - 'A' + 10); 10553 } else { 10554 EMLXS_MSGF(EMLXS_CONTEXT, 10555 &emlxs_attach_debug_msg, 10556 "Config error: Invalid WWNN found. " 10557 "entry=%d byte=%d lo_nibble=%c", 10558 i, j, c1); 10559 errors++; 10560 } 10561 10562 *np++ = sum; 10563 } 10564 10565 if (*s++ != ':') { 10566 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 10567 "Config error: Invalid delimiter after WWNN. " 10568 "entry=%d", i); 10569 goto out; 10570 } 10571 10572 np = (uint8_t *)&wwpn; 10573 for (j = 0; j < sizeof (NAME_TYPE); j++) { 10574 c1 = *s++; 10575 if ((c1 >= '0') && (c1 <= '9')) { 10576 sum = ((c1 - '0') << 4); 10577 } else if ((c1 >= 'a') && (c1 <= 'f')) { 10578 sum = ((c1 - 'a' + 10) << 4); 10579 } else if ((c1 >= 'A') && (c1 <= 'F')) { 10580 sum = ((c1 - 'A' + 10) << 4); 10581 } else { 10582 EMLXS_MSGF(EMLXS_CONTEXT, 10583 &emlxs_attach_debug_msg, 10584 "Config error: Invalid WWPN found. " 10585 "entry=%d byte=%d hi_nibble=%c", 10586 i, j, c1); 10587 10588 errors++; 10589 } 10590 10591 c1 = *s++; 10592 if ((c1 >= '0') && (c1 <= '9')) { 10593 sum |= (c1 - '0'); 10594 } else if ((c1 >= 'a') && (c1 <= 'f')) { 10595 sum |= (c1 - 'a' + 10); 10596 } else if ((c1 >= 'A') && (c1 <= 'F')) { 10597 sum |= (c1 - 'A' + 10); 10598 } else { 10599 EMLXS_MSGF(EMLXS_CONTEXT, 10600 &emlxs_attach_debug_msg, 10601 "Config error: Invalid WWPN found. " 10602 "entry=%d byte=%d lo_nibble=%c", 10603 i, j, c1); 10604 10605 errors++; 10606 } 10607 10608 *np++ = sum; 10609 } 10610 10611 if (*s++ != ':') { 10612 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_debug_msg, 10613 "Config error: Invalid delimiter after WWPN. " 10614 "entry=%d", i); 10615 10616 goto out; 10617 } 10618 10619 sum = 0; 10620 do { 10621 c1 = *s++; 10622 if ((c1 < '0') || (c1 > '9')) { 10623 EMLXS_MSGF(EMLXS_CONTEXT, 10624 &emlxs_attach_debug_msg, 10625 "Config error: Invalid VPI found. " 10626 "entry=%d c=%c vpi=%d", i, c1, sum); 10627 10628 goto out; 10629 } 10630 10631 sum = (sum * 10) + (c1 - '0'); 10632 10633 } while (*s != 0); 10634 10635 vpi = sum; 10636 10637 if (errors) { 10638 continue; 10639 } 10640 10641 /* Entry has been read */ 10642 10643 /* Check if the physical port wwpn */ 10644 /* matches our physical port wwpn */ 10645 if (bcmp((caddr_t)&hba->wwpn, (caddr_t)&pwwpn, 8)) { 10646 continue; 10647 } 10648 10649 /* Check vpi range */ 10650 if ((vpi == 0) || (vpi >= MAX_VPORTS)) { 10651 continue; 10652 } 10653 10654 /* Check if port has already been configured */ 10655 if (hba->port[vpi].flag & EMLXS_PORT_CONFIG) { 10656 continue; 10657 } 10658 10659 /* Set the highest configured vpi */ 10660 if (vpi > hba->vpi_high) { 10661 hba->vpi_high = vpi; 10662 } 10663 10664 bcopy((caddr_t)&wwnn, (caddr_t)&hba->port[vpi].wwnn, 10665 sizeof (NAME_TYPE)); 10666 bcopy((caddr_t)&wwpn, (caddr_t)&hba->port[vpi].wwpn, 10667 sizeof (NAME_TYPE)); 10668 10669 if (hba->port[vpi].snn[0] == 0) { 10670 (void) strncpy((caddr_t)hba->port[vpi].snn, 10671 (caddr_t)hba->snn, 256); 10672 } 10673 10674 if (hba->port[vpi].spn[0] == 0) { 10675 (void) sprintf((caddr_t)hba->port[vpi].spn, 10676 "%s VPort-%d", 10677 (caddr_t)hba->spn, vpi); 10678 } 10679 10680 hba->port[vpi].flag |= 10681 (EMLXS_PORT_CONFIG | EMLXS_PORT_ENABLE); 10682 10683 if (cfg[CFG_VPORT_RESTRICTED].current) { 10684 hba->port[vpi].flag |= EMLXS_PORT_RESTRICTED; 10685 } 10686 } 10687 10688 out: 10689 10690 (void) ddi_prop_free((void *) arrayp); 10691 return; 10692 10693 } /* emlxs_read_vport_prop() */ 10694 10695 10696 extern char * 10697 emlxs_wwn_xlate(char *buffer, uint8_t *wwn) 10698 { 10699 (void) sprintf(buffer, "%02x%02x%02x%02x%02x%02x%02x%02x", 10700 wwn[0] & 0xff, wwn[1] & 0xff, wwn[2] & 0xff, wwn[3] & 0xff, 10701 wwn[4] & 0xff, wwn[5] & 0xff, wwn[6] & 0xff, wwn[7] & 0xff); 10702 10703 return (buffer); 10704 10705 } /* emlxs_wwn_xlate() */ 10706 10707 10708 /* This is called at port online and offline */ 10709 extern void 10710 emlxs_ub_flush(emlxs_port_t *port) 10711 { 10712 emlxs_hba_t *hba = HBA; 10713 fc_unsol_buf_t *ubp; 10714 emlxs_ub_priv_t *ub_priv; 10715 emlxs_ub_priv_t *next; 10716 10717 /* Return if nothing to do */ 10718 if (!port->ub_wait_head) { 10719 return; 10720 } 10721 10722 mutex_enter(&EMLXS_PORT_LOCK); 10723 ub_priv = port->ub_wait_head; 10724 port->ub_wait_head = NULL; 10725 port->ub_wait_tail = NULL; 10726 mutex_exit(&EMLXS_PORT_LOCK); 10727 10728 while (ub_priv) { 10729 next = ub_priv->next; 10730 ubp = ub_priv->ubp; 10731 10732 /* Check if ULP is online and we have a callback function */ 10733 if ((port->ulp_statec != FC_STATE_OFFLINE) && 10734 port->ulp_unsol_cb) { 10735 /* Send ULP the ub buffer */ 10736 port->ulp_unsol_cb(port->ulp_handle, ubp, 10737 ubp->ub_frame.type); 10738 } else { /* Drop the buffer */ 10739 10740 (void) emlxs_ub_release(port, 1, &ubp->ub_token); 10741 } 10742 10743 ub_priv = next; 10744 10745 } /* while () */ 10746 10747 return; 10748 10749 } /* emlxs_ub_flush() */ 10750 10751 10752 extern void 10753 emlxs_ub_callback(emlxs_port_t *port, fc_unsol_buf_t *ubp) 10754 { 10755 emlxs_hba_t *hba = HBA; 10756 emlxs_ub_priv_t *ub_priv; 10757 10758 ub_priv = ubp->ub_fca_private; 10759 10760 /* Check if ULP is online */ 10761 if (port->ulp_statec != FC_STATE_OFFLINE) { 10762 if (port->ulp_unsol_cb) { 10763 port->ulp_unsol_cb(port->ulp_handle, ubp, 10764 ubp->ub_frame.type); 10765 } else { 10766 (void) emlxs_ub_release(port, 1, &ubp->ub_token); 10767 } 10768 10769 return; 10770 } else { /* ULP offline */ 10771 10772 if (hba->state >= FC_LINK_UP) { 10773 /* Add buffer to queue tail */ 10774 mutex_enter(&EMLXS_PORT_LOCK); 10775 10776 if (port->ub_wait_tail) { 10777 port->ub_wait_tail->next = ub_priv; 10778 } 10779 port->ub_wait_tail = ub_priv; 10780 10781 if (!port->ub_wait_head) { 10782 port->ub_wait_head = ub_priv; 10783 } 10784 10785 mutex_exit(&EMLXS_PORT_LOCK); 10786 } else { 10787 (void) emlxs_ub_release(port, 1, &ubp->ub_token); 10788 } 10789 } 10790 10791 return; 10792 10793 } /* emlxs_ub_callback() */ 10794 10795 10796 static uint32_t 10797 emlxs_integrity_check(emlxs_hba_t *hba) 10798 { 10799 uint32_t size; 10800 uint32_t errors = 0; 10801 int ddiinst = hba->ddiinst; 10802 10803 size = 16; 10804 if (sizeof (ULP_BDL) != size) { 10805 cmn_err(CE_WARN, "?%s%d: ULP_BDL size incorrect. %d != 16", 10806 DRIVER_NAME, ddiinst, (int)sizeof (ULP_BDL)); 10807 10808 errors++; 10809 } 10810 size = 8; 10811 if (sizeof (ULP_BDE) != size) { 10812 cmn_err(CE_WARN, "?%s%d: ULP_BDE size incorrect. %d != 8", 10813 DRIVER_NAME, ddiinst, (int)sizeof (ULP_BDE)); 10814 10815 errors++; 10816 } 10817 size = 12; 10818 if (sizeof (ULP_BDE64) != size) { 10819 cmn_err(CE_WARN, "?%s%d: ULP_BDE64 size incorrect. %d != 12", 10820 DRIVER_NAME, ddiinst, (int)sizeof (ULP_BDE64)); 10821 10822 errors++; 10823 } 10824 size = 16; 10825 if (sizeof (HBQE_t) != size) { 10826 cmn_err(CE_WARN, "?%s%d: HBQE size incorrect. %d != 16", 10827 DRIVER_NAME, ddiinst, (int)sizeof (HBQE_t)); 10828 10829 errors++; 10830 } 10831 size = 8; 10832 if (sizeof (HGP) != size) { 10833 cmn_err(CE_WARN, "?%s%d: HGP size incorrect. %d != 8", 10834 DRIVER_NAME, ddiinst, (int)sizeof (HGP)); 10835 10836 errors++; 10837 } 10838 if (sizeof (PGP) != size) { 10839 cmn_err(CE_WARN, "?%s%d: PGP size incorrect. %d != 8", 10840 DRIVER_NAME, ddiinst, (int)sizeof (PGP)); 10841 10842 errors++; 10843 } 10844 size = 4; 10845 if (sizeof (WORD5) != size) { 10846 cmn_err(CE_WARN, "?%s%d: WORD5 size incorrect. %d != 4", 10847 DRIVER_NAME, ddiinst, (int)sizeof (WORD5)); 10848 10849 errors++; 10850 } 10851 size = 124; 10852 if (sizeof (MAILVARIANTS) != size) { 10853 cmn_err(CE_WARN, "?%s%d: MAILVARIANTS size incorrect. " 10854 "%d != 124", DRIVER_NAME, ddiinst, 10855 (int)sizeof (MAILVARIANTS)); 10856 10857 errors++; 10858 } 10859 size = 128; 10860 if (sizeof (SLI1_DESC) != size) { 10861 cmn_err(CE_WARN, "?%s%d: SLI1_DESC size incorrect. %d != 128", 10862 DRIVER_NAME, ddiinst, (int)sizeof (SLI1_DESC)); 10863 10864 errors++; 10865 } 10866 if (sizeof (SLI2_DESC) != size) { 10867 cmn_err(CE_WARN, "?%s%d: SLI2_DESC size incorrect. %d != 128", 10868 DRIVER_NAME, ddiinst, (int)sizeof (SLI2_DESC)); 10869 10870 errors++; 10871 } 10872 size = MBOX_SIZE; 10873 if (sizeof (MAILBOX) != size) { 10874 cmn_err(CE_WARN, "?%s%d: MAILBOX size incorrect. %d != %d", 10875 DRIVER_NAME, ddiinst, (int)sizeof (MAILBOX), MBOX_SIZE); 10876 10877 errors++; 10878 } 10879 size = PCB_SIZE; 10880 if (sizeof (PCB) != size) { 10881 cmn_err(CE_WARN, "?%s%d: PCB size incorrect. %d != %d", 10882 DRIVER_NAME, ddiinst, (int)sizeof (PCB), PCB_SIZE); 10883 10884 errors++; 10885 } 10886 size = 260; 10887 if (sizeof (ATTRIBUTE_ENTRY) != size) { 10888 cmn_err(CE_WARN, "?%s%d: ATTRIBUTE_ENTRY size incorrect. " 10889 "%d != 260", DRIVER_NAME, ddiinst, 10890 (int)sizeof (ATTRIBUTE_ENTRY)); 10891 10892 errors++; 10893 } 10894 size = SLI_SLIM1_SIZE; 10895 if (sizeof (SLIM1) != size) { 10896 cmn_err(CE_WARN, "?%s%d: SLIM1 size incorrect. %d != %d", 10897 DRIVER_NAME, ddiinst, (int)sizeof (SLIM1), SLI_SLIM1_SIZE); 10898 10899 errors++; 10900 } 10901 size = SLI3_IOCB_CMD_SIZE; 10902 if (sizeof (IOCB) != size) { 10903 cmn_err(CE_WARN, "?%s%d: IOCB size incorrect. %d != %d", 10904 DRIVER_NAME, ddiinst, (int)sizeof (IOCB), 10905 SLI3_IOCB_CMD_SIZE); 10906 10907 errors++; 10908 } 10909 10910 size = SLI_SLIM2_SIZE; 10911 if (sizeof (SLIM2) != size) { 10912 cmn_err(CE_WARN, "?%s%d: SLIM2 size incorrect. %d != %d", 10913 DRIVER_NAME, ddiinst, (int)sizeof (SLIM2), 10914 SLI_SLIM2_SIZE); 10915 10916 errors++; 10917 } 10918 return (errors); 10919 10920 } /* emlxs_integrity_check() */ 10921 10922 10923 #ifdef FMA_SUPPORT 10924 /* 10925 * FMA support 10926 */ 10927 10928 extern void 10929 emlxs_fm_init(emlxs_hba_t *hba) 10930 { 10931 ddi_iblock_cookie_t iblk; 10932 10933 if (hba->fm_caps == DDI_FM_NOT_CAPABLE) { 10934 return; 10935 } 10936 10937 if (DDI_FM_ACC_ERR_CAP(hba->fm_caps)) { 10938 emlxs_dev_acc_attr.devacc_attr_access = DDI_FLAGERR_ACC; 10939 emlxs_data_acc_attr.devacc_attr_access = DDI_FLAGERR_ACC; 10940 } else { 10941 emlxs_dev_acc_attr.devacc_attr_access = DDI_DEFAULT_ACC; 10942 emlxs_data_acc_attr.devacc_attr_access = DDI_DEFAULT_ACC; 10943 } 10944 10945 if (DDI_FM_DMA_ERR_CAP(hba->fm_caps)) { 10946 emlxs_dma_attr.dma_attr_flags |= DDI_DMA_FLAGERR; 10947 emlxs_dma_attr_ro.dma_attr_flags |= DDI_DMA_FLAGERR; 10948 emlxs_dma_attr_1sg.dma_attr_flags |= DDI_DMA_FLAGERR; 10949 emlxs_dma_attr_fcip_rsp.dma_attr_flags |= DDI_DMA_FLAGERR; 10950 } else { 10951 emlxs_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR; 10952 emlxs_dma_attr_ro.dma_attr_flags &= ~DDI_DMA_FLAGERR; 10953 emlxs_dma_attr_1sg.dma_attr_flags &= ~DDI_DMA_FLAGERR; 10954 emlxs_dma_attr_fcip_rsp.dma_attr_flags &= ~DDI_DMA_FLAGERR; 10955 } 10956 10957 ddi_fm_init(hba->dip, &hba->fm_caps, &iblk); 10958 10959 if (DDI_FM_EREPORT_CAP(hba->fm_caps) || 10960 DDI_FM_ERRCB_CAP(hba->fm_caps)) { 10961 pci_ereport_setup(hba->dip); 10962 } 10963 10964 if (DDI_FM_ERRCB_CAP(hba->fm_caps)) { 10965 ddi_fm_handler_register(hba->dip, emlxs_fm_error_cb, 10966 (void *)hba); 10967 } 10968 10969 } /* emlxs_fm_init() */ 10970 10971 10972 extern void 10973 emlxs_fm_fini(emlxs_hba_t *hba) 10974 { 10975 if (hba->fm_caps == DDI_FM_NOT_CAPABLE) { 10976 return; 10977 } 10978 10979 if (DDI_FM_EREPORT_CAP(hba->fm_caps) || 10980 DDI_FM_ERRCB_CAP(hba->fm_caps)) { 10981 pci_ereport_teardown(hba->dip); 10982 } 10983 10984 if (DDI_FM_ERRCB_CAP(hba->fm_caps)) { 10985 ddi_fm_handler_unregister(hba->dip); 10986 } 10987 10988 (void) ddi_fm_fini(hba->dip); 10989 10990 } /* emlxs_fm_fini() */ 10991 10992 10993 extern int 10994 emlxs_fm_check_acc_handle(emlxs_hba_t *hba, ddi_acc_handle_t handle) 10995 { 10996 ddi_fm_error_t err; 10997 10998 if (!DDI_FM_ACC_ERR_CAP(hba->fm_caps)) { 10999 return (DDI_FM_OK); 11000 } 11001 11002 /* Some S10 versions do not define the ahi_err structure */ 11003 if (((ddi_acc_impl_t *)handle)->ahi_err == NULL) { 11004 return (DDI_FM_OK); 11005 } 11006 11007 err.fme_status = DDI_FM_OK; 11008 (void) ddi_fm_acc_err_get(handle, &err, DDI_FME_VERSION); 11009 11010 /* Some S10 versions do not define the ddi_fm_acc_err_clear function */ 11011 if ((void *)&ddi_fm_acc_err_clear != NULL) { 11012 (void) ddi_fm_acc_err_clear(handle, DDI_FME_VERSION); 11013 } 11014 11015 return (err.fme_status); 11016 11017 } /* emlxs_fm_check_acc_handle() */ 11018 11019 11020 extern int 11021 emlxs_fm_check_dma_handle(emlxs_hba_t *hba, ddi_dma_handle_t handle) 11022 { 11023 ddi_fm_error_t err; 11024 11025 if (!DDI_FM_ACC_ERR_CAP(hba->fm_caps)) { 11026 return (DDI_FM_OK); 11027 } 11028 11029 err.fme_status = DDI_FM_OK; 11030 (void) ddi_fm_dma_err_get(handle, &err, DDI_FME_VERSION); 11031 11032 return (err.fme_status); 11033 11034 } /* emlxs_fm_check_dma_handle() */ 11035 11036 11037 extern void 11038 emlxs_fm_ereport(emlxs_hba_t *hba, char *detail) 11039 { 11040 uint64_t ena; 11041 char buf[FM_MAX_CLASS]; 11042 11043 if (!DDI_FM_EREPORT_CAP(hba->fm_caps)) { 11044 return; 11045 } 11046 11047 if (detail == NULL) { 11048 return; 11049 } 11050 11051 (void) snprintf(buf, FM_MAX_CLASS, "%s.%s", DDI_FM_DEVICE, detail); 11052 ena = fm_ena_generate(0, FM_ENA_FMT1); 11053 11054 ddi_fm_ereport_post(hba->dip, buf, ena, DDI_NOSLEEP, 11055 FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0, NULL); 11056 11057 } /* emlxs_fm_ereport() */ 11058 11059 11060 extern void 11061 emlxs_fm_service_impact(emlxs_hba_t *hba, int impact) 11062 { 11063 if (!DDI_FM_EREPORT_CAP(hba->fm_caps)) { 11064 return; 11065 } 11066 11067 if (impact == NULL) { 11068 return; 11069 } 11070 11071 if ((hba->pm_state & EMLXS_PM_IN_DETACH) && 11072 (impact == DDI_SERVICE_DEGRADED)) { 11073 impact = DDI_SERVICE_UNAFFECTED; 11074 } 11075 11076 ddi_fm_service_impact(hba->dip, impact); 11077 11078 } /* emlxs_fm_service_impact() */ 11079 11080 11081 /* 11082 * The I/O fault service error handling callback function 11083 */ 11084 /*ARGSUSED*/ 11085 extern int 11086 emlxs_fm_error_cb(dev_info_t *dip, ddi_fm_error_t *err, 11087 const void *impl_data) 11088 { 11089 /* 11090 * as the driver can always deal with an error 11091 * in any dma or access handle, we can just return 11092 * the fme_status value. 11093 */ 11094 pci_ereport_post(dip, err, NULL); 11095 return (err->fme_status); 11096 11097 } /* emlxs_fm_error_cb() */ 11098 #endif /* FMA_SUPPORT */ 11099 11100 11101 extern void 11102 emlxs_swap32_buffer(uint8_t *buffer, uint32_t size) 11103 { 11104 uint32_t word; 11105 uint32_t *wptr; 11106 uint32_t i; 11107 11108 wptr = (uint32_t *)buffer; 11109 11110 size += (size%4)? (4-(size%4)):0; 11111 for (i = 0; i < size / 4; i++) { 11112 word = *wptr; 11113 *wptr++ = SWAP32(word); 11114 } 11115 11116 return; 11117 11118 } /* emlxs_swap32_buffer() */ 11119 11120 11121 extern void 11122 emlxs_swap32_bcopy(uint8_t *src, uint8_t *dst, uint32_t size) 11123 { 11124 uint32_t word; 11125 uint32_t *sptr; 11126 uint32_t *dptr; 11127 uint32_t i; 11128 11129 sptr = (uint32_t *)src; 11130 dptr = (uint32_t *)dst; 11131 11132 size += (size%4)? (4-(size%4)):0; 11133 for (i = 0; i < size / 4; i++) { 11134 word = *sptr++; 11135 *dptr++ = SWAP32(word); 11136 } 11137 11138 return; 11139 11140 } /* emlxs_swap32_buffer() */ 11141