1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* Copyright 2010 QLogic Corporation */ 23 24 /* 25 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. 26 */ 27 28 /* 29 * Copyright 2011 Nexenta Systems, Inc. All rights reserved. 30 */ 31 32 #pragma ident "Copyright 2010 QLogic Corporation; ql_xioctl.c" 33 34 /* 35 * ISP2xxx Solaris Fibre Channel Adapter (FCA) driver source file. 36 * 37 * *********************************************************************** 38 * * ** 39 * * NOTICE ** 40 * * COPYRIGHT (C) 1996-2010 QLOGIC CORPORATION ** 41 * * ALL RIGHTS RESERVED ** 42 * * ** 43 * *********************************************************************** 44 * 45 */ 46 47 #include <ql_apps.h> 48 #include <ql_api.h> 49 #include <ql_debug.h> 50 #include <ql_init.h> 51 #include <ql_iocb.h> 52 #include <ql_ioctl.h> 53 #include <ql_mbx.h> 54 #include <ql_xioctl.h> 55 56 /* 57 * Local data 58 */ 59 60 /* 61 * Local prototypes 62 */ 63 static int ql_sdm_ioctl(ql_adapter_state_t *, int, void *, int); 64 static int ql_sdm_setup(ql_adapter_state_t *, EXT_IOCTL **, void *, int, 65 boolean_t (*)(EXT_IOCTL *)); 66 static boolean_t ql_validate_signature(EXT_IOCTL *); 67 static int ql_sdm_return(ql_adapter_state_t *, EXT_IOCTL *, void *, int); 68 static void ql_query(ql_adapter_state_t *, EXT_IOCTL *, int); 69 static void ql_qry_hba_node(ql_adapter_state_t *, EXT_IOCTL *, int); 70 static void ql_qry_hba_port(ql_adapter_state_t *, EXT_IOCTL *, int); 71 static void ql_qry_disc_port(ql_adapter_state_t *, EXT_IOCTL *, int); 72 static void ql_qry_disc_tgt(ql_adapter_state_t *, EXT_IOCTL *, int); 73 static void ql_qry_fw(ql_adapter_state_t *, EXT_IOCTL *, int); 74 static void ql_qry_chip(ql_adapter_state_t *, EXT_IOCTL *, int); 75 static void ql_qry_driver(ql_adapter_state_t *, EXT_IOCTL *, int); 76 static void ql_fcct(ql_adapter_state_t *, EXT_IOCTL *, int); 77 static void ql_aen_reg(ql_adapter_state_t *, EXT_IOCTL *, int); 78 static void ql_aen_get(ql_adapter_state_t *, EXT_IOCTL *, int); 79 static void ql_scsi_passthru(ql_adapter_state_t *, EXT_IOCTL *, int); 80 static void ql_wwpn_to_scsiaddr(ql_adapter_state_t *, EXT_IOCTL *, int); 81 static void ql_host_idx(ql_adapter_state_t *, EXT_IOCTL *, int); 82 static void ql_host_drvname(ql_adapter_state_t *, EXT_IOCTL *, int); 83 static void ql_read_nvram(ql_adapter_state_t *, EXT_IOCTL *, int); 84 static void ql_write_nvram(ql_adapter_state_t *, EXT_IOCTL *, int); 85 static void ql_read_flash(ql_adapter_state_t *, EXT_IOCTL *, int); 86 static void ql_write_flash(ql_adapter_state_t *, EXT_IOCTL *, int); 87 static void ql_write_vpd(ql_adapter_state_t *, EXT_IOCTL *, int); 88 static void ql_read_vpd(ql_adapter_state_t *, EXT_IOCTL *, int); 89 static void ql_diagnostic_loopback(ql_adapter_state_t *, EXT_IOCTL *, int); 90 static void ql_send_els_rnid(ql_adapter_state_t *, EXT_IOCTL *, int); 91 static void ql_set_host_data(ql_adapter_state_t *, EXT_IOCTL *, int); 92 static void ql_get_host_data(ql_adapter_state_t *, EXT_IOCTL *, int); 93 static void ql_qry_cna_port(ql_adapter_state_t *, EXT_IOCTL *, int); 94 95 static int ql_lun_count(ql_adapter_state_t *, ql_tgt_t *); 96 static int ql_report_lun(ql_adapter_state_t *, ql_tgt_t *); 97 static int ql_inq_scan(ql_adapter_state_t *, ql_tgt_t *, int); 98 static int ql_inq(ql_adapter_state_t *, ql_tgt_t *, int, ql_mbx_iocb_t *, 99 uint8_t); 100 static uint32_t ql_get_buffer_data(caddr_t, caddr_t, uint32_t, int); 101 static uint32_t ql_send_buffer_data(caddr_t, caddr_t, uint32_t, int); 102 static int ql_24xx_flash_desc(ql_adapter_state_t *); 103 static int ql_setup_flash(ql_adapter_state_t *); 104 static ql_tgt_t *ql_find_port(ql_adapter_state_t *, uint8_t *, uint16_t); 105 static int ql_flash_fcode_load(ql_adapter_state_t *, void *, uint32_t, int); 106 static int ql_flash_fcode_dump(ql_adapter_state_t *, void *, uint32_t, 107 uint32_t, int); 108 static int ql_program_flash_address(ql_adapter_state_t *, uint32_t, 109 uint8_t); 110 static void ql_set_rnid_parameters(ql_adapter_state_t *, EXT_IOCTL *, int); 111 static void ql_get_rnid_parameters(ql_adapter_state_t *, EXT_IOCTL *, int); 112 static int ql_reset_statistics(ql_adapter_state_t *, EXT_IOCTL *); 113 static void ql_get_statistics(ql_adapter_state_t *, EXT_IOCTL *, int); 114 static void ql_get_statistics_fc(ql_adapter_state_t *, EXT_IOCTL *, int); 115 static void ql_get_statistics_fc4(ql_adapter_state_t *, EXT_IOCTL *, int); 116 static void ql_set_led_state(ql_adapter_state_t *, EXT_IOCTL *, int); 117 static void ql_get_led_state(ql_adapter_state_t *, EXT_IOCTL *, int); 118 static void ql_drive_led(ql_adapter_state_t *, uint32_t); 119 static uint32_t ql_setup_led(ql_adapter_state_t *); 120 static uint32_t ql_wrapup_led(ql_adapter_state_t *); 121 static void ql_get_port_summary(ql_adapter_state_t *, EXT_IOCTL *, int); 122 static void ql_get_target_id(ql_adapter_state_t *, EXT_IOCTL *, int); 123 static void ql_get_sfp(ql_adapter_state_t *, EXT_IOCTL *, int); 124 static int ql_dump_sfp(ql_adapter_state_t *, void *, int); 125 static ql_fcache_t *ql_setup_fnode(ql_adapter_state_t *); 126 static void ql_get_fcache(ql_adapter_state_t *, EXT_IOCTL *, int); 127 static void ql_get_fcache_ex(ql_adapter_state_t *, EXT_IOCTL *, int); 128 void ql_update_fcache(ql_adapter_state_t *, uint8_t *, uint32_t); 129 static int ql_check_pci(ql_adapter_state_t *, ql_fcache_t *, uint32_t *); 130 static void ql_flash_layout_table(ql_adapter_state_t *, uint32_t); 131 static void ql_process_flt(ql_adapter_state_t *, uint32_t); 132 static void ql_flash_nvram_defaults(ql_adapter_state_t *); 133 static void ql_port_param(ql_adapter_state_t *, EXT_IOCTL *, int); 134 static int ql_check_pci(ql_adapter_state_t *, ql_fcache_t *, uint32_t *); 135 static void ql_get_pci_data(ql_adapter_state_t *, EXT_IOCTL *, int); 136 static void ql_get_fwfcetrace(ql_adapter_state_t *, EXT_IOCTL *, int); 137 static void ql_get_fwexttrace(ql_adapter_state_t *, EXT_IOCTL *, int); 138 static void ql_menlo_reset(ql_adapter_state_t *, EXT_IOCTL *, int); 139 static void ql_menlo_get_fw_version(ql_adapter_state_t *, EXT_IOCTL *, int); 140 static void ql_menlo_update_fw(ql_adapter_state_t *, EXT_IOCTL *, int); 141 static void ql_menlo_manage_info(ql_adapter_state_t *, EXT_IOCTL *, int); 142 static int ql_suspend_hba(ql_adapter_state_t *, uint32_t); 143 static void ql_restart_hba(ql_adapter_state_t *); 144 static void ql_get_vp_cnt_id(ql_adapter_state_t *, EXT_IOCTL *, int); 145 static void ql_vp_ioctl(ql_adapter_state_t *, EXT_IOCTL *, int); 146 static void ql_qry_vport(ql_adapter_state_t *, EXT_IOCTL *, int); 147 static void ql_access_flash(ql_adapter_state_t *, EXT_IOCTL *, int); 148 static void ql_reset_cmd(ql_adapter_state_t *, EXT_IOCTL *); 149 static void ql_update_flash_caches(ql_adapter_state_t *); 150 static void ql_get_dcbx_parameters(ql_adapter_state_t *, EXT_IOCTL *, int); 151 static void ql_get_xgmac_statistics(ql_adapter_state_t *, EXT_IOCTL *, int); 152 static void ql_get_fcf_list(ql_adapter_state_t *, EXT_IOCTL *, int); 153 static void ql_get_resource_counts(ql_adapter_state_t *, EXT_IOCTL *, int); 154 static void ql_qry_adapter_versions(ql_adapter_state_t *, EXT_IOCTL *, int); 155 static int ql_set_loop_point(ql_adapter_state_t *, uint16_t); 156 157 /* ******************************************************************** */ 158 /* External IOCTL support. */ 159 /* ******************************************************************** */ 160 161 /* 162 * ql_alloc_xioctl_resource 163 * Allocates resources needed by module code. 164 * 165 * Input: 166 * ha: adapter state pointer. 167 * 168 * Returns: 169 * SYS_ERRNO 170 * 171 * Context: 172 * Kernel context. 173 */ 174 int 175 ql_alloc_xioctl_resource(ql_adapter_state_t *ha) 176 { 177 ql_xioctl_t *xp; 178 179 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 180 181 if (ha->xioctl != NULL) { 182 QL_PRINT_9(CE_CONT, "(%d): already allocated done\n", 183 ha->instance); 184 return (0); 185 } 186 187 xp = kmem_zalloc(sizeof (ql_xioctl_t), KM_SLEEP); 188 if (xp == NULL) { 189 EL(ha, "failed, kmem_zalloc\n"); 190 return (ENOMEM); 191 } 192 ha->xioctl = xp; 193 194 /* Allocate AEN tracking buffer */ 195 xp->aen_tracking_queue = kmem_zalloc(EXT_DEF_MAX_AEN_QUEUE * 196 sizeof (EXT_ASYNC_EVENT), KM_SLEEP); 197 if (xp->aen_tracking_queue == NULL) { 198 EL(ha, "failed, kmem_zalloc-2\n"); 199 ql_free_xioctl_resource(ha); 200 return (ENOMEM); 201 } 202 203 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 204 205 return (0); 206 } 207 208 /* 209 * ql_free_xioctl_resource 210 * Frees resources used by module code. 211 * 212 * Input: 213 * ha: adapter state pointer. 214 * 215 * Context: 216 * Kernel context. 217 */ 218 void 219 ql_free_xioctl_resource(ql_adapter_state_t *ha) 220 { 221 ql_xioctl_t *xp = ha->xioctl; 222 223 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 224 225 if (xp == NULL) { 226 QL_PRINT_9(CE_CONT, "(%d): already freed\n", ha->instance); 227 return; 228 } 229 230 if (xp->aen_tracking_queue != NULL) { 231 kmem_free(xp->aen_tracking_queue, EXT_DEF_MAX_AEN_QUEUE * 232 sizeof (EXT_ASYNC_EVENT)); 233 xp->aen_tracking_queue = NULL; 234 } 235 236 kmem_free(xp, sizeof (ql_xioctl_t)); 237 ha->xioctl = NULL; 238 239 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 240 } 241 242 /* 243 * ql_xioctl 244 * External IOCTL processing. 245 * 246 * Input: 247 * ha: adapter state pointer. 248 * cmd: function to perform 249 * arg: data type varies with request 250 * mode: flags 251 * cred_p: credentials pointer 252 * rval_p: pointer to result value 253 * 254 * Returns: 255 * 0: success 256 * ENXIO: No such device or address 257 * ENOPROTOOPT: Protocol not available 258 * 259 * Context: 260 * Kernel context. 261 */ 262 /* ARGSUSED */ 263 int 264 ql_xioctl(ql_adapter_state_t *ha, int cmd, intptr_t arg, int mode, 265 cred_t *cred_p, int *rval_p) 266 { 267 int rval; 268 269 QL_PRINT_9(CE_CONT, "(%d): started, cmd=%d\n", ha->instance, cmd); 270 271 if (ha->xioctl == NULL) { 272 QL_PRINT_9(CE_CONT, "(%d): no context\n", ha->instance); 273 return (ENXIO); 274 } 275 276 switch (cmd) { 277 case EXT_CC_QUERY: 278 case EXT_CC_SEND_FCCT_PASSTHRU: 279 case EXT_CC_REG_AEN: 280 case EXT_CC_GET_AEN: 281 case EXT_CC_SEND_SCSI_PASSTHRU: 282 case EXT_CC_WWPN_TO_SCSIADDR: 283 case EXT_CC_SEND_ELS_RNID: 284 case EXT_CC_SET_DATA: 285 case EXT_CC_GET_DATA: 286 case EXT_CC_HOST_IDX: 287 case EXT_CC_READ_NVRAM: 288 case EXT_CC_UPDATE_NVRAM: 289 case EXT_CC_READ_OPTION_ROM: 290 case EXT_CC_READ_OPTION_ROM_EX: 291 case EXT_CC_UPDATE_OPTION_ROM: 292 case EXT_CC_UPDATE_OPTION_ROM_EX: 293 case EXT_CC_GET_VPD: 294 case EXT_CC_SET_VPD: 295 case EXT_CC_LOOPBACK: 296 case EXT_CC_GET_FCACHE: 297 case EXT_CC_GET_FCACHE_EX: 298 case EXT_CC_HOST_DRVNAME: 299 case EXT_CC_GET_SFP_DATA: 300 case EXT_CC_PORT_PARAM: 301 case EXT_CC_GET_PCI_DATA: 302 case EXT_CC_GET_FWEXTTRACE: 303 case EXT_CC_GET_FWFCETRACE: 304 case EXT_CC_GET_VP_CNT_ID: 305 case EXT_CC_VPORT_CMD: 306 case EXT_CC_ACCESS_FLASH: 307 case EXT_CC_RESET_FW: 308 case EXT_CC_MENLO_MANAGE_INFO: 309 rval = ql_sdm_ioctl(ha, cmd, (void *)arg, mode); 310 break; 311 default: 312 /* function not supported. */ 313 EL(ha, "function=%d not supported\n", cmd); 314 rval = ENOPROTOOPT; 315 } 316 317 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 318 319 return (rval); 320 } 321 322 /* 323 * ql_sdm_ioctl 324 * Provides ioctl functions for SAN/Device Management functions 325 * AKA External Ioctl functions. 326 * 327 * Input: 328 * ha: adapter state pointer. 329 * ioctl_code: ioctl function to perform 330 * arg: Pointer to EXT_IOCTL cmd data in application land. 331 * mode: flags 332 * 333 * Returns: 334 * 0: success 335 * ENOMEM: Alloc of local EXT_IOCTL struct failed. 336 * EFAULT: Copyin of caller's EXT_IOCTL struct failed or 337 * copyout of EXT_IOCTL status info failed. 338 * EINVAL: Signature or version of caller's EXT_IOCTL invalid. 339 * EBUSY: Device busy 340 * 341 * Context: 342 * Kernel context. 343 */ 344 static int 345 ql_sdm_ioctl(ql_adapter_state_t *ha, int ioctl_code, void *arg, int mode) 346 { 347 EXT_IOCTL *cmd; 348 int rval; 349 ql_adapter_state_t *vha; 350 351 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 352 353 /* Copy argument structure (EXT_IOCTL) from application land. */ 354 if ((rval = ql_sdm_setup(ha, &cmd, arg, mode, 355 ql_validate_signature)) != 0) { 356 /* 357 * a non-zero value at this time means a problem getting 358 * the requested information from application land, just 359 * return the error code and hope for the best. 360 */ 361 EL(ha, "failed, sdm_setup\n"); 362 return (rval); 363 } 364 365 /* 366 * Map the physical ha ptr (which the ioctl is called with) 367 * to the virtual ha that the caller is addressing. 368 */ 369 if (ha->flags & VP_ENABLED) { 370 /* Check that it is within range. */ 371 if (cmd->HbaSelect > (CFG_IST(ha, CFG_CTRL_2422) ? 372 MAX_24_VIRTUAL_PORTS : MAX_25_VIRTUAL_PORTS)) { 373 EL(ha, "Invalid HbaSelect vp index: %xh\n", 374 cmd->HbaSelect); 375 cmd->Status = EXT_STATUS_INVALID_VPINDEX; 376 cmd->ResponseLen = 0; 377 return (EFAULT); 378 } 379 /* 380 * Special case: HbaSelect == 0 is physical ha 381 */ 382 if (cmd->HbaSelect != 0) { 383 vha = ha->vp_next; 384 while (vha != NULL) { 385 if (vha->vp_index == cmd->HbaSelect) { 386 ha = vha; 387 break; 388 } 389 vha = vha->vp_next; 390 } 391 /* 392 * The specified vp index may be valid(within range) 393 * but it's not in the list. Currently this is all 394 * we can say. 395 */ 396 if (vha == NULL) { 397 cmd->Status = EXT_STATUS_INVALID_VPINDEX; 398 cmd->ResponseLen = 0; 399 return (EFAULT); 400 } 401 } 402 } 403 404 /* 405 * If driver is suspended, stalled, or powered down rtn BUSY 406 */ 407 if (ha->flags & ADAPTER_SUSPENDED || 408 ha->task_daemon_flags & DRIVER_STALL || 409 ha->power_level != PM_LEVEL_D0) { 410 EL(ha, " %s\n", ha->flags & ADAPTER_SUSPENDED ? 411 "driver suspended" : 412 (ha->task_daemon_flags & DRIVER_STALL ? "driver stalled" : 413 "FCA powered down")); 414 cmd->Status = EXT_STATUS_BUSY; 415 cmd->ResponseLen = 0; 416 rval = EBUSY; 417 418 /* Return results to caller */ 419 if ((ql_sdm_return(ha, cmd, arg, mode)) == -1) { 420 EL(ha, "failed, sdm_return\n"); 421 rval = EFAULT; 422 } 423 return (rval); 424 } 425 426 switch (ioctl_code) { 427 case EXT_CC_QUERY_OS: 428 ql_query(ha, cmd, mode); 429 break; 430 case EXT_CC_SEND_FCCT_PASSTHRU_OS: 431 ql_fcct(ha, cmd, mode); 432 break; 433 case EXT_CC_REG_AEN_OS: 434 ql_aen_reg(ha, cmd, mode); 435 break; 436 case EXT_CC_GET_AEN_OS: 437 ql_aen_get(ha, cmd, mode); 438 break; 439 case EXT_CC_GET_DATA_OS: 440 ql_get_host_data(ha, cmd, mode); 441 break; 442 case EXT_CC_SET_DATA_OS: 443 ql_set_host_data(ha, cmd, mode); 444 break; 445 case EXT_CC_SEND_ELS_RNID_OS: 446 ql_send_els_rnid(ha, cmd, mode); 447 break; 448 case EXT_CC_SCSI_PASSTHRU_OS: 449 ql_scsi_passthru(ha, cmd, mode); 450 break; 451 case EXT_CC_WWPN_TO_SCSIADDR_OS: 452 ql_wwpn_to_scsiaddr(ha, cmd, mode); 453 break; 454 case EXT_CC_HOST_IDX_OS: 455 ql_host_idx(ha, cmd, mode); 456 break; 457 case EXT_CC_HOST_DRVNAME_OS: 458 ql_host_drvname(ha, cmd, mode); 459 break; 460 case EXT_CC_READ_NVRAM_OS: 461 ql_read_nvram(ha, cmd, mode); 462 break; 463 case EXT_CC_UPDATE_NVRAM_OS: 464 ql_write_nvram(ha, cmd, mode); 465 break; 466 case EXT_CC_READ_OPTION_ROM_OS: 467 case EXT_CC_READ_OPTION_ROM_EX_OS: 468 ql_read_flash(ha, cmd, mode); 469 break; 470 case EXT_CC_UPDATE_OPTION_ROM_OS: 471 case EXT_CC_UPDATE_OPTION_ROM_EX_OS: 472 ql_write_flash(ha, cmd, mode); 473 break; 474 case EXT_CC_LOOPBACK_OS: 475 ql_diagnostic_loopback(ha, cmd, mode); 476 break; 477 case EXT_CC_GET_VPD_OS: 478 ql_read_vpd(ha, cmd, mode); 479 break; 480 case EXT_CC_SET_VPD_OS: 481 ql_write_vpd(ha, cmd, mode); 482 break; 483 case EXT_CC_GET_FCACHE_OS: 484 ql_get_fcache(ha, cmd, mode); 485 break; 486 case EXT_CC_GET_FCACHE_EX_OS: 487 ql_get_fcache_ex(ha, cmd, mode); 488 break; 489 case EXT_CC_GET_SFP_DATA_OS: 490 ql_get_sfp(ha, cmd, mode); 491 break; 492 case EXT_CC_PORT_PARAM_OS: 493 ql_port_param(ha, cmd, mode); 494 break; 495 case EXT_CC_GET_PCI_DATA_OS: 496 ql_get_pci_data(ha, cmd, mode); 497 break; 498 case EXT_CC_GET_FWEXTTRACE_OS: 499 ql_get_fwexttrace(ha, cmd, mode); 500 break; 501 case EXT_CC_GET_FWFCETRACE_OS: 502 ql_get_fwfcetrace(ha, cmd, mode); 503 break; 504 case EXT_CC_MENLO_RESET: 505 ql_menlo_reset(ha, cmd, mode); 506 break; 507 case EXT_CC_MENLO_GET_FW_VERSION: 508 ql_menlo_get_fw_version(ha, cmd, mode); 509 break; 510 case EXT_CC_MENLO_UPDATE_FW: 511 ql_menlo_update_fw(ha, cmd, mode); 512 break; 513 case EXT_CC_MENLO_MANAGE_INFO: 514 ql_menlo_manage_info(ha, cmd, mode); 515 break; 516 case EXT_CC_GET_VP_CNT_ID_OS: 517 ql_get_vp_cnt_id(ha, cmd, mode); 518 break; 519 case EXT_CC_VPORT_CMD_OS: 520 ql_vp_ioctl(ha, cmd, mode); 521 break; 522 case EXT_CC_ACCESS_FLASH_OS: 523 ql_access_flash(ha, cmd, mode); 524 break; 525 case EXT_CC_RESET_FW_OS: 526 ql_reset_cmd(ha, cmd); 527 break; 528 default: 529 /* function not supported. */ 530 EL(ha, "failed, function not supported=%d\n", ioctl_code); 531 532 cmd->Status = EXT_STATUS_INVALID_REQUEST; 533 cmd->ResponseLen = 0; 534 break; 535 } 536 537 /* Return results to caller */ 538 if (ql_sdm_return(ha, cmd, arg, mode) == -1) { 539 EL(ha, "failed, sdm_return\n"); 540 return (EFAULT); 541 } 542 543 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 544 545 return (0); 546 } 547 548 /* 549 * ql_sdm_setup 550 * Make a local copy of the EXT_IOCTL struct and validate it. 551 * 552 * Input: 553 * ha: adapter state pointer. 554 * cmd_struct: Pointer to location to store local adrs of EXT_IOCTL. 555 * arg: Address of application EXT_IOCTL cmd data 556 * mode: flags 557 * val_sig: Pointer to a function to validate the ioctl signature. 558 * 559 * Returns: 560 * 0: success 561 * EFAULT: Copy in error of application EXT_IOCTL struct. 562 * EINVAL: Invalid version, signature. 563 * ENOMEM: Local allocation of EXT_IOCTL failed. 564 * 565 * Context: 566 * Kernel context. 567 */ 568 static int 569 ql_sdm_setup(ql_adapter_state_t *ha, EXT_IOCTL **cmd_struct, void *arg, 570 int mode, boolean_t (*val_sig)(EXT_IOCTL *)) 571 { 572 int rval; 573 EXT_IOCTL *cmd; 574 575 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 576 577 /* Allocate local memory for EXT_IOCTL. */ 578 *cmd_struct = NULL; 579 cmd = (EXT_IOCTL *)kmem_zalloc(sizeof (EXT_IOCTL), KM_SLEEP); 580 if (cmd == NULL) { 581 EL(ha, "failed, kmem_zalloc\n"); 582 return (ENOMEM); 583 } 584 /* Get argument structure. */ 585 rval = ddi_copyin(arg, (void *)cmd, sizeof (EXT_IOCTL), mode); 586 if (rval != 0) { 587 EL(ha, "failed, ddi_copyin\n"); 588 rval = EFAULT; 589 } else { 590 /* 591 * Check signature and the version. 592 * If either are not valid then neither is the 593 * structure so don't attempt to return any error status 594 * because we can't trust what caller's arg points to. 595 * Just return the errno. 596 */ 597 if (val_sig(cmd) == 0) { 598 EL(ha, "failed, signature\n"); 599 rval = EINVAL; 600 } else if (cmd->Version > EXT_VERSION) { 601 EL(ha, "failed, version\n"); 602 rval = EINVAL; 603 } 604 } 605 606 if (rval == 0) { 607 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 608 *cmd_struct = cmd; 609 cmd->Status = EXT_STATUS_OK; 610 cmd->DetailStatus = 0; 611 } else { 612 kmem_free((void *)cmd, sizeof (EXT_IOCTL)); 613 } 614 615 return (rval); 616 } 617 618 /* 619 * ql_validate_signature 620 * Validate the signature string for an external ioctl call. 621 * 622 * Input: 623 * sg: Pointer to EXT_IOCTL signature to validate. 624 * 625 * Returns: 626 * B_TRUE: Signature is valid. 627 * B_FALSE: Signature is NOT valid. 628 * 629 * Context: 630 * Kernel context. 631 */ 632 static boolean_t 633 ql_validate_signature(EXT_IOCTL *cmd_struct) 634 { 635 /* 636 * Check signature. 637 * 638 * If signature is not valid then neither is the rest of 639 * the structure (e.g., can't trust it), so don't attempt 640 * to return any error status other than the errno. 641 */ 642 if (bcmp(&cmd_struct->Signature, "QLOGIC", 6) != 0) { 643 QL_PRINT_2(CE_CONT, "failed,\n"); 644 return (B_FALSE); 645 } 646 647 return (B_TRUE); 648 } 649 650 /* 651 * ql_sdm_return 652 * Copies return data/status to application land for 653 * ioctl call using the SAN/Device Management EXT_IOCTL call interface. 654 * 655 * Input: 656 * ha: adapter state pointer. 657 * cmd: Pointer to kernel copy of requestor's EXT_IOCTL struct. 658 * ioctl_code: ioctl function to perform 659 * arg: EXT_IOCTL cmd data in application land. 660 * mode: flags 661 * 662 * Returns: 663 * 0: success 664 * EFAULT: Copy out error. 665 * 666 * Context: 667 * Kernel context. 668 */ 669 /* ARGSUSED */ 670 static int 671 ql_sdm_return(ql_adapter_state_t *ha, EXT_IOCTL *cmd, void *arg, int mode) 672 { 673 int rval = 0; 674 675 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 676 677 rval |= ddi_copyout((void *)&cmd->ResponseLen, 678 (void *)&(((EXT_IOCTL*)arg)->ResponseLen), sizeof (uint32_t), 679 mode); 680 681 rval |= ddi_copyout((void *)&cmd->Status, 682 (void *)&(((EXT_IOCTL*)arg)->Status), 683 sizeof (cmd->Status), mode); 684 rval |= ddi_copyout((void *)&cmd->DetailStatus, 685 (void *)&(((EXT_IOCTL*)arg)->DetailStatus), 686 sizeof (cmd->DetailStatus), mode); 687 688 kmem_free((void *)cmd, sizeof (EXT_IOCTL)); 689 690 if (rval != 0) { 691 /* Some copyout operation failed */ 692 EL(ha, "failed, ddi_copyout\n"); 693 return (EFAULT); 694 } 695 696 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 697 698 return (0); 699 } 700 701 /* 702 * ql_query 703 * Performs all EXT_CC_QUERY functions. 704 * 705 * Input: 706 * ha: adapter state pointer. 707 * cmd: Local EXT_IOCTL cmd struct pointer. 708 * mode: flags. 709 * 710 * Returns: 711 * None, request status indicated in cmd->Status. 712 * 713 * Context: 714 * Kernel context. 715 */ 716 static void 717 ql_query(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode) 718 { 719 QL_PRINT_9(CE_CONT, "(%d): started, cmd=%d\n", ha->instance, 720 cmd->SubCode); 721 722 /* case off on command subcode */ 723 switch (cmd->SubCode) { 724 case EXT_SC_QUERY_HBA_NODE: 725 ql_qry_hba_node(ha, cmd, mode); 726 break; 727 case EXT_SC_QUERY_HBA_PORT: 728 ql_qry_hba_port(ha, cmd, mode); 729 break; 730 case EXT_SC_QUERY_DISC_PORT: 731 ql_qry_disc_port(ha, cmd, mode); 732 break; 733 case EXT_SC_QUERY_DISC_TGT: 734 ql_qry_disc_tgt(ha, cmd, mode); 735 break; 736 case EXT_SC_QUERY_DRIVER: 737 ql_qry_driver(ha, cmd, mode); 738 break; 739 case EXT_SC_QUERY_FW: 740 ql_qry_fw(ha, cmd, mode); 741 break; 742 case EXT_SC_QUERY_CHIP: 743 ql_qry_chip(ha, cmd, mode); 744 break; 745 case EXT_SC_QUERY_CNA_PORT: 746 ql_qry_cna_port(ha, cmd, mode); 747 break; 748 case EXT_SC_QUERY_ADAPTER_VERSIONS: 749 ql_qry_adapter_versions(ha, cmd, mode); 750 break; 751 case EXT_SC_QUERY_DISC_LUN: 752 default: 753 /* function not supported. */ 754 cmd->Status = EXT_STATUS_UNSUPPORTED_SUBCODE; 755 EL(ha, "failed, Unsupported Subcode=%xh\n", 756 cmd->SubCode); 757 break; 758 } 759 760 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 761 } 762 763 /* 764 * ql_qry_hba_node 765 * Performs EXT_SC_QUERY_HBA_NODE subfunction. 766 * 767 * Input: 768 * ha: adapter state pointer. 769 * cmd: EXT_IOCTL cmd struct pointer. 770 * mode: flags. 771 * 772 * Returns: 773 * None, request status indicated in cmd->Status. 774 * 775 * Context: 776 * Kernel context. 777 */ 778 static void 779 ql_qry_hba_node(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode) 780 { 781 EXT_HBA_NODE tmp_node = {0}; 782 uint_t len; 783 caddr_t bufp; 784 785 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 786 787 if (cmd->ResponseLen < sizeof (EXT_HBA_NODE)) { 788 cmd->Status = EXT_STATUS_BUFFER_TOO_SMALL; 789 cmd->DetailStatus = sizeof (EXT_HBA_NODE); 790 EL(ha, "failed, ResponseLen < EXT_HBA_NODE, " 791 "Len=%xh\n", cmd->ResponseLen); 792 cmd->ResponseLen = 0; 793 return; 794 } 795 796 /* fill in the values */ 797 798 bcopy(ha->loginparams.node_ww_name.raw_wwn, tmp_node.WWNN, 799 EXT_DEF_WWN_NAME_SIZE); 800 801 (void) sprintf((char *)(tmp_node.Manufacturer), "QLogic Corporation"); 802 803 (void) sprintf((char *)(tmp_node.Model), "%x", ha->device_id); 804 805 bcopy(&tmp_node.WWNN[5], tmp_node.SerialNum, 3); 806 807 (void) sprintf((char *)(tmp_node.DriverVersion), QL_VERSION); 808 809 if (CFG_IST(ha, CFG_SBUS_CARD)) { 810 size_t verlen; 811 uint16_t w; 812 char *tmpptr; 813 814 verlen = strlen((char *)(tmp_node.DriverVersion)); 815 if (verlen + 5 > EXT_DEF_MAX_STR_SIZE) { 816 EL(ha, "failed, No room for fpga version string\n"); 817 } else { 818 w = (uint16_t)ddi_get16(ha->sbus_fpga_dev_handle, 819 (uint16_t *) 820 (ha->sbus_fpga_iobase + FPGA_REVISION)); 821 822 tmpptr = (char *)&(tmp_node.DriverVersion[verlen+1]); 823 if (tmpptr == NULL) { 824 EL(ha, "Unable to insert fpga version str\n"); 825 } else { 826 (void) sprintf(tmpptr, "%d.%d", 827 ((w & 0xf0) >> 4), (w & 0x0f)); 828 tmp_node.DriverAttr |= EXT_CC_HBA_NODE_SBUS; 829 } 830 } 831 } 832 833 (void) sprintf((char *)(tmp_node.FWVersion), "%01d.%02d.%02d", 834 ha->fw_major_version, ha->fw_minor_version, 835 ha->fw_subminor_version); 836 837 if ((CFG_IST(ha, CFG_CTRL_24258081)) == 0) { 838 switch (ha->fw_attributes) { 839 case FWATTRIB_EF: 840 (void) strcat((char *)(tmp_node.FWVersion), " EF"); 841 break; 842 case FWATTRIB_TP: 843 (void) strcat((char *)(tmp_node.FWVersion), " TP"); 844 break; 845 case FWATTRIB_IP: 846 (void) strcat((char *)(tmp_node.FWVersion), " IP"); 847 break; 848 case FWATTRIB_IPX: 849 (void) strcat((char *)(tmp_node.FWVersion), " IPX"); 850 break; 851 case FWATTRIB_FL: 852 (void) strcat((char *)(tmp_node.FWVersion), " FL"); 853 break; 854 case FWATTRIB_FPX: 855 (void) strcat((char *)(tmp_node.FWVersion), " FLX"); 856 break; 857 default: 858 break; 859 } 860 } 861 862 /* FCode version. */ 863 /*LINTED [Solaris DDI_DEV_T_ANY Lint error]*/ 864 if (ddi_getlongprop(DDI_DEV_T_ANY, ha->dip, PROP_LEN_AND_VAL_ALLOC | 865 DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, "version", (caddr_t)&bufp, 866 (int *)&len) == DDI_PROP_SUCCESS) { 867 if (len < EXT_DEF_MAX_STR_SIZE) { 868 bcopy(bufp, tmp_node.OptRomVersion, len); 869 } else { 870 bcopy(bufp, tmp_node.OptRomVersion, 871 EXT_DEF_MAX_STR_SIZE - 1); 872 tmp_node.OptRomVersion[EXT_DEF_MAX_STR_SIZE - 1] = 873 '\0'; 874 } 875 kmem_free(bufp, len); 876 } else { 877 (void) sprintf((char *)tmp_node.OptRomVersion, "0"); 878 } 879 tmp_node.PortCount = 1; 880 tmp_node.InterfaceType = EXT_DEF_FC_INTF_TYPE; 881 882 if (ddi_copyout((void *)&tmp_node, 883 (void *)(uintptr_t)(cmd->ResponseAdr), 884 sizeof (EXT_HBA_NODE), mode) != 0) { 885 cmd->Status = EXT_STATUS_COPY_ERR; 886 cmd->ResponseLen = 0; 887 EL(ha, "failed, ddi_copyout\n"); 888 } else { 889 cmd->ResponseLen = sizeof (EXT_HBA_NODE); 890 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 891 } 892 } 893 894 /* 895 * ql_qry_hba_port 896 * Performs EXT_SC_QUERY_HBA_PORT subfunction. 897 * 898 * Input: 899 * ha: adapter state pointer. 900 * cmd: EXT_IOCTL cmd struct pointer. 901 * mode: flags. 902 * 903 * Returns: 904 * None, request status indicated in cmd->Status. 905 * 906 * Context: 907 * Kernel context. 908 */ 909 static void 910 ql_qry_hba_port(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode) 911 { 912 ql_link_t *link; 913 ql_tgt_t *tq; 914 ql_mbx_data_t mr; 915 EXT_HBA_PORT tmp_port = {0}; 916 int rval; 917 uint16_t port_cnt, tgt_cnt, index; 918 919 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 920 921 if (cmd->ResponseLen < sizeof (EXT_HBA_PORT)) { 922 cmd->Status = EXT_STATUS_BUFFER_TOO_SMALL; 923 cmd->DetailStatus = sizeof (EXT_HBA_PORT); 924 EL(ha, "failed, ResponseLen < EXT_HBA_NODE, Len=%xh\n", 925 cmd->ResponseLen); 926 cmd->ResponseLen = 0; 927 return; 928 } 929 930 /* fill in the values */ 931 932 bcopy(ha->loginparams.nport_ww_name.raw_wwn, tmp_port.WWPN, 933 EXT_DEF_WWN_NAME_SIZE); 934 tmp_port.Id[0] = 0; 935 tmp_port.Id[1] = ha->d_id.b.domain; 936 tmp_port.Id[2] = ha->d_id.b.area; 937 tmp_port.Id[3] = ha->d_id.b.al_pa; 938 939 /* For now we are initiator only driver */ 940 tmp_port.Type = EXT_DEF_INITIATOR_DEV; 941 942 if (ha->task_daemon_flags & LOOP_DOWN) { 943 tmp_port.State = EXT_DEF_HBA_LOOP_DOWN; 944 } else if (DRIVER_SUSPENDED(ha)) { 945 tmp_port.State = EXT_DEF_HBA_SUSPENDED; 946 } else { 947 tmp_port.State = EXT_DEF_HBA_OK; 948 } 949 950 if (ha->flags & POINT_TO_POINT) { 951 tmp_port.Mode = EXT_DEF_P2P_MODE; 952 } else { 953 tmp_port.Mode = EXT_DEF_LOOP_MODE; 954 } 955 /* 956 * fill in the portspeed values. 957 * 958 * default to not yet negotiated state 959 */ 960 tmp_port.PortSpeed = EXT_PORTSPEED_NOT_NEGOTIATED; 961 962 if (tmp_port.State == EXT_DEF_HBA_OK) { 963 switch (ha->iidma_rate) { 964 case IIDMA_RATE_1GB: 965 tmp_port.PortSpeed = EXT_DEF_PORTSPEED_1GBIT; 966 break; 967 case IIDMA_RATE_2GB: 968 tmp_port.PortSpeed = EXT_DEF_PORTSPEED_2GBIT; 969 break; 970 case IIDMA_RATE_4GB: 971 tmp_port.PortSpeed = EXT_DEF_PORTSPEED_4GBIT; 972 break; 973 case IIDMA_RATE_8GB: 974 tmp_port.PortSpeed = EXT_DEF_PORTSPEED_8GBIT; 975 break; 976 case IIDMA_RATE_10GB: 977 tmp_port.PortSpeed = EXT_DEF_PORTSPEED_10GBIT; 978 break; 979 default: 980 tmp_port.PortSpeed = EXT_DEF_PORTSPEED_UNKNOWN; 981 EL(ha, "failed, data rate=%xh\n", mr.mb[1]); 982 break; 983 } 984 } 985 986 /* Report all supported port speeds */ 987 if (CFG_IST(ha, CFG_CTRL_25XX)) { 988 tmp_port.PortSupportedSpeed = (EXT_DEF_PORTSPEED_8GBIT | 989 EXT_DEF_PORTSPEED_4GBIT | EXT_DEF_PORTSPEED_2GBIT | 990 EXT_DEF_PORTSPEED_1GBIT); 991 /* 992 * Correct supported speeds based on type of 993 * sfp that is present 994 */ 995 switch (ha->sfp_stat) { 996 case 1: 997 /* no sfp detected */ 998 break; 999 case 2: 1000 case 4: 1001 /* 4GB sfp */ 1002 tmp_port.PortSupportedSpeed &= 1003 ~EXT_DEF_PORTSPEED_8GBIT; 1004 break; 1005 case 3: 1006 case 5: 1007 /* 8GB sfp */ 1008 tmp_port.PortSupportedSpeed &= 1009 ~EXT_DEF_PORTSPEED_1GBIT; 1010 break; 1011 default: 1012 EL(ha, "sfp_stat: %xh\n", ha->sfp_stat); 1013 break; 1014 1015 } 1016 } else if (CFG_IST(ha, CFG_CTRL_8081)) { 1017 tmp_port.PortSupportedSpeed = EXT_DEF_PORTSPEED_10GBIT; 1018 } else if (CFG_IST(ha, CFG_CTRL_2422)) { 1019 tmp_port.PortSupportedSpeed = (EXT_DEF_PORTSPEED_4GBIT | 1020 EXT_DEF_PORTSPEED_2GBIT | EXT_DEF_PORTSPEED_1GBIT); 1021 } else if (CFG_IST(ha, CFG_CTRL_2300)) { 1022 tmp_port.PortSupportedSpeed = (EXT_DEF_PORTSPEED_2GBIT | 1023 EXT_DEF_PORTSPEED_1GBIT); 1024 } else if (CFG_IST(ha, CFG_CTRL_6322)) { 1025 tmp_port.PortSupportedSpeed = EXT_DEF_PORTSPEED_2GBIT; 1026 } else if (CFG_IST(ha, CFG_CTRL_2200)) { 1027 tmp_port.PortSupportedSpeed = EXT_DEF_PORTSPEED_1GBIT; 1028 } else { 1029 tmp_port.PortSupportedSpeed = EXT_DEF_PORTSPEED_UNKNOWN; 1030 EL(ha, "unknown HBA type: %xh\n", ha->device_id); 1031 } 1032 tmp_port.LinkState2 = LSB(ha->sfp_stat); 1033 port_cnt = 0; 1034 tgt_cnt = 0; 1035 1036 for (index = 0; index < DEVICE_HEAD_LIST_SIZE; index++) { 1037 for (link = ha->dev[index].first; link != NULL; 1038 link = link->next) { 1039 tq = link->base_address; 1040 1041 if (!VALID_TARGET_ID(ha, tq->loop_id)) { 1042 continue; 1043 } 1044 1045 port_cnt++; 1046 if ((tq->flags & TQF_INITIATOR_DEVICE) == 0) { 1047 tgt_cnt++; 1048 } 1049 } 1050 } 1051 1052 tmp_port.DiscPortCount = port_cnt; 1053 tmp_port.DiscTargetCount = tgt_cnt; 1054 1055 tmp_port.DiscPortNameType = EXT_DEF_USE_NODE_NAME; 1056 1057 rval = ddi_copyout((void *)&tmp_port, 1058 (void *)(uintptr_t)(cmd->ResponseAdr), 1059 sizeof (EXT_HBA_PORT), mode); 1060 if (rval != 0) { 1061 cmd->Status = EXT_STATUS_COPY_ERR; 1062 cmd->ResponseLen = 0; 1063 EL(ha, "failed, ddi_copyout\n"); 1064 } else { 1065 cmd->ResponseLen = sizeof (EXT_HBA_PORT); 1066 QL_PRINT_9(CE_CONT, "(%d): done, ports=%d, targets=%d\n", 1067 ha->instance, port_cnt, tgt_cnt); 1068 } 1069 } 1070 1071 /* 1072 * ql_qry_disc_port 1073 * Performs EXT_SC_QUERY_DISC_PORT subfunction. 1074 * 1075 * Input: 1076 * ha: adapter state pointer. 1077 * cmd: EXT_IOCTL cmd struct pointer. 1078 * mode: flags. 1079 * 1080 * cmd->Instance = Port instance in fcport chain. 1081 * 1082 * Returns: 1083 * None, request status indicated in cmd->Status. 1084 * 1085 * Context: 1086 * Kernel context. 1087 */ 1088 static void 1089 ql_qry_disc_port(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode) 1090 { 1091 EXT_DISC_PORT tmp_port = {0}; 1092 ql_link_t *link; 1093 ql_tgt_t *tq; 1094 uint16_t index; 1095 uint16_t inst = 0; 1096 1097 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 1098 1099 if (cmd->ResponseLen < sizeof (EXT_DISC_PORT)) { 1100 cmd->Status = EXT_STATUS_BUFFER_TOO_SMALL; 1101 cmd->DetailStatus = sizeof (EXT_DISC_PORT); 1102 EL(ha, "failed, ResponseLen < EXT_DISC_PORT, Len=%xh\n", 1103 cmd->ResponseLen); 1104 cmd->ResponseLen = 0; 1105 return; 1106 } 1107 1108 for (link = NULL, index = 0; 1109 index < DEVICE_HEAD_LIST_SIZE && link == NULL; index++) { 1110 for (link = ha->dev[index].first; link != NULL; 1111 link = link->next) { 1112 tq = link->base_address; 1113 1114 if (!VALID_TARGET_ID(ha, tq->loop_id)) { 1115 continue; 1116 } 1117 if (inst != cmd->Instance) { 1118 inst++; 1119 continue; 1120 } 1121 1122 /* fill in the values */ 1123 bcopy(tq->node_name, tmp_port.WWNN, 1124 EXT_DEF_WWN_NAME_SIZE); 1125 bcopy(tq->port_name, tmp_port.WWPN, 1126 EXT_DEF_WWN_NAME_SIZE); 1127 1128 break; 1129 } 1130 } 1131 1132 if (link == NULL) { 1133 /* no matching device */ 1134 cmd->Status = EXT_STATUS_DEV_NOT_FOUND; 1135 EL(ha, "failed, port not found port=%d\n", cmd->Instance); 1136 cmd->ResponseLen = 0; 1137 return; 1138 } 1139 1140 tmp_port.Id[0] = 0; 1141 tmp_port.Id[1] = tq->d_id.b.domain; 1142 tmp_port.Id[2] = tq->d_id.b.area; 1143 tmp_port.Id[3] = tq->d_id.b.al_pa; 1144 1145 tmp_port.Type = 0; 1146 if (tq->flags & TQF_INITIATOR_DEVICE) { 1147 tmp_port.Type = (uint16_t)(tmp_port.Type | 1148 EXT_DEF_INITIATOR_DEV); 1149 } else if ((tq->flags & TQF_TAPE_DEVICE) == 0) { 1150 (void) ql_inq_scan(ha, tq, 1); 1151 } else if (tq->flags & TQF_TAPE_DEVICE) { 1152 tmp_port.Type = (uint16_t)(tmp_port.Type | EXT_DEF_TAPE_DEV); 1153 } 1154 1155 if (tq->flags & TQF_FABRIC_DEVICE) { 1156 tmp_port.Type = (uint16_t)(tmp_port.Type | EXT_DEF_FABRIC_DEV); 1157 } else { 1158 tmp_port.Type = (uint16_t)(tmp_port.Type | EXT_DEF_TARGET_DEV); 1159 } 1160 1161 tmp_port.Status = 0; 1162 tmp_port.Bus = 0; /* Hard-coded for Solaris */ 1163 1164 bcopy(tq->port_name, &tmp_port.TargetId, 8); 1165 1166 if (ddi_copyout((void *)&tmp_port, 1167 (void *)(uintptr_t)(cmd->ResponseAdr), 1168 sizeof (EXT_DISC_PORT), mode) != 0) { 1169 cmd->Status = EXT_STATUS_COPY_ERR; 1170 cmd->ResponseLen = 0; 1171 EL(ha, "failed, ddi_copyout\n"); 1172 } else { 1173 cmd->ResponseLen = sizeof (EXT_DISC_PORT); 1174 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 1175 } 1176 } 1177 1178 /* 1179 * ql_qry_disc_tgt 1180 * Performs EXT_SC_QUERY_DISC_TGT subfunction. 1181 * 1182 * Input: 1183 * ha: adapter state pointer. 1184 * cmd: EXT_IOCTL cmd struct pointer. 1185 * mode: flags. 1186 * 1187 * cmd->Instance = Port instance in fcport chain. 1188 * 1189 * Returns: 1190 * None, request status indicated in cmd->Status. 1191 * 1192 * Context: 1193 * Kernel context. 1194 */ 1195 static void 1196 ql_qry_disc_tgt(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode) 1197 { 1198 EXT_DISC_TARGET tmp_tgt = {0}; 1199 ql_link_t *link; 1200 ql_tgt_t *tq; 1201 uint16_t index; 1202 uint16_t inst = 0; 1203 1204 QL_PRINT_9(CE_CONT, "(%d): started, target=%d\n", ha->instance, 1205 cmd->Instance); 1206 1207 if (cmd->ResponseLen < sizeof (EXT_DISC_TARGET)) { 1208 cmd->Status = EXT_STATUS_BUFFER_TOO_SMALL; 1209 cmd->DetailStatus = sizeof (EXT_DISC_TARGET); 1210 EL(ha, "failed, ResponseLen < EXT_DISC_TARGET, Len=%xh\n", 1211 cmd->ResponseLen); 1212 cmd->ResponseLen = 0; 1213 return; 1214 } 1215 1216 /* Scan port list for requested target and fill in the values */ 1217 for (link = NULL, index = 0; 1218 index < DEVICE_HEAD_LIST_SIZE && link == NULL; index++) { 1219 for (link = ha->dev[index].first; link != NULL; 1220 link = link->next) { 1221 tq = link->base_address; 1222 1223 if (!VALID_TARGET_ID(ha, tq->loop_id) || 1224 tq->flags & TQF_INITIATOR_DEVICE) { 1225 continue; 1226 } 1227 if (inst != cmd->Instance) { 1228 inst++; 1229 continue; 1230 } 1231 1232 /* fill in the values */ 1233 bcopy(tq->node_name, tmp_tgt.WWNN, 1234 EXT_DEF_WWN_NAME_SIZE); 1235 bcopy(tq->port_name, tmp_tgt.WWPN, 1236 EXT_DEF_WWN_NAME_SIZE); 1237 1238 break; 1239 } 1240 } 1241 1242 if (link == NULL) { 1243 /* no matching device */ 1244 cmd->Status = EXT_STATUS_DEV_NOT_FOUND; 1245 cmd->DetailStatus = EXT_DSTATUS_TARGET; 1246 EL(ha, "failed, not found target=%d\n", cmd->Instance); 1247 cmd->ResponseLen = 0; 1248 return; 1249 } 1250 tmp_tgt.Id[0] = 0; 1251 tmp_tgt.Id[1] = tq->d_id.b.domain; 1252 tmp_tgt.Id[2] = tq->d_id.b.area; 1253 tmp_tgt.Id[3] = tq->d_id.b.al_pa; 1254 1255 tmp_tgt.LunCount = (uint16_t)ql_lun_count(ha, tq); 1256 1257 if ((tq->flags & TQF_TAPE_DEVICE) == 0) { 1258 (void) ql_inq_scan(ha, tq, 1); 1259 } 1260 1261 tmp_tgt.Type = 0; 1262 if (tq->flags & TQF_TAPE_DEVICE) { 1263 tmp_tgt.Type = (uint16_t)(tmp_tgt.Type | EXT_DEF_TAPE_DEV); 1264 } 1265 1266 if (tq->flags & TQF_FABRIC_DEVICE) { 1267 tmp_tgt.Type = (uint16_t)(tmp_tgt.Type | EXT_DEF_FABRIC_DEV); 1268 } else { 1269 tmp_tgt.Type = (uint16_t)(tmp_tgt.Type | EXT_DEF_TARGET_DEV); 1270 } 1271 1272 tmp_tgt.Status = 0; 1273 1274 tmp_tgt.Bus = 0; /* Hard-coded for Solaris. */ 1275 1276 bcopy(tq->port_name, &tmp_tgt.TargetId, 8); 1277 1278 if (ddi_copyout((void *)&tmp_tgt, 1279 (void *)(uintptr_t)(cmd->ResponseAdr), 1280 sizeof (EXT_DISC_TARGET), mode) != 0) { 1281 cmd->Status = EXT_STATUS_COPY_ERR; 1282 cmd->ResponseLen = 0; 1283 EL(ha, "failed, ddi_copyout\n"); 1284 } else { 1285 cmd->ResponseLen = sizeof (EXT_DISC_TARGET); 1286 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 1287 } 1288 } 1289 1290 /* 1291 * ql_qry_fw 1292 * Performs EXT_SC_QUERY_FW subfunction. 1293 * 1294 * Input: 1295 * ha: adapter state pointer. 1296 * cmd: EXT_IOCTL cmd struct pointer. 1297 * mode: flags. 1298 * 1299 * Returns: 1300 * None, request status indicated in cmd->Status. 1301 * 1302 * Context: 1303 * Kernel context. 1304 */ 1305 static void 1306 ql_qry_fw(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode) 1307 { 1308 EXT_FW fw_info = {0}; 1309 1310 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 1311 1312 if (cmd->ResponseLen < sizeof (EXT_FW)) { 1313 cmd->Status = EXT_STATUS_BUFFER_TOO_SMALL; 1314 cmd->DetailStatus = sizeof (EXT_FW); 1315 EL(ha, "failed, ResponseLen < EXT_FW, Len=%xh\n", 1316 cmd->ResponseLen); 1317 cmd->ResponseLen = 0; 1318 return; 1319 } 1320 1321 (void) sprintf((char *)(fw_info.Version), "%d.%02d.%02d", 1322 ha->fw_major_version, ha->fw_minor_version, 1323 ha->fw_subminor_version); 1324 1325 fw_info.Attrib = ha->fw_attributes; 1326 1327 if (ddi_copyout((void *)&fw_info, 1328 (void *)(uintptr_t)(cmd->ResponseAdr), 1329 sizeof (EXT_FW), mode) != 0) { 1330 cmd->Status = EXT_STATUS_COPY_ERR; 1331 cmd->ResponseLen = 0; 1332 EL(ha, "failed, ddi_copyout\n"); 1333 return; 1334 } else { 1335 cmd->ResponseLen = sizeof (EXT_FW); 1336 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 1337 } 1338 } 1339 1340 /* 1341 * ql_qry_chip 1342 * Performs EXT_SC_QUERY_CHIP subfunction. 1343 * 1344 * Input: 1345 * ha: adapter state pointer. 1346 * cmd: EXT_IOCTL cmd struct pointer. 1347 * mode: flags. 1348 * 1349 * Returns: 1350 * None, request status indicated in cmd->Status. 1351 * 1352 * Context: 1353 * Kernel context. 1354 */ 1355 static void 1356 ql_qry_chip(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode) 1357 { 1358 EXT_CHIP chip = {0}; 1359 1360 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 1361 1362 if (cmd->ResponseLen < sizeof (EXT_CHIP)) { 1363 cmd->Status = EXT_STATUS_BUFFER_TOO_SMALL; 1364 cmd->DetailStatus = sizeof (EXT_CHIP); 1365 EL(ha, "failed, ResponseLen < EXT_CHIP, Len=%xh\n", 1366 cmd->ResponseLen); 1367 cmd->ResponseLen = 0; 1368 return; 1369 } 1370 1371 chip.VendorId = ha->ven_id; 1372 chip.DeviceId = ha->device_id; 1373 chip.SubVendorId = ha->subven_id; 1374 chip.SubSystemId = ha->subsys_id; 1375 chip.IoAddr = ql_pci_config_get32(ha, PCI_CONF_BASE0); 1376 chip.IoAddrLen = 0x100; 1377 chip.MemAddr = ql_pci_config_get32(ha, PCI_CONF_BASE1); 1378 chip.MemAddrLen = 0x100; 1379 chip.ChipRevID = ha->rev_id; 1380 if (ha->flags & FUNCTION_1) { 1381 chip.FuncNo = 1; 1382 } 1383 1384 if (ddi_copyout((void *)&chip, 1385 (void *)(uintptr_t)(cmd->ResponseAdr), 1386 sizeof (EXT_CHIP), mode) != 0) { 1387 cmd->Status = EXT_STATUS_COPY_ERR; 1388 cmd->ResponseLen = 0; 1389 EL(ha, "failed, ddi_copyout\n"); 1390 } else { 1391 cmd->ResponseLen = sizeof (EXT_CHIP); 1392 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 1393 } 1394 } 1395 1396 /* 1397 * ql_qry_driver 1398 * Performs EXT_SC_QUERY_DRIVER subfunction. 1399 * 1400 * Input: 1401 * ha: adapter state pointer. 1402 * cmd: EXT_IOCTL cmd struct pointer. 1403 * mode: flags. 1404 * 1405 * Returns: 1406 * None, request status indicated in cmd->Status. 1407 * 1408 * Context: 1409 * Kernel context. 1410 */ 1411 static void 1412 ql_qry_driver(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode) 1413 { 1414 EXT_DRIVER qd = {0}; 1415 1416 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 1417 1418 if (cmd->ResponseLen < sizeof (EXT_DRIVER)) { 1419 cmd->Status = EXT_STATUS_DATA_OVERRUN; 1420 cmd->DetailStatus = sizeof (EXT_DRIVER); 1421 EL(ha, "failed, ResponseLen < EXT_DRIVER, Len=%xh\n", 1422 cmd->ResponseLen); 1423 cmd->ResponseLen = 0; 1424 return; 1425 } 1426 1427 (void) strcpy((void *)&qd.Version[0], QL_VERSION); 1428 qd.NumOfBus = 1; /* Fixed for Solaris */ 1429 qd.TargetsPerBus = (uint16_t) 1430 (CFG_IST(ha, (CFG_CTRL_24258081 | CFG_EXT_FW_INTERFACE)) ? 1431 MAX_24_FIBRE_DEVICES : MAX_22_FIBRE_DEVICES); 1432 qd.LunsPerTarget = 2030; 1433 qd.MaxTransferLen = QL_DMA_MAX_XFER_SIZE; 1434 qd.MaxDataSegments = QL_DMA_SG_LIST_LENGTH; 1435 1436 if (ddi_copyout((void *)&qd, (void *)(uintptr_t)cmd->ResponseAdr, 1437 sizeof (EXT_DRIVER), mode) != 0) { 1438 cmd->Status = EXT_STATUS_COPY_ERR; 1439 cmd->ResponseLen = 0; 1440 EL(ha, "failed, ddi_copyout\n"); 1441 } else { 1442 cmd->ResponseLen = sizeof (EXT_DRIVER); 1443 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 1444 } 1445 } 1446 1447 /* 1448 * ql_fcct 1449 * IOCTL management server FC-CT passthrough. 1450 * 1451 * Input: 1452 * ha: adapter state pointer. 1453 * cmd: User space CT arguments pointer. 1454 * mode: flags. 1455 * 1456 * Returns: 1457 * None, request status indicated in cmd->Status. 1458 * 1459 * Context: 1460 * Kernel context. 1461 */ 1462 static void 1463 ql_fcct(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode) 1464 { 1465 ql_mbx_iocb_t *pkt; 1466 ql_mbx_data_t mr; 1467 dma_mem_t *dma_mem; 1468 caddr_t pld; 1469 uint32_t pkt_size, pld_byte_cnt, *long_ptr; 1470 int rval; 1471 ql_ct_iu_preamble_t *ct; 1472 ql_xioctl_t *xp = ha->xioctl; 1473 ql_tgt_t tq; 1474 uint16_t comp_status, loop_id; 1475 1476 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 1477 1478 /* Get CT argument structure. */ 1479 if ((ha->topology & QL_SNS_CONNECTION) == 0) { 1480 EL(ha, "failed, No switch\n"); 1481 cmd->Status = EXT_STATUS_DEV_NOT_FOUND; 1482 cmd->ResponseLen = 0; 1483 return; 1484 } 1485 1486 if (DRIVER_SUSPENDED(ha)) { 1487 EL(ha, "failed, LOOP_NOT_READY\n"); 1488 cmd->Status = EXT_STATUS_BUSY; 1489 cmd->ResponseLen = 0; 1490 return; 1491 } 1492 1493 /* Login management server device. */ 1494 if ((xp->flags & QL_MGMT_SERVER_LOGIN) == 0) { 1495 tq.d_id.b.al_pa = 0xfa; 1496 tq.d_id.b.area = 0xff; 1497 tq.d_id.b.domain = 0xff; 1498 tq.loop_id = (uint16_t)(CFG_IST(ha, CFG_CTRL_24258081) ? 1499 MANAGEMENT_SERVER_24XX_LOOP_ID : 1500 MANAGEMENT_SERVER_LOOP_ID); 1501 rval = ql_login_fport(ha, &tq, tq.loop_id, LFF_NO_PRLI, &mr); 1502 if (rval != QL_SUCCESS) { 1503 EL(ha, "failed, server login\n"); 1504 cmd->Status = EXT_STATUS_DEV_NOT_FOUND; 1505 cmd->ResponseLen = 0; 1506 return; 1507 } else { 1508 xp->flags |= QL_MGMT_SERVER_LOGIN; 1509 } 1510 } 1511 1512 QL_PRINT_9(CE_CONT, "(%d): cmd\n", ha->instance); 1513 QL_DUMP_9(cmd, 8, sizeof (EXT_IOCTL)); 1514 1515 /* Allocate a DMA Memory Descriptor */ 1516 dma_mem = (dma_mem_t *)kmem_zalloc(sizeof (dma_mem_t), KM_SLEEP); 1517 if (dma_mem == NULL) { 1518 EL(ha, "failed, kmem_zalloc\n"); 1519 cmd->Status = EXT_STATUS_NO_MEMORY; 1520 cmd->ResponseLen = 0; 1521 return; 1522 } 1523 /* Determine maximum buffer size. */ 1524 if (cmd->RequestLen < cmd->ResponseLen) { 1525 pld_byte_cnt = cmd->ResponseLen; 1526 } else { 1527 pld_byte_cnt = cmd->RequestLen; 1528 } 1529 1530 /* Allocate command block. */ 1531 pkt_size = (uint32_t)(sizeof (ql_mbx_iocb_t) + pld_byte_cnt); 1532 pkt = kmem_zalloc(pkt_size, KM_SLEEP); 1533 if (pkt == NULL) { 1534 EL(ha, "failed, kmem_zalloc\n"); 1535 cmd->Status = EXT_STATUS_NO_MEMORY; 1536 cmd->ResponseLen = 0; 1537 return; 1538 } 1539 pld = (caddr_t)pkt + sizeof (ql_mbx_iocb_t); 1540 1541 /* Get command payload data. */ 1542 if (ql_get_buffer_data((caddr_t)(uintptr_t)cmd->RequestAdr, pld, 1543 cmd->RequestLen, mode) != cmd->RequestLen) { 1544 EL(ha, "failed, get_buffer_data\n"); 1545 kmem_free(pkt, pkt_size); 1546 cmd->Status = EXT_STATUS_COPY_ERR; 1547 cmd->ResponseLen = 0; 1548 return; 1549 } 1550 1551 /* Get DMA memory for the IOCB */ 1552 if (ql_get_dma_mem(ha, dma_mem, pkt_size, LITTLE_ENDIAN_DMA, 1553 QL_DMA_RING_ALIGN) != QL_SUCCESS) { 1554 cmn_err(CE_WARN, "%s(%d): DMA memory " 1555 "alloc failed", QL_NAME, ha->instance); 1556 kmem_free(pkt, pkt_size); 1557 kmem_free(dma_mem, sizeof (dma_mem_t)); 1558 cmd->Status = EXT_STATUS_MS_NO_RESPONSE; 1559 cmd->ResponseLen = 0; 1560 return; 1561 } 1562 1563 /* Copy out going payload data to IOCB DMA buffer. */ 1564 ddi_rep_put8(dma_mem->acc_handle, (uint8_t *)pld, 1565 (uint8_t *)dma_mem->bp, pld_byte_cnt, DDI_DEV_AUTOINCR); 1566 1567 /* Sync IOCB DMA buffer. */ 1568 (void) ddi_dma_sync(dma_mem->dma_handle, 0, pld_byte_cnt, 1569 DDI_DMA_SYNC_FORDEV); 1570 1571 /* 1572 * Setup IOCB 1573 */ 1574 ct = (ql_ct_iu_preamble_t *)pld; 1575 if (CFG_IST(ha, CFG_CTRL_24258081)) { 1576 pkt->ms24.entry_type = CT_PASSTHRU_TYPE; 1577 pkt->ms24.entry_count = 1; 1578 1579 pkt->ms24.vp_index = ha->vp_index; 1580 1581 /* Set loop ID */ 1582 pkt->ms24.n_port_hdl = (uint16_t) 1583 (ct->gs_type == GS_TYPE_DIR_SERVER ? 1584 LE_16(SNS_24XX_HDL) : 1585 LE_16(MANAGEMENT_SERVER_24XX_LOOP_ID)); 1586 1587 /* Set ISP command timeout. */ 1588 pkt->ms24.timeout = LE_16(120); 1589 1590 /* Set cmd/response data segment counts. */ 1591 pkt->ms24.cmd_dseg_count = LE_16(1); 1592 pkt->ms24.resp_dseg_count = LE_16(1); 1593 1594 /* Load ct cmd byte count. */ 1595 pkt->ms24.cmd_byte_count = LE_32(cmd->RequestLen); 1596 1597 /* Load ct rsp byte count. */ 1598 pkt->ms24.resp_byte_count = LE_32(cmd->ResponseLen); 1599 1600 long_ptr = (uint32_t *)&pkt->ms24.dseg_0_address; 1601 1602 /* Load MS command entry data segments. */ 1603 *long_ptr++ = (uint32_t) 1604 LE_32(LSD(dma_mem->cookie.dmac_laddress)); 1605 *long_ptr++ = (uint32_t) 1606 LE_32(MSD(dma_mem->cookie.dmac_laddress)); 1607 *long_ptr++ = (uint32_t)(LE_32(cmd->RequestLen)); 1608 1609 /* Load MS response entry data segments. */ 1610 *long_ptr++ = (uint32_t) 1611 LE_32(LSD(dma_mem->cookie.dmac_laddress)); 1612 *long_ptr++ = (uint32_t) 1613 LE_32(MSD(dma_mem->cookie.dmac_laddress)); 1614 *long_ptr = (uint32_t)LE_32(cmd->ResponseLen); 1615 1616 rval = ql_issue_mbx_iocb(ha, (caddr_t)pkt, 1617 sizeof (ql_mbx_iocb_t)); 1618 1619 comp_status = (uint16_t)LE_16(pkt->sts24.comp_status); 1620 if (comp_status == CS_DATA_UNDERRUN) { 1621 if ((BE_16(ct->max_residual_size)) == 0) { 1622 comp_status = CS_COMPLETE; 1623 } 1624 } 1625 1626 if (rval != QL_SUCCESS || (pkt->sts24.entry_status & 0x3c) != 1627 0) { 1628 EL(ha, "failed, I/O timeout or " 1629 "es=%xh, ss_l=%xh, rval=%xh\n", 1630 pkt->sts24.entry_status, 1631 pkt->sts24.scsi_status_l, rval); 1632 kmem_free(pkt, pkt_size); 1633 ql_free_dma_resource(ha, dma_mem); 1634 kmem_free(dma_mem, sizeof (dma_mem_t)); 1635 cmd->Status = EXT_STATUS_MS_NO_RESPONSE; 1636 cmd->ResponseLen = 0; 1637 return; 1638 } 1639 } else { 1640 pkt->ms.entry_type = MS_TYPE; 1641 pkt->ms.entry_count = 1; 1642 1643 /* Set loop ID */ 1644 loop_id = (uint16_t)(ct->gs_type == GS_TYPE_DIR_SERVER ? 1645 SIMPLE_NAME_SERVER_LOOP_ID : MANAGEMENT_SERVER_LOOP_ID); 1646 if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) { 1647 pkt->ms.loop_id_l = LSB(loop_id); 1648 pkt->ms.loop_id_h = MSB(loop_id); 1649 } else { 1650 pkt->ms.loop_id_h = LSB(loop_id); 1651 } 1652 1653 /* Set ISP command timeout. */ 1654 pkt->ms.timeout = LE_16(120); 1655 1656 /* Set data segment counts. */ 1657 pkt->ms.cmd_dseg_count_l = 1; 1658 pkt->ms.total_dseg_count = LE_16(2); 1659 1660 /* Response total byte count. */ 1661 pkt->ms.resp_byte_count = LE_32(cmd->ResponseLen); 1662 pkt->ms.dseg_1_length = LE_32(cmd->ResponseLen); 1663 1664 /* Command total byte count. */ 1665 pkt->ms.cmd_byte_count = LE_32(cmd->RequestLen); 1666 pkt->ms.dseg_0_length = LE_32(cmd->RequestLen); 1667 1668 /* Load command/response data segments. */ 1669 pkt->ms.dseg_0_address[0] = (uint32_t) 1670 LE_32(LSD(dma_mem->cookie.dmac_laddress)); 1671 pkt->ms.dseg_0_address[1] = (uint32_t) 1672 LE_32(MSD(dma_mem->cookie.dmac_laddress)); 1673 pkt->ms.dseg_1_address[0] = (uint32_t) 1674 LE_32(LSD(dma_mem->cookie.dmac_laddress)); 1675 pkt->ms.dseg_1_address[1] = (uint32_t) 1676 LE_32(MSD(dma_mem->cookie.dmac_laddress)); 1677 1678 rval = ql_issue_mbx_iocb(ha, (caddr_t)pkt, 1679 sizeof (ql_mbx_iocb_t)); 1680 1681 comp_status = (uint16_t)LE_16(pkt->sts.comp_status); 1682 if (comp_status == CS_DATA_UNDERRUN) { 1683 if ((BE_16(ct->max_residual_size)) == 0) { 1684 comp_status = CS_COMPLETE; 1685 } 1686 } 1687 if (rval != QL_SUCCESS || (pkt->sts.entry_status & 0x7e) != 0) { 1688 EL(ha, "failed, I/O timeout or " 1689 "es=%xh, rval=%xh\n", pkt->sts.entry_status, rval); 1690 kmem_free(pkt, pkt_size); 1691 ql_free_dma_resource(ha, dma_mem); 1692 kmem_free(dma_mem, sizeof (dma_mem_t)); 1693 cmd->Status = EXT_STATUS_MS_NO_RESPONSE; 1694 cmd->ResponseLen = 0; 1695 return; 1696 } 1697 } 1698 1699 /* Sync in coming DMA buffer. */ 1700 (void) ddi_dma_sync(dma_mem->dma_handle, 0, 1701 pld_byte_cnt, DDI_DMA_SYNC_FORKERNEL); 1702 /* Copy in coming DMA data. */ 1703 ddi_rep_get8(dma_mem->acc_handle, (uint8_t *)pld, 1704 (uint8_t *)dma_mem->bp, pld_byte_cnt, 1705 DDI_DEV_AUTOINCR); 1706 1707 /* Copy response payload from DMA buffer to application. */ 1708 if (cmd->ResponseLen != 0) { 1709 QL_PRINT_9(CE_CONT, "(%d): ResponseLen=%d\n", ha->instance, 1710 cmd->ResponseLen); 1711 QL_DUMP_9(pld, 8, cmd->ResponseLen); 1712 1713 /* Send response payload. */ 1714 if (ql_send_buffer_data(pld, 1715 (caddr_t)(uintptr_t)cmd->ResponseAdr, 1716 cmd->ResponseLen, mode) != cmd->ResponseLen) { 1717 EL(ha, "failed, send_buffer_data\n"); 1718 cmd->Status = EXT_STATUS_COPY_ERR; 1719 cmd->ResponseLen = 0; 1720 } 1721 } 1722 1723 kmem_free(pkt, pkt_size); 1724 ql_free_dma_resource(ha, dma_mem); 1725 kmem_free(dma_mem, sizeof (dma_mem_t)); 1726 1727 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 1728 } 1729 1730 /* 1731 * ql_aen_reg 1732 * IOCTL management server Asynchronous Event Tracking Enable/Disable. 1733 * 1734 * Input: 1735 * ha: adapter state pointer. 1736 * cmd: EXT_IOCTL cmd struct pointer. 1737 * mode: flags. 1738 * 1739 * Returns: 1740 * None, request status indicated in cmd->Status. 1741 * 1742 * Context: 1743 * Kernel context. 1744 */ 1745 static void 1746 ql_aen_reg(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode) 1747 { 1748 EXT_REG_AEN reg_struct; 1749 int rval = 0; 1750 ql_xioctl_t *xp = ha->xioctl; 1751 1752 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 1753 1754 rval = ddi_copyin((void*)(uintptr_t)cmd->RequestAdr, ®_struct, 1755 cmd->RequestLen, mode); 1756 1757 if (rval == 0) { 1758 if (reg_struct.Enable) { 1759 xp->flags |= QL_AEN_TRACKING_ENABLE; 1760 } else { 1761 xp->flags &= ~QL_AEN_TRACKING_ENABLE; 1762 /* Empty the queue. */ 1763 INTR_LOCK(ha); 1764 xp->aen_q_head = 0; 1765 xp->aen_q_tail = 0; 1766 INTR_UNLOCK(ha); 1767 } 1768 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 1769 } else { 1770 cmd->Status = EXT_STATUS_COPY_ERR; 1771 EL(ha, "failed, ddi_copyin\n"); 1772 } 1773 } 1774 1775 /* 1776 * ql_aen_get 1777 * IOCTL management server Asynchronous Event Record Transfer. 1778 * 1779 * Input: 1780 * ha: adapter state pointer. 1781 * cmd: EXT_IOCTL cmd struct pointer. 1782 * mode: flags. 1783 * 1784 * Returns: 1785 * None, request status indicated in cmd->Status. 1786 * 1787 * Context: 1788 * Kernel context. 1789 */ 1790 static void 1791 ql_aen_get(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode) 1792 { 1793 uint32_t out_size; 1794 EXT_ASYNC_EVENT *tmp_q; 1795 EXT_ASYNC_EVENT aen[EXT_DEF_MAX_AEN_QUEUE]; 1796 uint8_t i; 1797 uint8_t queue_cnt; 1798 uint8_t request_cnt; 1799 ql_xioctl_t *xp = ha->xioctl; 1800 1801 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 1802 1803 /* Compute the number of events that can be returned */ 1804 request_cnt = (uint8_t)(cmd->ResponseLen / sizeof (EXT_ASYNC_EVENT)); 1805 1806 if (request_cnt < EXT_DEF_MAX_AEN_QUEUE) { 1807 cmd->Status = EXT_STATUS_BUFFER_TOO_SMALL; 1808 cmd->DetailStatus = EXT_DEF_MAX_AEN_QUEUE; 1809 EL(ha, "failed, request_cnt < EXT_DEF_MAX_AEN_QUEUE, " 1810 "Len=%xh\n", request_cnt); 1811 cmd->ResponseLen = 0; 1812 return; 1813 } 1814 1815 /* 1st: Make a local copy of the entire queue content. */ 1816 tmp_q = (EXT_ASYNC_EVENT *)xp->aen_tracking_queue; 1817 queue_cnt = 0; 1818 1819 INTR_LOCK(ha); 1820 i = xp->aen_q_head; 1821 1822 for (; queue_cnt < EXT_DEF_MAX_AEN_QUEUE; ) { 1823 if (tmp_q[i].AsyncEventCode != 0) { 1824 bcopy(&tmp_q[i], &aen[queue_cnt], 1825 sizeof (EXT_ASYNC_EVENT)); 1826 queue_cnt++; 1827 tmp_q[i].AsyncEventCode = 0; /* empty out the slot */ 1828 } 1829 if (i == xp->aen_q_tail) { 1830 /* done. */ 1831 break; 1832 } 1833 i++; 1834 if (i == EXT_DEF_MAX_AEN_QUEUE) { 1835 i = 0; 1836 } 1837 } 1838 1839 /* Empty the queue. */ 1840 xp->aen_q_head = 0; 1841 xp->aen_q_tail = 0; 1842 1843 INTR_UNLOCK(ha); 1844 1845 /* 2nd: Now transfer the queue content to user buffer */ 1846 /* Copy the entire queue to user's buffer. */ 1847 out_size = (uint32_t)(queue_cnt * sizeof (EXT_ASYNC_EVENT)); 1848 if (queue_cnt == 0) { 1849 cmd->ResponseLen = 0; 1850 } else if (ddi_copyout((void *)&aen[0], 1851 (void *)(uintptr_t)(cmd->ResponseAdr), 1852 out_size, mode) != 0) { 1853 cmd->Status = EXT_STATUS_COPY_ERR; 1854 cmd->ResponseLen = 0; 1855 EL(ha, "failed, ddi_copyout\n"); 1856 } else { 1857 cmd->ResponseLen = out_size; 1858 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 1859 } 1860 } 1861 1862 /* 1863 * ql_enqueue_aen 1864 * 1865 * Input: 1866 * ha: adapter state pointer. 1867 * event_code: async event code of the event to add to queue. 1868 * payload: event payload for the queue. 1869 * INTR_LOCK must be already obtained. 1870 * 1871 * Context: 1872 * Interrupt or Kernel context, no mailbox commands allowed. 1873 */ 1874 void 1875 ql_enqueue_aen(ql_adapter_state_t *ha, uint16_t event_code, void *payload) 1876 { 1877 uint8_t new_entry; /* index to current entry */ 1878 uint16_t *mbx; 1879 EXT_ASYNC_EVENT *aen_queue; 1880 ql_xioctl_t *xp = ha->xioctl; 1881 1882 QL_PRINT_9(CE_CONT, "(%d): started, event_code=%d\n", ha->instance, 1883 event_code); 1884 1885 if (xp == NULL) { 1886 QL_PRINT_9(CE_CONT, "(%d): no context\n", ha->instance); 1887 return; 1888 } 1889 aen_queue = (EXT_ASYNC_EVENT *)xp->aen_tracking_queue; 1890 1891 if (aen_queue[xp->aen_q_tail].AsyncEventCode != NULL) { 1892 /* Need to change queue pointers to make room. */ 1893 1894 /* Increment tail for adding new entry. */ 1895 xp->aen_q_tail++; 1896 if (xp->aen_q_tail == EXT_DEF_MAX_AEN_QUEUE) { 1897 xp->aen_q_tail = 0; 1898 } 1899 if (xp->aen_q_head == xp->aen_q_tail) { 1900 /* 1901 * We're overwriting the oldest entry, so need to 1902 * update the head pointer. 1903 */ 1904 xp->aen_q_head++; 1905 if (xp->aen_q_head == EXT_DEF_MAX_AEN_QUEUE) { 1906 xp->aen_q_head = 0; 1907 } 1908 } 1909 } 1910 1911 new_entry = xp->aen_q_tail; 1912 aen_queue[new_entry].AsyncEventCode = event_code; 1913 1914 /* Update payload */ 1915 if (payload != NULL) { 1916 switch (event_code) { 1917 case MBA_LIP_OCCURRED: 1918 case MBA_LOOP_UP: 1919 case MBA_LOOP_DOWN: 1920 case MBA_LIP_F8: 1921 case MBA_LIP_RESET: 1922 case MBA_PORT_UPDATE: 1923 break; 1924 case MBA_RSCN_UPDATE: 1925 mbx = (uint16_t *)payload; 1926 /* al_pa */ 1927 aen_queue[new_entry].Payload.RSCN.RSCNInfo[0] = 1928 LSB(mbx[2]); 1929 /* area */ 1930 aen_queue[new_entry].Payload.RSCN.RSCNInfo[1] = 1931 MSB(mbx[2]); 1932 /* domain */ 1933 aen_queue[new_entry].Payload.RSCN.RSCNInfo[2] = 1934 LSB(mbx[1]); 1935 /* save in big endian */ 1936 BIG_ENDIAN_24(&aen_queue[new_entry]. 1937 Payload.RSCN.RSCNInfo[0]); 1938 1939 aen_queue[new_entry].Payload.RSCN.AddrFormat = 1940 MSB(mbx[1]); 1941 1942 break; 1943 default: 1944 /* Not supported */ 1945 EL(ha, "failed, event code not supported=%xh\n", 1946 event_code); 1947 aen_queue[new_entry].AsyncEventCode = 0; 1948 break; 1949 } 1950 } 1951 1952 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 1953 } 1954 1955 /* 1956 * ql_scsi_passthru 1957 * IOCTL SCSI passthrough. 1958 * 1959 * Input: 1960 * ha: adapter state pointer. 1961 * cmd: User space SCSI command pointer. 1962 * mode: flags. 1963 * 1964 * Returns: 1965 * None, request status indicated in cmd->Status. 1966 * 1967 * Context: 1968 * Kernel context. 1969 */ 1970 static void 1971 ql_scsi_passthru(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode) 1972 { 1973 ql_mbx_iocb_t *pkt; 1974 ql_mbx_data_t mr; 1975 dma_mem_t *dma_mem; 1976 caddr_t pld; 1977 uint32_t pkt_size, pld_size; 1978 uint16_t qlnt, retries, cnt, cnt2; 1979 uint8_t *name; 1980 EXT_FC_SCSI_PASSTHRU *ufc_req; 1981 EXT_SCSI_PASSTHRU *usp_req; 1982 int rval; 1983 union _passthru { 1984 EXT_SCSI_PASSTHRU sp_cmd; 1985 EXT_FC_SCSI_PASSTHRU fc_cmd; 1986 } pt_req; /* Passthru request */ 1987 uint32_t status, sense_sz = 0; 1988 ql_tgt_t *tq = NULL; 1989 EXT_SCSI_PASSTHRU *sp_req = &pt_req.sp_cmd; 1990 EXT_FC_SCSI_PASSTHRU *fc_req = &pt_req.fc_cmd; 1991 1992 /* SCSI request struct for SCSI passthrough IOs. */ 1993 struct { 1994 uint16_t lun; 1995 uint16_t sense_length; /* Sense buffer size */ 1996 size_t resid; /* Residual */ 1997 uint8_t *cdbp; /* Requestor's CDB */ 1998 uint8_t *u_sense; /* Requestor's sense buffer */ 1999 uint8_t cdb_len; /* Requestor's CDB length */ 2000 uint8_t direction; 2001 } scsi_req; 2002 2003 struct { 2004 uint8_t *rsp_info; 2005 uint8_t *req_sense_data; 2006 uint32_t residual_length; 2007 uint32_t rsp_info_length; 2008 uint32_t req_sense_length; 2009 uint16_t comp_status; 2010 uint8_t state_flags_l; 2011 uint8_t state_flags_h; 2012 uint8_t scsi_status_l; 2013 uint8_t scsi_status_h; 2014 } sts; 2015 2016 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 2017 2018 /* Verify Sub Code and set cnt to needed request size. */ 2019 if (cmd->SubCode == EXT_SC_SEND_SCSI_PASSTHRU) { 2020 pld_size = sizeof (EXT_SCSI_PASSTHRU); 2021 } else if (cmd->SubCode == EXT_SC_SEND_FC_SCSI_PASSTHRU) { 2022 pld_size = sizeof (EXT_FC_SCSI_PASSTHRU); 2023 } else { 2024 EL(ha, "failed, invalid SubCode=%xh\n", cmd->SubCode); 2025 cmd->Status = EXT_STATUS_UNSUPPORTED_SUBCODE; 2026 cmd->ResponseLen = 0; 2027 return; 2028 } 2029 2030 dma_mem = (dma_mem_t *)kmem_zalloc(sizeof (dma_mem_t), KM_SLEEP); 2031 if (dma_mem == NULL) { 2032 EL(ha, "failed, kmem_zalloc\n"); 2033 cmd->Status = EXT_STATUS_NO_MEMORY; 2034 cmd->ResponseLen = 0; 2035 return; 2036 } 2037 /* Verify the size of and copy in the passthru request structure. */ 2038 if (cmd->RequestLen != pld_size) { 2039 /* Return error */ 2040 EL(ha, "failed, RequestLen != cnt, is=%xh, expected=%xh\n", 2041 cmd->RequestLen, pld_size); 2042 cmd->Status = EXT_STATUS_INVALID_PARAM; 2043 cmd->DetailStatus = EXT_DSTATUS_REQUEST_LEN; 2044 cmd->ResponseLen = 0; 2045 return; 2046 } 2047 2048 if (ddi_copyin((void *)(uintptr_t)cmd->RequestAdr, &pt_req, 2049 pld_size, mode) != 0) { 2050 EL(ha, "failed, ddi_copyin\n"); 2051 cmd->Status = EXT_STATUS_COPY_ERR; 2052 cmd->ResponseLen = 0; 2053 return; 2054 } 2055 2056 /* 2057 * Find fc_port from SCSI PASSTHRU structure fill in the scsi_req 2058 * request data structure. 2059 */ 2060 if (cmd->SubCode == EXT_SC_SEND_SCSI_PASSTHRU) { 2061 scsi_req.lun = sp_req->TargetAddr.Lun; 2062 scsi_req.sense_length = sizeof (sp_req->SenseData); 2063 scsi_req.cdbp = &sp_req->Cdb[0]; 2064 scsi_req.cdb_len = sp_req->CdbLength; 2065 scsi_req.direction = sp_req->Direction; 2066 usp_req = (EXT_SCSI_PASSTHRU *)(uintptr_t)cmd->RequestAdr; 2067 scsi_req.u_sense = &usp_req->SenseData[0]; 2068 cmd->DetailStatus = EXT_DSTATUS_TARGET; 2069 2070 qlnt = QLNT_PORT; 2071 name = (uint8_t *)&sp_req->TargetAddr.Target; 2072 QL_PRINT_9(CE_CONT, "(%d): SubCode=%xh, Target=%lld\n", 2073 ha->instance, cmd->SubCode, sp_req->TargetAddr.Target); 2074 tq = ql_find_port(ha, name, qlnt); 2075 } else { 2076 /* 2077 * Must be FC PASSTHRU, verified above. 2078 */ 2079 if (fc_req->FCScsiAddr.DestType == EXT_DEF_DESTTYPE_WWPN) { 2080 qlnt = QLNT_PORT; 2081 name = &fc_req->FCScsiAddr.DestAddr.WWPN[0]; 2082 QL_PRINT_9(CE_CONT, "(%d): SubCode=%xh, " 2083 "wwpn=%02x%02x%02x%02x%02x%02x%02x%02x\n", 2084 ha->instance, cmd->SubCode, name[0], name[1], 2085 name[2], name[3], name[4], name[5], name[6], 2086 name[7]); 2087 tq = ql_find_port(ha, name, qlnt); 2088 } else if (fc_req->FCScsiAddr.DestType == 2089 EXT_DEF_DESTTYPE_WWNN) { 2090 qlnt = QLNT_NODE; 2091 name = &fc_req->FCScsiAddr.DestAddr.WWNN[0]; 2092 QL_PRINT_9(CE_CONT, "(%d): SubCode=%xh, " 2093 "wwnn=%02x%02x%02x%02x%02x%02x%02x%02x\n", 2094 ha->instance, cmd->SubCode, name[0], name[1], 2095 name[2], name[3], name[4], name[5], name[6], 2096 name[7]); 2097 tq = ql_find_port(ha, name, qlnt); 2098 } else if (fc_req->FCScsiAddr.DestType == 2099 EXT_DEF_DESTTYPE_PORTID) { 2100 qlnt = QLNT_PID; 2101 name = &fc_req->FCScsiAddr.DestAddr.Id[0]; 2102 QL_PRINT_9(CE_CONT, "(%d): SubCode=%xh, PID=" 2103 "%02x%02x%02x\n", ha->instance, cmd->SubCode, 2104 name[0], name[1], name[2]); 2105 tq = ql_find_port(ha, name, qlnt); 2106 } else { 2107 EL(ha, "failed, SubCode=%xh invalid DestType=%xh\n", 2108 cmd->SubCode, fc_req->FCScsiAddr.DestType); 2109 cmd->Status = EXT_STATUS_INVALID_PARAM; 2110 cmd->ResponseLen = 0; 2111 return; 2112 } 2113 scsi_req.lun = fc_req->FCScsiAddr.Lun; 2114 scsi_req.sense_length = sizeof (fc_req->SenseData); 2115 scsi_req.cdbp = &sp_req->Cdb[0]; 2116 scsi_req.cdb_len = sp_req->CdbLength; 2117 ufc_req = (EXT_FC_SCSI_PASSTHRU *)(uintptr_t)cmd->RequestAdr; 2118 scsi_req.u_sense = &ufc_req->SenseData[0]; 2119 scsi_req.direction = fc_req->Direction; 2120 } 2121 2122 if (tq == NULL || !VALID_TARGET_ID(ha, tq->loop_id)) { 2123 EL(ha, "failed, fc_port not found\n"); 2124 cmd->Status = EXT_STATUS_DEV_NOT_FOUND; 2125 cmd->ResponseLen = 0; 2126 return; 2127 } 2128 2129 if (tq->flags & TQF_NEED_AUTHENTICATION) { 2130 EL(ha, "target not available; loopid=%xh\n", tq->loop_id); 2131 cmd->Status = EXT_STATUS_DEVICE_OFFLINE; 2132 cmd->ResponseLen = 0; 2133 return; 2134 } 2135 2136 /* Allocate command block. */ 2137 if ((scsi_req.direction == EXT_DEF_SCSI_PASSTHRU_DATA_IN || 2138 scsi_req.direction == EXT_DEF_SCSI_PASSTHRU_DATA_OUT) && 2139 cmd->ResponseLen) { 2140 pld_size = cmd->ResponseLen; 2141 pkt_size = (uint32_t)(sizeof (ql_mbx_iocb_t) + pld_size); 2142 pkt = kmem_zalloc(pkt_size, KM_SLEEP); 2143 if (pkt == NULL) { 2144 EL(ha, "failed, kmem_zalloc\n"); 2145 cmd->Status = EXT_STATUS_NO_MEMORY; 2146 cmd->ResponseLen = 0; 2147 return; 2148 } 2149 pld = (caddr_t)pkt + sizeof (ql_mbx_iocb_t); 2150 2151 /* Get DMA memory for the IOCB */ 2152 if (ql_get_dma_mem(ha, dma_mem, pld_size, LITTLE_ENDIAN_DMA, 2153 QL_DMA_DATA_ALIGN) != QL_SUCCESS) { 2154 cmn_err(CE_WARN, "%s(%d): request queue DMA memory " 2155 "alloc failed", QL_NAME, ha->instance); 2156 kmem_free(pkt, pkt_size); 2157 cmd->Status = EXT_STATUS_MS_NO_RESPONSE; 2158 cmd->ResponseLen = 0; 2159 return; 2160 } 2161 2162 if (scsi_req.direction == EXT_DEF_SCSI_PASSTHRU_DATA_IN) { 2163 scsi_req.direction = (uint8_t) 2164 (CFG_IST(ha, CFG_CTRL_24258081) ? 2165 CF_RD : CF_DATA_IN | CF_STAG); 2166 } else { 2167 scsi_req.direction = (uint8_t) 2168 (CFG_IST(ha, CFG_CTRL_24258081) ? 2169 CF_WR : CF_DATA_OUT | CF_STAG); 2170 cmd->ResponseLen = 0; 2171 2172 /* Get command payload. */ 2173 if (ql_get_buffer_data( 2174 (caddr_t)(uintptr_t)cmd->ResponseAdr, 2175 pld, pld_size, mode) != pld_size) { 2176 EL(ha, "failed, get_buffer_data\n"); 2177 cmd->Status = EXT_STATUS_COPY_ERR; 2178 2179 kmem_free(pkt, pkt_size); 2180 ql_free_dma_resource(ha, dma_mem); 2181 kmem_free(dma_mem, sizeof (dma_mem_t)); 2182 return; 2183 } 2184 2185 /* Copy out going data to DMA buffer. */ 2186 ddi_rep_put8(dma_mem->acc_handle, (uint8_t *)pld, 2187 (uint8_t *)dma_mem->bp, pld_size, 2188 DDI_DEV_AUTOINCR); 2189 2190 /* Sync DMA buffer. */ 2191 (void) ddi_dma_sync(dma_mem->dma_handle, 0, 2192 dma_mem->size, DDI_DMA_SYNC_FORDEV); 2193 } 2194 } else { 2195 scsi_req.direction = (uint8_t) 2196 (CFG_IST(ha, CFG_CTRL_24258081) ? 0 : CF_STAG); 2197 cmd->ResponseLen = 0; 2198 2199 pkt_size = sizeof (ql_mbx_iocb_t); 2200 pkt = kmem_zalloc(pkt_size, KM_SLEEP); 2201 if (pkt == NULL) { 2202 EL(ha, "failed, kmem_zalloc-2\n"); 2203 cmd->Status = EXT_STATUS_NO_MEMORY; 2204 return; 2205 } 2206 pld = NULL; 2207 pld_size = 0; 2208 } 2209 2210 /* retries = ha->port_down_retry_count; */ 2211 retries = 1; 2212 cmd->Status = EXT_STATUS_OK; 2213 cmd->DetailStatus = EXT_DSTATUS_NOADNL_INFO; 2214 2215 QL_PRINT_9(CE_CONT, "(%d): SCSI cdb\n", ha->instance); 2216 QL_DUMP_9(scsi_req.cdbp, 8, scsi_req.cdb_len); 2217 2218 do { 2219 if (DRIVER_SUSPENDED(ha)) { 2220 sts.comp_status = CS_LOOP_DOWN_ABORT; 2221 break; 2222 } 2223 2224 if (CFG_IST(ha, CFG_CTRL_24258081)) { 2225 pkt->cmd24.entry_type = IOCB_CMD_TYPE_7; 2226 pkt->cmd24.entry_count = 1; 2227 2228 /* Set LUN number */ 2229 pkt->cmd24.fcp_lun[2] = LSB(scsi_req.lun); 2230 pkt->cmd24.fcp_lun[3] = MSB(scsi_req.lun); 2231 2232 /* Set N_port handle */ 2233 pkt->cmd24.n_port_hdl = (uint16_t)LE_16(tq->loop_id); 2234 2235 /* Set VP Index */ 2236 pkt->cmd24.vp_index = ha->vp_index; 2237 2238 /* Set target ID */ 2239 pkt->cmd24.target_id[0] = tq->d_id.b.al_pa; 2240 pkt->cmd24.target_id[1] = tq->d_id.b.area; 2241 pkt->cmd24.target_id[2] = tq->d_id.b.domain; 2242 2243 /* Set ISP command timeout. */ 2244 pkt->cmd24.timeout = (uint16_t)LE_16(15); 2245 2246 /* Load SCSI CDB */ 2247 ddi_rep_put8(ha->hba_buf.acc_handle, scsi_req.cdbp, 2248 pkt->cmd24.scsi_cdb, scsi_req.cdb_len, 2249 DDI_DEV_AUTOINCR); 2250 for (cnt = 0; cnt < MAX_CMDSZ; 2251 cnt = (uint16_t)(cnt + 4)) { 2252 ql_chg_endian((uint8_t *)&pkt->cmd24.scsi_cdb 2253 + cnt, 4); 2254 } 2255 2256 /* Set tag queue control flags */ 2257 pkt->cmd24.task = TA_STAG; 2258 2259 if (pld_size) { 2260 /* Set transfer direction. */ 2261 pkt->cmd24.control_flags = scsi_req.direction; 2262 2263 /* Set data segment count. */ 2264 pkt->cmd24.dseg_count = LE_16(1); 2265 2266 /* Load total byte count. */ 2267 pkt->cmd24.total_byte_count = LE_32(pld_size); 2268 2269 /* Load data descriptor. */ 2270 pkt->cmd24.dseg_0_address[0] = (uint32_t) 2271 LE_32(LSD(dma_mem->cookie.dmac_laddress)); 2272 pkt->cmd24.dseg_0_address[1] = (uint32_t) 2273 LE_32(MSD(dma_mem->cookie.dmac_laddress)); 2274 pkt->cmd24.dseg_0_length = LE_32(pld_size); 2275 } 2276 } else if (CFG_IST(ha, CFG_ENABLE_64BIT_ADDRESSING)) { 2277 pkt->cmd3.entry_type = IOCB_CMD_TYPE_3; 2278 pkt->cmd3.entry_count = 1; 2279 if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) { 2280 pkt->cmd3.target_l = LSB(tq->loop_id); 2281 pkt->cmd3.target_h = MSB(tq->loop_id); 2282 } else { 2283 pkt->cmd3.target_h = LSB(tq->loop_id); 2284 } 2285 pkt->cmd3.lun_l = LSB(scsi_req.lun); 2286 pkt->cmd3.lun_h = MSB(scsi_req.lun); 2287 pkt->cmd3.control_flags_l = scsi_req.direction; 2288 pkt->cmd3.timeout = LE_16(15); 2289 for (cnt = 0; cnt < scsi_req.cdb_len; cnt++) { 2290 pkt->cmd3.scsi_cdb[cnt] = scsi_req.cdbp[cnt]; 2291 } 2292 if (pld_size) { 2293 pkt->cmd3.dseg_count = LE_16(1); 2294 pkt->cmd3.byte_count = LE_32(pld_size); 2295 pkt->cmd3.dseg_0_address[0] = (uint32_t) 2296 LE_32(LSD(dma_mem->cookie.dmac_laddress)); 2297 pkt->cmd3.dseg_0_address[1] = (uint32_t) 2298 LE_32(MSD(dma_mem->cookie.dmac_laddress)); 2299 pkt->cmd3.dseg_0_length = LE_32(pld_size); 2300 } 2301 } else { 2302 pkt->cmd.entry_type = IOCB_CMD_TYPE_2; 2303 pkt->cmd.entry_count = 1; 2304 if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) { 2305 pkt->cmd.target_l = LSB(tq->loop_id); 2306 pkt->cmd.target_h = MSB(tq->loop_id); 2307 } else { 2308 pkt->cmd.target_h = LSB(tq->loop_id); 2309 } 2310 pkt->cmd.lun_l = LSB(scsi_req.lun); 2311 pkt->cmd.lun_h = MSB(scsi_req.lun); 2312 pkt->cmd.control_flags_l = scsi_req.direction; 2313 pkt->cmd.timeout = LE_16(15); 2314 for (cnt = 0; cnt < scsi_req.cdb_len; cnt++) { 2315 pkt->cmd.scsi_cdb[cnt] = scsi_req.cdbp[cnt]; 2316 } 2317 if (pld_size) { 2318 pkt->cmd.dseg_count = LE_16(1); 2319 pkt->cmd.byte_count = LE_32(pld_size); 2320 pkt->cmd.dseg_0_address = (uint32_t) 2321 LE_32(LSD(dma_mem->cookie.dmac_laddress)); 2322 pkt->cmd.dseg_0_length = LE_32(pld_size); 2323 } 2324 } 2325 /* Go issue command and wait for completion. */ 2326 QL_PRINT_9(CE_CONT, "(%d): request pkt\n", ha->instance); 2327 QL_DUMP_9(pkt, 8, pkt_size); 2328 2329 status = ql_issue_mbx_iocb(ha, (caddr_t)pkt, pkt_size); 2330 2331 if (pld_size) { 2332 /* Sync in coming DMA buffer. */ 2333 (void) ddi_dma_sync(dma_mem->dma_handle, 0, 2334 dma_mem->size, DDI_DMA_SYNC_FORKERNEL); 2335 /* Copy in coming DMA data. */ 2336 ddi_rep_get8(dma_mem->acc_handle, (uint8_t *)pld, 2337 (uint8_t *)dma_mem->bp, pld_size, 2338 DDI_DEV_AUTOINCR); 2339 } 2340 2341 if (CFG_IST(ha, CFG_CTRL_24258081)) { 2342 pkt->sts24.entry_status = (uint8_t) 2343 (pkt->sts24.entry_status & 0x3c); 2344 } else { 2345 pkt->sts.entry_status = (uint8_t) 2346 (pkt->sts.entry_status & 0x7e); 2347 } 2348 2349 if (status == QL_SUCCESS && pkt->sts.entry_status != 0) { 2350 EL(ha, "failed, entry_status=%xh, d_id=%xh\n", 2351 pkt->sts.entry_status, tq->d_id.b24); 2352 status = QL_FUNCTION_PARAMETER_ERROR; 2353 } 2354 2355 sts.comp_status = (uint16_t)(CFG_IST(ha, CFG_CTRL_24258081) ? 2356 LE_16(pkt->sts24.comp_status) : 2357 LE_16(pkt->sts.comp_status)); 2358 2359 /* 2360 * We have verified about all the request that can be so far. 2361 * Now we need to start verification of our ability to 2362 * actually issue the CDB. 2363 */ 2364 if (DRIVER_SUSPENDED(ha)) { 2365 sts.comp_status = CS_LOOP_DOWN_ABORT; 2366 break; 2367 } else if (status == QL_SUCCESS && 2368 (sts.comp_status == CS_PORT_LOGGED_OUT || 2369 sts.comp_status == CS_PORT_UNAVAILABLE)) { 2370 EL(ha, "login retry d_id=%xh\n", tq->d_id.b24); 2371 if (tq->flags & TQF_FABRIC_DEVICE) { 2372 rval = ql_login_fport(ha, tq, tq->loop_id, 2373 LFF_NO_PLOGI, &mr); 2374 if (rval != QL_SUCCESS) { 2375 EL(ha, "failed, login_fport=%xh, " 2376 "d_id=%xh\n", rval, tq->d_id.b24); 2377 } 2378 } else { 2379 rval = ql_login_lport(ha, tq, tq->loop_id, 2380 LLF_NONE); 2381 if (rval != QL_SUCCESS) { 2382 EL(ha, "failed, login_lport=%xh, " 2383 "d_id=%xh\n", rval, tq->d_id.b24); 2384 } 2385 } 2386 } else { 2387 break; 2388 } 2389 2390 bzero((caddr_t)pkt, sizeof (ql_mbx_iocb_t)); 2391 2392 } while (retries--); 2393 2394 if (sts.comp_status == CS_LOOP_DOWN_ABORT) { 2395 /* Cannot issue command now, maybe later */ 2396 EL(ha, "failed, suspended\n"); 2397 kmem_free(pkt, pkt_size); 2398 ql_free_dma_resource(ha, dma_mem); 2399 kmem_free(dma_mem, sizeof (dma_mem_t)); 2400 cmd->Status = EXT_STATUS_SUSPENDED; 2401 cmd->ResponseLen = 0; 2402 return; 2403 } 2404 2405 if (status != QL_SUCCESS) { 2406 /* Command error */ 2407 EL(ha, "failed, I/O\n"); 2408 kmem_free(pkt, pkt_size); 2409 ql_free_dma_resource(ha, dma_mem); 2410 kmem_free(dma_mem, sizeof (dma_mem_t)); 2411 cmd->Status = EXT_STATUS_ERR; 2412 cmd->DetailStatus = status; 2413 cmd->ResponseLen = 0; 2414 return; 2415 } 2416 2417 /* Setup status. */ 2418 if (CFG_IST(ha, CFG_CTRL_24258081)) { 2419 sts.scsi_status_l = pkt->sts24.scsi_status_l; 2420 sts.scsi_status_h = pkt->sts24.scsi_status_h; 2421 2422 /* Setup residuals. */ 2423 sts.residual_length = LE_32(pkt->sts24.residual_length); 2424 2425 /* Setup state flags. */ 2426 sts.state_flags_l = pkt->sts24.state_flags_l; 2427 sts.state_flags_h = pkt->sts24.state_flags_h; 2428 if (pld_size && sts.comp_status != CS_DATA_UNDERRUN) { 2429 sts.state_flags_h = (uint8_t)(sts.state_flags_h | 2430 SF_GOT_BUS | SF_GOT_TARGET | SF_SENT_CMD | 2431 SF_XFERRED_DATA | SF_GOT_STATUS); 2432 } else { 2433 sts.state_flags_h = (uint8_t)(sts.state_flags_h | 2434 SF_GOT_BUS | SF_GOT_TARGET | SF_SENT_CMD | 2435 SF_GOT_STATUS); 2436 } 2437 if (scsi_req.direction & CF_WR) { 2438 sts.state_flags_l = (uint8_t)(sts.state_flags_l | 2439 SF_DATA_OUT); 2440 } else if (scsi_req.direction & CF_RD) { 2441 sts.state_flags_l = (uint8_t)(sts.state_flags_l | 2442 SF_DATA_IN); 2443 } 2444 sts.state_flags_l = (uint8_t)(sts.state_flags_l | SF_SIMPLE_Q); 2445 2446 /* Setup FCP response info. */ 2447 sts.rsp_info_length = sts.scsi_status_h & FCP_RSP_LEN_VALID ? 2448 LE_32(pkt->sts24.fcp_rsp_data_length) : 0; 2449 sts.rsp_info = &pkt->sts24.rsp_sense_data[0]; 2450 for (cnt = 0; cnt < sts.rsp_info_length; 2451 cnt = (uint16_t)(cnt + 4)) { 2452 ql_chg_endian(sts.rsp_info + cnt, 4); 2453 } 2454 2455 /* Setup sense data. */ 2456 if (sts.scsi_status_h & FCP_SNS_LEN_VALID) { 2457 sts.req_sense_length = 2458 LE_32(pkt->sts24.fcp_sense_length); 2459 sts.state_flags_h = (uint8_t)(sts.state_flags_h | 2460 SF_ARQ_DONE); 2461 } else { 2462 sts.req_sense_length = 0; 2463 } 2464 sts.req_sense_data = 2465 &pkt->sts24.rsp_sense_data[sts.rsp_info_length]; 2466 cnt2 = (uint16_t)(((uintptr_t)pkt + sizeof (sts_24xx_entry_t)) - 2467 (uintptr_t)sts.req_sense_data); 2468 for (cnt = 0; cnt < cnt2; cnt = (uint16_t)(cnt + 4)) { 2469 ql_chg_endian(sts.req_sense_data + cnt, 4); 2470 } 2471 } else { 2472 sts.scsi_status_l = pkt->sts.scsi_status_l; 2473 sts.scsi_status_h = pkt->sts.scsi_status_h; 2474 2475 /* Setup residuals. */ 2476 sts.residual_length = LE_32(pkt->sts.residual_length); 2477 2478 /* Setup state flags. */ 2479 sts.state_flags_l = pkt->sts.state_flags_l; 2480 sts.state_flags_h = pkt->sts.state_flags_h; 2481 2482 /* Setup FCP response info. */ 2483 sts.rsp_info_length = sts.scsi_status_h & FCP_RSP_LEN_VALID ? 2484 LE_16(pkt->sts.rsp_info_length) : 0; 2485 sts.rsp_info = &pkt->sts.rsp_info[0]; 2486 2487 /* Setup sense data. */ 2488 sts.req_sense_length = sts.scsi_status_h & FCP_SNS_LEN_VALID ? 2489 LE_16(pkt->sts.req_sense_length) : 0; 2490 sts.req_sense_data = &pkt->sts.req_sense_data[0]; 2491 } 2492 2493 QL_PRINT_9(CE_CONT, "(%d): response pkt\n", ha->instance); 2494 QL_DUMP_9(&pkt->sts, 8, sizeof (sts_entry_t)); 2495 2496 switch (sts.comp_status) { 2497 case CS_INCOMPLETE: 2498 case CS_ABORTED: 2499 case CS_DEVICE_UNAVAILABLE: 2500 case CS_PORT_UNAVAILABLE: 2501 case CS_PORT_LOGGED_OUT: 2502 case CS_PORT_CONFIG_CHG: 2503 case CS_PORT_BUSY: 2504 case CS_LOOP_DOWN_ABORT: 2505 cmd->Status = EXT_STATUS_BUSY; 2506 break; 2507 case CS_RESET: 2508 case CS_QUEUE_FULL: 2509 cmd->Status = EXT_STATUS_ERR; 2510 break; 2511 case CS_TIMEOUT: 2512 cmd->Status = EXT_STATUS_ERR; 2513 break; 2514 case CS_DATA_OVERRUN: 2515 cmd->Status = EXT_STATUS_DATA_OVERRUN; 2516 break; 2517 case CS_DATA_UNDERRUN: 2518 cmd->Status = EXT_STATUS_DATA_UNDERRUN; 2519 break; 2520 } 2521 2522 /* 2523 * If non data transfer commands fix tranfer counts. 2524 */ 2525 if (scsi_req.cdbp[0] == SCMD_TEST_UNIT_READY || 2526 scsi_req.cdbp[0] == SCMD_REZERO_UNIT || 2527 scsi_req.cdbp[0] == SCMD_SEEK || 2528 scsi_req.cdbp[0] == SCMD_SEEK_G1 || 2529 scsi_req.cdbp[0] == SCMD_RESERVE || 2530 scsi_req.cdbp[0] == SCMD_RELEASE || 2531 scsi_req.cdbp[0] == SCMD_START_STOP || 2532 scsi_req.cdbp[0] == SCMD_DOORLOCK || 2533 scsi_req.cdbp[0] == SCMD_VERIFY || 2534 scsi_req.cdbp[0] == SCMD_WRITE_FILE_MARK || 2535 scsi_req.cdbp[0] == SCMD_VERIFY_G0 || 2536 scsi_req.cdbp[0] == SCMD_SPACE || 2537 scsi_req.cdbp[0] == SCMD_ERASE || 2538 (scsi_req.cdbp[0] == SCMD_FORMAT && 2539 (scsi_req.cdbp[1] & FPB_DATA) == 0)) { 2540 /* 2541 * Non data transfer command, clear sts_entry residual 2542 * length. 2543 */ 2544 sts.residual_length = 0; 2545 cmd->ResponseLen = 0; 2546 if (sts.comp_status == CS_DATA_UNDERRUN) { 2547 sts.comp_status = CS_COMPLETE; 2548 cmd->Status = EXT_STATUS_OK; 2549 } 2550 } else { 2551 cmd->ResponseLen = pld_size; 2552 } 2553 2554 /* Correct ISP completion status */ 2555 if (sts.comp_status == CS_COMPLETE && sts.scsi_status_l == 0 && 2556 (sts.scsi_status_h & FCP_RSP_MASK) == 0) { 2557 QL_PRINT_9(CE_CONT, "(%d): Correct completion\n", 2558 ha->instance); 2559 scsi_req.resid = 0; 2560 } else if (sts.comp_status == CS_DATA_UNDERRUN) { 2561 QL_PRINT_9(CE_CONT, "(%d): Correct UNDERRUN\n", 2562 ha->instance); 2563 scsi_req.resid = sts.residual_length; 2564 if (sts.scsi_status_h & FCP_RESID_UNDER) { 2565 cmd->Status = (uint32_t)EXT_STATUS_OK; 2566 2567 cmd->ResponseLen = (uint32_t) 2568 (pld_size - scsi_req.resid); 2569 } else { 2570 EL(ha, "failed, Transfer ERROR\n"); 2571 cmd->Status = EXT_STATUS_ERR; 2572 cmd->ResponseLen = 0; 2573 } 2574 } else { 2575 QL_PRINT_9(CE_CONT, "(%d): error d_id=%xh, comp_status=%xh, " 2576 "scsi_status_h=%xh, scsi_status_l=%xh\n", ha->instance, 2577 tq->d_id.b24, sts.comp_status, sts.scsi_status_h, 2578 sts.scsi_status_l); 2579 2580 scsi_req.resid = pld_size; 2581 /* 2582 * Handle residual count on SCSI check 2583 * condition. 2584 * 2585 * - If Residual Under / Over is set, use the 2586 * Residual Transfer Length field in IOCB. 2587 * - If Residual Under / Over is not set, and 2588 * Transferred Data bit is set in State Flags 2589 * field of IOCB, report residual value of 0 2590 * (you may want to do this for tape 2591 * Write-type commands only). This takes care 2592 * of logical end of tape problem and does 2593 * not break Unit Attention. 2594 * - If Residual Under / Over is not set, and 2595 * Transferred Data bit is not set in State 2596 * Flags, report residual value equal to 2597 * original data transfer length. 2598 */ 2599 if (sts.scsi_status_l & STATUS_CHECK) { 2600 cmd->Status = EXT_STATUS_SCSI_STATUS; 2601 cmd->DetailStatus = sts.scsi_status_l; 2602 if (sts.scsi_status_h & 2603 (FCP_RESID_OVER | FCP_RESID_UNDER)) { 2604 scsi_req.resid = sts.residual_length; 2605 } else if (sts.state_flags_h & 2606 STATE_XFERRED_DATA) { 2607 scsi_req.resid = 0; 2608 } 2609 } 2610 } 2611 2612 if (sts.scsi_status_l & STATUS_CHECK && 2613 sts.scsi_status_h & FCP_SNS_LEN_VALID && 2614 sts.req_sense_length) { 2615 /* 2616 * Check condition with vaild sense data flag set and sense 2617 * length != 0 2618 */ 2619 if (sts.req_sense_length > scsi_req.sense_length) { 2620 sense_sz = scsi_req.sense_length; 2621 } else { 2622 sense_sz = sts.req_sense_length; 2623 } 2624 2625 EL(ha, "failed, Check Condition Status, d_id=%xh\n", 2626 tq->d_id.b24); 2627 QL_DUMP_2(sts.req_sense_data, 8, sts.req_sense_length); 2628 2629 if (ddi_copyout(sts.req_sense_data, scsi_req.u_sense, 2630 (size_t)sense_sz, mode) != 0) { 2631 EL(ha, "failed, request sense ddi_copyout\n"); 2632 } 2633 2634 cmd->Status = EXT_STATUS_SCSI_STATUS; 2635 cmd->DetailStatus = sts.scsi_status_l; 2636 } 2637 2638 /* Copy response payload from DMA buffer to application. */ 2639 if (scsi_req.direction & (CF_RD | CF_DATA_IN) && 2640 cmd->ResponseLen != 0) { 2641 QL_PRINT_9(CE_CONT, "(%d): Data Return resid=%lu, " 2642 "byte_count=%u, ResponseLen=%xh\n", ha->instance, 2643 scsi_req.resid, pld_size, cmd->ResponseLen); 2644 QL_DUMP_9(pld, 8, cmd->ResponseLen); 2645 2646 /* Send response payload. */ 2647 if (ql_send_buffer_data(pld, 2648 (caddr_t)(uintptr_t)cmd->ResponseAdr, 2649 cmd->ResponseLen, mode) != cmd->ResponseLen) { 2650 EL(ha, "failed, send_buffer_data\n"); 2651 cmd->Status = EXT_STATUS_COPY_ERR; 2652 cmd->ResponseLen = 0; 2653 } 2654 } 2655 2656 if (cmd->Status != EXT_STATUS_OK) { 2657 EL(ha, "failed, cmd->Status=%xh, comp_status=%xh, " 2658 "d_id=%xh\n", cmd->Status, sts.comp_status, tq->d_id.b24); 2659 } else { 2660 /*EMPTY*/ 2661 QL_PRINT_9(CE_CONT, "(%d): done, ResponseLen=%d\n", 2662 ha->instance, cmd->ResponseLen); 2663 } 2664 2665 kmem_free(pkt, pkt_size); 2666 ql_free_dma_resource(ha, dma_mem); 2667 kmem_free(dma_mem, sizeof (dma_mem_t)); 2668 } 2669 2670 /* 2671 * ql_wwpn_to_scsiaddr 2672 * 2673 * Input: 2674 * ha: adapter state pointer. 2675 * cmd: EXT_IOCTL cmd struct pointer. 2676 * mode: flags. 2677 * 2678 * Context: 2679 * Kernel context. 2680 */ 2681 static void 2682 ql_wwpn_to_scsiaddr(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode) 2683 { 2684 int status; 2685 uint8_t wwpn[EXT_DEF_WWN_NAME_SIZE]; 2686 EXT_SCSI_ADDR *tmp_addr; 2687 ql_tgt_t *tq; 2688 2689 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 2690 2691 if (cmd->RequestLen != EXT_DEF_WWN_NAME_SIZE) { 2692 /* Return error */ 2693 EL(ha, "incorrect RequestLen\n"); 2694 cmd->Status = EXT_STATUS_INVALID_PARAM; 2695 cmd->DetailStatus = EXT_DSTATUS_REQUEST_LEN; 2696 return; 2697 } 2698 2699 status = ddi_copyin((void*)(uintptr_t)cmd->RequestAdr, wwpn, 2700 cmd->RequestLen, mode); 2701 2702 if (status != 0) { 2703 cmd->Status = EXT_STATUS_COPY_ERR; 2704 EL(ha, "failed, ddi_copyin\n"); 2705 return; 2706 } 2707 2708 tq = ql_find_port(ha, wwpn, QLNT_PORT); 2709 2710 if (tq == NULL || tq->flags & TQF_INITIATOR_DEVICE) { 2711 /* no matching device */ 2712 cmd->Status = EXT_STATUS_DEV_NOT_FOUND; 2713 EL(ha, "failed, device not found\n"); 2714 return; 2715 } 2716 2717 /* Copy out the IDs found. For now we can only return target ID. */ 2718 tmp_addr = (EXT_SCSI_ADDR *)(uintptr_t)cmd->ResponseAdr; 2719 2720 status = ddi_copyout((void *)wwpn, (void *)&tmp_addr->Target, 8, mode); 2721 2722 if (status != 0) { 2723 cmd->Status = EXT_STATUS_COPY_ERR; 2724 EL(ha, "failed, ddi_copyout\n"); 2725 } else { 2726 cmd->Status = EXT_STATUS_OK; 2727 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 2728 } 2729 } 2730 2731 /* 2732 * ql_host_idx 2733 * Gets host order index. 2734 * 2735 * Input: 2736 * ha: adapter state pointer. 2737 * cmd: EXT_IOCTL cmd struct pointer. 2738 * mode: flags. 2739 * 2740 * Returns: 2741 * None, request status indicated in cmd->Status. 2742 * 2743 * Context: 2744 * Kernel context. 2745 */ 2746 static void 2747 ql_host_idx(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode) 2748 { 2749 uint16_t idx; 2750 2751 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 2752 2753 if (cmd->ResponseLen < sizeof (uint16_t)) { 2754 cmd->Status = EXT_STATUS_BUFFER_TOO_SMALL; 2755 cmd->DetailStatus = sizeof (uint16_t); 2756 EL(ha, "failed, ResponseLen < Len=%xh\n", cmd->ResponseLen); 2757 cmd->ResponseLen = 0; 2758 return; 2759 } 2760 2761 idx = (uint16_t)ha->instance; 2762 2763 if (ddi_copyout((void *)&idx, (void *)(uintptr_t)(cmd->ResponseAdr), 2764 sizeof (uint16_t), mode) != 0) { 2765 cmd->Status = EXT_STATUS_COPY_ERR; 2766 cmd->ResponseLen = 0; 2767 EL(ha, "failed, ddi_copyout\n"); 2768 } else { 2769 cmd->ResponseLen = sizeof (uint16_t); 2770 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 2771 } 2772 } 2773 2774 /* 2775 * ql_host_drvname 2776 * Gets host driver name 2777 * 2778 * Input: 2779 * ha: adapter state pointer. 2780 * cmd: EXT_IOCTL cmd struct pointer. 2781 * mode: flags. 2782 * 2783 * Returns: 2784 * None, request status indicated in cmd->Status. 2785 * 2786 * Context: 2787 * Kernel context. 2788 */ 2789 static void 2790 ql_host_drvname(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode) 2791 { 2792 2793 char drvname[] = QL_NAME; 2794 uint32_t qlnamelen; 2795 2796 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 2797 2798 qlnamelen = (uint32_t)(strlen(QL_NAME)+1); 2799 2800 if (cmd->ResponseLen < qlnamelen) { 2801 cmd->Status = EXT_STATUS_BUFFER_TOO_SMALL; 2802 cmd->DetailStatus = qlnamelen; 2803 EL(ha, "failed, ResponseLen: %xh, needed: %xh\n", 2804 cmd->ResponseLen, qlnamelen); 2805 cmd->ResponseLen = 0; 2806 return; 2807 } 2808 2809 if (ddi_copyout((void *)&drvname, 2810 (void *)(uintptr_t)(cmd->ResponseAdr), 2811 qlnamelen, mode) != 0) { 2812 cmd->Status = EXT_STATUS_COPY_ERR; 2813 cmd->ResponseLen = 0; 2814 EL(ha, "failed, ddi_copyout\n"); 2815 } else { 2816 cmd->ResponseLen = qlnamelen-1; 2817 } 2818 2819 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 2820 } 2821 2822 /* 2823 * ql_read_nvram 2824 * Get NVRAM contents. 2825 * 2826 * Input: 2827 * ha: adapter state pointer. 2828 * cmd: EXT_IOCTL cmd struct pointer. 2829 * mode: flags. 2830 * 2831 * Returns: 2832 * None, request status indicated in cmd->Status. 2833 * 2834 * Context: 2835 * Kernel context. 2836 */ 2837 static void 2838 ql_read_nvram(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode) 2839 { 2840 2841 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 2842 2843 if (cmd->ResponseLen < ha->nvram_cache->size) { 2844 cmd->Status = EXT_STATUS_BUFFER_TOO_SMALL; 2845 cmd->DetailStatus = ha->nvram_cache->size; 2846 EL(ha, "failed, ResponseLen != NVRAM, Len=%xh\n", 2847 cmd->ResponseLen); 2848 cmd->ResponseLen = 0; 2849 return; 2850 } 2851 2852 /* Get NVRAM data. */ 2853 if (ql_nv_util_dump(ha, (void *)(uintptr_t)(cmd->ResponseAdr), 2854 mode) != 0) { 2855 cmd->Status = EXT_STATUS_COPY_ERR; 2856 cmd->ResponseLen = 0; 2857 EL(ha, "failed, copy error\n"); 2858 } else { 2859 cmd->ResponseLen = ha->nvram_cache->size; 2860 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 2861 } 2862 } 2863 2864 /* 2865 * ql_write_nvram 2866 * Loads NVRAM contents. 2867 * 2868 * Input: 2869 * ha: adapter state pointer. 2870 * cmd: EXT_IOCTL cmd struct pointer. 2871 * mode: flags. 2872 * 2873 * Returns: 2874 * None, request status indicated in cmd->Status. 2875 * 2876 * Context: 2877 * Kernel context. 2878 */ 2879 static void 2880 ql_write_nvram(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode) 2881 { 2882 2883 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 2884 2885 if (cmd->RequestLen < ha->nvram_cache->size) { 2886 cmd->Status = EXT_STATUS_BUFFER_TOO_SMALL; 2887 cmd->DetailStatus = ha->nvram_cache->size; 2888 EL(ha, "failed, RequestLen != NVRAM, Len=%xh\n", 2889 cmd->RequestLen); 2890 return; 2891 } 2892 2893 /* Load NVRAM data. */ 2894 if (ql_nv_util_load(ha, (void *)(uintptr_t)(cmd->RequestAdr), 2895 mode) != 0) { 2896 cmd->Status = EXT_STATUS_COPY_ERR; 2897 EL(ha, "failed, copy error\n"); 2898 } else { 2899 /*EMPTY*/ 2900 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 2901 } 2902 } 2903 2904 /* 2905 * ql_write_vpd 2906 * Loads VPD contents. 2907 * 2908 * Input: 2909 * ha: adapter state pointer. 2910 * cmd: EXT_IOCTL cmd struct pointer. 2911 * mode: flags. 2912 * 2913 * Returns: 2914 * None, request status indicated in cmd->Status. 2915 * 2916 * Context: 2917 * Kernel context. 2918 */ 2919 static void 2920 ql_write_vpd(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode) 2921 { 2922 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 2923 2924 int32_t rval = 0; 2925 2926 if ((CFG_IST(ha, CFG_CTRL_24258081)) == 0) { 2927 cmd->Status = EXT_STATUS_INVALID_REQUEST; 2928 EL(ha, "failed, invalid request for HBA\n"); 2929 return; 2930 } 2931 2932 if (cmd->RequestLen < QL_24XX_VPD_SIZE) { 2933 cmd->Status = EXT_STATUS_BUFFER_TOO_SMALL; 2934 cmd->DetailStatus = QL_24XX_VPD_SIZE; 2935 EL(ha, "failed, RequestLen != VPD len, len passed=%xh\n", 2936 cmd->RequestLen); 2937 return; 2938 } 2939 2940 /* Load VPD data. */ 2941 if ((rval = ql_vpd_load(ha, (void *)(uintptr_t)(cmd->RequestAdr), 2942 mode)) != 0) { 2943 cmd->Status = EXT_STATUS_COPY_ERR; 2944 cmd->DetailStatus = rval; 2945 EL(ha, "failed, errno=%x\n", rval); 2946 } else { 2947 /*EMPTY*/ 2948 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 2949 } 2950 } 2951 2952 /* 2953 * ql_read_vpd 2954 * Dumps VPD contents. 2955 * 2956 * Input: 2957 * ha: adapter state pointer. 2958 * cmd: EXT_IOCTL cmd struct pointer. 2959 * mode: flags. 2960 * 2961 * Returns: 2962 * None, request status indicated in cmd->Status. 2963 * 2964 * Context: 2965 * Kernel context. 2966 */ 2967 static void 2968 ql_read_vpd(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode) 2969 { 2970 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 2971 2972 if ((CFG_IST(ha, CFG_CTRL_24258081)) == 0) { 2973 cmd->Status = EXT_STATUS_INVALID_REQUEST; 2974 EL(ha, "failed, invalid request for HBA\n"); 2975 return; 2976 } 2977 2978 if (cmd->ResponseLen < QL_24XX_VPD_SIZE) { 2979 cmd->Status = EXT_STATUS_BUFFER_TOO_SMALL; 2980 cmd->DetailStatus = QL_24XX_VPD_SIZE; 2981 EL(ha, "failed, ResponseLen < VPD len, len passed=%xh\n", 2982 cmd->ResponseLen); 2983 return; 2984 } 2985 2986 /* Dump VPD data. */ 2987 if ((ql_vpd_dump(ha, (void *)(uintptr_t)(cmd->ResponseAdr), 2988 mode)) != 0) { 2989 cmd->Status = EXT_STATUS_COPY_ERR; 2990 EL(ha, "failed,\n"); 2991 } else { 2992 /*EMPTY*/ 2993 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 2994 } 2995 } 2996 2997 /* 2998 * ql_get_fcache 2999 * Dumps flash cache contents. 3000 * 3001 * Input: 3002 * ha: adapter state pointer. 3003 * cmd: EXT_IOCTL cmd struct pointer. 3004 * mode: flags. 3005 * 3006 * Returns: 3007 * None, request status indicated in cmd->Status. 3008 * 3009 * Context: 3010 * Kernel context. 3011 */ 3012 static void 3013 ql_get_fcache(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode) 3014 { 3015 uint32_t bsize, boff, types, cpsize, hsize; 3016 ql_fcache_t *fptr; 3017 3018 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 3019 3020 CACHE_LOCK(ha); 3021 3022 if (ha->fcache == NULL) { 3023 CACHE_UNLOCK(ha); 3024 cmd->Status = EXT_STATUS_ERR; 3025 EL(ha, "failed, adapter fcache not setup\n"); 3026 return; 3027 } 3028 3029 if ((CFG_IST(ha, CFG_CTRL_24258081)) == 0) { 3030 bsize = 100; 3031 } else { 3032 bsize = 400; 3033 } 3034 3035 if (cmd->ResponseLen < bsize) { 3036 CACHE_UNLOCK(ha); 3037 cmd->Status = EXT_STATUS_BUFFER_TOO_SMALL; 3038 cmd->DetailStatus = bsize; 3039 EL(ha, "failed, ResponseLen < %d, len passed=%xh\n", 3040 bsize, cmd->ResponseLen); 3041 return; 3042 } 3043 3044 boff = 0; 3045 bsize = 0; 3046 fptr = ha->fcache; 3047 3048 /* 3049 * For backwards compatibility, get one of each image type 3050 */ 3051 types = (FTYPE_BIOS | FTYPE_FCODE | FTYPE_EFI); 3052 while ((fptr != NULL) && (fptr->buf != NULL) && (types != 0)) { 3053 /* Get the next image */ 3054 if ((fptr = ql_get_fbuf(ha->fcache, types)) != NULL) { 3055 3056 cpsize = (fptr->buflen < 100 ? fptr->buflen : 100); 3057 3058 if (ddi_copyout(fptr->buf, 3059 (void *)(uintptr_t)(cmd->ResponseAdr + boff), 3060 cpsize, mode) != 0) { 3061 CACHE_UNLOCK(ha); 3062 EL(ha, "ddicopy failed, done\n"); 3063 cmd->Status = EXT_STATUS_COPY_ERR; 3064 cmd->DetailStatus = 0; 3065 return; 3066 } 3067 boff += 100; 3068 bsize += cpsize; 3069 types &= ~(fptr->type); 3070 } 3071 } 3072 3073 /* 3074 * Get the firmware image -- it needs to be last in the 3075 * buffer at offset 300 for backwards compatibility. Also for 3076 * backwards compatibility, the pci header is stripped off. 3077 */ 3078 if ((fptr = ql_get_fbuf(ha->fcache, FTYPE_FW)) != NULL) { 3079 3080 hsize = sizeof (pci_header_t) + sizeof (pci_data_t); 3081 if (hsize > fptr->buflen) { 3082 CACHE_UNLOCK(ha); 3083 EL(ha, "header size (%xh) exceeds buflen (%xh)\n", 3084 hsize, fptr->buflen); 3085 cmd->Status = EXT_STATUS_COPY_ERR; 3086 cmd->DetailStatus = 0; 3087 return; 3088 } 3089 3090 cpsize = ((fptr->buflen - hsize) < 100 ? 3091 fptr->buflen - hsize : 100); 3092 3093 if (ddi_copyout(fptr->buf+hsize, 3094 (void *)(uintptr_t)(cmd->ResponseAdr + 300), 3095 cpsize, mode) != 0) { 3096 CACHE_UNLOCK(ha); 3097 EL(ha, "fw ddicopy failed, done\n"); 3098 cmd->Status = EXT_STATUS_COPY_ERR; 3099 cmd->DetailStatus = 0; 3100 return; 3101 } 3102 bsize += 100; 3103 } 3104 3105 CACHE_UNLOCK(ha); 3106 cmd->Status = EXT_STATUS_OK; 3107 cmd->DetailStatus = bsize; 3108 3109 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 3110 } 3111 3112 /* 3113 * ql_get_fcache_ex 3114 * Dumps flash cache contents. 3115 * 3116 * Input: 3117 * ha: adapter state pointer. 3118 * cmd: EXT_IOCTL cmd struct pointer. 3119 * mode: flags. 3120 * 3121 * Returns: 3122 * None, request status indicated in cmd->Status. 3123 * 3124 * Context: 3125 * Kernel context. 3126 */ 3127 static void 3128 ql_get_fcache_ex(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode) 3129 { 3130 uint32_t bsize = 0; 3131 uint32_t boff = 0; 3132 ql_fcache_t *fptr; 3133 3134 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 3135 3136 CACHE_LOCK(ha); 3137 if (ha->fcache == NULL) { 3138 CACHE_UNLOCK(ha); 3139 cmd->Status = EXT_STATUS_ERR; 3140 EL(ha, "failed, adapter fcache not setup\n"); 3141 return; 3142 } 3143 3144 /* Make sure user passed enough buffer space */ 3145 for (fptr = ha->fcache; fptr != NULL; fptr = fptr->next) { 3146 bsize += FBUFSIZE; 3147 } 3148 3149 if (cmd->ResponseLen < bsize) { 3150 CACHE_UNLOCK(ha); 3151 if (cmd->ResponseLen != 0) { 3152 EL(ha, "failed, ResponseLen < %d, len passed=%xh\n", 3153 bsize, cmd->ResponseLen); 3154 } 3155 cmd->Status = EXT_STATUS_BUFFER_TOO_SMALL; 3156 cmd->DetailStatus = bsize; 3157 return; 3158 } 3159 3160 boff = 0; 3161 fptr = ha->fcache; 3162 while ((fptr != NULL) && (fptr->buf != NULL)) { 3163 /* Get the next image */ 3164 if (ddi_copyout(fptr->buf, 3165 (void *)(uintptr_t)(cmd->ResponseAdr + boff), 3166 (fptr->buflen < FBUFSIZE ? fptr->buflen : FBUFSIZE), 3167 mode) != 0) { 3168 CACHE_UNLOCK(ha); 3169 EL(ha, "failed, ddicopy at %xh, done\n", boff); 3170 cmd->Status = EXT_STATUS_COPY_ERR; 3171 cmd->DetailStatus = 0; 3172 return; 3173 } 3174 boff += FBUFSIZE; 3175 fptr = fptr->next; 3176 } 3177 3178 CACHE_UNLOCK(ha); 3179 cmd->Status = EXT_STATUS_OK; 3180 cmd->DetailStatus = bsize; 3181 3182 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 3183 } 3184 3185 /* 3186 * ql_read_flash 3187 * Get flash contents. 3188 * 3189 * Input: 3190 * ha: adapter state pointer. 3191 * cmd: EXT_IOCTL cmd struct pointer. 3192 * mode: flags. 3193 * 3194 * Returns: 3195 * None, request status indicated in cmd->Status. 3196 * 3197 * Context: 3198 * Kernel context. 3199 */ 3200 static void 3201 ql_read_flash(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode) 3202 { 3203 ql_xioctl_t *xp = ha->xioctl; 3204 3205 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 3206 3207 if (ql_stall_driver(ha, 0) != QL_SUCCESS) { 3208 EL(ha, "ql_stall_driver failed\n"); 3209 cmd->Status = EXT_STATUS_BUSY; 3210 cmd->DetailStatus = xp->fdesc.flash_size; 3211 cmd->ResponseLen = 0; 3212 return; 3213 } 3214 3215 if (ql_setup_fcache(ha) != QL_SUCCESS) { 3216 cmd->Status = EXT_STATUS_ERR; 3217 cmd->DetailStatus = xp->fdesc.flash_size; 3218 EL(ha, "failed, ResponseLen=%xh, flash size=%xh\n", 3219 cmd->ResponseLen, xp->fdesc.flash_size); 3220 cmd->ResponseLen = 0; 3221 } else { 3222 /* adjust read size to flash size */ 3223 if (cmd->ResponseLen > xp->fdesc.flash_size) { 3224 EL(ha, "adjusting req=%xh, max=%xh\n", 3225 cmd->ResponseLen, xp->fdesc.flash_size); 3226 cmd->ResponseLen = xp->fdesc.flash_size; 3227 } 3228 3229 /* Get flash data. */ 3230 if (ql_flash_fcode_dump(ha, 3231 (void *)(uintptr_t)(cmd->ResponseAdr), 3232 (size_t)(cmd->ResponseLen), 0, mode) != 0) { 3233 cmd->Status = EXT_STATUS_COPY_ERR; 3234 cmd->ResponseLen = 0; 3235 EL(ha, "failed,\n"); 3236 } 3237 } 3238 3239 /* Resume I/O */ 3240 if (CFG_IST(ha, CFG_CTRL_24258081)) { 3241 ql_restart_driver(ha); 3242 } else { 3243 EL(ha, "isp_abort_needed for restart\n"); 3244 ql_awaken_task_daemon(ha, NULL, ISP_ABORT_NEEDED, 3245 DRIVER_STALL); 3246 } 3247 3248 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 3249 } 3250 3251 /* 3252 * ql_write_flash 3253 * Loads flash contents. 3254 * 3255 * Input: 3256 * ha: adapter state pointer. 3257 * cmd: EXT_IOCTL cmd struct pointer. 3258 * mode: flags. 3259 * 3260 * Returns: 3261 * None, request status indicated in cmd->Status. 3262 * 3263 * Context: 3264 * Kernel context. 3265 */ 3266 static void 3267 ql_write_flash(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode) 3268 { 3269 ql_xioctl_t *xp = ha->xioctl; 3270 3271 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 3272 3273 if (ql_stall_driver(ha, 0) != QL_SUCCESS) { 3274 EL(ha, "ql_stall_driver failed\n"); 3275 cmd->Status = EXT_STATUS_BUSY; 3276 cmd->DetailStatus = xp->fdesc.flash_size; 3277 cmd->ResponseLen = 0; 3278 return; 3279 } 3280 3281 if (ql_setup_fcache(ha) != QL_SUCCESS) { 3282 cmd->Status = EXT_STATUS_ERR; 3283 cmd->DetailStatus = xp->fdesc.flash_size; 3284 EL(ha, "failed, RequestLen=%xh, size=%xh\n", 3285 cmd->RequestLen, xp->fdesc.flash_size); 3286 cmd->ResponseLen = 0; 3287 } else { 3288 /* Load flash data. */ 3289 if (cmd->RequestLen > xp->fdesc.flash_size) { 3290 cmd->Status = EXT_STATUS_ERR; 3291 cmd->DetailStatus = xp->fdesc.flash_size; 3292 EL(ha, "failed, RequestLen=%xh, flash size=%xh\n", 3293 cmd->RequestLen, xp->fdesc.flash_size); 3294 } else if (ql_flash_fcode_load(ha, 3295 (void *)(uintptr_t)(cmd->RequestAdr), 3296 (size_t)(cmd->RequestLen), mode) != 0) { 3297 cmd->Status = EXT_STATUS_COPY_ERR; 3298 EL(ha, "failed,\n"); 3299 } 3300 } 3301 3302 /* Resume I/O */ 3303 if (CFG_IST(ha, CFG_CTRL_24258081)) { 3304 ql_restart_driver(ha); 3305 } else { 3306 EL(ha, "isp_abort_needed for restart\n"); 3307 ql_awaken_task_daemon(ha, NULL, ISP_ABORT_NEEDED, 3308 DRIVER_STALL); 3309 } 3310 3311 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 3312 } 3313 3314 /* 3315 * ql_diagnostic_loopback 3316 * Performs EXT_CC_LOOPBACK Command 3317 * 3318 * Input: 3319 * ha: adapter state pointer. 3320 * cmd: Local EXT_IOCTL cmd struct pointer. 3321 * mode: flags. 3322 * 3323 * Returns: 3324 * None, request status indicated in cmd->Status. 3325 * 3326 * Context: 3327 * Kernel context. 3328 */ 3329 static void 3330 ql_diagnostic_loopback(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode) 3331 { 3332 EXT_LOOPBACK_REQ plbreq; 3333 EXT_LOOPBACK_RSP plbrsp; 3334 ql_mbx_data_t mr; 3335 uint32_t rval; 3336 caddr_t bp; 3337 uint16_t opt; 3338 3339 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 3340 3341 /* Get loop back request. */ 3342 if (ddi_copyin((void *)(uintptr_t)cmd->RequestAdr, 3343 (void *)&plbreq, sizeof (EXT_LOOPBACK_REQ), mode) != 0) { 3344 EL(ha, "failed, ddi_copyin\n"); 3345 cmd->Status = EXT_STATUS_COPY_ERR; 3346 cmd->ResponseLen = 0; 3347 return; 3348 } 3349 3350 opt = (uint16_t)(plbreq.Options & MBC_LOOPBACK_POINT_MASK); 3351 3352 /* Check transfer length fits in buffer. */ 3353 if (plbreq.BufferLength < plbreq.TransferCount && 3354 plbreq.TransferCount < MAILBOX_BUFFER_SIZE) { 3355 EL(ha, "failed, BufferLength=%d, xfercnt=%d, " 3356 "mailbox_buffer_size=%d\n", plbreq.BufferLength, 3357 plbreq.TransferCount, MAILBOX_BUFFER_SIZE); 3358 cmd->Status = EXT_STATUS_INVALID_PARAM; 3359 cmd->ResponseLen = 0; 3360 return; 3361 } 3362 3363 /* Allocate command memory. */ 3364 bp = kmem_zalloc(plbreq.TransferCount, KM_SLEEP); 3365 if (bp == NULL) { 3366 EL(ha, "failed, kmem_zalloc\n"); 3367 cmd->Status = EXT_STATUS_NO_MEMORY; 3368 cmd->ResponseLen = 0; 3369 return; 3370 } 3371 3372 /* Get loopback data. */ 3373 if (ql_get_buffer_data((caddr_t)(uintptr_t)plbreq.BufferAddress, 3374 bp, plbreq.TransferCount, mode) != plbreq.TransferCount) { 3375 EL(ha, "failed, ddi_copyin-2\n"); 3376 kmem_free(bp, plbreq.TransferCount); 3377 cmd->Status = EXT_STATUS_COPY_ERR; 3378 cmd->ResponseLen = 0; 3379 return; 3380 } 3381 3382 if ((ha->task_daemon_flags & (QL_LOOP_TRANSITION | DRIVER_STALL)) || 3383 ql_stall_driver(ha, 0) != QL_SUCCESS) { 3384 EL(ha, "failed, LOOP_NOT_READY\n"); 3385 kmem_free(bp, plbreq.TransferCount); 3386 cmd->Status = EXT_STATUS_BUSY; 3387 cmd->ResponseLen = 0; 3388 return; 3389 } 3390 3391 /* Shutdown IP. */ 3392 if (ha->flags & IP_INITIALIZED) { 3393 (void) ql_shutdown_ip(ha); 3394 } 3395 3396 /* determine topology so we can send the loopback or the echo */ 3397 /* Echo is supported on 2300's only and above */ 3398 3399 if (CFG_IST(ha, CFG_CTRL_8081)) { 3400 if (!(ha->task_daemon_flags & LOOP_DOWN) && opt == 3401 MBC_LOOPBACK_POINT_EXTERNAL) { 3402 if (plbreq.TransferCount > 252) { 3403 EL(ha, "transfer count (%d) > 252\n", 3404 plbreq.TransferCount); 3405 kmem_free(bp, plbreq.TransferCount); 3406 cmd->Status = EXT_STATUS_INVALID_PARAM; 3407 cmd->ResponseLen = 0; 3408 return; 3409 } 3410 plbrsp.CommandSent = INT_DEF_LB_ECHO_CMD; 3411 rval = ql_diag_echo(ha, 0, bp, plbreq.TransferCount, 3412 MBC_ECHO_ELS, &mr); 3413 } else { 3414 if (CFG_IST(ha, CFG_CTRL_81XX)) { 3415 (void) ql_set_loop_point(ha, opt); 3416 } 3417 plbrsp.CommandSent = INT_DEF_LB_LOOPBACK_CMD; 3418 rval = ql_diag_loopback(ha, 0, bp, plbreq.TransferCount, 3419 opt, plbreq.IterationCount, &mr); 3420 if (CFG_IST(ha, CFG_CTRL_81XX)) { 3421 (void) ql_set_loop_point(ha, 0); 3422 } 3423 } 3424 } else { 3425 if (!(ha->task_daemon_flags & LOOP_DOWN) && 3426 (ha->topology & QL_F_PORT) && 3427 ha->device_id >= 0x2300) { 3428 QL_PRINT_9(CE_CONT, "(%d): F_PORT topology -- using " 3429 "echo\n", ha->instance); 3430 plbrsp.CommandSent = INT_DEF_LB_ECHO_CMD; 3431 rval = ql_diag_echo(ha, 0, bp, plbreq.TransferCount, 3432 (uint16_t)(CFG_IST(ha, CFG_CTRL_8081) ? 3433 MBC_ECHO_ELS : MBC_ECHO_64BIT), &mr); 3434 } else { 3435 plbrsp.CommandSent = INT_DEF_LB_LOOPBACK_CMD; 3436 rval = ql_diag_loopback(ha, 0, bp, plbreq.TransferCount, 3437 opt, plbreq.IterationCount, &mr); 3438 } 3439 } 3440 3441 ql_restart_driver(ha); 3442 3443 /* Restart IP if it was shutdown. */ 3444 if (ha->flags & IP_ENABLED && !(ha->flags & IP_INITIALIZED)) { 3445 (void) ql_initialize_ip(ha); 3446 ql_isp_rcvbuf(ha); 3447 } 3448 3449 if (rval != QL_SUCCESS) { 3450 EL(ha, "failed, diagnostic_loopback_mbx=%xh\n", rval); 3451 kmem_free(bp, plbreq.TransferCount); 3452 cmd->Status = EXT_STATUS_MAILBOX; 3453 cmd->DetailStatus = rval; 3454 cmd->ResponseLen = 0; 3455 return; 3456 } 3457 3458 /* Return loopback data. */ 3459 if (ql_send_buffer_data(bp, (caddr_t)(uintptr_t)plbreq.BufferAddress, 3460 plbreq.TransferCount, mode) != plbreq.TransferCount) { 3461 EL(ha, "failed, ddi_copyout\n"); 3462 kmem_free(bp, plbreq.TransferCount); 3463 cmd->Status = EXT_STATUS_COPY_ERR; 3464 cmd->ResponseLen = 0; 3465 return; 3466 } 3467 kmem_free(bp, plbreq.TransferCount); 3468 3469 /* Return loopback results. */ 3470 plbrsp.BufferAddress = plbreq.BufferAddress; 3471 plbrsp.BufferLength = plbreq.TransferCount; 3472 plbrsp.CompletionStatus = mr.mb[0]; 3473 3474 if (plbrsp.CommandSent == INT_DEF_LB_ECHO_CMD) { 3475 plbrsp.CrcErrorCount = 0; 3476 plbrsp.DisparityErrorCount = 0; 3477 plbrsp.FrameLengthErrorCount = 0; 3478 plbrsp.IterationCountLastError = 0; 3479 } else { 3480 plbrsp.CrcErrorCount = mr.mb[1]; 3481 plbrsp.DisparityErrorCount = mr.mb[2]; 3482 plbrsp.FrameLengthErrorCount = mr.mb[3]; 3483 plbrsp.IterationCountLastError = (mr.mb[19] >> 16) | mr.mb[18]; 3484 } 3485 3486 rval = ddi_copyout((void *)&plbrsp, 3487 (void *)(uintptr_t)cmd->ResponseAdr, 3488 sizeof (EXT_LOOPBACK_RSP), mode); 3489 if (rval != 0) { 3490 EL(ha, "failed, ddi_copyout-2\n"); 3491 cmd->Status = EXT_STATUS_COPY_ERR; 3492 cmd->ResponseLen = 0; 3493 return; 3494 } 3495 cmd->ResponseLen = sizeof (EXT_LOOPBACK_RSP); 3496 3497 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 3498 } 3499 3500 /* 3501 * ql_set_loop_point 3502 * Setup loop point for port configuration. 3503 * 3504 * Input: 3505 * ha: adapter state structure. 3506 * opt: loop point option. 3507 * 3508 * Returns: 3509 * ql local function return status code. 3510 * 3511 * Context: 3512 * Kernel context. 3513 */ 3514 static int 3515 ql_set_loop_point(ql_adapter_state_t *ha, uint16_t opt) 3516 { 3517 ql_mbx_data_t mr; 3518 int rval; 3519 uint32_t timer; 3520 3521 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 3522 3523 /* 3524 * We get the current port config, modify the loopback field and 3525 * write it back out. 3526 */ 3527 if ((rval = ql_get_port_config(ha, &mr)) != QL_SUCCESS) { 3528 EL(ha, "get_port_config status=%xh\n", rval); 3529 return (rval); 3530 } 3531 /* 3532 * Set the loopback mode field while maintaining the others. 3533 * Currently only internal or none are supported. 3534 */ 3535 mr.mb[1] = (uint16_t)(mr.mb[1] &~LOOPBACK_MODE_FIELD_MASK); 3536 if (opt == MBC_LOOPBACK_POINT_INTERNAL) { 3537 mr.mb[1] = (uint16_t)(mr.mb[1] | 3538 LOOPBACK_MODE(LOOPBACK_MODE_INTERNAL)); 3539 } 3540 /* 3541 * Changing the port configuration will cause the port state to cycle 3542 * down and back up. The indication that this has happened is that 3543 * the point to point flag gets set. 3544 */ 3545 ADAPTER_STATE_LOCK(ha); 3546 ha->flags &= ~POINT_TO_POINT; 3547 ADAPTER_STATE_UNLOCK(ha); 3548 if ((rval = ql_set_port_config(ha, &mr)) != QL_SUCCESS) { 3549 EL(ha, "set_port_config status=%xh\n", rval); 3550 } 3551 3552 /* wait for a while */ 3553 for (timer = opt ? 10 : 0; timer; timer--) { 3554 if (ha->flags & POINT_TO_POINT) { 3555 break; 3556 } 3557 /* Delay for 1000000 usec (1 second). */ 3558 ql_delay(ha, 1000000); 3559 } 3560 3561 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 3562 3563 return (rval); 3564 } 3565 3566 /* 3567 * ql_send_els_rnid 3568 * IOCTL for extended link service RNID command. 3569 * 3570 * Input: 3571 * ha: adapter state pointer. 3572 * cmd: User space CT arguments pointer. 3573 * mode: flags. 3574 * 3575 * Returns: 3576 * None, request status indicated in cmd->Status. 3577 * 3578 * Context: 3579 * Kernel context. 3580 */ 3581 static void 3582 ql_send_els_rnid(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode) 3583 { 3584 EXT_RNID_REQ tmp_rnid; 3585 port_id_t tmp_fcid; 3586 caddr_t tmp_buf, bptr; 3587 uint32_t copy_len; 3588 ql_tgt_t *tq; 3589 EXT_RNID_DATA rnid_data; 3590 uint32_t loop_ready_wait = 10 * 60 * 10; 3591 int rval = 0; 3592 uint32_t local_hba = 0; 3593 3594 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 3595 3596 if (DRIVER_SUSPENDED(ha)) { 3597 EL(ha, "failed, LOOP_NOT_READY\n"); 3598 cmd->Status = EXT_STATUS_BUSY; 3599 cmd->ResponseLen = 0; 3600 return; 3601 } 3602 3603 if (cmd->RequestLen != sizeof (EXT_RNID_REQ)) { 3604 /* parameter error */ 3605 EL(ha, "failed, RequestLen < EXT_RNID_REQ, Len=%xh\n", 3606 cmd->RequestLen); 3607 cmd->Status = EXT_STATUS_INVALID_PARAM; 3608 cmd->DetailStatus = EXT_DSTATUS_REQUEST_LEN; 3609 cmd->ResponseLen = 0; 3610 return; 3611 } 3612 3613 if (ddi_copyin((void*)(uintptr_t)cmd->RequestAdr, 3614 &tmp_rnid, cmd->RequestLen, mode) != 0) { 3615 EL(ha, "failed, ddi_copyin\n"); 3616 cmd->Status = EXT_STATUS_COPY_ERR; 3617 cmd->ResponseLen = 0; 3618 return; 3619 } 3620 3621 /* Find loop ID of the device */ 3622 if (tmp_rnid.Addr.Type == EXT_DEF_TYPE_WWNN) { 3623 bptr = CFG_IST(ha, CFG_CTRL_24258081) ? 3624 (caddr_t)&ha->init_ctrl_blk.cb24.node_name : 3625 (caddr_t)&ha->init_ctrl_blk.cb.node_name; 3626 if (bcmp((void *)bptr, (void *)tmp_rnid.Addr.FcAddr.WWNN, 3627 EXT_DEF_WWN_NAME_SIZE) == 0) { 3628 local_hba = 1; 3629 } else { 3630 tq = ql_find_port(ha, 3631 (uint8_t *)tmp_rnid.Addr.FcAddr.WWNN, QLNT_NODE); 3632 } 3633 } else if (tmp_rnid.Addr.Type == EXT_DEF_TYPE_WWPN) { 3634 bptr = CFG_IST(ha, CFG_CTRL_24258081) ? 3635 (caddr_t)&ha->init_ctrl_blk.cb24.port_name : 3636 (caddr_t)&ha->init_ctrl_blk.cb.port_name; 3637 if (bcmp((void *)bptr, (void *)tmp_rnid.Addr.FcAddr.WWPN, 3638 EXT_DEF_WWN_NAME_SIZE) == 0) { 3639 local_hba = 1; 3640 } else { 3641 tq = ql_find_port(ha, 3642 (uint8_t *)tmp_rnid.Addr.FcAddr.WWPN, QLNT_PORT); 3643 } 3644 } else if (tmp_rnid.Addr.Type == EXT_DEF_TYPE_PORTID) { 3645 /* 3646 * Copy caller's d_id to tmp space. 3647 */ 3648 bcopy(&tmp_rnid.Addr.FcAddr.Id[1], tmp_fcid.r.d_id, 3649 EXT_DEF_PORTID_SIZE_ACTUAL); 3650 BIG_ENDIAN_24(&tmp_fcid.r.d_id[0]); 3651 3652 if (bcmp((void *)&ha->d_id, (void *)tmp_fcid.r.d_id, 3653 EXT_DEF_PORTID_SIZE_ACTUAL) == 0) { 3654 local_hba = 1; 3655 } else { 3656 tq = ql_find_port(ha, (uint8_t *)tmp_fcid.r.d_id, 3657 QLNT_PID); 3658 } 3659 } 3660 3661 /* Allocate memory for command. */ 3662 tmp_buf = kmem_zalloc(SEND_RNID_RSP_SIZE, KM_SLEEP); 3663 if (tmp_buf == NULL) { 3664 EL(ha, "failed, kmem_zalloc\n"); 3665 cmd->Status = EXT_STATUS_NO_MEMORY; 3666 cmd->ResponseLen = 0; 3667 return; 3668 } 3669 3670 if (local_hba) { 3671 rval = ql_get_rnid_params(ha, SEND_RNID_RSP_SIZE, tmp_buf); 3672 if (rval != QL_SUCCESS) { 3673 EL(ha, "failed, get_rnid_params_mbx=%xh\n", rval); 3674 kmem_free(tmp_buf, SEND_RNID_RSP_SIZE); 3675 cmd->Status = EXT_STATUS_ERR; 3676 cmd->ResponseLen = 0; 3677 return; 3678 } 3679 3680 /* Save gotten RNID data. */ 3681 bcopy(tmp_buf, &rnid_data, sizeof (EXT_RNID_DATA)); 3682 3683 /* Now build the Send RNID response */ 3684 tmp_buf[0] = (char)(EXT_DEF_RNID_DFORMAT_TOPO_DISC); 3685 tmp_buf[1] = (2 * EXT_DEF_WWN_NAME_SIZE); 3686 tmp_buf[2] = 0; 3687 tmp_buf[3] = sizeof (EXT_RNID_DATA); 3688 3689 if (CFG_IST(ha, CFG_CTRL_24258081)) { 3690 bcopy(ha->init_ctrl_blk.cb24.port_name, &tmp_buf[4], 3691 EXT_DEF_WWN_NAME_SIZE); 3692 bcopy(ha->init_ctrl_blk.cb24.node_name, 3693 &tmp_buf[4 + EXT_DEF_WWN_NAME_SIZE], 3694 EXT_DEF_WWN_NAME_SIZE); 3695 } else { 3696 bcopy(ha->init_ctrl_blk.cb.port_name, &tmp_buf[4], 3697 EXT_DEF_WWN_NAME_SIZE); 3698 bcopy(ha->init_ctrl_blk.cb.node_name, 3699 &tmp_buf[4 + EXT_DEF_WWN_NAME_SIZE], 3700 EXT_DEF_WWN_NAME_SIZE); 3701 } 3702 3703 bcopy((uint8_t *)&rnid_data, 3704 &tmp_buf[4 + 2 * EXT_DEF_WWN_NAME_SIZE], 3705 sizeof (EXT_RNID_DATA)); 3706 } else { 3707 if (tq == NULL) { 3708 /* no matching device */ 3709 EL(ha, "failed, device not found\n"); 3710 kmem_free(tmp_buf, SEND_RNID_RSP_SIZE); 3711 cmd->Status = EXT_STATUS_DEV_NOT_FOUND; 3712 cmd->DetailStatus = EXT_DSTATUS_TARGET; 3713 cmd->ResponseLen = 0; 3714 return; 3715 } 3716 3717 /* Send command */ 3718 rval = ql_send_rnid_els(ha, tq->loop_id, 3719 (uint8_t)tmp_rnid.DataFormat, SEND_RNID_RSP_SIZE, tmp_buf); 3720 if (rval != QL_SUCCESS) { 3721 EL(ha, "failed, send_rnid_mbx=%xh, id=%xh\n", 3722 rval, tq->loop_id); 3723 while (LOOP_NOT_READY(ha)) { 3724 ql_delay(ha, 100000); 3725 if (loop_ready_wait-- == 0) { 3726 EL(ha, "failed, loop not ready\n"); 3727 cmd->Status = EXT_STATUS_ERR; 3728 cmd->ResponseLen = 0; 3729 } 3730 } 3731 rval = ql_send_rnid_els(ha, tq->loop_id, 3732 (uint8_t)tmp_rnid.DataFormat, SEND_RNID_RSP_SIZE, 3733 tmp_buf); 3734 if (rval != QL_SUCCESS) { 3735 /* error */ 3736 EL(ha, "failed, send_rnid_mbx=%xh, id=%xh\n", 3737 rval, tq->loop_id); 3738 kmem_free(tmp_buf, SEND_RNID_RSP_SIZE); 3739 cmd->Status = EXT_STATUS_ERR; 3740 cmd->ResponseLen = 0; 3741 return; 3742 } 3743 } 3744 } 3745 3746 /* Copy the response */ 3747 copy_len = (cmd->ResponseLen > SEND_RNID_RSP_SIZE) ? 3748 SEND_RNID_RSP_SIZE : cmd->ResponseLen; 3749 3750 if (ql_send_buffer_data(tmp_buf, (caddr_t)(uintptr_t)cmd->ResponseAdr, 3751 copy_len, mode) != copy_len) { 3752 cmd->Status = EXT_STATUS_COPY_ERR; 3753 EL(ha, "failed, ddi_copyout\n"); 3754 } else { 3755 cmd->ResponseLen = copy_len; 3756 if (copy_len < SEND_RNID_RSP_SIZE) { 3757 cmd->Status = EXT_STATUS_DATA_OVERRUN; 3758 EL(ha, "failed, EXT_STATUS_DATA_OVERRUN\n"); 3759 3760 } else if (cmd->ResponseLen > SEND_RNID_RSP_SIZE) { 3761 cmd->Status = EXT_STATUS_DATA_UNDERRUN; 3762 EL(ha, "failed, EXT_STATUS_DATA_UNDERRUN\n"); 3763 } else { 3764 cmd->Status = EXT_STATUS_OK; 3765 QL_PRINT_9(CE_CONT, "(%d): done\n", 3766 ha->instance); 3767 } 3768 } 3769 3770 kmem_free(tmp_buf, SEND_RNID_RSP_SIZE); 3771 } 3772 3773 /* 3774 * ql_set_host_data 3775 * Process IOCTL subcommand to set host/adapter related data. 3776 * 3777 * Input: 3778 * ha: adapter state pointer. 3779 * cmd: User space CT arguments pointer. 3780 * mode: flags. 3781 * 3782 * Returns: 3783 * None, request status indicated in cmd->Status. 3784 * 3785 * Context: 3786 * Kernel context. 3787 */ 3788 static void 3789 ql_set_host_data(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode) 3790 { 3791 QL_PRINT_9(CE_CONT, "(%d): started, SubCode=%d\n", ha->instance, 3792 cmd->SubCode); 3793 3794 /* 3795 * case off on command subcode 3796 */ 3797 switch (cmd->SubCode) { 3798 case EXT_SC_SET_RNID: 3799 ql_set_rnid_parameters(ha, cmd, mode); 3800 break; 3801 case EXT_SC_RST_STATISTICS: 3802 (void) ql_reset_statistics(ha, cmd); 3803 break; 3804 case EXT_SC_SET_BEACON_STATE: 3805 ql_set_led_state(ha, cmd, mode); 3806 break; 3807 case EXT_SC_SET_PARMS: 3808 case EXT_SC_SET_BUS_MODE: 3809 case EXT_SC_SET_DR_DUMP_BUF: 3810 case EXT_SC_SET_RISC_CODE: 3811 case EXT_SC_SET_FLASH_RAM: 3812 case EXT_SC_SET_LUN_BITMASK: 3813 case EXT_SC_SET_RETRY_CNT: 3814 case EXT_SC_SET_RTIN: 3815 case EXT_SC_SET_FC_LUN_BITMASK: 3816 case EXT_SC_ADD_TARGET_DEVICE: 3817 case EXT_SC_SWAP_TARGET_DEVICE: 3818 case EXT_SC_SET_SEL_TIMEOUT: 3819 default: 3820 /* function not supported. */ 3821 EL(ha, "failed, function not supported=%d\n", cmd->SubCode); 3822 cmd->Status = EXT_STATUS_UNSUPPORTED_SUBCODE; 3823 break; 3824 } 3825 3826 if (cmd->Status != EXT_STATUS_OK) { 3827 EL(ha, "failed, Status=%d\n", cmd->Status); 3828 } else { 3829 /*EMPTY*/ 3830 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 3831 } 3832 } 3833 3834 /* 3835 * ql_get_host_data 3836 * Performs EXT_CC_GET_DATA subcommands. 3837 * 3838 * Input: 3839 * ha: adapter state pointer. 3840 * cmd: Local EXT_IOCTL cmd struct pointer. 3841 * mode: flags. 3842 * 3843 * Returns: 3844 * None, request status indicated in cmd->Status. 3845 * 3846 * Context: 3847 * Kernel context. 3848 */ 3849 static void 3850 ql_get_host_data(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode) 3851 { 3852 int out_size = 0; 3853 3854 QL_PRINT_9(CE_CONT, "(%d): started, SubCode=%d\n", ha->instance, 3855 cmd->SubCode); 3856 3857 /* case off on command subcode */ 3858 switch (cmd->SubCode) { 3859 case EXT_SC_GET_STATISTICS: 3860 out_size = sizeof (EXT_HBA_PORT_STAT); 3861 break; 3862 case EXT_SC_GET_FC_STATISTICS: 3863 out_size = sizeof (EXT_HBA_PORT_STAT); 3864 break; 3865 case EXT_SC_GET_PORT_SUMMARY: 3866 out_size = sizeof (EXT_DEVICEDATA); 3867 break; 3868 case EXT_SC_GET_RNID: 3869 out_size = sizeof (EXT_RNID_DATA); 3870 break; 3871 case EXT_SC_GET_TARGET_ID: 3872 out_size = sizeof (EXT_DEST_ADDR); 3873 break; 3874 case EXT_SC_GET_BEACON_STATE: 3875 out_size = sizeof (EXT_BEACON_CONTROL); 3876 break; 3877 case EXT_SC_GET_FC4_STATISTICS: 3878 out_size = sizeof (EXT_HBA_FC4STATISTICS); 3879 break; 3880 case EXT_SC_GET_DCBX_PARAM: 3881 out_size = EXT_DEF_DCBX_PARAM_BUF_SIZE; 3882 break; 3883 case EXT_SC_GET_RESOURCE_CNTS: 3884 out_size = sizeof (EXT_RESOURCE_CNTS); 3885 break; 3886 case EXT_SC_GET_FCF_LIST: 3887 out_size = sizeof (EXT_FCF_LIST); 3888 break; 3889 case EXT_SC_GET_SCSI_ADDR: 3890 case EXT_SC_GET_ERR_DETECTIONS: 3891 case EXT_SC_GET_BUS_MODE: 3892 case EXT_SC_GET_DR_DUMP_BUF: 3893 case EXT_SC_GET_RISC_CODE: 3894 case EXT_SC_GET_FLASH_RAM: 3895 case EXT_SC_GET_LINK_STATUS: 3896 case EXT_SC_GET_LOOP_ID: 3897 case EXT_SC_GET_LUN_BITMASK: 3898 case EXT_SC_GET_PORT_DATABASE: 3899 case EXT_SC_GET_PORT_DATABASE_MEM: 3900 case EXT_SC_GET_POSITION_MAP: 3901 case EXT_SC_GET_RETRY_CNT: 3902 case EXT_SC_GET_RTIN: 3903 case EXT_SC_GET_FC_LUN_BITMASK: 3904 case EXT_SC_GET_SEL_TIMEOUT: 3905 default: 3906 /* function not supported. */ 3907 EL(ha, "failed, function not supported=%d\n", cmd->SubCode); 3908 cmd->Status = EXT_STATUS_UNSUPPORTED_SUBCODE; 3909 cmd->ResponseLen = 0; 3910 return; 3911 } 3912 3913 if (cmd->ResponseLen < out_size) { 3914 cmd->Status = EXT_STATUS_BUFFER_TOO_SMALL; 3915 cmd->DetailStatus = out_size; 3916 EL(ha, "failed, ResponseLen=%xh, size=%xh\n", 3917 cmd->ResponseLen, out_size); 3918 cmd->ResponseLen = 0; 3919 return; 3920 } 3921 3922 switch (cmd->SubCode) { 3923 case EXT_SC_GET_RNID: 3924 ql_get_rnid_parameters(ha, cmd, mode); 3925 break; 3926 case EXT_SC_GET_STATISTICS: 3927 ql_get_statistics(ha, cmd, mode); 3928 break; 3929 case EXT_SC_GET_FC_STATISTICS: 3930 ql_get_statistics_fc(ha, cmd, mode); 3931 break; 3932 case EXT_SC_GET_FC4_STATISTICS: 3933 ql_get_statistics_fc4(ha, cmd, mode); 3934 break; 3935 case EXT_SC_GET_PORT_SUMMARY: 3936 ql_get_port_summary(ha, cmd, mode); 3937 break; 3938 case EXT_SC_GET_TARGET_ID: 3939 ql_get_target_id(ha, cmd, mode); 3940 break; 3941 case EXT_SC_GET_BEACON_STATE: 3942 ql_get_led_state(ha, cmd, mode); 3943 break; 3944 case EXT_SC_GET_DCBX_PARAM: 3945 ql_get_dcbx_parameters(ha, cmd, mode); 3946 break; 3947 case EXT_SC_GET_FCF_LIST: 3948 ql_get_fcf_list(ha, cmd, mode); 3949 break; 3950 case EXT_SC_GET_RESOURCE_CNTS: 3951 ql_get_resource_counts(ha, cmd, mode); 3952 break; 3953 } 3954 3955 if (cmd->Status != EXT_STATUS_OK) { 3956 EL(ha, "failed, Status=%d\n", cmd->Status); 3957 } else { 3958 /*EMPTY*/ 3959 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 3960 } 3961 } 3962 3963 /* ******************************************************************** */ 3964 /* Helper Functions */ 3965 /* ******************************************************************** */ 3966 3967 /* 3968 * ql_lun_count 3969 * Get numbers of LUNS on target. 3970 * 3971 * Input: 3972 * ha: adapter state pointer. 3973 * q: device queue pointer. 3974 * 3975 * Returns: 3976 * Number of LUNs. 3977 * 3978 * Context: 3979 * Kernel context. 3980 */ 3981 static int 3982 ql_lun_count(ql_adapter_state_t *ha, ql_tgt_t *tq) 3983 { 3984 int cnt; 3985 3986 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 3987 3988 /* Bypass LUNs that failed. */ 3989 cnt = ql_report_lun(ha, tq); 3990 if (cnt == 0) { 3991 cnt = ql_inq_scan(ha, tq, ha->maximum_luns_per_target); 3992 } 3993 3994 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 3995 3996 return (cnt); 3997 } 3998 3999 /* 4000 * ql_report_lun 4001 * Get numbers of LUNS using report LUN command. 4002 * 4003 * Input: 4004 * ha: adapter state pointer. 4005 * q: target queue pointer. 4006 * 4007 * Returns: 4008 * Number of LUNs. 4009 * 4010 * Context: 4011 * Kernel context. 4012 */ 4013 static int 4014 ql_report_lun(ql_adapter_state_t *ha, ql_tgt_t *tq) 4015 { 4016 int rval; 4017 uint8_t retries; 4018 ql_mbx_iocb_t *pkt; 4019 ql_rpt_lun_lst_t *rpt; 4020 dma_mem_t dma_mem; 4021 uint32_t pkt_size, cnt; 4022 uint16_t comp_status; 4023 uint8_t scsi_status_h, scsi_status_l, *reqs; 4024 4025 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 4026 4027 if (DRIVER_SUSPENDED(ha)) { 4028 EL(ha, "failed, LOOP_NOT_READY\n"); 4029 return (0); 4030 } 4031 4032 pkt_size = sizeof (ql_mbx_iocb_t) + sizeof (ql_rpt_lun_lst_t); 4033 pkt = kmem_zalloc(pkt_size, KM_SLEEP); 4034 if (pkt == NULL) { 4035 EL(ha, "failed, kmem_zalloc\n"); 4036 return (0); 4037 } 4038 rpt = (ql_rpt_lun_lst_t *)((caddr_t)pkt + sizeof (ql_mbx_iocb_t)); 4039 4040 /* Get DMA memory for the IOCB */ 4041 if (ql_get_dma_mem(ha, &dma_mem, sizeof (ql_rpt_lun_lst_t), 4042 LITTLE_ENDIAN_DMA, QL_DMA_RING_ALIGN) != QL_SUCCESS) { 4043 cmn_err(CE_WARN, "%s(%d): DMA memory " 4044 "alloc failed", QL_NAME, ha->instance); 4045 kmem_free(pkt, pkt_size); 4046 return (0); 4047 } 4048 4049 for (retries = 0; retries < 4; retries++) { 4050 if (CFG_IST(ha, CFG_CTRL_24258081)) { 4051 pkt->cmd24.entry_type = IOCB_CMD_TYPE_7; 4052 pkt->cmd24.entry_count = 1; 4053 4054 /* Set N_port handle */ 4055 pkt->cmd24.n_port_hdl = (uint16_t)LE_16(tq->loop_id); 4056 4057 /* Set target ID */ 4058 pkt->cmd24.target_id[0] = tq->d_id.b.al_pa; 4059 pkt->cmd24.target_id[1] = tq->d_id.b.area; 4060 pkt->cmd24.target_id[2] = tq->d_id.b.domain; 4061 4062 /* Set Virtual Port ID */ 4063 pkt->cmd24.vp_index = ha->vp_index; 4064 4065 /* Set ISP command timeout. */ 4066 pkt->cmd24.timeout = LE_16(15); 4067 4068 /* Load SCSI CDB */ 4069 pkt->cmd24.scsi_cdb[0] = SCMD_REPORT_LUNS; 4070 pkt->cmd24.scsi_cdb[6] = 4071 MSB(MSW(sizeof (ql_rpt_lun_lst_t))); 4072 pkt->cmd24.scsi_cdb[7] = 4073 LSB(MSW(sizeof (ql_rpt_lun_lst_t))); 4074 pkt->cmd24.scsi_cdb[8] = 4075 MSB(LSW(sizeof (ql_rpt_lun_lst_t))); 4076 pkt->cmd24.scsi_cdb[9] = 4077 LSB(LSW(sizeof (ql_rpt_lun_lst_t))); 4078 for (cnt = 0; cnt < MAX_CMDSZ; cnt += 4) { 4079 ql_chg_endian((uint8_t *)&pkt->cmd24.scsi_cdb 4080 + cnt, 4); 4081 } 4082 4083 /* Set tag queue control flags */ 4084 pkt->cmd24.task = TA_STAG; 4085 4086 /* Set transfer direction. */ 4087 pkt->cmd24.control_flags = CF_RD; 4088 4089 /* Set data segment count. */ 4090 pkt->cmd24.dseg_count = LE_16(1); 4091 4092 /* Load total byte count. */ 4093 /* Load data descriptor. */ 4094 pkt->cmd24.dseg_0_address[0] = (uint32_t) 4095 LE_32(LSD(dma_mem.cookie.dmac_laddress)); 4096 pkt->cmd24.dseg_0_address[1] = (uint32_t) 4097 LE_32(MSD(dma_mem.cookie.dmac_laddress)); 4098 pkt->cmd24.total_byte_count = 4099 LE_32(sizeof (ql_rpt_lun_lst_t)); 4100 pkt->cmd24.dseg_0_length = 4101 LE_32(sizeof (ql_rpt_lun_lst_t)); 4102 } else if (CFG_IST(ha, CFG_ENABLE_64BIT_ADDRESSING)) { 4103 pkt->cmd3.entry_type = IOCB_CMD_TYPE_3; 4104 pkt->cmd3.entry_count = 1; 4105 if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) { 4106 pkt->cmd3.target_l = LSB(tq->loop_id); 4107 pkt->cmd3.target_h = MSB(tq->loop_id); 4108 } else { 4109 pkt->cmd3.target_h = LSB(tq->loop_id); 4110 } 4111 pkt->cmd3.control_flags_l = CF_DATA_IN | CF_STAG; 4112 pkt->cmd3.timeout = LE_16(15); 4113 pkt->cmd3.dseg_count = LE_16(1); 4114 pkt->cmd3.scsi_cdb[0] = SCMD_REPORT_LUNS; 4115 pkt->cmd3.scsi_cdb[6] = 4116 MSB(MSW(sizeof (ql_rpt_lun_lst_t))); 4117 pkt->cmd3.scsi_cdb[7] = 4118 LSB(MSW(sizeof (ql_rpt_lun_lst_t))); 4119 pkt->cmd3.scsi_cdb[8] = 4120 MSB(LSW(sizeof (ql_rpt_lun_lst_t))); 4121 pkt->cmd3.scsi_cdb[9] = 4122 LSB(LSW(sizeof (ql_rpt_lun_lst_t))); 4123 pkt->cmd3.byte_count = 4124 LE_32(sizeof (ql_rpt_lun_lst_t)); 4125 pkt->cmd3.dseg_0_address[0] = (uint32_t) 4126 LE_32(LSD(dma_mem.cookie.dmac_laddress)); 4127 pkt->cmd3.dseg_0_address[1] = (uint32_t) 4128 LE_32(MSD(dma_mem.cookie.dmac_laddress)); 4129 pkt->cmd3.dseg_0_length = 4130 LE_32(sizeof (ql_rpt_lun_lst_t)); 4131 } else { 4132 pkt->cmd.entry_type = IOCB_CMD_TYPE_2; 4133 pkt->cmd.entry_count = 1; 4134 if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) { 4135 pkt->cmd.target_l = LSB(tq->loop_id); 4136 pkt->cmd.target_h = MSB(tq->loop_id); 4137 } else { 4138 pkt->cmd.target_h = LSB(tq->loop_id); 4139 } 4140 pkt->cmd.control_flags_l = CF_DATA_IN | CF_STAG; 4141 pkt->cmd.timeout = LE_16(15); 4142 pkt->cmd.dseg_count = LE_16(1); 4143 pkt->cmd.scsi_cdb[0] = SCMD_REPORT_LUNS; 4144 pkt->cmd.scsi_cdb[6] = 4145 MSB(MSW(sizeof (ql_rpt_lun_lst_t))); 4146 pkt->cmd.scsi_cdb[7] = 4147 LSB(MSW(sizeof (ql_rpt_lun_lst_t))); 4148 pkt->cmd.scsi_cdb[8] = 4149 MSB(LSW(sizeof (ql_rpt_lun_lst_t))); 4150 pkt->cmd.scsi_cdb[9] = 4151 LSB(LSW(sizeof (ql_rpt_lun_lst_t))); 4152 pkt->cmd.byte_count = 4153 LE_32(sizeof (ql_rpt_lun_lst_t)); 4154 pkt->cmd.dseg_0_address = (uint32_t) 4155 LE_32(LSD(dma_mem.cookie.dmac_laddress)); 4156 pkt->cmd.dseg_0_length = 4157 LE_32(sizeof (ql_rpt_lun_lst_t)); 4158 } 4159 4160 rval = ql_issue_mbx_iocb(ha, (caddr_t)pkt, 4161 sizeof (ql_mbx_iocb_t)); 4162 4163 /* Sync in coming DMA buffer. */ 4164 (void) ddi_dma_sync(dma_mem.dma_handle, 0, dma_mem.size, 4165 DDI_DMA_SYNC_FORKERNEL); 4166 /* Copy in coming DMA data. */ 4167 ddi_rep_get8(dma_mem.acc_handle, (uint8_t *)rpt, 4168 (uint8_t *)dma_mem.bp, dma_mem.size, DDI_DEV_AUTOINCR); 4169 4170 if (CFG_IST(ha, CFG_CTRL_24258081)) { 4171 pkt->sts24.entry_status = (uint8_t) 4172 (pkt->sts24.entry_status & 0x3c); 4173 comp_status = (uint16_t)LE_16(pkt->sts24.comp_status); 4174 scsi_status_h = pkt->sts24.scsi_status_h; 4175 scsi_status_l = pkt->sts24.scsi_status_l; 4176 cnt = scsi_status_h & FCP_RSP_LEN_VALID ? 4177 LE_32(pkt->sts24.fcp_rsp_data_length) : 0; 4178 reqs = &pkt->sts24.rsp_sense_data[cnt]; 4179 } else { 4180 pkt->sts.entry_status = (uint8_t) 4181 (pkt->sts.entry_status & 0x7e); 4182 comp_status = (uint16_t)LE_16(pkt->sts.comp_status); 4183 scsi_status_h = pkt->sts.scsi_status_h; 4184 scsi_status_l = pkt->sts.scsi_status_l; 4185 reqs = &pkt->sts.req_sense_data[0]; 4186 } 4187 if (rval == QL_SUCCESS && pkt->sts.entry_status != 0) { 4188 EL(ha, "failed, entry_status=%xh, d_id=%xh\n", 4189 pkt->sts.entry_status, tq->d_id.b24); 4190 rval = QL_FUNCTION_PARAMETER_ERROR; 4191 } 4192 4193 if (rval != QL_SUCCESS || comp_status != CS_COMPLETE || 4194 scsi_status_l & STATUS_CHECK) { 4195 /* Device underrun, treat as OK. */ 4196 if (rval == QL_SUCCESS && 4197 comp_status == CS_DATA_UNDERRUN && 4198 scsi_status_h & FCP_RESID_UNDER) { 4199 break; 4200 } 4201 4202 EL(ha, "failed, issue_iocb=%xh, d_id=%xh, cs=%xh, " 4203 "ss_h=%xh, ss_l=%xh\n", rval, tq->d_id.b24, 4204 comp_status, scsi_status_h, scsi_status_l); 4205 4206 if (rval == QL_SUCCESS) { 4207 if ((comp_status == CS_TIMEOUT) || 4208 (comp_status == CS_PORT_UNAVAILABLE) || 4209 (comp_status == CS_PORT_LOGGED_OUT)) { 4210 rval = QL_FUNCTION_TIMEOUT; 4211 break; 4212 } 4213 rval = QL_FUNCTION_FAILED; 4214 } else if (rval == QL_ABORTED) { 4215 break; 4216 } 4217 4218 if (scsi_status_l & STATUS_CHECK) { 4219 EL(ha, "STATUS_CHECK Sense Data\n%2xh%3xh" 4220 "%3xh%3xh%3xh%3xh%3xh%3xh%3xh%3xh%3xh" 4221 "%3xh%3xh%3xh%3xh%3xh%3xh%3xh\n", reqs[0], 4222 reqs[1], reqs[2], reqs[3], reqs[4], 4223 reqs[5], reqs[6], reqs[7], reqs[8], 4224 reqs[9], reqs[10], reqs[11], reqs[12], 4225 reqs[13], reqs[14], reqs[15], reqs[16], 4226 reqs[17]); 4227 } 4228 } else { 4229 break; 4230 } 4231 bzero((caddr_t)pkt, pkt_size); 4232 } 4233 4234 if (rval != QL_SUCCESS) { 4235 EL(ha, "failed=%xh\n", rval); 4236 rval = 0; 4237 } else { 4238 QL_PRINT_9(CE_CONT, "(%d): LUN list\n", ha->instance); 4239 QL_DUMP_9(rpt, 8, rpt->hdr.len + 8); 4240 rval = (int)(BE_32(rpt->hdr.len) / 8); 4241 } 4242 4243 kmem_free(pkt, pkt_size); 4244 ql_free_dma_resource(ha, &dma_mem); 4245 4246 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 4247 4248 return (rval); 4249 } 4250 4251 /* 4252 * ql_inq_scan 4253 * Get numbers of LUNS using inquiry command. 4254 * 4255 * Input: 4256 * ha: adapter state pointer. 4257 * tq: target queue pointer. 4258 * count: scan for the number of existing LUNs. 4259 * 4260 * Returns: 4261 * Number of LUNs. 4262 * 4263 * Context: 4264 * Kernel context. 4265 */ 4266 static int 4267 ql_inq_scan(ql_adapter_state_t *ha, ql_tgt_t *tq, int count) 4268 { 4269 int lun, cnt, rval; 4270 ql_mbx_iocb_t *pkt; 4271 uint8_t *inq; 4272 uint32_t pkt_size; 4273 4274 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 4275 4276 pkt_size = sizeof (ql_mbx_iocb_t) + INQ_DATA_SIZE; 4277 pkt = kmem_zalloc(pkt_size, KM_SLEEP); 4278 if (pkt == NULL) { 4279 EL(ha, "failed, kmem_zalloc\n"); 4280 return (0); 4281 } 4282 inq = (uint8_t *)((caddr_t)pkt + sizeof (ql_mbx_iocb_t)); 4283 4284 cnt = 0; 4285 for (lun = 0; lun < MAX_LUNS; lun++) { 4286 4287 if (DRIVER_SUSPENDED(ha)) { 4288 rval = QL_LOOP_DOWN; 4289 cnt = 0; 4290 break; 4291 } 4292 4293 rval = ql_inq(ha, tq, lun, pkt, INQ_DATA_SIZE); 4294 if (rval == QL_SUCCESS) { 4295 switch (*inq) { 4296 case DTYPE_DIRECT: 4297 case DTYPE_PROCESSOR: /* Appliance. */ 4298 case DTYPE_WORM: 4299 case DTYPE_RODIRECT: 4300 case DTYPE_SCANNER: 4301 case DTYPE_OPTICAL: 4302 case DTYPE_CHANGER: 4303 case DTYPE_ESI: 4304 cnt++; 4305 break; 4306 case DTYPE_SEQUENTIAL: 4307 cnt++; 4308 tq->flags |= TQF_TAPE_DEVICE; 4309 break; 4310 default: 4311 QL_PRINT_9(CE_CONT, "(%d): failed, " 4312 "unsupported device id=%xh, lun=%d, " 4313 "type=%xh\n", ha->instance, tq->loop_id, 4314 lun, *inq); 4315 break; 4316 } 4317 4318 if (*inq == DTYPE_ESI || cnt >= count) { 4319 break; 4320 } 4321 } else if (rval == QL_ABORTED || rval == QL_FUNCTION_TIMEOUT) { 4322 cnt = 0; 4323 break; 4324 } 4325 } 4326 4327 kmem_free(pkt, pkt_size); 4328 4329 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 4330 4331 return (cnt); 4332 } 4333 4334 /* 4335 * ql_inq 4336 * Issue inquiry command. 4337 * 4338 * Input: 4339 * ha: adapter state pointer. 4340 * tq: target queue pointer. 4341 * lun: LUN number. 4342 * pkt: command and buffer pointer. 4343 * inq_len: amount of inquiry data. 4344 * 4345 * Returns: 4346 * ql local function return status code. 4347 * 4348 * Context: 4349 * Kernel context. 4350 */ 4351 static int 4352 ql_inq(ql_adapter_state_t *ha, ql_tgt_t *tq, int lun, ql_mbx_iocb_t *pkt, 4353 uint8_t inq_len) 4354 { 4355 dma_mem_t dma_mem; 4356 int rval, retries; 4357 uint32_t pkt_size, cnt; 4358 uint16_t comp_status; 4359 uint8_t scsi_status_h, scsi_status_l, *reqs; 4360 caddr_t inq_data; 4361 4362 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 4363 4364 if (DRIVER_SUSPENDED(ha)) { 4365 EL(ha, "failed, loop down\n"); 4366 return (QL_FUNCTION_TIMEOUT); 4367 } 4368 4369 pkt_size = (uint32_t)(sizeof (ql_mbx_iocb_t) + inq_len); 4370 bzero((caddr_t)pkt, pkt_size); 4371 4372 inq_data = (caddr_t)pkt + sizeof (ql_mbx_iocb_t); 4373 4374 /* Get DMA memory for the IOCB */ 4375 if (ql_get_dma_mem(ha, &dma_mem, inq_len, 4376 LITTLE_ENDIAN_DMA, QL_DMA_RING_ALIGN) != QL_SUCCESS) { 4377 cmn_err(CE_WARN, "%s(%d): DMA memory " 4378 "alloc failed", QL_NAME, ha->instance); 4379 return (0); 4380 } 4381 4382 for (retries = 0; retries < 4; retries++) { 4383 if (CFG_IST(ha, CFG_CTRL_24258081)) { 4384 pkt->cmd24.entry_type = IOCB_CMD_TYPE_7; 4385 pkt->cmd24.entry_count = 1; 4386 4387 /* Set LUN number */ 4388 pkt->cmd24.fcp_lun[2] = LSB(lun); 4389 pkt->cmd24.fcp_lun[3] = MSB(lun); 4390 4391 /* Set N_port handle */ 4392 pkt->cmd24.n_port_hdl = (uint16_t)LE_16(tq->loop_id); 4393 4394 /* Set target ID */ 4395 pkt->cmd24.target_id[0] = tq->d_id.b.al_pa; 4396 pkt->cmd24.target_id[1] = tq->d_id.b.area; 4397 pkt->cmd24.target_id[2] = tq->d_id.b.domain; 4398 4399 /* Set Virtual Port ID */ 4400 pkt->cmd24.vp_index = ha->vp_index; 4401 4402 /* Set ISP command timeout. */ 4403 pkt->cmd24.timeout = LE_16(15); 4404 4405 /* Load SCSI CDB */ 4406 pkt->cmd24.scsi_cdb[0] = SCMD_INQUIRY; 4407 pkt->cmd24.scsi_cdb[4] = inq_len; 4408 for (cnt = 0; cnt < MAX_CMDSZ; cnt += 4) { 4409 ql_chg_endian((uint8_t *)&pkt->cmd24.scsi_cdb 4410 + cnt, 4); 4411 } 4412 4413 /* Set tag queue control flags */ 4414 pkt->cmd24.task = TA_STAG; 4415 4416 /* Set transfer direction. */ 4417 pkt->cmd24.control_flags = CF_RD; 4418 4419 /* Set data segment count. */ 4420 pkt->cmd24.dseg_count = LE_16(1); 4421 4422 /* Load total byte count. */ 4423 pkt->cmd24.total_byte_count = LE_32(inq_len); 4424 4425 /* Load data descriptor. */ 4426 pkt->cmd24.dseg_0_address[0] = (uint32_t) 4427 LE_32(LSD(dma_mem.cookie.dmac_laddress)); 4428 pkt->cmd24.dseg_0_address[1] = (uint32_t) 4429 LE_32(MSD(dma_mem.cookie.dmac_laddress)); 4430 pkt->cmd24.dseg_0_length = LE_32(inq_len); 4431 } else if (CFG_IST(ha, CFG_ENABLE_64BIT_ADDRESSING)) { 4432 pkt->cmd3.entry_type = IOCB_CMD_TYPE_3; 4433 cnt = CMD_TYPE_3_DATA_SEGMENTS; 4434 4435 pkt->cmd3.entry_count = 1; 4436 if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) { 4437 pkt->cmd3.target_l = LSB(tq->loop_id); 4438 pkt->cmd3.target_h = MSB(tq->loop_id); 4439 } else { 4440 pkt->cmd3.target_h = LSB(tq->loop_id); 4441 } 4442 pkt->cmd3.lun_l = LSB(lun); 4443 pkt->cmd3.lun_h = MSB(lun); 4444 pkt->cmd3.control_flags_l = CF_DATA_IN | CF_STAG; 4445 pkt->cmd3.timeout = LE_16(15); 4446 pkt->cmd3.scsi_cdb[0] = SCMD_INQUIRY; 4447 pkt->cmd3.scsi_cdb[4] = inq_len; 4448 pkt->cmd3.dseg_count = LE_16(1); 4449 pkt->cmd3.byte_count = LE_32(inq_len); 4450 pkt->cmd3.dseg_0_address[0] = (uint32_t) 4451 LE_32(LSD(dma_mem.cookie.dmac_laddress)); 4452 pkt->cmd3.dseg_0_address[1] = (uint32_t) 4453 LE_32(MSD(dma_mem.cookie.dmac_laddress)); 4454 pkt->cmd3.dseg_0_length = LE_32(inq_len); 4455 } else { 4456 pkt->cmd.entry_type = IOCB_CMD_TYPE_2; 4457 cnt = CMD_TYPE_2_DATA_SEGMENTS; 4458 4459 pkt->cmd.entry_count = 1; 4460 if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) { 4461 pkt->cmd.target_l = LSB(tq->loop_id); 4462 pkt->cmd.target_h = MSB(tq->loop_id); 4463 } else { 4464 pkt->cmd.target_h = LSB(tq->loop_id); 4465 } 4466 pkt->cmd.lun_l = LSB(lun); 4467 pkt->cmd.lun_h = MSB(lun); 4468 pkt->cmd.control_flags_l = CF_DATA_IN | CF_STAG; 4469 pkt->cmd.timeout = LE_16(15); 4470 pkt->cmd.scsi_cdb[0] = SCMD_INQUIRY; 4471 pkt->cmd.scsi_cdb[4] = inq_len; 4472 pkt->cmd.dseg_count = LE_16(1); 4473 pkt->cmd.byte_count = LE_32(inq_len); 4474 pkt->cmd.dseg_0_address = (uint32_t) 4475 LE_32(LSD(dma_mem.cookie.dmac_laddress)); 4476 pkt->cmd.dseg_0_length = LE_32(inq_len); 4477 } 4478 4479 /* rval = ql_issue_mbx_iocb(ha, (caddr_t)pkt, pkt_size); */ 4480 rval = ql_issue_mbx_iocb(ha, (caddr_t)pkt, 4481 sizeof (ql_mbx_iocb_t)); 4482 4483 /* Sync in coming IOCB DMA buffer. */ 4484 (void) ddi_dma_sync(dma_mem.dma_handle, 0, dma_mem.size, 4485 DDI_DMA_SYNC_FORKERNEL); 4486 /* Copy in coming DMA data. */ 4487 ddi_rep_get8(dma_mem.acc_handle, (uint8_t *)inq_data, 4488 (uint8_t *)dma_mem.bp, dma_mem.size, DDI_DEV_AUTOINCR); 4489 4490 if (CFG_IST(ha, CFG_CTRL_24258081)) { 4491 pkt->sts24.entry_status = (uint8_t) 4492 (pkt->sts24.entry_status & 0x3c); 4493 comp_status = (uint16_t)LE_16(pkt->sts24.comp_status); 4494 scsi_status_h = pkt->sts24.scsi_status_h; 4495 scsi_status_l = pkt->sts24.scsi_status_l; 4496 cnt = scsi_status_h & FCP_RSP_LEN_VALID ? 4497 LE_32(pkt->sts24.fcp_rsp_data_length) : 0; 4498 reqs = &pkt->sts24.rsp_sense_data[cnt]; 4499 } else { 4500 pkt->sts.entry_status = (uint8_t) 4501 (pkt->sts.entry_status & 0x7e); 4502 comp_status = (uint16_t)LE_16(pkt->sts.comp_status); 4503 scsi_status_h = pkt->sts.scsi_status_h; 4504 scsi_status_l = pkt->sts.scsi_status_l; 4505 reqs = &pkt->sts.req_sense_data[0]; 4506 } 4507 if (rval == QL_SUCCESS && pkt->sts.entry_status != 0) { 4508 EL(ha, "failed, entry_status=%xh, d_id=%xh\n", 4509 pkt->sts.entry_status, tq->d_id.b24); 4510 rval = QL_FUNCTION_PARAMETER_ERROR; 4511 } 4512 4513 if (rval != QL_SUCCESS || comp_status != CS_COMPLETE || 4514 scsi_status_l & STATUS_CHECK) { 4515 EL(ha, "failed, issue_iocb=%xh, d_id=%xh, cs=%xh, " 4516 "ss_h=%xh, ss_l=%xh\n", rval, tq->d_id.b24, 4517 comp_status, scsi_status_h, scsi_status_l); 4518 4519 if (rval == QL_SUCCESS) { 4520 if ((comp_status == CS_TIMEOUT) || 4521 (comp_status == CS_PORT_UNAVAILABLE) || 4522 (comp_status == CS_PORT_LOGGED_OUT)) { 4523 rval = QL_FUNCTION_TIMEOUT; 4524 break; 4525 } 4526 rval = QL_FUNCTION_FAILED; 4527 } 4528 4529 if (scsi_status_l & STATUS_CHECK) { 4530 EL(ha, "STATUS_CHECK Sense Data\n%2xh%3xh" 4531 "%3xh%3xh%3xh%3xh%3xh%3xh%3xh%3xh%3xh" 4532 "%3xh%3xh%3xh%3xh%3xh%3xh%3xh\n", reqs[0], 4533 reqs[1], reqs[2], reqs[3], reqs[4], 4534 reqs[5], reqs[6], reqs[7], reqs[8], 4535 reqs[9], reqs[10], reqs[11], reqs[12], 4536 reqs[13], reqs[14], reqs[15], reqs[16], 4537 reqs[17]); 4538 } 4539 } else { 4540 break; 4541 } 4542 } 4543 ql_free_dma_resource(ha, &dma_mem); 4544 4545 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 4546 4547 return (rval); 4548 } 4549 4550 /* 4551 * ql_get_buffer_data 4552 * Copies data from user space to kernal buffer. 4553 * 4554 * Input: 4555 * src: User source buffer address. 4556 * dst: Kernal destination buffer address. 4557 * size: Amount of data. 4558 * mode: flags. 4559 * 4560 * Returns: 4561 * Returns number of bytes transferred. 4562 * 4563 * Context: 4564 * Kernel context. 4565 */ 4566 static uint32_t 4567 ql_get_buffer_data(caddr_t src, caddr_t dst, uint32_t size, int mode) 4568 { 4569 uint32_t cnt; 4570 4571 for (cnt = 0; cnt < size; cnt++) { 4572 if (ddi_copyin(src++, dst++, 1, mode) != 0) { 4573 QL_PRINT_2(CE_CONT, "failed, ddi_copyin\n"); 4574 break; 4575 } 4576 } 4577 4578 return (cnt); 4579 } 4580 4581 /* 4582 * ql_send_buffer_data 4583 * Copies data from kernal buffer to user space. 4584 * 4585 * Input: 4586 * src: Kernal source buffer address. 4587 * dst: User destination buffer address. 4588 * size: Amount of data. 4589 * mode: flags. 4590 * 4591 * Returns: 4592 * Returns number of bytes transferred. 4593 * 4594 * Context: 4595 * Kernel context. 4596 */ 4597 static uint32_t 4598 ql_send_buffer_data(caddr_t src, caddr_t dst, uint32_t size, int mode) 4599 { 4600 uint32_t cnt; 4601 4602 for (cnt = 0; cnt < size; cnt++) { 4603 if (ddi_copyout(src++, dst++, 1, mode) != 0) { 4604 QL_PRINT_2(CE_CONT, "failed, ddi_copyin\n"); 4605 break; 4606 } 4607 } 4608 4609 return (cnt); 4610 } 4611 4612 /* 4613 * ql_find_port 4614 * Locates device queue. 4615 * 4616 * Input: 4617 * ha: adapter state pointer. 4618 * name: device port name. 4619 * 4620 * Returns: 4621 * Returns target queue pointer. 4622 * 4623 * Context: 4624 * Kernel context. 4625 */ 4626 static ql_tgt_t * 4627 ql_find_port(ql_adapter_state_t *ha, uint8_t *name, uint16_t type) 4628 { 4629 ql_link_t *link; 4630 ql_tgt_t *tq; 4631 uint16_t index; 4632 4633 /* Scan port list for requested target */ 4634 for (index = 0; index < DEVICE_HEAD_LIST_SIZE; index++) { 4635 for (link = ha->dev[index].first; link != NULL; 4636 link = link->next) { 4637 tq = link->base_address; 4638 4639 switch (type) { 4640 case QLNT_LOOP_ID: 4641 if (bcmp(name, &tq->loop_id, 4642 sizeof (uint16_t)) == 0) { 4643 return (tq); 4644 } 4645 break; 4646 case QLNT_PORT: 4647 if (bcmp(name, tq->port_name, 8) == 0) { 4648 return (tq); 4649 } 4650 break; 4651 case QLNT_NODE: 4652 if (bcmp(name, tq->node_name, 8) == 0) { 4653 return (tq); 4654 } 4655 break; 4656 case QLNT_PID: 4657 if (bcmp(name, tq->d_id.r.d_id, 4658 sizeof (tq->d_id.r.d_id)) == 0) { 4659 return (tq); 4660 } 4661 break; 4662 default: 4663 EL(ha, "failed, invalid type=%d\n", type); 4664 return (NULL); 4665 } 4666 } 4667 } 4668 4669 return (NULL); 4670 } 4671 4672 /* 4673 * ql_24xx_flash_desc 4674 * Get flash descriptor table. 4675 * 4676 * Input: 4677 * ha: adapter state pointer. 4678 * 4679 * Returns: 4680 * ql local function return status code. 4681 * 4682 * Context: 4683 * Kernel context. 4684 */ 4685 static int 4686 ql_24xx_flash_desc(ql_adapter_state_t *ha) 4687 { 4688 uint32_t cnt; 4689 uint16_t chksum, *bp, data; 4690 int rval; 4691 flash_desc_t *fdesc; 4692 ql_xioctl_t *xp = ha->xioctl; 4693 4694 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 4695 4696 if (ha->flash_desc_addr == 0) { 4697 QL_PRINT_9(CE_CONT, "(%d): desc ptr=0\n", ha->instance); 4698 return (QL_FUNCTION_FAILED); 4699 } 4700 4701 if ((fdesc = kmem_zalloc(sizeof (flash_desc_t), KM_SLEEP)) == NULL) { 4702 EL(ha, "kmem_zalloc=null\n"); 4703 return (QL_MEMORY_ALLOC_FAILED); 4704 } 4705 rval = ql_dump_fcode(ha, (uint8_t *)fdesc, sizeof (flash_desc_t), 4706 ha->flash_desc_addr << 2); 4707 if (rval != QL_SUCCESS) { 4708 EL(ha, "read status=%xh\n", rval); 4709 kmem_free(fdesc, sizeof (flash_desc_t)); 4710 return (rval); 4711 } 4712 4713 chksum = 0; 4714 bp = (uint16_t *)fdesc; 4715 for (cnt = 0; cnt < (sizeof (flash_desc_t)) / 2; cnt++) { 4716 data = *bp++; 4717 LITTLE_ENDIAN_16(&data); 4718 chksum += data; 4719 } 4720 4721 LITTLE_ENDIAN_32(&fdesc->flash_valid); 4722 LITTLE_ENDIAN_16(&fdesc->flash_version); 4723 LITTLE_ENDIAN_16(&fdesc->flash_len); 4724 LITTLE_ENDIAN_16(&fdesc->flash_checksum); 4725 LITTLE_ENDIAN_16(&fdesc->flash_manuf); 4726 LITTLE_ENDIAN_16(&fdesc->flash_id); 4727 LITTLE_ENDIAN_32(&fdesc->block_size); 4728 LITTLE_ENDIAN_32(&fdesc->alt_block_size); 4729 LITTLE_ENDIAN_32(&fdesc->flash_size); 4730 LITTLE_ENDIAN_32(&fdesc->write_enable_data); 4731 LITTLE_ENDIAN_32(&fdesc->read_timeout); 4732 4733 /* flash size in desc table is in 1024 bytes */ 4734 fdesc->flash_size = fdesc->flash_size * 0x400; 4735 4736 if (chksum != 0 || fdesc->flash_valid != FLASH_DESC_VAILD || 4737 fdesc->flash_version != FLASH_DESC_VERSION) { 4738 EL(ha, "invalid descriptor table\n"); 4739 kmem_free(fdesc, sizeof (flash_desc_t)); 4740 return (QL_FUNCTION_FAILED); 4741 } 4742 4743 bcopy(fdesc, &xp->fdesc, sizeof (flash_desc_t)); 4744 kmem_free(fdesc, sizeof (flash_desc_t)); 4745 4746 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 4747 4748 return (QL_SUCCESS); 4749 } 4750 4751 /* 4752 * ql_setup_flash 4753 * Gets the manufacturer and id number of the flash chip, and 4754 * sets up the size parameter. 4755 * 4756 * Input: 4757 * ha: adapter state pointer. 4758 * 4759 * Returns: 4760 * int: ql local function return status code. 4761 * 4762 * Context: 4763 * Kernel context. 4764 */ 4765 static int 4766 ql_setup_flash(ql_adapter_state_t *ha) 4767 { 4768 ql_xioctl_t *xp = ha->xioctl; 4769 int rval = QL_SUCCESS; 4770 4771 if (xp->fdesc.flash_size != 0) { 4772 return (rval); 4773 } 4774 4775 if (CFG_IST(ha, CFG_CTRL_2200) && !ha->subven_id) { 4776 return (QL_FUNCTION_FAILED); 4777 } 4778 4779 if (CFG_IST(ha, CFG_CTRL_258081)) { 4780 /* 4781 * Temporarily set the ha->xioctl->fdesc.flash_size to 4782 * 25xx flash size to avoid failing of ql_dump_focde. 4783 */ 4784 if (CFG_IST(ha, CFG_CTRL_8021)) { 4785 ha->xioctl->fdesc.flash_size = 0x800000; 4786 } else if (CFG_IST(ha, CFG_CTRL_25XX)) { 4787 ha->xioctl->fdesc.flash_size = 0x200000; 4788 } else { 4789 ha->xioctl->fdesc.flash_size = 0x400000; 4790 } 4791 4792 if (ql_24xx_flash_desc(ha) == QL_SUCCESS) { 4793 EL(ha, "flash desc table ok, exit\n"); 4794 return (rval); 4795 } 4796 if (CFG_IST(ha, CFG_CTRL_8021)) { 4797 xp->fdesc.flash_manuf = WINBOND_FLASH; 4798 xp->fdesc.flash_id = WINBOND_FLASHID; 4799 xp->fdesc.flash_len = 0x17; 4800 } else { 4801 (void) ql_24xx_flash_id(ha); 4802 } 4803 4804 } else if (CFG_IST(ha, CFG_CTRL_2422)) { 4805 (void) ql_24xx_flash_id(ha); 4806 } else { 4807 ql_flash_enable(ha); 4808 4809 ql_write_flash_byte(ha, 0x5555, 0xaa); 4810 ql_write_flash_byte(ha, 0x2aaa, 0x55); 4811 ql_write_flash_byte(ha, 0x5555, 0x90); 4812 xp->fdesc.flash_manuf = (uint8_t)ql_read_flash_byte(ha, 0x0000); 4813 4814 if (CFG_IST(ha, CFG_SBUS_CARD)) { 4815 ql_write_flash_byte(ha, 0xaaaa, 0xaa); 4816 ql_write_flash_byte(ha, 0x5555, 0x55); 4817 ql_write_flash_byte(ha, 0xaaaa, 0x90); 4818 xp->fdesc.flash_id = (uint16_t) 4819 ql_read_flash_byte(ha, 0x0002); 4820 } else { 4821 ql_write_flash_byte(ha, 0x5555, 0xaa); 4822 ql_write_flash_byte(ha, 0x2aaa, 0x55); 4823 ql_write_flash_byte(ha, 0x5555, 0x90); 4824 xp->fdesc.flash_id = (uint16_t) 4825 ql_read_flash_byte(ha, 0x0001); 4826 } 4827 4828 ql_write_flash_byte(ha, 0x5555, 0xaa); 4829 ql_write_flash_byte(ha, 0x2aaa, 0x55); 4830 ql_write_flash_byte(ha, 0x5555, 0xf0); 4831 4832 ql_flash_disable(ha); 4833 } 4834 4835 /* Default flash descriptor table. */ 4836 xp->fdesc.write_statusreg_cmd = 1; 4837 xp->fdesc.write_enable_bits = 0; 4838 xp->fdesc.unprotect_sector_cmd = 0; 4839 xp->fdesc.protect_sector_cmd = 0; 4840 xp->fdesc.write_disable_bits = 0x9c; 4841 xp->fdesc.block_size = 0x10000; 4842 xp->fdesc.erase_cmd = 0xd8; 4843 4844 switch (xp->fdesc.flash_manuf) { 4845 case AMD_FLASH: 4846 switch (xp->fdesc.flash_id) { 4847 case SPAN_FLASHID_2048K: 4848 xp->fdesc.flash_size = 0x200000; 4849 break; 4850 case AMD_FLASHID_1024K: 4851 xp->fdesc.flash_size = 0x100000; 4852 break; 4853 case AMD_FLASHID_512K: 4854 case AMD_FLASHID_512Kt: 4855 case AMD_FLASHID_512Kb: 4856 if (CFG_IST(ha, CFG_SBUS_CARD)) { 4857 xp->fdesc.flash_size = QL_SBUS_FCODE_SIZE; 4858 } else { 4859 xp->fdesc.flash_size = 0x80000; 4860 } 4861 break; 4862 case AMD_FLASHID_128K: 4863 xp->fdesc.flash_size = 0x20000; 4864 break; 4865 default: 4866 rval = QL_FUNCTION_FAILED; 4867 break; 4868 } 4869 break; 4870 case ST_FLASH: 4871 switch (xp->fdesc.flash_id) { 4872 case ST_FLASHID_128K: 4873 xp->fdesc.flash_size = 0x20000; 4874 break; 4875 case ST_FLASHID_512K: 4876 xp->fdesc.flash_size = 0x80000; 4877 break; 4878 case ST_FLASHID_M25PXX: 4879 if (xp->fdesc.flash_len == 0x14) { 4880 xp->fdesc.flash_size = 0x100000; 4881 } else if (xp->fdesc.flash_len == 0x15) { 4882 xp->fdesc.flash_size = 0x200000; 4883 } else { 4884 rval = QL_FUNCTION_FAILED; 4885 } 4886 break; 4887 default: 4888 rval = QL_FUNCTION_FAILED; 4889 break; 4890 } 4891 break; 4892 case SST_FLASH: 4893 switch (xp->fdesc.flash_id) { 4894 case SST_FLASHID_128K: 4895 xp->fdesc.flash_size = 0x20000; 4896 break; 4897 case SST_FLASHID_1024K_A: 4898 xp->fdesc.flash_size = 0x100000; 4899 xp->fdesc.block_size = 0x8000; 4900 xp->fdesc.erase_cmd = 0x52; 4901 break; 4902 case SST_FLASHID_1024K: 4903 case SST_FLASHID_1024K_B: 4904 xp->fdesc.flash_size = 0x100000; 4905 break; 4906 case SST_FLASHID_2048K: 4907 xp->fdesc.flash_size = 0x200000; 4908 break; 4909 default: 4910 rval = QL_FUNCTION_FAILED; 4911 break; 4912 } 4913 break; 4914 case MXIC_FLASH: 4915 switch (xp->fdesc.flash_id) { 4916 case MXIC_FLASHID_512K: 4917 xp->fdesc.flash_size = 0x80000; 4918 break; 4919 case MXIC_FLASHID_1024K: 4920 xp->fdesc.flash_size = 0x100000; 4921 break; 4922 case MXIC_FLASHID_25LXX: 4923 if (xp->fdesc.flash_len == 0x14) { 4924 xp->fdesc.flash_size = 0x100000; 4925 } else if (xp->fdesc.flash_len == 0x15) { 4926 xp->fdesc.flash_size = 0x200000; 4927 } else { 4928 rval = QL_FUNCTION_FAILED; 4929 } 4930 break; 4931 default: 4932 rval = QL_FUNCTION_FAILED; 4933 break; 4934 } 4935 break; 4936 case ATMEL_FLASH: 4937 switch (xp->fdesc.flash_id) { 4938 case ATMEL_FLASHID_1024K: 4939 xp->fdesc.flash_size = 0x100000; 4940 xp->fdesc.write_disable_bits = 0xbc; 4941 xp->fdesc.unprotect_sector_cmd = 0x39; 4942 xp->fdesc.protect_sector_cmd = 0x36; 4943 break; 4944 default: 4945 rval = QL_FUNCTION_FAILED; 4946 break; 4947 } 4948 break; 4949 case WINBOND_FLASH: 4950 switch (xp->fdesc.flash_id) { 4951 case WINBOND_FLASHID: 4952 if (xp->fdesc.flash_len == 0x15) { 4953 xp->fdesc.flash_size = 0x200000; 4954 } else if (xp->fdesc.flash_len == 0x16) { 4955 xp->fdesc.flash_size = 0x400000; 4956 } else if (xp->fdesc.flash_len == 0x17) { 4957 xp->fdesc.flash_size = 0x800000; 4958 } else { 4959 rval = QL_FUNCTION_FAILED; 4960 } 4961 break; 4962 default: 4963 rval = QL_FUNCTION_FAILED; 4964 break; 4965 } 4966 break; 4967 case INTEL_FLASH: 4968 switch (xp->fdesc.flash_id) { 4969 case INTEL_FLASHID: 4970 if (xp->fdesc.flash_len == 0x11) { 4971 xp->fdesc.flash_size = 0x200000; 4972 } else if (xp->fdesc.flash_len == 0x12) { 4973 xp->fdesc.flash_size = 0x400000; 4974 } else if (xp->fdesc.flash_len == 0x13) { 4975 xp->fdesc.flash_size = 0x800000; 4976 } else { 4977 rval = QL_FUNCTION_FAILED; 4978 } 4979 break; 4980 default: 4981 rval = QL_FUNCTION_FAILED; 4982 break; 4983 } 4984 break; 4985 default: 4986 rval = QL_FUNCTION_FAILED; 4987 break; 4988 } 4989 4990 /* Try flash table later. */ 4991 if (rval != QL_SUCCESS && CFG_IST(ha, CFG_CTRL_24258081)) { 4992 EL(ha, "no default id\n"); 4993 return (QL_SUCCESS); 4994 } 4995 4996 /* 4997 * hack for non std 2312 and 6312 boards. hardware people need to 4998 * use either the 128k flash chip (original), or something larger. 4999 * For driver purposes, we'll treat it as a 128k flash chip. 5000 */ 5001 if ((ha->device_id == 0x2312 || ha->device_id == 0x6312 || 5002 ha->device_id == 0x2322 || ha->device_id == 0x6322) && 5003 (xp->fdesc.flash_size > 0x20000) && 5004 (CFG_IST(ha, CFG_SBUS_CARD) == 0)) { 5005 EL(ha, "chip exceeds max size: %xh, using 128k\n", 5006 xp->fdesc.flash_size); 5007 xp->fdesc.flash_size = 0x20000; 5008 } 5009 5010 if (rval == QL_SUCCESS) { 5011 EL(ha, "man_id=%xh, flash_id=%xh, size=%xh\n", 5012 xp->fdesc.flash_manuf, xp->fdesc.flash_id, 5013 xp->fdesc.flash_size); 5014 } else { 5015 EL(ha, "unsupported mfr / type: man_id=%xh, flash_id=%xh\n", 5016 xp->fdesc.flash_manuf, xp->fdesc.flash_id); 5017 } 5018 5019 return (rval); 5020 } 5021 5022 /* 5023 * ql_flash_fcode_load 5024 * Loads fcode data into flash from application. 5025 * 5026 * Input: 5027 * ha: adapter state pointer. 5028 * bp: user buffer address. 5029 * size: user buffer size. 5030 * mode: flags 5031 * 5032 * Returns: 5033 * 5034 * Context: 5035 * Kernel context. 5036 */ 5037 static int 5038 ql_flash_fcode_load(ql_adapter_state_t *ha, void *bp, uint32_t bsize, 5039 int mode) 5040 { 5041 uint8_t *bfp; 5042 ql_xioctl_t *xp = ha->xioctl; 5043 int rval = 0; 5044 5045 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 5046 5047 if (bsize > xp->fdesc.flash_size) { 5048 EL(ha, "failed, bufsize: %xh, flash size: %xh\n", bsize, 5049 xp->fdesc.flash_size); 5050 return (ENOMEM); 5051 } 5052 5053 if ((bfp = (uint8_t *)kmem_zalloc(bsize, KM_SLEEP)) == NULL) { 5054 EL(ha, "failed, kmem_zalloc\n"); 5055 rval = ENOMEM; 5056 } else { 5057 if (ddi_copyin(bp, bfp, bsize, mode) != 0) { 5058 EL(ha, "failed, ddi_copyin\n"); 5059 rval = EFAULT; 5060 } else if (ql_load_fcode(ha, bfp, bsize, 0) != QL_SUCCESS) { 5061 EL(ha, "failed, load_fcode\n"); 5062 rval = EFAULT; 5063 } else { 5064 /* Reset caches on all adapter instances. */ 5065 ql_update_flash_caches(ha); 5066 rval = 0; 5067 } 5068 kmem_free(bfp, bsize); 5069 } 5070 5071 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 5072 5073 return (rval); 5074 } 5075 5076 /* 5077 * ql_load_fcode 5078 * Loads fcode in to flash. 5079 * 5080 * Input: 5081 * ha: adapter state pointer. 5082 * dp: data pointer. 5083 * size: data length. 5084 * addr: flash byte address. 5085 * 5086 * Returns: 5087 * ql local function return status code. 5088 * 5089 * Context: 5090 * Kernel context. 5091 */ 5092 int 5093 ql_load_fcode(ql_adapter_state_t *ha, uint8_t *dp, uint32_t size, uint32_t addr) 5094 { 5095 uint32_t cnt; 5096 int rval; 5097 5098 if (CFG_IST(ha, CFG_CTRL_24258081)) { 5099 return (ql_24xx_load_flash(ha, dp, size, addr)); 5100 } 5101 5102 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 5103 5104 if (CFG_IST(ha, CFG_SBUS_CARD)) { 5105 /* 5106 * sbus has an additional check to make 5107 * sure they don't brick the HBA. 5108 */ 5109 if (dp[0] != 0xf1) { 5110 EL(ha, "failed, incorrect fcode for sbus\n"); 5111 return (QL_FUNCTION_PARAMETER_ERROR); 5112 } 5113 } 5114 5115 GLOBAL_HW_LOCK(); 5116 5117 /* Enable Flash Read/Write. */ 5118 ql_flash_enable(ha); 5119 5120 /* Erase flash prior to write. */ 5121 rval = ql_erase_flash(ha, 0); 5122 5123 if (rval == QL_SUCCESS) { 5124 /* Write fcode data to flash. */ 5125 for (cnt = 0; cnt < (uint32_t)size; cnt++) { 5126 /* Allow other system activity. */ 5127 if (cnt % 0x1000 == 0) { 5128 drv_usecwait(1); 5129 } 5130 rval = ql_program_flash_address(ha, addr++, *dp++); 5131 if (rval != QL_SUCCESS) 5132 break; 5133 } 5134 } 5135 5136 ql_flash_disable(ha); 5137 5138 GLOBAL_HW_UNLOCK(); 5139 5140 if (rval != QL_SUCCESS) { 5141 EL(ha, "failed, rval=%xh\n", rval); 5142 } else { 5143 /*EMPTY*/ 5144 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 5145 } 5146 return (rval); 5147 } 5148 5149 /* 5150 * ql_flash_fcode_dump 5151 * Dumps FLASH to application. 5152 * 5153 * Input: 5154 * ha: adapter state pointer. 5155 * bp: user buffer address. 5156 * bsize: user buffer size 5157 * faddr: flash byte address 5158 * mode: flags 5159 * 5160 * Returns: 5161 * 5162 * Context: 5163 * Kernel context. 5164 */ 5165 static int 5166 ql_flash_fcode_dump(ql_adapter_state_t *ha, void *bp, uint32_t bsize, 5167 uint32_t faddr, int mode) 5168 { 5169 uint8_t *bfp; 5170 int rval; 5171 ql_xioctl_t *xp = ha->xioctl; 5172 5173 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 5174 5175 /* adjust max read size to flash size */ 5176 if (bsize > xp->fdesc.flash_size) { 5177 EL(ha, "adjusting req=%xh, max=%xh\n", bsize, 5178 xp->fdesc.flash_size); 5179 bsize = xp->fdesc.flash_size; 5180 } 5181 5182 if ((bfp = (uint8_t *)kmem_zalloc(bsize, KM_SLEEP)) == NULL) { 5183 EL(ha, "failed, kmem_zalloc\n"); 5184 rval = ENOMEM; 5185 } else { 5186 /* Dump Flash fcode. */ 5187 rval = ql_dump_fcode(ha, bfp, bsize, faddr); 5188 5189 if (rval != QL_SUCCESS) { 5190 EL(ha, "failed, dump_fcode = %x\n", rval); 5191 rval = EFAULT; 5192 } else if (ddi_copyout(bfp, bp, bsize, mode) != 0) { 5193 EL(ha, "failed, ddi_copyout\n"); 5194 rval = EFAULT; 5195 } else { 5196 rval = 0; 5197 } 5198 kmem_free(bfp, bsize); 5199 } 5200 5201 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 5202 5203 return (rval); 5204 } 5205 5206 /* 5207 * ql_dump_fcode 5208 * Dumps fcode from flash. 5209 * 5210 * Input: 5211 * ha: adapter state pointer. 5212 * dp: data pointer. 5213 * size: data length in bytes. 5214 * startpos: starting position in flash (byte address). 5215 * 5216 * Returns: 5217 * ql local function return status code. 5218 * 5219 * Context: 5220 * Kernel context. 5221 * 5222 */ 5223 int 5224 ql_dump_fcode(ql_adapter_state_t *ha, uint8_t *dp, uint32_t size, 5225 uint32_t startpos) 5226 { 5227 uint32_t cnt, data, addr; 5228 uint8_t bp[4], *src; 5229 int fp_rval, rval = QL_SUCCESS; 5230 dma_mem_t mem; 5231 5232 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 5233 5234 /* make sure startpos+size doesn't exceed flash */ 5235 if (size + startpos > ha->xioctl->fdesc.flash_size) { 5236 EL(ha, "exceeded flash range, sz=%xh, stp=%xh, flsz=%xh\n", 5237 size, startpos, ha->xioctl->fdesc.flash_size); 5238 return (QL_FUNCTION_PARAMETER_ERROR); 5239 } 5240 5241 if (CFG_IST(ha, CFG_CTRL_24258081)) { 5242 /* check start addr is 32 bit aligned for 24xx */ 5243 if ((startpos & 0x3) != 0) { 5244 rval = ql_24xx_read_flash(ha, 5245 ha->flash_data_addr | startpos >> 2, &data); 5246 if (rval != QL_SUCCESS) { 5247 EL(ha, "failed2, rval = %xh\n", rval); 5248 return (rval); 5249 } 5250 bp[0] = LSB(LSW(data)); 5251 bp[1] = MSB(LSW(data)); 5252 bp[2] = LSB(MSW(data)); 5253 bp[3] = MSB(MSW(data)); 5254 while (size && startpos & 0x3) { 5255 *dp++ = bp[startpos & 0x3]; 5256 startpos++; 5257 size--; 5258 } 5259 if (size == 0) { 5260 QL_PRINT_9(CE_CONT, "(%d): done2\n", 5261 ha->instance); 5262 return (rval); 5263 } 5264 } 5265 5266 /* adjust 24xx start addr for 32 bit words */ 5267 addr = startpos / 4 | ha->flash_data_addr; 5268 } 5269 5270 bzero(&mem, sizeof (dma_mem_t)); 5271 /* Check for Fast page is supported */ 5272 if ((ha->pha->task_daemon_flags & FIRMWARE_UP) && 5273 (CFG_IST(ha, CFG_CTRL_2581))) { 5274 fp_rval = QL_SUCCESS; 5275 /* Setup DMA buffer. */ 5276 rval = ql_get_dma_mem(ha, &mem, size, 5277 LITTLE_ENDIAN_DMA, QL_DMA_DATA_ALIGN); 5278 if (rval != QL_SUCCESS) { 5279 EL(ha, "failed, ql_get_dma_mem=%xh\n", 5280 rval); 5281 return (ENOMEM); 5282 } 5283 } else { 5284 fp_rval = QL_NOT_SUPPORTED; 5285 } 5286 5287 GLOBAL_HW_LOCK(); 5288 5289 /* Enable Flash Read/Write. */ 5290 if (CFG_IST(ha, CFG_CTRL_24258081) == 0) { 5291 ql_flash_enable(ha); 5292 } 5293 5294 /* Read fcode data from flash. */ 5295 while (size) { 5296 /* Allow other system activity. */ 5297 if (size % 0x1000 == 0) { 5298 ql_delay(ha, 100000); 5299 } 5300 if (CFG_IST(ha, CFG_CTRL_24258081)) { 5301 if (fp_rval == QL_SUCCESS && (addr & 0x3f) == 0) { 5302 cnt = (size + 3) >> 2; 5303 fp_rval = ql_rd_risc_ram(ha, addr, 5304 mem.cookie.dmac_laddress, cnt); 5305 if (fp_rval == QL_SUCCESS) { 5306 for (src = mem.bp; size; size--) { 5307 *dp++ = *src++; 5308 } 5309 addr += cnt; 5310 continue; 5311 } 5312 } 5313 rval = ql_24xx_read_flash(ha, addr++, 5314 &data); 5315 if (rval != QL_SUCCESS) { 5316 break; 5317 } 5318 bp[0] = LSB(LSW(data)); 5319 bp[1] = MSB(LSW(data)); 5320 bp[2] = LSB(MSW(data)); 5321 bp[3] = MSB(MSW(data)); 5322 for (cnt = 0; size && cnt < 4; size--) { 5323 *dp++ = bp[cnt++]; 5324 } 5325 } else { 5326 *dp++ = (uint8_t)ql_read_flash_byte(ha, startpos++); 5327 size--; 5328 } 5329 } 5330 5331 if (CFG_IST(ha, CFG_CTRL_24258081) == 0) { 5332 ql_flash_disable(ha); 5333 } 5334 5335 GLOBAL_HW_UNLOCK(); 5336 5337 if (mem.dma_handle != NULL) { 5338 ql_free_dma_resource(ha, &mem); 5339 } 5340 5341 if (rval != QL_SUCCESS) { 5342 EL(ha, "failed, rval = %xh\n", rval); 5343 } else { 5344 /*EMPTY*/ 5345 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 5346 } 5347 return (rval); 5348 } 5349 5350 /* 5351 * ql_program_flash_address 5352 * Program flash address. 5353 * 5354 * Input: 5355 * ha: adapter state pointer. 5356 * addr: flash byte address. 5357 * data: data to be written to flash. 5358 * 5359 * Returns: 5360 * ql local function return status code. 5361 * 5362 * Context: 5363 * Kernel context. 5364 */ 5365 static int 5366 ql_program_flash_address(ql_adapter_state_t *ha, uint32_t addr, 5367 uint8_t data) 5368 { 5369 int rval; 5370 5371 /* Write Program Command Sequence */ 5372 if (CFG_IST(ha, CFG_SBUS_CARD)) { 5373 ql_write_flash_byte(ha, 0x5555, 0xa0); 5374 ql_write_flash_byte(ha, addr, data); 5375 } else { 5376 ql_write_flash_byte(ha, 0x5555, 0xaa); 5377 ql_write_flash_byte(ha, 0x2aaa, 0x55); 5378 ql_write_flash_byte(ha, 0x5555, 0xa0); 5379 ql_write_flash_byte(ha, addr, data); 5380 } 5381 5382 /* Wait for write to complete. */ 5383 rval = ql_poll_flash(ha, addr, data); 5384 5385 if (rval != QL_SUCCESS) { 5386 EL(ha, "failed, rval=%xh\n", rval); 5387 } 5388 return (rval); 5389 } 5390 5391 /* 5392 * ql_set_rnid_parameters 5393 * Set RNID parameters. 5394 * 5395 * Input: 5396 * ha: adapter state pointer. 5397 * cmd: User space CT arguments pointer. 5398 * mode: flags. 5399 */ 5400 static void 5401 ql_set_rnid_parameters(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode) 5402 { 5403 EXT_SET_RNID_REQ tmp_set; 5404 EXT_RNID_DATA *tmp_buf; 5405 int rval = 0; 5406 5407 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 5408 5409 if (DRIVER_SUSPENDED(ha)) { 5410 EL(ha, "failed, LOOP_NOT_READY\n"); 5411 cmd->Status = EXT_STATUS_BUSY; 5412 cmd->ResponseLen = 0; 5413 return; 5414 } 5415 5416 cmd->ResponseLen = 0; /* NO response to caller. */ 5417 if (cmd->RequestLen != sizeof (EXT_SET_RNID_REQ)) { 5418 /* parameter error */ 5419 EL(ha, "failed, RequestLen < EXT_SET_RNID_REQ, Len=%xh\n", 5420 cmd->RequestLen); 5421 cmd->Status = EXT_STATUS_INVALID_PARAM; 5422 cmd->DetailStatus = EXT_DSTATUS_REQUEST_LEN; 5423 cmd->ResponseLen = 0; 5424 return; 5425 } 5426 5427 rval = ddi_copyin((void*)(uintptr_t)cmd->RequestAdr, &tmp_set, 5428 cmd->RequestLen, mode); 5429 if (rval != 0) { 5430 EL(ha, "failed, ddi_copyin\n"); 5431 cmd->Status = EXT_STATUS_COPY_ERR; 5432 cmd->ResponseLen = 0; 5433 return; 5434 } 5435 5436 /* Allocate memory for command. */ 5437 tmp_buf = kmem_zalloc(sizeof (EXT_RNID_DATA), KM_SLEEP); 5438 if (tmp_buf == NULL) { 5439 EL(ha, "failed, kmem_zalloc\n"); 5440 cmd->Status = EXT_STATUS_NO_MEMORY; 5441 cmd->ResponseLen = 0; 5442 return; 5443 } 5444 5445 rval = ql_get_rnid_params(ha, sizeof (EXT_RNID_DATA), 5446 (caddr_t)tmp_buf); 5447 if (rval != QL_SUCCESS) { 5448 /* error */ 5449 EL(ha, "failed, get_rnid_params_mbx=%xh\n", rval); 5450 kmem_free(tmp_buf, sizeof (EXT_RNID_DATA)); 5451 cmd->Status = EXT_STATUS_ERR; 5452 cmd->ResponseLen = 0; 5453 return; 5454 } 5455 5456 /* Now set the requested params. */ 5457 bcopy(tmp_set.IPVersion, tmp_buf->IPVersion, 2); 5458 bcopy(tmp_set.UDPPortNumber, tmp_buf->UDPPortNumber, 2); 5459 bcopy(tmp_set.IPAddress, tmp_buf->IPAddress, 16); 5460 5461 rval = ql_set_rnid_params(ha, sizeof (EXT_RNID_DATA), 5462 (caddr_t)tmp_buf); 5463 if (rval != QL_SUCCESS) { 5464 /* error */ 5465 EL(ha, "failed, set_rnid_params_mbx=%xh\n", rval); 5466 cmd->Status = EXT_STATUS_ERR; 5467 cmd->ResponseLen = 0; 5468 } 5469 5470 kmem_free(tmp_buf, sizeof (EXT_RNID_DATA)); 5471 5472 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 5473 } 5474 5475 /* 5476 * ql_get_rnid_parameters 5477 * Get RNID parameters. 5478 * 5479 * Input: 5480 * ha: adapter state pointer. 5481 * cmd: User space CT arguments pointer. 5482 * mode: flags. 5483 */ 5484 static void 5485 ql_get_rnid_parameters(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode) 5486 { 5487 EXT_RNID_DATA *tmp_buf; 5488 uint32_t rval; 5489 5490 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 5491 5492 if (DRIVER_SUSPENDED(ha)) { 5493 EL(ha, "failed, LOOP_NOT_READY\n"); 5494 cmd->Status = EXT_STATUS_BUSY; 5495 cmd->ResponseLen = 0; 5496 return; 5497 } 5498 5499 /* Allocate memory for command. */ 5500 tmp_buf = kmem_zalloc(sizeof (EXT_RNID_DATA), KM_SLEEP); 5501 if (tmp_buf == NULL) { 5502 EL(ha, "failed, kmem_zalloc\n"); 5503 cmd->Status = EXT_STATUS_NO_MEMORY; 5504 cmd->ResponseLen = 0; 5505 return; 5506 } 5507 5508 /* Send command */ 5509 rval = ql_get_rnid_params(ha, sizeof (EXT_RNID_DATA), 5510 (caddr_t)tmp_buf); 5511 if (rval != QL_SUCCESS) { 5512 /* error */ 5513 EL(ha, "failed, get_rnid_params_mbx=%xh\n", rval); 5514 kmem_free(tmp_buf, sizeof (EXT_RNID_DATA)); 5515 cmd->Status = EXT_STATUS_ERR; 5516 cmd->ResponseLen = 0; 5517 return; 5518 } 5519 5520 /* Copy the response */ 5521 if (ql_send_buffer_data((caddr_t)tmp_buf, 5522 (caddr_t)(uintptr_t)cmd->ResponseAdr, 5523 sizeof (EXT_RNID_DATA), mode) != sizeof (EXT_RNID_DATA)) { 5524 EL(ha, "failed, ddi_copyout\n"); 5525 cmd->Status = EXT_STATUS_COPY_ERR; 5526 cmd->ResponseLen = 0; 5527 } else { 5528 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 5529 cmd->ResponseLen = sizeof (EXT_RNID_DATA); 5530 } 5531 5532 kmem_free(tmp_buf, sizeof (EXT_RNID_DATA)); 5533 } 5534 5535 /* 5536 * ql_reset_statistics 5537 * Performs EXT_SC_RST_STATISTICS subcommand. of EXT_CC_SET_DATA. 5538 * 5539 * Input: 5540 * ha: adapter state pointer. 5541 * cmd: Local EXT_IOCTL cmd struct pointer. 5542 * 5543 * Returns: 5544 * None, request status indicated in cmd->Status. 5545 * 5546 * Context: 5547 * Kernel context. 5548 */ 5549 static int 5550 ql_reset_statistics(ql_adapter_state_t *ha, EXT_IOCTL *cmd) 5551 { 5552 ql_xioctl_t *xp = ha->xioctl; 5553 int rval = 0; 5554 5555 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 5556 5557 if (DRIVER_SUSPENDED(ha)) { 5558 EL(ha, "failed, LOOP_NOT_READY\n"); 5559 cmd->Status = EXT_STATUS_BUSY; 5560 cmd->ResponseLen = 0; 5561 return (QL_FUNCTION_SUSPENDED); 5562 } 5563 5564 rval = ql_reset_link_status(ha); 5565 if (rval != QL_SUCCESS) { 5566 EL(ha, "failed, reset_link_status_mbx=%xh\n", rval); 5567 cmd->Status = EXT_STATUS_MAILBOX; 5568 cmd->DetailStatus = rval; 5569 cmd->ResponseLen = 0; 5570 } 5571 5572 TASK_DAEMON_LOCK(ha); 5573 xp->IosRequested = 0; 5574 xp->BytesRequested = 0; 5575 xp->IOInputRequests = 0; 5576 xp->IOOutputRequests = 0; 5577 xp->IOControlRequests = 0; 5578 xp->IOInputMByteCnt = 0; 5579 xp->IOOutputMByteCnt = 0; 5580 xp->IOOutputByteCnt = 0; 5581 xp->IOInputByteCnt = 0; 5582 TASK_DAEMON_UNLOCK(ha); 5583 5584 INTR_LOCK(ha); 5585 xp->ControllerErrorCount = 0; 5586 xp->DeviceErrorCount = 0; 5587 xp->TotalLipResets = 0; 5588 xp->TotalInterrupts = 0; 5589 INTR_UNLOCK(ha); 5590 5591 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 5592 5593 return (rval); 5594 } 5595 5596 /* 5597 * ql_get_statistics 5598 * Performs EXT_SC_GET_STATISTICS subcommand. of EXT_CC_GET_DATA. 5599 * 5600 * Input: 5601 * ha: adapter state pointer. 5602 * cmd: Local EXT_IOCTL cmd struct pointer. 5603 * mode: flags. 5604 * 5605 * Returns: 5606 * None, request status indicated in cmd->Status. 5607 * 5608 * Context: 5609 * Kernel context. 5610 */ 5611 static void 5612 ql_get_statistics(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode) 5613 { 5614 EXT_HBA_PORT_STAT ps = {0}; 5615 ql_link_stats_t *ls; 5616 int rval; 5617 ql_xioctl_t *xp = ha->xioctl; 5618 int retry = 10; 5619 5620 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 5621 5622 while (ha->task_daemon_flags & 5623 (ABORT_ISP_ACTIVE | LOOP_RESYNC_ACTIVE | DRIVER_STALL)) { 5624 ql_delay(ha, 10000000); /* 10 second delay */ 5625 5626 retry--; 5627 5628 if (retry == 0) { /* effectively 100 seconds */ 5629 EL(ha, "failed, LOOP_NOT_READY\n"); 5630 cmd->Status = EXT_STATUS_BUSY; 5631 cmd->ResponseLen = 0; 5632 return; 5633 } 5634 } 5635 5636 /* Allocate memory for command. */ 5637 ls = kmem_zalloc(sizeof (ql_link_stats_t), KM_SLEEP); 5638 if (ls == NULL) { 5639 EL(ha, "failed, kmem_zalloc\n"); 5640 cmd->Status = EXT_STATUS_NO_MEMORY; 5641 cmd->ResponseLen = 0; 5642 return; 5643 } 5644 5645 /* 5646 * I think these are supposed to be port statistics 5647 * the loop ID or port ID should be in cmd->Instance. 5648 */ 5649 rval = ql_get_status_counts(ha, (uint16_t) 5650 (ha->task_daemon_flags & LOOP_DOWN ? 0xFF : ha->loop_id), 5651 sizeof (ql_link_stats_t), (caddr_t)ls, 0); 5652 if (rval != QL_SUCCESS) { 5653 EL(ha, "failed, get_link_status=%xh, id=%xh\n", rval, 5654 ha->loop_id); 5655 cmd->Status = EXT_STATUS_MAILBOX; 5656 cmd->DetailStatus = rval; 5657 cmd->ResponseLen = 0; 5658 } else { 5659 ps.ControllerErrorCount = xp->ControllerErrorCount; 5660 ps.DeviceErrorCount = xp->DeviceErrorCount; 5661 ps.IoCount = (uint32_t)(xp->IOInputRequests + 5662 xp->IOOutputRequests + xp->IOControlRequests); 5663 ps.MBytesCount = (uint32_t)(xp->IOInputMByteCnt + 5664 xp->IOOutputMByteCnt); 5665 ps.LipResetCount = xp->TotalLipResets; 5666 ps.InterruptCount = xp->TotalInterrupts; 5667 ps.LinkFailureCount = LE_32(ls->link_fail_cnt); 5668 ps.LossOfSyncCount = LE_32(ls->sync_loss_cnt); 5669 ps.LossOfSignalsCount = LE_32(ls->signal_loss_cnt); 5670 ps.PrimitiveSeqProtocolErrorCount = LE_32(ls->prot_err_cnt); 5671 ps.InvalidTransmissionWordCount = LE_32(ls->inv_xmit_cnt); 5672 ps.InvalidCRCCount = LE_32(ls->inv_crc_cnt); 5673 5674 rval = ddi_copyout((void *)&ps, 5675 (void *)(uintptr_t)cmd->ResponseAdr, 5676 sizeof (EXT_HBA_PORT_STAT), mode); 5677 if (rval != 0) { 5678 EL(ha, "failed, ddi_copyout\n"); 5679 cmd->Status = EXT_STATUS_COPY_ERR; 5680 cmd->ResponseLen = 0; 5681 } else { 5682 cmd->ResponseLen = sizeof (EXT_HBA_PORT_STAT); 5683 } 5684 } 5685 5686 kmem_free(ls, sizeof (ql_link_stats_t)); 5687 5688 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 5689 } 5690 5691 /* 5692 * ql_get_statistics_fc 5693 * Performs EXT_SC_GET_FC_STATISTICS subcommand. of EXT_CC_GET_DATA. 5694 * 5695 * Input: 5696 * ha: adapter state pointer. 5697 * cmd: Local EXT_IOCTL cmd struct pointer. 5698 * mode: flags. 5699 * 5700 * Returns: 5701 * None, request status indicated in cmd->Status. 5702 * 5703 * Context: 5704 * Kernel context. 5705 */ 5706 static void 5707 ql_get_statistics_fc(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode) 5708 { 5709 EXT_HBA_PORT_STAT ps = {0}; 5710 ql_link_stats_t *ls; 5711 int rval; 5712 uint16_t qlnt; 5713 EXT_DEST_ADDR pextdestaddr; 5714 uint8_t *name; 5715 ql_tgt_t *tq = NULL; 5716 int retry = 10; 5717 5718 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 5719 5720 if (ddi_copyin((void *)(uintptr_t)cmd->RequestAdr, 5721 (void *)&pextdestaddr, sizeof (EXT_DEST_ADDR), mode) != 0) { 5722 EL(ha, "failed, ddi_copyin\n"); 5723 cmd->Status = EXT_STATUS_COPY_ERR; 5724 cmd->ResponseLen = 0; 5725 return; 5726 } 5727 5728 qlnt = QLNT_PORT; 5729 name = pextdestaddr.DestAddr.WWPN; 5730 5731 QL_PRINT_9(CE_CONT, "(%d): wwpn=%02x%02x%02x%02x%02x%02x%02x%02x\n", 5732 ha->instance, name[0], name[1], name[2], name[3], name[4], 5733 name[5], name[6], name[7]); 5734 5735 tq = ql_find_port(ha, name, qlnt); 5736 5737 if (tq == NULL || !VALID_TARGET_ID(ha, tq->loop_id)) { 5738 EL(ha, "failed, fc_port not found\n"); 5739 cmd->Status = EXT_STATUS_DEV_NOT_FOUND; 5740 cmd->ResponseLen = 0; 5741 return; 5742 } 5743 5744 while (ha->task_daemon_flags & 5745 (ABORT_ISP_ACTIVE | LOOP_RESYNC_ACTIVE | DRIVER_STALL)) { 5746 ql_delay(ha, 10000000); /* 10 second delay */ 5747 5748 retry--; 5749 5750 if (retry == 0) { /* effectively 100 seconds */ 5751 EL(ha, "failed, LOOP_NOT_READY\n"); 5752 cmd->Status = EXT_STATUS_BUSY; 5753 cmd->ResponseLen = 0; 5754 return; 5755 } 5756 } 5757 5758 /* Allocate memory for command. */ 5759 ls = kmem_zalloc(sizeof (ql_link_stats_t), KM_SLEEP); 5760 if (ls == NULL) { 5761 EL(ha, "failed, kmem_zalloc\n"); 5762 cmd->Status = EXT_STATUS_NO_MEMORY; 5763 cmd->ResponseLen = 0; 5764 return; 5765 } 5766 5767 rval = ql_get_link_status(ha, tq->loop_id, sizeof (ql_link_stats_t), 5768 (caddr_t)ls, 0); 5769 if (rval != QL_SUCCESS) { 5770 EL(ha, "failed, get_link_status=%xh, d_id=%xh\n", rval, 5771 tq->d_id.b24); 5772 cmd->Status = EXT_STATUS_MAILBOX; 5773 cmd->DetailStatus = rval; 5774 cmd->ResponseLen = 0; 5775 } else { 5776 ps.LinkFailureCount = LE_32(ls->link_fail_cnt); 5777 ps.LossOfSyncCount = LE_32(ls->sync_loss_cnt); 5778 ps.LossOfSignalsCount = LE_32(ls->signal_loss_cnt); 5779 ps.PrimitiveSeqProtocolErrorCount = LE_32(ls->prot_err_cnt); 5780 ps.InvalidTransmissionWordCount = LE_32(ls->inv_xmit_cnt); 5781 ps.InvalidCRCCount = LE_32(ls->inv_crc_cnt); 5782 5783 rval = ddi_copyout((void *)&ps, 5784 (void *)(uintptr_t)cmd->ResponseAdr, 5785 sizeof (EXT_HBA_PORT_STAT), mode); 5786 5787 if (rval != 0) { 5788 EL(ha, "failed, ddi_copyout\n"); 5789 cmd->Status = EXT_STATUS_COPY_ERR; 5790 cmd->ResponseLen = 0; 5791 } else { 5792 cmd->ResponseLen = sizeof (EXT_HBA_PORT_STAT); 5793 } 5794 } 5795 5796 kmem_free(ls, sizeof (ql_link_stats_t)); 5797 5798 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 5799 } 5800 5801 /* 5802 * ql_get_statistics_fc4 5803 * Performs EXT_SC_GET_FC_STATISTICS subcommand. of EXT_CC_GET_DATA. 5804 * 5805 * Input: 5806 * ha: adapter state pointer. 5807 * cmd: Local EXT_IOCTL cmd struct pointer. 5808 * mode: flags. 5809 * 5810 * Returns: 5811 * None, request status indicated in cmd->Status. 5812 * 5813 * Context: 5814 * Kernel context. 5815 */ 5816 static void 5817 ql_get_statistics_fc4(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode) 5818 { 5819 uint32_t rval; 5820 EXT_HBA_FC4STATISTICS fc4stats = {0}; 5821 ql_xioctl_t *xp = ha->xioctl; 5822 5823 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 5824 5825 fc4stats.InputRequests = xp->IOInputRequests; 5826 fc4stats.OutputRequests = xp->IOOutputRequests; 5827 fc4stats.ControlRequests = xp->IOControlRequests; 5828 fc4stats.InputMegabytes = xp->IOInputMByteCnt; 5829 fc4stats.OutputMegabytes = xp->IOOutputMByteCnt; 5830 5831 rval = ddi_copyout((void *)&fc4stats, 5832 (void *)(uintptr_t)cmd->ResponseAdr, 5833 sizeof (EXT_HBA_FC4STATISTICS), mode); 5834 5835 if (rval != 0) { 5836 EL(ha, "failed, ddi_copyout\n"); 5837 cmd->Status = EXT_STATUS_COPY_ERR; 5838 cmd->ResponseLen = 0; 5839 } else { 5840 cmd->ResponseLen = sizeof (EXT_HBA_FC4STATISTICS); 5841 } 5842 5843 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 5844 } 5845 5846 /* 5847 * ql_set_led_state 5848 * Performs EXT_SET_BEACON_STATE subcommand of EXT_CC_SET_DATA. 5849 * 5850 * Input: 5851 * ha: adapter state pointer. 5852 * cmd: Local EXT_IOCTL cmd struct pointer. 5853 * mode: flags. 5854 * 5855 * Returns: 5856 * None, request status indicated in cmd->Status. 5857 * 5858 * Context: 5859 * Kernel context. 5860 */ 5861 static void 5862 ql_set_led_state(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode) 5863 { 5864 EXT_BEACON_CONTROL bstate; 5865 uint32_t rval; 5866 ql_xioctl_t *xp = ha->xioctl; 5867 5868 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 5869 5870 if (cmd->RequestLen < sizeof (EXT_BEACON_CONTROL)) { 5871 cmd->Status = EXT_STATUS_BUFFER_TOO_SMALL; 5872 cmd->DetailStatus = sizeof (EXT_BEACON_CONTROL); 5873 EL(ha, "done - failed, RequestLen < EXT_BEACON_CONTROL," 5874 " Len=%xh\n", cmd->RequestLen); 5875 cmd->ResponseLen = 0; 5876 return; 5877 } 5878 5879 if (ha->device_id < 0x2300) { 5880 cmd->Status = EXT_STATUS_UNSUPPORTED_SUBCODE; 5881 cmd->DetailStatus = 0; 5882 EL(ha, "done - failed, Invalid function for HBA model\n"); 5883 cmd->ResponseLen = 0; 5884 return; 5885 } 5886 5887 rval = ddi_copyin((void*)(uintptr_t)cmd->RequestAdr, &bstate, 5888 cmd->RequestLen, mode); 5889 5890 if (rval != 0) { 5891 cmd->Status = EXT_STATUS_COPY_ERR; 5892 EL(ha, "done - failed, ddi_copyin\n"); 5893 return; 5894 } 5895 5896 switch (bstate.State) { 5897 case EXT_DEF_GRN_BLINK_OFF: /* turn beacon off */ 5898 if (xp->ledstate.BeaconState == BEACON_OFF) { 5899 /* not quite an error -- LED state is already off */ 5900 cmd->Status = EXT_STATUS_OK; 5901 EL(ha, "LED off request -- LED is already off\n"); 5902 break; 5903 } 5904 5905 xp->ledstate.BeaconState = BEACON_OFF; 5906 xp->ledstate.LEDflags = LED_ALL_OFF; 5907 5908 if ((rval = ql_wrapup_led(ha)) != QL_SUCCESS) { 5909 cmd->Status = EXT_STATUS_MAILBOX; 5910 } else { 5911 cmd->Status = EXT_STATUS_OK; 5912 } 5913 break; 5914 5915 case EXT_DEF_GRN_BLINK_ON: /* turn beacon on */ 5916 if (xp->ledstate.BeaconState == BEACON_ON) { 5917 /* not quite an error -- LED state is already on */ 5918 cmd->Status = EXT_STATUS_OK; 5919 EL(ha, "LED on request - LED is already on\n"); 5920 break; 5921 } 5922 5923 if ((rval = ql_setup_led(ha)) != QL_SUCCESS) { 5924 cmd->Status = EXT_STATUS_MAILBOX; 5925 break; 5926 } 5927 5928 if (CFG_IST(ha, CFG_CTRL_24258081)) { 5929 xp->ledstate.LEDflags = LED_YELLOW_24 | LED_AMBER_24; 5930 } else { 5931 xp->ledstate.LEDflags = LED_GREEN; 5932 } 5933 xp->ledstate.BeaconState = BEACON_ON; 5934 5935 cmd->Status = EXT_STATUS_OK; 5936 break; 5937 default: 5938 cmd->Status = EXT_STATUS_ERR; 5939 EL(ha, "failed, unknown state request %xh\n", bstate.State); 5940 break; 5941 } 5942 5943 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 5944 } 5945 5946 /* 5947 * ql_get_led_state 5948 * Performs EXT_GET_BEACON_STATE subcommand of EXT_CC_GET_DATA. 5949 * 5950 * Input: 5951 * ha: adapter state pointer. 5952 * cmd: Local EXT_IOCTL cmd struct pointer. 5953 * mode: flags. 5954 * 5955 * Returns: 5956 * None, request status indicated in cmd->Status. 5957 * 5958 * Context: 5959 * Kernel context. 5960 */ 5961 static void 5962 ql_get_led_state(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode) 5963 { 5964 EXT_BEACON_CONTROL bstate = {0}; 5965 uint32_t rval; 5966 ql_xioctl_t *xp = ha->xioctl; 5967 5968 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 5969 5970 if (cmd->ResponseLen < sizeof (EXT_BEACON_CONTROL)) { 5971 cmd->Status = EXT_STATUS_BUFFER_TOO_SMALL; 5972 cmd->DetailStatus = sizeof (EXT_BEACON_CONTROL); 5973 EL(ha, "done - failed, ResponseLen < EXT_BEACON_CONTROL," 5974 "Len=%xh\n", cmd->ResponseLen); 5975 cmd->ResponseLen = 0; 5976 return; 5977 } 5978 5979 if (ha->device_id < 0x2300) { 5980 cmd->Status = EXT_STATUS_UNSUPPORTED_SUBCODE; 5981 cmd->DetailStatus = 0; 5982 EL(ha, "done - failed, Invalid function for HBA model\n"); 5983 cmd->ResponseLen = 0; 5984 return; 5985 } 5986 5987 if (ha->task_daemon_flags & ABORT_ISP_ACTIVE) { 5988 cmd->Status = EXT_STATUS_BUSY; 5989 EL(ha, "done - failed, isp abort active\n"); 5990 cmd->ResponseLen = 0; 5991 return; 5992 } 5993 5994 /* inform the user of the current beacon state (off or on) */ 5995 bstate.State = xp->ledstate.BeaconState; 5996 5997 rval = ddi_copyout((void *)&bstate, 5998 (void *)(uintptr_t)cmd->ResponseAdr, 5999 sizeof (EXT_BEACON_CONTROL), mode); 6000 6001 if (rval != 0) { 6002 EL(ha, "failed, ddi_copyout\n"); 6003 cmd->Status = EXT_STATUS_COPY_ERR; 6004 cmd->ResponseLen = 0; 6005 } else { 6006 cmd->Status = EXT_STATUS_OK; 6007 cmd->ResponseLen = sizeof (EXT_BEACON_CONTROL); 6008 } 6009 6010 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 6011 } 6012 6013 /* 6014 * ql_blink_led 6015 * Determine the next state of the LED and drive it 6016 * 6017 * Input: 6018 * ha: adapter state pointer. 6019 * 6020 * Context: 6021 * Interrupt context. 6022 */ 6023 void 6024 ql_blink_led(ql_adapter_state_t *ha) 6025 { 6026 uint32_t nextstate; 6027 ql_xioctl_t *xp = ha->xioctl; 6028 6029 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 6030 6031 if (xp->ledstate.BeaconState == BEACON_ON) { 6032 /* determine the next led state */ 6033 if (CFG_IST(ha, CFG_CTRL_24258081)) { 6034 nextstate = (xp->ledstate.LEDflags) & 6035 (~(RD32_IO_REG(ha, gpiod))); 6036 } else { 6037 nextstate = (xp->ledstate.LEDflags) & 6038 (~(RD16_IO_REG(ha, gpiod))); 6039 } 6040 6041 /* turn the led on or off */ 6042 ql_drive_led(ha, nextstate); 6043 } 6044 6045 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 6046 } 6047 6048 /* 6049 * ql_drive_led 6050 * drive the led's as determined by LEDflags 6051 * 6052 * Input: 6053 * ha: adapter state pointer. 6054 * LEDflags: LED flags 6055 * 6056 * Context: 6057 * Kernel/Interrupt context. 6058 */ 6059 static void 6060 ql_drive_led(ql_adapter_state_t *ha, uint32_t LEDflags) 6061 { 6062 6063 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 6064 6065 if (CFG_IST(ha, (CFG_CTRL_2300 | CFG_CTRL_6322))) { 6066 6067 uint16_t gpio_enable, gpio_data; 6068 6069 /* setup to send new data */ 6070 gpio_enable = (uint16_t)RD16_IO_REG(ha, gpioe); 6071 gpio_enable = (uint16_t)(gpio_enable | LED_MASK); 6072 WRT16_IO_REG(ha, gpioe, gpio_enable); 6073 6074 /* read current data and clear out old led data */ 6075 gpio_data = (uint16_t)RD16_IO_REG(ha, gpiod); 6076 gpio_data = (uint16_t)(gpio_data & ~LED_MASK); 6077 6078 /* set in the new led data. */ 6079 gpio_data = (uint16_t)(gpio_data | LEDflags); 6080 6081 /* write out the new led data */ 6082 WRT16_IO_REG(ha, gpiod, gpio_data); 6083 6084 } else if (CFG_IST(ha, CFG_CTRL_24258081)) { 6085 6086 uint32_t gpio_data; 6087 6088 /* setup to send new data */ 6089 gpio_data = RD32_IO_REG(ha, gpiod); 6090 gpio_data |= LED_MASK_UPDATE_24; 6091 WRT32_IO_REG(ha, gpiod, gpio_data); 6092 6093 /* read current data and clear out old led data */ 6094 gpio_data = RD32_IO_REG(ha, gpiod); 6095 gpio_data &= ~LED_MASK_COLORS_24; 6096 6097 /* set in the new led data */ 6098 gpio_data |= LEDflags; 6099 6100 /* write out the new led data */ 6101 WRT32_IO_REG(ha, gpiod, gpio_data); 6102 6103 } else { 6104 EL(ha, "unsupported HBA: %xh", ha->device_id); 6105 } 6106 6107 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 6108 } 6109 6110 /* 6111 * ql_setup_led 6112 * Setup LED for driver control 6113 * 6114 * Input: 6115 * ha: adapter state pointer. 6116 * 6117 * Context: 6118 * Kernel/Interrupt context. 6119 */ 6120 static uint32_t 6121 ql_setup_led(ql_adapter_state_t *ha) 6122 { 6123 uint32_t rval; 6124 ql_mbx_data_t mr; 6125 6126 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 6127 6128 /* decouple the LED control from the fw */ 6129 rval = ql_get_firmware_option(ha, &mr); 6130 if (rval != QL_SUCCESS) { 6131 EL(ha, "failed, get_firmware_option=%xh\n", rval); 6132 return (rval); 6133 } 6134 6135 /* set the appropriate options */ 6136 mr.mb[1] = (uint16_t)(mr.mb[1] | FO1_DISABLE_GPIO); 6137 6138 /* send it back to the firmware */ 6139 rval = ql_set_firmware_option(ha, &mr); 6140 if (rval != QL_SUCCESS) { 6141 EL(ha, "failed, set_firmware_option=%xh\n", rval); 6142 return (rval); 6143 } 6144 6145 /* initally, turn the LED's off */ 6146 ql_drive_led(ha, LED_ALL_OFF); 6147 6148 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 6149 6150 return (rval); 6151 } 6152 6153 /* 6154 * ql_wrapup_led 6155 * Return LED control to the firmware 6156 * 6157 * Input: 6158 * ha: adapter state pointer. 6159 * 6160 * Context: 6161 * Kernel/Interrupt context. 6162 */ 6163 static uint32_t 6164 ql_wrapup_led(ql_adapter_state_t *ha) 6165 { 6166 uint32_t rval; 6167 ql_mbx_data_t mr; 6168 6169 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 6170 6171 /* Turn all LED's off */ 6172 ql_drive_led(ha, LED_ALL_OFF); 6173 6174 if (CFG_IST(ha, CFG_CTRL_24258081)) { 6175 6176 uint32_t gpio_data; 6177 6178 /* disable the LED update mask */ 6179 gpio_data = RD32_IO_REG(ha, gpiod); 6180 gpio_data &= ~LED_MASK_UPDATE_24; 6181 6182 /* write out the data */ 6183 WRT32_IO_REG(ha, gpiod, gpio_data); 6184 } 6185 6186 /* give LED control back to the f/w */ 6187 rval = ql_get_firmware_option(ha, &mr); 6188 if (rval != QL_SUCCESS) { 6189 EL(ha, "failed, get_firmware_option=%xh\n", rval); 6190 return (rval); 6191 } 6192 6193 mr.mb[1] = (uint16_t)(mr.mb[1] & ~FO1_DISABLE_GPIO); 6194 6195 rval = ql_set_firmware_option(ha, &mr); 6196 if (rval != QL_SUCCESS) { 6197 EL(ha, "failed, set_firmware_option=%xh\n", rval); 6198 return (rval); 6199 } 6200 6201 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 6202 6203 return (rval); 6204 } 6205 6206 /* 6207 * ql_get_port_summary 6208 * Performs EXT_SC_GET_PORT_SUMMARY subcommand. of EXT_CC_GET_DATA. 6209 * 6210 * The EXT_IOCTL->RequestAdr points to a single 6211 * UINT32 which identifies the device type. 6212 * 6213 * Input: 6214 * ha: adapter state pointer. 6215 * cmd: Local EXT_IOCTL cmd struct pointer. 6216 * mode: flags. 6217 * 6218 * Returns: 6219 * None, request status indicated in cmd->Status. 6220 * 6221 * Context: 6222 * Kernel context. 6223 */ 6224 static void 6225 ql_get_port_summary(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode) 6226 { 6227 EXT_DEVICEDATA dd = {0}; 6228 EXT_DEVICEDATA *uddp; 6229 ql_link_t *link; 6230 ql_tgt_t *tq; 6231 uint32_t rlen, dev_type, index; 6232 int rval = 0; 6233 EXT_DEVICEDATAENTRY *uddep, *ddep; 6234 6235 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 6236 6237 ddep = &dd.EntryList[0]; 6238 6239 /* 6240 * Get the type of device the requestor is looking for. 6241 * 6242 * We ignore this for now. 6243 */ 6244 rval = ddi_copyin((void *)(uintptr_t)cmd->RequestAdr, 6245 (void *)&dev_type, sizeof (dev_type), mode); 6246 if (rval != 0) { 6247 cmd->Status = EXT_STATUS_COPY_ERR; 6248 cmd->ResponseLen = 0; 6249 EL(ha, "failed, ddi_copyin\n"); 6250 return; 6251 } 6252 /* 6253 * Count the number of entries to be returned. Count devices 6254 * that are offlline, but have been persistently bound. 6255 */ 6256 for (index = 0; index < DEVICE_HEAD_LIST_SIZE; index++) { 6257 for (link = ha->dev[index].first; link != NULL; 6258 link = link->next) { 6259 tq = link->base_address; 6260 if (tq->flags & TQF_INITIATOR_DEVICE || 6261 !VALID_TARGET_ID(ha, tq->loop_id)) { 6262 continue; /* Skip this one */ 6263 } 6264 dd.TotalDevices++; 6265 } 6266 } 6267 /* 6268 * Compute the number of entries that can be returned 6269 * based upon the size of caller's response buffer. 6270 */ 6271 dd.ReturnListEntryCount = 0; 6272 if (dd.TotalDevices == 0) { 6273 rlen = sizeof (EXT_DEVICEDATA) - sizeof (EXT_DEVICEDATAENTRY); 6274 } else { 6275 rlen = (uint32_t)(sizeof (EXT_DEVICEDATA) + 6276 (sizeof (EXT_DEVICEDATAENTRY) * (dd.TotalDevices - 1))); 6277 } 6278 if (rlen > cmd->ResponseLen) { 6279 cmd->Status = EXT_STATUS_BUFFER_TOO_SMALL; 6280 cmd->DetailStatus = rlen; 6281 EL(ha, "failed, rlen > ResponseLen, rlen=%d, Len=%d\n", 6282 rlen, cmd->ResponseLen); 6283 cmd->ResponseLen = 0; 6284 return; 6285 } 6286 cmd->ResponseLen = 0; 6287 uddp = (EXT_DEVICEDATA *)(uintptr_t)cmd->ResponseAdr; 6288 uddep = &uddp->EntryList[0]; 6289 for (index = 0; index < DEVICE_HEAD_LIST_SIZE; index++) { 6290 for (link = ha->dev[index].first; link != NULL; 6291 link = link->next) { 6292 tq = link->base_address; 6293 if (tq->flags & TQF_INITIATOR_DEVICE || 6294 !VALID_TARGET_ID(ha, tq->loop_id)) { 6295 continue; /* Skip this one */ 6296 } 6297 6298 bzero((void *)ddep, sizeof (EXT_DEVICEDATAENTRY)); 6299 6300 bcopy(tq->node_name, ddep->NodeWWN, 8); 6301 bcopy(tq->port_name, ddep->PortWWN, 8); 6302 6303 ddep->PortID[0] = tq->d_id.b.domain; 6304 ddep->PortID[1] = tq->d_id.b.area; 6305 ddep->PortID[2] = tq->d_id.b.al_pa; 6306 6307 bcopy(tq->port_name, 6308 (caddr_t)&ddep->TargetAddress.Target, 8); 6309 6310 ddep->DeviceFlags = tq->flags; 6311 ddep->LoopID = tq->loop_id; 6312 QL_PRINT_9(CE_CONT, "(%d): Tgt=%lld, loop=%xh, " 6313 "wwnn=%02x%02x%02x%02x%02x%02x%02x%02x, " 6314 "wwpn=%02x%02x%02x%02x%02x%02x%02x%02x\n", 6315 ha->instance, ddep->TargetAddress.Target, 6316 ddep->LoopID, ddep->NodeWWN[0], ddep->NodeWWN[1], 6317 ddep->NodeWWN[2], ddep->NodeWWN[3], 6318 ddep->NodeWWN[4], ddep->NodeWWN[5], 6319 ddep->NodeWWN[6], ddep->NodeWWN[7], 6320 ddep->PortWWN[0], ddep->PortWWN[1], 6321 ddep->PortWWN[2], ddep->PortWWN[3], 6322 ddep->PortWWN[4], ddep->PortWWN[5], 6323 ddep->PortWWN[6], ddep->PortWWN[7]); 6324 rval = ddi_copyout((void *)ddep, (void *)uddep, 6325 sizeof (EXT_DEVICEDATAENTRY), mode); 6326 6327 if (rval != 0) { 6328 cmd->Status = EXT_STATUS_COPY_ERR; 6329 cmd->ResponseLen = 0; 6330 EL(ha, "failed, ddi_copyout\n"); 6331 break; 6332 } 6333 dd.ReturnListEntryCount++; 6334 uddep++; 6335 cmd->ResponseLen += (uint32_t) 6336 sizeof (EXT_DEVICEDATAENTRY); 6337 } 6338 } 6339 rval = ddi_copyout((void *)&dd, (void *)uddp, 6340 sizeof (EXT_DEVICEDATA) - sizeof (EXT_DEVICEDATAENTRY), mode); 6341 6342 if (rval != 0) { 6343 cmd->Status = EXT_STATUS_COPY_ERR; 6344 cmd->ResponseLen = 0; 6345 EL(ha, "failed, ddi_copyout-2\n"); 6346 } else { 6347 cmd->ResponseLen += (uint32_t)sizeof (EXT_DEVICEDATAENTRY); 6348 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 6349 } 6350 } 6351 6352 /* 6353 * ql_get_target_id 6354 * Performs EXT_SC_GET_TARGET_ID subcommand. of EXT_CC_GET_DATA. 6355 * 6356 * Input: 6357 * ha: adapter state pointer. 6358 * cmd: Local EXT_IOCTL cmd struct pointer. 6359 * mode: flags. 6360 * 6361 * Returns: 6362 * None, request status indicated in cmd->Status. 6363 * 6364 * Context: 6365 * Kernel context. 6366 */ 6367 static void 6368 ql_get_target_id(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode) 6369 { 6370 uint32_t rval; 6371 uint16_t qlnt; 6372 EXT_DEST_ADDR extdestaddr = {0}; 6373 uint8_t *name; 6374 uint8_t wwpn[EXT_DEF_WWN_NAME_SIZE]; 6375 ql_tgt_t *tq; 6376 6377 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 6378 6379 if (ddi_copyin((void *)(uintptr_t)cmd->RequestAdr, 6380 (void*)wwpn, sizeof (EXT_DEST_ADDR), mode) != 0) { 6381 EL(ha, "failed, ddi_copyin\n"); 6382 cmd->Status = EXT_STATUS_COPY_ERR; 6383 cmd->ResponseLen = 0; 6384 return; 6385 } 6386 6387 qlnt = QLNT_PORT; 6388 name = wwpn; 6389 QL_PRINT_9(CE_CONT, "(%d): wwpn=%02x%02x%02x%02x%02x%02x%02x%02x\n", 6390 ha->instance, name[0], name[1], name[2], name[3], name[4], 6391 name[5], name[6], name[7]); 6392 6393 tq = ql_find_port(ha, name, qlnt); 6394 if (tq == NULL || !VALID_TARGET_ID(ha, tq->loop_id)) { 6395 EL(ha, "failed, fc_port not found\n"); 6396 cmd->Status = EXT_STATUS_DEV_NOT_FOUND; 6397 cmd->ResponseLen = 0; 6398 return; 6399 } 6400 6401 bcopy(tq->port_name, (caddr_t)&extdestaddr.DestAddr.ScsiAddr.Target, 8); 6402 6403 rval = ddi_copyout((void *)&extdestaddr, 6404 (void *)(uintptr_t)cmd->ResponseAdr, sizeof (EXT_DEST_ADDR), mode); 6405 if (rval != 0) { 6406 EL(ha, "failed, ddi_copyout\n"); 6407 cmd->Status = EXT_STATUS_COPY_ERR; 6408 cmd->ResponseLen = 0; 6409 } 6410 6411 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 6412 } 6413 6414 /* 6415 * ql_setup_fcache 6416 * Populates selected flash sections into the cache 6417 * 6418 * Input: 6419 * ha = adapter state pointer. 6420 * 6421 * Returns: 6422 * ql local function return status code. 6423 * 6424 * Context: 6425 * Kernel context. 6426 * 6427 * Note: 6428 * Driver must be in stalled state prior to entering or 6429 * add code to this function prior to calling ql_setup_flash() 6430 */ 6431 int 6432 ql_setup_fcache(ql_adapter_state_t *ha) 6433 { 6434 int rval; 6435 uint32_t freadpos = 0; 6436 uint32_t fw_done = 0; 6437 ql_fcache_t *head = NULL; 6438 ql_fcache_t *tail = NULL; 6439 ql_fcache_t *ftmp; 6440 6441 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 6442 6443 CACHE_LOCK(ha); 6444 6445 /* If we already have populated it, rtn */ 6446 if (ha->fcache != NULL) { 6447 CACHE_UNLOCK(ha); 6448 EL(ha, "buffer already populated\n"); 6449 return (QL_SUCCESS); 6450 } 6451 6452 ql_flash_nvram_defaults(ha); 6453 6454 if ((rval = ql_setup_flash(ha)) != QL_SUCCESS) { 6455 CACHE_UNLOCK(ha); 6456 EL(ha, "unable to setup flash; rval=%xh\n", rval); 6457 return (rval); 6458 } 6459 6460 while (freadpos != 0xffffffff) { 6461 /* Allocate & populate this node */ 6462 if ((ftmp = ql_setup_fnode(ha)) == NULL) { 6463 EL(ha, "node alloc failed\n"); 6464 rval = QL_FUNCTION_FAILED; 6465 break; 6466 } 6467 6468 /* link in the new node */ 6469 if (head == NULL) { 6470 head = tail = ftmp; 6471 } else { 6472 tail->next = ftmp; 6473 tail = ftmp; 6474 } 6475 6476 /* Do the firmware node first for 24xx/25xx's */ 6477 if (fw_done == 0) { 6478 if (CFG_IST(ha, CFG_CTRL_24258081)) { 6479 freadpos = ha->flash_fw_addr << 2; 6480 } 6481 fw_done = 1; 6482 } 6483 6484 if ((rval = ql_dump_fcode(ha, ftmp->buf, FBUFSIZE, 6485 freadpos)) != QL_SUCCESS) { 6486 EL(ha, "failed, 24xx dump_fcode" 6487 " pos=%xh rval=%xh\n", freadpos, rval); 6488 rval = QL_FUNCTION_FAILED; 6489 break; 6490 } 6491 6492 /* checkout the pci data / format */ 6493 if (ql_check_pci(ha, ftmp, &freadpos)) { 6494 EL(ha, "flash header incorrect\n"); 6495 rval = QL_FUNCTION_FAILED; 6496 break; 6497 } 6498 } 6499 6500 if (rval != QL_SUCCESS) { 6501 /* release all resources we have */ 6502 ftmp = head; 6503 while (ftmp != NULL) { 6504 tail = ftmp->next; 6505 kmem_free(ftmp->buf, FBUFSIZE); 6506 kmem_free(ftmp, sizeof (ql_fcache_t)); 6507 ftmp = tail; 6508 } 6509 6510 EL(ha, "failed, done\n"); 6511 } else { 6512 ha->fcache = head; 6513 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 6514 } 6515 CACHE_UNLOCK(ha); 6516 6517 return (rval); 6518 } 6519 6520 /* 6521 * ql_update_fcache 6522 * re-populates updated flash into the fcache. If 6523 * fcache does not exist (e.g., flash was empty/invalid on 6524 * boot), this routine will create and the populate it. 6525 * 6526 * Input: 6527 * ha = adapter state pointer. 6528 * *bpf = Pointer to flash buffer. 6529 * bsize = Size of flash buffer. 6530 * 6531 * Returns: 6532 * 6533 * Context: 6534 * Kernel context. 6535 */ 6536 void 6537 ql_update_fcache(ql_adapter_state_t *ha, uint8_t *bfp, uint32_t bsize) 6538 { 6539 int rval = QL_SUCCESS; 6540 uint32_t freadpos = 0; 6541 uint32_t fw_done = 0; 6542 ql_fcache_t *head = NULL; 6543 ql_fcache_t *tail = NULL; 6544 ql_fcache_t *ftmp; 6545 6546 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 6547 6548 while (freadpos != 0xffffffff) { 6549 6550 /* Allocate & populate this node */ 6551 6552 if ((ftmp = ql_setup_fnode(ha)) == NULL) { 6553 EL(ha, "node alloc failed\n"); 6554 rval = QL_FUNCTION_FAILED; 6555 break; 6556 } 6557 6558 /* link in the new node */ 6559 if (head == NULL) { 6560 head = tail = ftmp; 6561 } else { 6562 tail->next = ftmp; 6563 tail = ftmp; 6564 } 6565 6566 /* Do the firmware node first for 24xx's */ 6567 if (fw_done == 0) { 6568 if (CFG_IST(ha, CFG_CTRL_24258081)) { 6569 freadpos = ha->flash_fw_addr << 2; 6570 } 6571 fw_done = 1; 6572 } 6573 6574 /* read in first FBUFSIZE bytes of this flash section */ 6575 if (freadpos+FBUFSIZE > bsize) { 6576 EL(ha, "passed buffer too small; fr=%xh, bsize=%xh\n", 6577 freadpos, bsize); 6578 rval = QL_FUNCTION_FAILED; 6579 break; 6580 } 6581 bcopy(bfp+freadpos, ftmp->buf, FBUFSIZE); 6582 6583 /* checkout the pci data / format */ 6584 if (ql_check_pci(ha, ftmp, &freadpos)) { 6585 EL(ha, "flash header incorrect\n"); 6586 rval = QL_FUNCTION_FAILED; 6587 break; 6588 } 6589 } 6590 6591 if (rval != QL_SUCCESS) { 6592 /* 6593 * release all resources we have 6594 */ 6595 ql_fcache_rel(head); 6596 EL(ha, "failed, done\n"); 6597 } else { 6598 /* 6599 * Release previous fcache resources and update with new 6600 */ 6601 CACHE_LOCK(ha); 6602 ql_fcache_rel(ha->fcache); 6603 ha->fcache = head; 6604 CACHE_UNLOCK(ha); 6605 6606 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 6607 } 6608 } 6609 6610 /* 6611 * ql_setup_fnode 6612 * Allocates fcache node 6613 * 6614 * Input: 6615 * ha = adapter state pointer. 6616 * node = point to allocated fcache node (NULL = failed) 6617 * 6618 * Returns: 6619 * 6620 * Context: 6621 * Kernel context. 6622 * 6623 * Note: 6624 * Driver must be in stalled state prior to entering or 6625 * add code to this function prior to calling ql_setup_flash() 6626 */ 6627 static ql_fcache_t * 6628 ql_setup_fnode(ql_adapter_state_t *ha) 6629 { 6630 ql_fcache_t *fnode = NULL; 6631 6632 if ((fnode = (ql_fcache_t *)(kmem_zalloc(sizeof (ql_fcache_t), 6633 KM_SLEEP))) == NULL) { 6634 EL(ha, "fnode alloc failed\n"); 6635 fnode = NULL; 6636 } else if ((fnode->buf = (uint8_t *)(kmem_zalloc(FBUFSIZE, 6637 KM_SLEEP))) == NULL) { 6638 EL(ha, "buf alloc failed\n"); 6639 kmem_free(fnode, sizeof (ql_fcache_t)); 6640 fnode = NULL; 6641 } else { 6642 fnode->buflen = FBUFSIZE; 6643 } 6644 6645 return (fnode); 6646 } 6647 6648 /* 6649 * ql_fcache_rel 6650 * Releases the fcache resources 6651 * 6652 * Input: 6653 * ha = adapter state pointer. 6654 * head = Pointer to fcache linked list 6655 * 6656 * Returns: 6657 * 6658 * Context: 6659 * Kernel context. 6660 * 6661 */ 6662 void 6663 ql_fcache_rel(ql_fcache_t *head) 6664 { 6665 ql_fcache_t *ftmp = head; 6666 ql_fcache_t *tail; 6667 6668 /* release all resources we have */ 6669 while (ftmp != NULL) { 6670 tail = ftmp->next; 6671 kmem_free(ftmp->buf, FBUFSIZE); 6672 kmem_free(ftmp, sizeof (ql_fcache_t)); 6673 ftmp = tail; 6674 } 6675 } 6676 6677 /* 6678 * ql_update_flash_caches 6679 * Updates driver flash caches 6680 * 6681 * Input: 6682 * ha: adapter state pointer. 6683 * 6684 * Context: 6685 * Kernel context. 6686 */ 6687 static void 6688 ql_update_flash_caches(ql_adapter_state_t *ha) 6689 { 6690 uint32_t len; 6691 ql_link_t *link; 6692 ql_adapter_state_t *ha2; 6693 6694 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 6695 6696 /* Get base path length. */ 6697 for (len = (uint32_t)strlen(ha->devpath); len; len--) { 6698 if (ha->devpath[len] == ',' || 6699 ha->devpath[len] == '@') { 6700 break; 6701 } 6702 } 6703 6704 /* Reset fcache on all adapter instances. */ 6705 for (link = ql_hba.first; link != NULL; link = link->next) { 6706 ha2 = link->base_address; 6707 6708 if (strncmp(ha->devpath, ha2->devpath, len) != 0) { 6709 continue; 6710 } 6711 6712 CACHE_LOCK(ha2); 6713 ql_fcache_rel(ha2->fcache); 6714 ha2->fcache = NULL; 6715 6716 if (CFG_IST(ha, CFG_CTRL_24258081)) { 6717 if (ha2->vcache != NULL) { 6718 kmem_free(ha2->vcache, QL_24XX_VPD_SIZE); 6719 ha2->vcache = NULL; 6720 } 6721 } 6722 CACHE_UNLOCK(ha2); 6723 6724 (void) ql_setup_fcache(ha2); 6725 } 6726 6727 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 6728 } 6729 6730 /* 6731 * ql_get_fbuf 6732 * Search the fcache list for the type specified 6733 * 6734 * Input: 6735 * fptr = Pointer to fcache linked list 6736 * ftype = Type of image to be returned. 6737 * 6738 * Returns: 6739 * Pointer to ql_fcache_t. 6740 * NULL means not found. 6741 * 6742 * Context: 6743 * Kernel context. 6744 * 6745 * 6746 */ 6747 ql_fcache_t * 6748 ql_get_fbuf(ql_fcache_t *fptr, uint32_t ftype) 6749 { 6750 while (fptr != NULL) { 6751 /* does this image meet criteria? */ 6752 if (ftype & fptr->type) { 6753 break; 6754 } 6755 fptr = fptr->next; 6756 } 6757 return (fptr); 6758 } 6759 6760 /* 6761 * ql_check_pci 6762 * 6763 * checks the passed buffer for a valid pci signature and 6764 * expected (and in range) pci length values. 6765 * 6766 * For firmware type, a pci header is added since the image in 6767 * the flash does not have one (!!!). 6768 * 6769 * On successful pci check, nextpos adjusted to next pci header. 6770 * 6771 * Returns: 6772 * -1 --> last pci image 6773 * 0 --> pci header valid 6774 * 1 --> pci header invalid. 6775 * 6776 * Context: 6777 * Kernel context. 6778 */ 6779 static int 6780 ql_check_pci(ql_adapter_state_t *ha, ql_fcache_t *fcache, uint32_t *nextpos) 6781 { 6782 pci_header_t *pcih; 6783 pci_data_t *pcid; 6784 uint32_t doff; 6785 uint8_t *pciinfo; 6786 6787 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 6788 6789 if (fcache != NULL) { 6790 pciinfo = fcache->buf; 6791 } else { 6792 EL(ha, "failed, null fcache ptr passed\n"); 6793 return (1); 6794 } 6795 6796 if (pciinfo == NULL) { 6797 EL(ha, "failed, null pciinfo ptr passed\n"); 6798 return (1); 6799 } 6800 6801 if (CFG_IST(ha, CFG_SBUS_CARD)) { 6802 caddr_t bufp; 6803 uint_t len; 6804 6805 if (pciinfo[0] != SBUS_CODE_FCODE) { 6806 EL(ha, "failed, unable to detect sbus fcode\n"); 6807 return (1); 6808 } 6809 fcache->type = FTYPE_FCODE; 6810 6811 /*LINTED [Solaris DDI_DEV_T_ANY Lint error]*/ 6812 if (ddi_getlongprop(DDI_DEV_T_ANY, ha->dip, 6813 PROP_LEN_AND_VAL_ALLOC | DDI_PROP_DONTPASS | 6814 DDI_PROP_CANSLEEP, "version", (caddr_t)&bufp, 6815 (int *)&len) == DDI_PROP_SUCCESS) { 6816 6817 (void) snprintf(fcache->verstr, 6818 FCHBA_OPTION_ROM_VERSION_LEN, "%s", bufp); 6819 kmem_free(bufp, len); 6820 } 6821 6822 *nextpos = 0xffffffff; 6823 6824 QL_PRINT_9(CE_CONT, "(%d): CFG_SBUS_CARD, done\n", 6825 ha->instance); 6826 6827 return (0); 6828 } 6829 6830 if (*nextpos == ha->flash_fw_addr << 2) { 6831 6832 pci_header_t fwh = {0}; 6833 pci_data_t fwd = {0}; 6834 uint8_t *buf, *bufp; 6835 6836 /* 6837 * Build a pci header for the firmware module 6838 */ 6839 if ((buf = (uint8_t *)(kmem_zalloc(FBUFSIZE, KM_SLEEP))) == 6840 NULL) { 6841 EL(ha, "failed, unable to allocate buffer\n"); 6842 return (1); 6843 } 6844 6845 fwh.signature[0] = PCI_HEADER0; 6846 fwh.signature[1] = PCI_HEADER1; 6847 fwh.dataoffset[0] = LSB(sizeof (pci_header_t)); 6848 fwh.dataoffset[1] = MSB(sizeof (pci_header_t)); 6849 6850 fwd.signature[0] = 'P'; 6851 fwd.signature[1] = 'C'; 6852 fwd.signature[2] = 'I'; 6853 fwd.signature[3] = 'R'; 6854 fwd.codetype = PCI_CODE_FW; 6855 fwd.pcidatalen[0] = LSB(sizeof (pci_data_t)); 6856 fwd.pcidatalen[1] = MSB(sizeof (pci_data_t)); 6857 6858 bufp = buf; 6859 bcopy(&fwh, bufp, sizeof (pci_header_t)); 6860 bufp += sizeof (pci_header_t); 6861 bcopy(&fwd, bufp, sizeof (pci_data_t)); 6862 bufp += sizeof (pci_data_t); 6863 6864 bcopy(fcache->buf, bufp, (FBUFSIZE - sizeof (pci_header_t) - 6865 sizeof (pci_data_t))); 6866 bcopy(buf, fcache->buf, FBUFSIZE); 6867 6868 fcache->type = FTYPE_FW; 6869 6870 (void) snprintf(fcache->verstr, FCHBA_OPTION_ROM_VERSION_LEN, 6871 "%d.%02d.%02d", fcache->buf[19], fcache->buf[23], 6872 fcache->buf[27]); 6873 6874 if (CFG_IST(ha, CFG_CTRL_81XX)) { 6875 *nextpos = 0x200000; 6876 } else if (CFG_IST(ha, CFG_CTRL_8021)) { 6877 *nextpos = 0x80000; 6878 } else { 6879 *nextpos = 0; 6880 } 6881 kmem_free(buf, FBUFSIZE); 6882 6883 QL_PRINT_9(CE_CONT, "(%d): FTYPE_FW, done\n", ha->instance); 6884 6885 return (0); 6886 } 6887 6888 /* get to the pci header image length */ 6889 pcih = (pci_header_t *)pciinfo; 6890 6891 doff = pcih->dataoffset[0] | (pcih->dataoffset[1] << 8); 6892 6893 /* some header section sanity check */ 6894 if (pcih->signature[0] != PCI_HEADER0 || 6895 pcih->signature[1] != PCI_HEADER1 || doff > 50) { 6896 EL(ha, "buffer format error: s0=%xh, s1=%xh, off=%xh\n", 6897 pcih->signature[0], pcih->signature[1], doff); 6898 return (1); 6899 } 6900 6901 pcid = (pci_data_t *)(pciinfo + doff); 6902 6903 /* a slight sanity data section check */ 6904 if (pcid->signature[0] != 'P' || pcid->signature[1] != 'C' || 6905 pcid->signature[2] != 'I' || pcid->signature[3] != 'R') { 6906 EL(ha, "failed, data sig mismatch!\n"); 6907 return (1); 6908 } 6909 6910 if (pcid->indicator == PCI_IND_LAST_IMAGE) { 6911 QL_PRINT_9(CE_CONT, "(%d): last image\n", ha->instance); 6912 if (CFG_IST(ha, CFG_CTRL_24258081)) { 6913 ql_flash_layout_table(ha, *nextpos + 6914 (pcid->imagelength[0] | (pcid->imagelength[1] << 6915 8)) * PCI_SECTOR_SIZE); 6916 (void) ql_24xx_flash_desc(ha); 6917 } 6918 *nextpos = 0xffffffff; 6919 } else { 6920 /* adjust the next flash read start position */ 6921 *nextpos += (pcid->imagelength[0] | 6922 (pcid->imagelength[1] << 8)) * PCI_SECTOR_SIZE; 6923 } 6924 6925 switch (pcid->codetype) { 6926 case PCI_CODE_X86PC: 6927 fcache->type = FTYPE_BIOS; 6928 break; 6929 case PCI_CODE_FCODE: 6930 fcache->type = FTYPE_FCODE; 6931 break; 6932 case PCI_CODE_EFI: 6933 fcache->type = FTYPE_EFI; 6934 break; 6935 case PCI_CODE_HPPA: 6936 fcache->type = FTYPE_HPPA; 6937 break; 6938 default: 6939 fcache->type = FTYPE_UNKNOWN; 6940 break; 6941 } 6942 6943 (void) snprintf(fcache->verstr, FCHBA_OPTION_ROM_VERSION_LEN, 6944 "%d.%02d", pcid->revisionlevel[1], pcid->revisionlevel[0]); 6945 6946 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 6947 6948 return (0); 6949 } 6950 6951 /* 6952 * ql_flash_layout_table 6953 * Obtains flash addresses from table 6954 * 6955 * Input: 6956 * ha: adapter state pointer. 6957 * flt_paddr: flash layout pointer address. 6958 * 6959 * Context: 6960 * Kernel context. 6961 */ 6962 static void 6963 ql_flash_layout_table(ql_adapter_state_t *ha, uint32_t flt_paddr) 6964 { 6965 ql_flt_ptr_t *fptr; 6966 uint8_t *bp; 6967 int rval; 6968 uint32_t len, faddr, cnt; 6969 uint16_t chksum, w16; 6970 6971 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 6972 6973 /* Process flash layout table header */ 6974 len = sizeof (ql_flt_ptr_t); 6975 if ((bp = kmem_zalloc(len, KM_SLEEP)) == NULL) { 6976 EL(ha, "kmem_zalloc=null\n"); 6977 return; 6978 } 6979 6980 /* Process pointer to flash layout table */ 6981 if ((rval = ql_dump_fcode(ha, bp, len, flt_paddr)) != QL_SUCCESS) { 6982 EL(ha, "fptr dump_flash pos=%xh, status=%xh\n", flt_paddr, 6983 rval); 6984 kmem_free(bp, len); 6985 return; 6986 } 6987 fptr = (ql_flt_ptr_t *)bp; 6988 6989 /* Verify pointer to flash layout table. */ 6990 for (chksum = 0, cnt = 0; cnt < len; cnt += 2) { 6991 w16 = (uint16_t)CHAR_TO_SHORT(bp[cnt], bp[cnt + 1]); 6992 chksum += w16; 6993 } 6994 if (chksum != 0 || fptr->sig[0] != 'Q' || fptr->sig[1] != 'F' || 6995 fptr->sig[2] != 'L' || fptr->sig[3] != 'T') { 6996 EL(ha, "ptr chksum=%xh, sig=%c%c%c%c\n", chksum, fptr->sig[0], 6997 fptr->sig[1], fptr->sig[2], fptr->sig[3]); 6998 kmem_free(bp, len); 6999 return; 7000 } 7001 faddr = CHAR_TO_LONG(fptr->addr[0], fptr->addr[1], fptr->addr[2], 7002 fptr->addr[3]); 7003 7004 kmem_free(bp, len); 7005 7006 ql_process_flt(ha, faddr); 7007 7008 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 7009 } 7010 7011 /* 7012 * ql_process_flt 7013 * Obtains flash addresses from flash layout table 7014 * 7015 * Input: 7016 * ha: adapter state pointer. 7017 * faddr: flash layout table byte address. 7018 * 7019 * Context: 7020 * Kernel context. 7021 */ 7022 static void 7023 ql_process_flt(ql_adapter_state_t *ha, uint32_t faddr) 7024 { 7025 ql_flt_hdr_t *fhdr; 7026 ql_flt_region_t *frgn; 7027 uint8_t *bp, *eaddr, nv_rg, vpd_rg; 7028 int rval; 7029 uint32_t len, cnt, fe_addr; 7030 uint16_t chksum, w16; 7031 7032 QL_PRINT_9(CE_CONT, "(%d): started faddr=%xh\n", ha->instance, faddr); 7033 7034 /* Process flash layout table header */ 7035 if ((bp = kmem_zalloc(FLASH_LAYOUT_TABLE_SIZE, KM_SLEEP)) == NULL) { 7036 EL(ha, "kmem_zalloc=null\n"); 7037 return; 7038 } 7039 fhdr = (ql_flt_hdr_t *)bp; 7040 7041 /* Process flash layout table. */ 7042 if ((rval = ql_dump_fcode(ha, bp, FLASH_LAYOUT_TABLE_SIZE, faddr)) != 7043 QL_SUCCESS) { 7044 EL(ha, "fhdr dump_flash pos=%xh, status=%xh\n", faddr, rval); 7045 kmem_free(bp, FLASH_LAYOUT_TABLE_SIZE); 7046 return; 7047 } 7048 7049 /* Verify flash layout table. */ 7050 len = (uint32_t)(CHAR_TO_SHORT(fhdr->len[0], fhdr->len[1]) + 7051 sizeof (ql_flt_hdr_t) + sizeof (ql_flt_region_t)); 7052 if (len > FLASH_LAYOUT_TABLE_SIZE) { 7053 chksum = 0xffff; 7054 } else { 7055 for (chksum = 0, cnt = 0; cnt < len; cnt += 2) { 7056 w16 = (uint16_t)CHAR_TO_SHORT(bp[cnt], bp[cnt + 1]); 7057 chksum += w16; 7058 } 7059 } 7060 w16 = CHAR_TO_SHORT(fhdr->version[0], fhdr->version[1]); 7061 if (chksum != 0 || w16 != 1) { 7062 EL(ha, "table chksum=%xh, version=%d\n", chksum, w16); 7063 kmem_free(bp, FLASH_LAYOUT_TABLE_SIZE); 7064 return; 7065 } 7066 eaddr = bp + len; 7067 7068 /* Process Function/Port Configuration Map. */ 7069 nv_rg = vpd_rg = 0; 7070 if (CFG_IST(ha, CFG_CTRL_8021)) { 7071 uint16_t i; 7072 uint8_t *mbp = eaddr; 7073 ql_fp_cfg_map_t *cmp = (ql_fp_cfg_map_t *)mbp; 7074 7075 len = (uint32_t)(CHAR_TO_SHORT(cmp->hdr.len[0], 7076 cmp->hdr.len[1])); 7077 if (len > FLASH_LAYOUT_TABLE_SIZE) { 7078 chksum = 0xffff; 7079 } else { 7080 for (chksum = 0, cnt = 0; cnt < len; cnt += 2) { 7081 w16 = (uint16_t)CHAR_TO_SHORT(mbp[cnt], 7082 mbp[cnt + 1]); 7083 chksum += w16; 7084 } 7085 } 7086 w16 = CHAR_TO_SHORT(cmp->hdr.version[0], cmp->hdr.version[1]); 7087 if (chksum != 0 || w16 != 1 || 7088 cmp->hdr.Signature[0] != 'F' || 7089 cmp->hdr.Signature[1] != 'P' || 7090 cmp->hdr.Signature[2] != 'C' || 7091 cmp->hdr.Signature[3] != 'M') { 7092 EL(ha, "cfg_map chksum=%xh, version=%d, " 7093 "sig=%c%c%c%c\n", chksum, w16, 7094 cmp->hdr.Signature[0], cmp->hdr.Signature[1], 7095 cmp->hdr.Signature[2], cmp->hdr.Signature[3]); 7096 } else { 7097 cnt = (uint16_t) 7098 (CHAR_TO_SHORT(cmp->hdr.NumberEntries[0], 7099 cmp->hdr.NumberEntries[1])); 7100 /* Locate entry for function. */ 7101 for (i = 0; i < cnt; i++) { 7102 if (cmp->cfg[i].FunctionType == FT_FC && 7103 cmp->cfg[i].FunctionNumber[0] == 7104 ha->function_number && 7105 cmp->cfg[i].FunctionNumber[1] == 0) { 7106 nv_rg = cmp->cfg[i].ConfigRegion; 7107 vpd_rg = cmp->cfg[i].VpdRegion; 7108 break; 7109 } 7110 } 7111 7112 if (nv_rg == 0 || vpd_rg == 0) { 7113 EL(ha, "cfg_map nv_rg=%d, vpd_rg=%d\n", nv_rg, 7114 vpd_rg); 7115 nv_rg = vpd_rg = 0; 7116 } 7117 } 7118 } 7119 7120 /* Process flash layout table regions */ 7121 for (frgn = (ql_flt_region_t *)(bp + sizeof (ql_flt_hdr_t)); 7122 (uint8_t *)frgn < eaddr; frgn++) { 7123 faddr = CHAR_TO_LONG(frgn->beg_addr[0], frgn->beg_addr[1], 7124 frgn->beg_addr[2], frgn->beg_addr[3]); 7125 faddr >>= 2; 7126 fe_addr = CHAR_TO_LONG(frgn->end_addr[0], frgn->end_addr[1], 7127 frgn->end_addr[2], frgn->end_addr[3]); 7128 fe_addr >>= 2; 7129 7130 switch (frgn->region) { 7131 case FLASH_8021_BOOTLOADER_REGION: 7132 ha->bootloader_addr = faddr; 7133 ha->bootloader_size = (fe_addr - faddr) + 1; 7134 QL_PRINT_9(CE_CONT, "(%d): bootloader_addr=%xh, " 7135 "size=%xh\n", ha->instance, faddr, 7136 ha->bootloader_size); 7137 break; 7138 case FLASH_FW_REGION: 7139 case FLASH_8021_FW_REGION: 7140 ha->flash_fw_addr = faddr; 7141 ha->flash_fw_size = (fe_addr - faddr) + 1; 7142 QL_PRINT_9(CE_CONT, "(%d): flash_fw_addr=%xh, " 7143 "size=%xh\n", ha->instance, faddr, 7144 ha->flash_fw_size); 7145 break; 7146 case FLASH_GOLDEN_FW_REGION: 7147 case FLASH_8021_GOLDEN_FW_REGION: 7148 ha->flash_golden_fw_addr = faddr; 7149 QL_PRINT_9(CE_CONT, "(%d): flash_golden_fw_addr=%xh\n", 7150 ha->instance, faddr); 7151 break; 7152 case FLASH_8021_VPD_REGION: 7153 if (!vpd_rg || vpd_rg == FLASH_8021_VPD_REGION) { 7154 ha->flash_vpd_addr = faddr; 7155 QL_PRINT_9(CE_CONT, "(%d): 8021_flash_vpd_" 7156 "addr=%xh\n", ha->instance, faddr); 7157 } 7158 break; 7159 case FLASH_VPD_0_REGION: 7160 if (vpd_rg) { 7161 if (vpd_rg == FLASH_VPD_0_REGION) { 7162 ha->flash_vpd_addr = faddr; 7163 QL_PRINT_9(CE_CONT, "(%d): vpd_rg " 7164 "flash_vpd_addr=%xh\n", 7165 ha->instance, faddr); 7166 } 7167 } else if (!(ha->flags & FUNCTION_1) && 7168 !(CFG_IST(ha, CFG_CTRL_8021))) { 7169 ha->flash_vpd_addr = faddr; 7170 QL_PRINT_9(CE_CONT, "(%d): flash_vpd_addr=%xh" 7171 "\n", ha->instance, faddr); 7172 } 7173 break; 7174 case FLASH_NVRAM_0_REGION: 7175 if (nv_rg) { 7176 if (nv_rg == FLASH_NVRAM_0_REGION) { 7177 ADAPTER_STATE_LOCK(ha); 7178 ha->flags &= ~FUNCTION_1; 7179 ADAPTER_STATE_UNLOCK(ha); 7180 ha->flash_nvram_addr = faddr; 7181 QL_PRINT_9(CE_CONT, "(%d): nv_rg " 7182 "flash_nvram_addr=%xh\n", 7183 ha->instance, faddr); 7184 } 7185 } else if (!(ha->flags & FUNCTION_1)) { 7186 ha->flash_nvram_addr = faddr; 7187 QL_PRINT_9(CE_CONT, "(%d): flash_nvram_addr=" 7188 "%xh\n", ha->instance, faddr); 7189 } 7190 break; 7191 case FLASH_VPD_1_REGION: 7192 if (vpd_rg) { 7193 if (vpd_rg == FLASH_VPD_1_REGION) { 7194 ha->flash_vpd_addr = faddr; 7195 QL_PRINT_9(CE_CONT, "(%d): vpd_rg " 7196 "flash_vpd_addr=%xh\n", 7197 ha->instance, faddr); 7198 } 7199 } else if (ha->flags & FUNCTION_1 && 7200 !(CFG_IST(ha, CFG_CTRL_8021))) { 7201 ha->flash_vpd_addr = faddr; 7202 QL_PRINT_9(CE_CONT, "(%d): flash_vpd_addr=%xh" 7203 "\n", ha->instance, faddr); 7204 } 7205 break; 7206 case FLASH_NVRAM_1_REGION: 7207 if (nv_rg) { 7208 if (nv_rg == FLASH_NVRAM_1_REGION) { 7209 ADAPTER_STATE_LOCK(ha); 7210 ha->flags |= FUNCTION_1; 7211 ADAPTER_STATE_UNLOCK(ha); 7212 ha->flash_nvram_addr = faddr; 7213 QL_PRINT_9(CE_CONT, "(%d): nv_rg " 7214 "flash_nvram_addr=%xh\n", 7215 ha->instance, faddr); 7216 } 7217 } else if (ha->flags & FUNCTION_1) { 7218 ha->flash_nvram_addr = faddr; 7219 QL_PRINT_9(CE_CONT, "(%d): flash_nvram_addr=" 7220 "%xh\n", ha->instance, faddr); 7221 } 7222 break; 7223 case FLASH_DESC_TABLE_REGION: 7224 if (!(CFG_IST(ha, CFG_CTRL_8021))) { 7225 ha->flash_desc_addr = faddr; 7226 QL_PRINT_9(CE_CONT, "(%d): flash_desc_addr=" 7227 "%xh\n", ha->instance, faddr); 7228 } 7229 break; 7230 case FLASH_ERROR_LOG_0_REGION: 7231 if (!(ha->flags & FUNCTION_1)) { 7232 ha->flash_errlog_start = faddr; 7233 QL_PRINT_9(CE_CONT, "(%d): flash_errlog_addr=" 7234 "%xh\n", ha->instance, faddr); 7235 } 7236 break; 7237 case FLASH_ERROR_LOG_1_REGION: 7238 if (ha->flags & FUNCTION_1) { 7239 ha->flash_errlog_start = faddr; 7240 QL_PRINT_9(CE_CONT, "(%d): flash_errlog_addr=" 7241 "%xh\n", ha->instance, faddr); 7242 } 7243 break; 7244 default: 7245 break; 7246 } 7247 } 7248 kmem_free(bp, FLASH_LAYOUT_TABLE_SIZE); 7249 7250 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 7251 } 7252 7253 /* 7254 * ql_flash_nvram_defaults 7255 * Flash default addresses. 7256 * 7257 * Input: 7258 * ha: adapter state pointer. 7259 * 7260 * Returns: 7261 * ql local function return status code. 7262 * 7263 * Context: 7264 * Kernel context. 7265 */ 7266 static void 7267 ql_flash_nvram_defaults(ql_adapter_state_t *ha) 7268 { 7269 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 7270 7271 if (ha->flags & FUNCTION_1) { 7272 if (CFG_IST(ha, CFG_CTRL_2300)) { 7273 ha->flash_nvram_addr = NVRAM_2300_FUNC1_ADDR; 7274 ha->flash_fw_addr = FLASH_2300_FIRMWARE_ADDR; 7275 } else if (CFG_IST(ha, CFG_CTRL_2422)) { 7276 ha->flash_data_addr = FLASH_24_25_DATA_ADDR; 7277 ha->flash_nvram_addr = NVRAM_2400_FUNC1_ADDR; 7278 ha->flash_vpd_addr = VPD_2400_FUNC1_ADDR; 7279 ha->flash_errlog_start = FLASH_2400_ERRLOG_START_ADDR_1; 7280 ha->flash_desc_addr = FLASH_2400_DESCRIPTOR_TABLE; 7281 ha->flash_fw_addr = FLASH_2400_FIRMWARE_ADDR; 7282 } else if (CFG_IST(ha, CFG_CTRL_25XX)) { 7283 ha->flash_data_addr = FLASH_24_25_DATA_ADDR; 7284 ha->flash_nvram_addr = NVRAM_2500_FUNC1_ADDR; 7285 ha->flash_vpd_addr = VPD_2500_FUNC1_ADDR; 7286 ha->flash_errlog_start = FLASH_2500_ERRLOG_START_ADDR_1; 7287 ha->flash_desc_addr = FLASH_2500_DESCRIPTOR_TABLE; 7288 ha->flash_fw_addr = FLASH_2500_FIRMWARE_ADDR; 7289 } else if (CFG_IST(ha, CFG_CTRL_81XX)) { 7290 ha->flash_data_addr = FLASH_8100_DATA_ADDR; 7291 ha->flash_nvram_addr = NVRAM_8100_FUNC1_ADDR; 7292 ha->flash_vpd_addr = VPD_8100_FUNC1_ADDR; 7293 ha->flash_errlog_start = FLASH_8100_ERRLOG_START_ADDR_1; 7294 ha->flash_desc_addr = FLASH_8100_DESCRIPTOR_TABLE; 7295 ha->flash_fw_addr = FLASH_8100_FIRMWARE_ADDR; 7296 } else if (CFG_IST(ha, CFG_CTRL_8021)) { 7297 ha->flash_data_addr = 0; 7298 ha->flash_nvram_addr = NVRAM_8021_FUNC1_ADDR; 7299 ha->flash_vpd_addr = VPD_8021_FUNC1_ADDR; 7300 ha->flash_errlog_start = 0; 7301 ha->flash_desc_addr = FLASH_8021_DESCRIPTOR_TABLE; 7302 ha->flash_fw_addr = FLASH_8021_FIRMWARE_ADDR; 7303 ha->flash_fw_size = FLASH_8021_FIRMWARE_SIZE; 7304 ha->bootloader_addr = FLASH_8021_BOOTLOADER_ADDR; 7305 ha->bootloader_size = FLASH_8021_BOOTLOADER_SIZE; 7306 } 7307 } else { 7308 if (CFG_IST(ha, CFG_CTRL_2200)) { 7309 ha->flash_nvram_addr = NVRAM_2200_FUNC0_ADDR; 7310 ha->flash_fw_addr = FLASH_2200_FIRMWARE_ADDR; 7311 } else if (CFG_IST(ha, CFG_CTRL_2300) || 7312 (CFG_IST(ha, CFG_CTRL_6322))) { 7313 ha->flash_nvram_addr = NVRAM_2300_FUNC0_ADDR; 7314 ha->flash_fw_addr = FLASH_2300_FIRMWARE_ADDR; 7315 } else if (CFG_IST(ha, CFG_CTRL_2422)) { 7316 ha->flash_data_addr = FLASH_24_25_DATA_ADDR; 7317 ha->flash_nvram_addr = NVRAM_2400_FUNC0_ADDR; 7318 ha->flash_vpd_addr = VPD_2400_FUNC0_ADDR; 7319 ha->flash_errlog_start = FLASH_2400_ERRLOG_START_ADDR_0; 7320 ha->flash_desc_addr = FLASH_2400_DESCRIPTOR_TABLE; 7321 ha->flash_fw_addr = FLASH_2400_FIRMWARE_ADDR; 7322 } else if (CFG_IST(ha, CFG_CTRL_25XX)) { 7323 ha->flash_data_addr = FLASH_24_25_DATA_ADDR; 7324 ha->flash_nvram_addr = NVRAM_2500_FUNC0_ADDR; 7325 ha->flash_vpd_addr = VPD_2500_FUNC0_ADDR; 7326 ha->flash_errlog_start = FLASH_2500_ERRLOG_START_ADDR_0; 7327 ha->flash_desc_addr = FLASH_2500_DESCRIPTOR_TABLE; 7328 ha->flash_fw_addr = FLASH_2500_FIRMWARE_ADDR; 7329 } else if (CFG_IST(ha, CFG_CTRL_81XX)) { 7330 ha->flash_data_addr = FLASH_8100_DATA_ADDR; 7331 ha->flash_nvram_addr = NVRAM_8100_FUNC0_ADDR; 7332 ha->flash_vpd_addr = VPD_8100_FUNC0_ADDR; 7333 ha->flash_errlog_start = FLASH_8100_ERRLOG_START_ADDR_0; 7334 ha->flash_desc_addr = FLASH_8100_DESCRIPTOR_TABLE; 7335 ha->flash_fw_addr = FLASH_8100_FIRMWARE_ADDR; 7336 } else if (CFG_IST(ha, CFG_CTRL_8021)) { 7337 ha->flash_data_addr = 0; 7338 ha->flash_nvram_addr = NVRAM_8021_FUNC0_ADDR; 7339 ha->flash_vpd_addr = VPD_8021_FUNC0_ADDR; 7340 ha->flash_errlog_start = 0; 7341 ha->flash_desc_addr = FLASH_8021_DESCRIPTOR_TABLE; 7342 ha->flash_fw_addr = FLASH_8021_FIRMWARE_ADDR; 7343 ha->flash_fw_size = FLASH_8021_FIRMWARE_SIZE; 7344 ha->bootloader_addr = FLASH_8021_BOOTLOADER_ADDR; 7345 ha->bootloader_size = FLASH_8021_BOOTLOADER_SIZE; 7346 } else { 7347 EL(ha, "unassigned flash fn0 addr: %x\n", 7348 ha->device_id); 7349 } 7350 } 7351 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 7352 } 7353 7354 /* 7355 * ql_get_sfp 7356 * Returns sfp data to sdmapi caller 7357 * 7358 * Input: 7359 * ha: adapter state pointer. 7360 * cmd: Local EXT_IOCTL cmd struct pointer. 7361 * mode: flags. 7362 * 7363 * Returns: 7364 * None, request status indicated in cmd->Status. 7365 * 7366 * Context: 7367 * Kernel context. 7368 */ 7369 static void 7370 ql_get_sfp(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode) 7371 { 7372 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 7373 7374 if ((CFG_IST(ha, CFG_CTRL_24258081)) == 0) { 7375 cmd->Status = EXT_STATUS_INVALID_REQUEST; 7376 EL(ha, "failed, invalid request for HBA\n"); 7377 return; 7378 } 7379 7380 if (cmd->ResponseLen < QL_24XX_SFP_SIZE) { 7381 cmd->Status = EXT_STATUS_BUFFER_TOO_SMALL; 7382 cmd->DetailStatus = QL_24XX_SFP_SIZE; 7383 EL(ha, "failed, ResponseLen < SFP len, len passed=%xh\n", 7384 cmd->ResponseLen); 7385 return; 7386 } 7387 7388 /* Dump SFP data in user buffer */ 7389 if ((ql_dump_sfp(ha, (void *)(uintptr_t)(cmd->ResponseAdr), 7390 mode)) != 0) { 7391 cmd->Status = EXT_STATUS_COPY_ERR; 7392 EL(ha, "failed, copy error\n"); 7393 } else { 7394 cmd->Status = EXT_STATUS_OK; 7395 } 7396 7397 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 7398 } 7399 7400 /* 7401 * ql_dump_sfp 7402 * Dumps SFP. 7403 * 7404 * Input: 7405 * ha: adapter state pointer. 7406 * bp: buffer address. 7407 * mode: flags 7408 * 7409 * Returns: 7410 * 7411 * Context: 7412 * Kernel context. 7413 */ 7414 static int 7415 ql_dump_sfp(ql_adapter_state_t *ha, void *bp, int mode) 7416 { 7417 dma_mem_t mem; 7418 uint32_t cnt; 7419 int rval2, rval = 0; 7420 uint32_t dxfer; 7421 7422 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 7423 7424 /* Get memory for SFP. */ 7425 7426 if ((rval2 = ql_get_dma_mem(ha, &mem, 64, LITTLE_ENDIAN_DMA, 7427 QL_DMA_DATA_ALIGN)) != QL_SUCCESS) { 7428 EL(ha, "failed, ql_get_dma_mem=%xh\n", rval2); 7429 return (ENOMEM); 7430 } 7431 7432 for (cnt = 0; cnt < QL_24XX_SFP_SIZE; cnt += mem.size) { 7433 rval2 = ql_read_sfp(ha, &mem, 7434 (uint16_t)(cnt < 256 ? 0xA0 : 0xA2), 7435 (uint16_t)(cnt & 0xff)); 7436 if (rval2 != QL_SUCCESS) { 7437 EL(ha, "failed, read_sfp=%xh\n", rval2); 7438 rval = EFAULT; 7439 break; 7440 } 7441 7442 /* copy the data back */ 7443 if ((dxfer = ql_send_buffer_data(mem.bp, bp, mem.size, 7444 mode)) != mem.size) { 7445 /* ddi copy error */ 7446 EL(ha, "failed, ddi copy; byte cnt = %xh", dxfer); 7447 rval = EFAULT; 7448 break; 7449 } 7450 7451 /* adjust the buffer pointer */ 7452 bp = (caddr_t)bp + mem.size; 7453 } 7454 7455 ql_free_phys(ha, &mem); 7456 7457 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 7458 7459 return (rval); 7460 } 7461 7462 /* 7463 * ql_port_param 7464 * Retrieves or sets the firmware port speed settings 7465 * 7466 * Input: 7467 * ha: adapter state pointer. 7468 * cmd: Local EXT_IOCTL cmd struct pointer. 7469 * mode: flags. 7470 * 7471 * Returns: 7472 * None, request status indicated in cmd->Status. 7473 * 7474 * Context: 7475 * Kernel context. 7476 * 7477 */ 7478 static void 7479 ql_port_param(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode) 7480 { 7481 uint8_t *name; 7482 ql_tgt_t *tq; 7483 EXT_PORT_PARAM port_param = {0}; 7484 uint32_t rval = QL_SUCCESS; 7485 uint32_t idma_rate; 7486 7487 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 7488 7489 if (CFG_IST(ha, CFG_CTRL_242581) == 0) { 7490 EL(ha, "invalid request for this HBA\n"); 7491 cmd->Status = EXT_STATUS_INVALID_REQUEST; 7492 cmd->ResponseLen = 0; 7493 return; 7494 } 7495 7496 if (LOOP_NOT_READY(ha)) { 7497 EL(ha, "failed, loop not ready\n"); 7498 cmd->Status = EXT_STATUS_DEVICE_OFFLINE; 7499 cmd->ResponseLen = 0; 7500 return; 7501 } 7502 7503 if (ddi_copyin((void *)(uintptr_t)cmd->RequestAdr, 7504 (void*)&port_param, sizeof (EXT_PORT_PARAM), mode) != 0) { 7505 EL(ha, "failed, ddi_copyin\n"); 7506 cmd->Status = EXT_STATUS_COPY_ERR; 7507 cmd->ResponseLen = 0; 7508 return; 7509 } 7510 7511 if (port_param.FCScsiAddr.DestType != EXT_DEF_DESTTYPE_WWPN) { 7512 EL(ha, "Unsupported dest lookup type: %xh\n", 7513 port_param.FCScsiAddr.DestType); 7514 cmd->Status = EXT_STATUS_DEV_NOT_FOUND; 7515 cmd->ResponseLen = 0; 7516 return; 7517 } 7518 7519 name = port_param.FCScsiAddr.DestAddr.WWPN; 7520 7521 QL_PRINT_9(CE_CONT, "(%d): wwpn=%02x%02x%02x%02x%02x%02x%02x%02x\n", 7522 ha->instance, name[0], name[1], name[2], name[3], name[4], 7523 name[5], name[6], name[7]); 7524 7525 tq = ql_find_port(ha, name, (uint16_t)QLNT_PORT); 7526 if (tq == NULL || !VALID_TARGET_ID(ha, tq->loop_id)) { 7527 EL(ha, "failed, fc_port not found\n"); 7528 cmd->Status = EXT_STATUS_DEV_NOT_FOUND; 7529 cmd->ResponseLen = 0; 7530 return; 7531 } 7532 7533 cmd->Status = EXT_STATUS_OK; 7534 cmd->DetailStatus = EXT_STATUS_OK; 7535 7536 switch (port_param.Mode) { 7537 case EXT_IIDMA_MODE_GET: 7538 /* 7539 * Report the firmware's port rate for the wwpn 7540 */ 7541 rval = ql_iidma_rate(ha, tq->loop_id, &idma_rate, 7542 port_param.Mode); 7543 7544 if (rval != QL_SUCCESS) { 7545 EL(ha, "iidma get failed: %xh\n", rval); 7546 cmd->Status = EXT_STATUS_MAILBOX; 7547 cmd->DetailStatus = rval; 7548 cmd->ResponseLen = 0; 7549 } else { 7550 switch (idma_rate) { 7551 case IIDMA_RATE_1GB: 7552 port_param.Speed = 7553 EXT_DEF_PORTSPEED_1GBIT; 7554 break; 7555 case IIDMA_RATE_2GB: 7556 port_param.Speed = 7557 EXT_DEF_PORTSPEED_2GBIT; 7558 break; 7559 case IIDMA_RATE_4GB: 7560 port_param.Speed = 7561 EXT_DEF_PORTSPEED_4GBIT; 7562 break; 7563 case IIDMA_RATE_8GB: 7564 port_param.Speed = 7565 EXT_DEF_PORTSPEED_8GBIT; 7566 break; 7567 case IIDMA_RATE_10GB: 7568 port_param.Speed = 7569 EXT_DEF_PORTSPEED_10GBIT; 7570 break; 7571 default: 7572 port_param.Speed = 7573 EXT_DEF_PORTSPEED_UNKNOWN; 7574 EL(ha, "failed, Port speed rate=%xh\n", 7575 idma_rate); 7576 break; 7577 } 7578 7579 /* Copy back the data */ 7580 rval = ddi_copyout((void *)&port_param, 7581 (void *)(uintptr_t)cmd->ResponseAdr, 7582 sizeof (EXT_PORT_PARAM), mode); 7583 7584 if (rval != 0) { 7585 cmd->Status = EXT_STATUS_COPY_ERR; 7586 cmd->ResponseLen = 0; 7587 EL(ha, "failed, ddi_copyout\n"); 7588 } else { 7589 cmd->ResponseLen = (uint32_t) 7590 sizeof (EXT_PORT_PARAM); 7591 } 7592 } 7593 break; 7594 7595 case EXT_IIDMA_MODE_SET: 7596 /* 7597 * Set the firmware's port rate for the wwpn 7598 */ 7599 switch (port_param.Speed) { 7600 case EXT_DEF_PORTSPEED_1GBIT: 7601 idma_rate = IIDMA_RATE_1GB; 7602 break; 7603 case EXT_DEF_PORTSPEED_2GBIT: 7604 idma_rate = IIDMA_RATE_2GB; 7605 break; 7606 case EXT_DEF_PORTSPEED_4GBIT: 7607 idma_rate = IIDMA_RATE_4GB; 7608 break; 7609 case EXT_DEF_PORTSPEED_8GBIT: 7610 idma_rate = IIDMA_RATE_8GB; 7611 break; 7612 case EXT_DEF_PORTSPEED_10GBIT: 7613 port_param.Speed = IIDMA_RATE_10GB; 7614 break; 7615 default: 7616 EL(ha, "invalid set iidma rate: %x\n", 7617 port_param.Speed); 7618 cmd->Status = EXT_STATUS_INVALID_PARAM; 7619 cmd->ResponseLen = 0; 7620 rval = QL_PARAMETER_ERROR; 7621 break; 7622 } 7623 7624 if (rval == QL_SUCCESS) { 7625 rval = ql_iidma_rate(ha, tq->loop_id, &idma_rate, 7626 port_param.Mode); 7627 if (rval != QL_SUCCESS) { 7628 EL(ha, "iidma set failed: %xh\n", rval); 7629 cmd->Status = EXT_STATUS_MAILBOX; 7630 cmd->DetailStatus = rval; 7631 cmd->ResponseLen = 0; 7632 } 7633 } 7634 break; 7635 default: 7636 EL(ha, "invalid mode specified: %x\n", port_param.Mode); 7637 cmd->Status = EXT_STATUS_INVALID_PARAM; 7638 cmd->ResponseLen = 0; 7639 cmd->DetailStatus = 0; 7640 break; 7641 } 7642 7643 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 7644 } 7645 7646 /* 7647 * ql_get_fwexttrace 7648 * Dumps f/w extended trace buffer 7649 * 7650 * Input: 7651 * ha: adapter state pointer. 7652 * bp: buffer address. 7653 * mode: flags 7654 * 7655 * Returns: 7656 * 7657 * Context: 7658 * Kernel context. 7659 */ 7660 /* ARGSUSED */ 7661 static void 7662 ql_get_fwexttrace(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode) 7663 { 7664 int rval; 7665 caddr_t payload; 7666 7667 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 7668 7669 if (CFG_IST(ha, CFG_CTRL_24258081) == 0) { 7670 EL(ha, "invalid request for this HBA\n"); 7671 cmd->Status = EXT_STATUS_INVALID_REQUEST; 7672 cmd->ResponseLen = 0; 7673 return; 7674 } 7675 7676 if ((CFG_IST(ha, CFG_ENABLE_FWEXTTRACE) == 0) || 7677 (ha->fwexttracebuf.bp == NULL)) { 7678 EL(ha, "f/w extended trace is not enabled\n"); 7679 cmd->Status = EXT_STATUS_INVALID_REQUEST; 7680 cmd->ResponseLen = 0; 7681 return; 7682 } 7683 7684 if (cmd->ResponseLen < FWEXTSIZE) { 7685 cmd->Status = EXT_STATUS_BUFFER_TOO_SMALL; 7686 cmd->DetailStatus = FWEXTSIZE; 7687 EL(ha, "failed, ResponseLen (%xh) < %xh (FWEXTSIZE)\n", 7688 cmd->ResponseLen, FWEXTSIZE); 7689 cmd->ResponseLen = 0; 7690 return; 7691 } 7692 7693 /* Time Stamp */ 7694 rval = ql_fw_etrace(ha, &ha->fwexttracebuf, FTO_INSERT_TIME_STAMP); 7695 if (rval != QL_SUCCESS) { 7696 EL(ha, "f/w extended trace insert" 7697 "time stamp failed: %xh\n", rval); 7698 cmd->Status = EXT_STATUS_ERR; 7699 cmd->ResponseLen = 0; 7700 return; 7701 } 7702 7703 /* Disable Tracing */ 7704 rval = ql_fw_etrace(ha, &ha->fwexttracebuf, FTO_EXT_TRACE_DISABLE); 7705 if (rval != QL_SUCCESS) { 7706 EL(ha, "f/w extended trace disable failed: %xh\n", rval); 7707 cmd->Status = EXT_STATUS_ERR; 7708 cmd->ResponseLen = 0; 7709 return; 7710 } 7711 7712 /* Allocate payload buffer */ 7713 payload = kmem_zalloc(FWEXTSIZE, KM_SLEEP); 7714 if (payload == NULL) { 7715 EL(ha, "failed, kmem_zalloc\n"); 7716 cmd->Status = EXT_STATUS_NO_MEMORY; 7717 cmd->ResponseLen = 0; 7718 return; 7719 } 7720 7721 /* Sync DMA buffer. */ 7722 (void) ddi_dma_sync(ha->fwexttracebuf.dma_handle, 0, 7723 FWEXTSIZE, DDI_DMA_SYNC_FORKERNEL); 7724 7725 /* Copy trace buffer data. */ 7726 ddi_rep_get8(ha->fwexttracebuf.acc_handle, (uint8_t *)payload, 7727 (uint8_t *)ha->fwexttracebuf.bp, FWEXTSIZE, 7728 DDI_DEV_AUTOINCR); 7729 7730 /* Send payload to application. */ 7731 if (ql_send_buffer_data(payload, (caddr_t)(uintptr_t)cmd->ResponseAdr, 7732 cmd->ResponseLen, mode) != cmd->ResponseLen) { 7733 EL(ha, "failed, send_buffer_data\n"); 7734 cmd->Status = EXT_STATUS_COPY_ERR; 7735 cmd->ResponseLen = 0; 7736 } else { 7737 cmd->Status = EXT_STATUS_OK; 7738 } 7739 7740 kmem_free(payload, FWEXTSIZE); 7741 7742 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 7743 } 7744 7745 /* 7746 * ql_get_fwfcetrace 7747 * Dumps f/w fibre channel event trace buffer 7748 * 7749 * Input: 7750 * ha: adapter state pointer. 7751 * bp: buffer address. 7752 * mode: flags 7753 * 7754 * Returns: 7755 * 7756 * Context: 7757 * Kernel context. 7758 */ 7759 /* ARGSUSED */ 7760 static void 7761 ql_get_fwfcetrace(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode) 7762 { 7763 int rval; 7764 caddr_t payload; 7765 7766 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 7767 7768 if (CFG_IST(ha, CFG_CTRL_24258081) == 0) { 7769 EL(ha, "invalid request for this HBA\n"); 7770 cmd->Status = EXT_STATUS_INVALID_REQUEST; 7771 cmd->ResponseLen = 0; 7772 return; 7773 } 7774 7775 if ((CFG_IST(ha, CFG_ENABLE_FWFCETRACE) == 0) || 7776 (ha->fwfcetracebuf.bp == NULL)) { 7777 EL(ha, "f/w FCE trace is not enabled\n"); 7778 cmd->Status = EXT_STATUS_INVALID_REQUEST; 7779 cmd->ResponseLen = 0; 7780 return; 7781 } 7782 7783 if (cmd->ResponseLen < FWFCESIZE) { 7784 cmd->Status = EXT_STATUS_BUFFER_TOO_SMALL; 7785 cmd->DetailStatus = FWFCESIZE; 7786 EL(ha, "failed, ResponseLen (%xh) < %xh (FWFCESIZE)\n", 7787 cmd->ResponseLen, FWFCESIZE); 7788 cmd->ResponseLen = 0; 7789 return; 7790 } 7791 7792 /* Disable Tracing */ 7793 rval = ql_fw_etrace(ha, &ha->fwfcetracebuf, FTO_FCE_TRACE_DISABLE); 7794 if (rval != QL_SUCCESS) { 7795 EL(ha, "f/w FCE trace disable failed: %xh\n", rval); 7796 cmd->Status = EXT_STATUS_ERR; 7797 cmd->ResponseLen = 0; 7798 return; 7799 } 7800 7801 /* Allocate payload buffer */ 7802 payload = kmem_zalloc(FWEXTSIZE, KM_SLEEP); 7803 if (payload == NULL) { 7804 EL(ha, "failed, kmem_zalloc\n"); 7805 cmd->Status = EXT_STATUS_NO_MEMORY; 7806 cmd->ResponseLen = 0; 7807 return; 7808 } 7809 7810 /* Sync DMA buffer. */ 7811 (void) ddi_dma_sync(ha->fwfcetracebuf.dma_handle, 0, 7812 FWFCESIZE, DDI_DMA_SYNC_FORKERNEL); 7813 7814 /* Copy trace buffer data. */ 7815 ddi_rep_get8(ha->fwfcetracebuf.acc_handle, (uint8_t *)payload, 7816 (uint8_t *)ha->fwfcetracebuf.bp, FWFCESIZE, 7817 DDI_DEV_AUTOINCR); 7818 7819 /* Send payload to application. */ 7820 if (ql_send_buffer_data(payload, (caddr_t)(uintptr_t)cmd->ResponseAdr, 7821 cmd->ResponseLen, mode) != cmd->ResponseLen) { 7822 EL(ha, "failed, send_buffer_data\n"); 7823 cmd->Status = EXT_STATUS_COPY_ERR; 7824 cmd->ResponseLen = 0; 7825 } else { 7826 cmd->Status = EXT_STATUS_OK; 7827 } 7828 7829 kmem_free(payload, FWFCESIZE); 7830 7831 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 7832 } 7833 7834 /* 7835 * ql_get_pci_data 7836 * Retrieves pci config space data 7837 * 7838 * Input: 7839 * ha: adapter state pointer. 7840 * cmd: Local EXT_IOCTL cmd struct pointer. 7841 * mode: flags. 7842 * 7843 * Returns: 7844 * None, request status indicated in cmd->Status. 7845 * 7846 * Context: 7847 * Kernel context. 7848 * 7849 */ 7850 static void 7851 ql_get_pci_data(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode) 7852 { 7853 uint8_t cap_ptr; 7854 uint8_t cap_id; 7855 uint32_t buf_size = 256; 7856 7857 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 7858 7859 /* 7860 * First check the "Capabilities List" bit of the status register. 7861 */ 7862 if (ql_pci_config_get16(ha, PCI_CONF_STAT) & PCI_STAT_CAP) { 7863 /* 7864 * Now get the capability pointer 7865 */ 7866 cap_ptr = (uint8_t)ql_pci_config_get8(ha, PCI_CONF_CAP_PTR); 7867 while (cap_ptr != PCI_CAP_NEXT_PTR_NULL) { 7868 /* 7869 * Check for the pcie capability. 7870 */ 7871 cap_id = (uint8_t)ql_pci_config_get8(ha, cap_ptr); 7872 if (cap_id == PCI_CAP_ID_PCI_E) { 7873 buf_size = 4096; 7874 break; 7875 } 7876 cap_ptr = (uint8_t)ql_pci_config_get8(ha, 7877 (cap_ptr + PCI_CAP_NEXT_PTR)); 7878 } 7879 } 7880 7881 if (cmd->ResponseLen < buf_size) { 7882 cmd->Status = EXT_STATUS_BUFFER_TOO_SMALL; 7883 cmd->DetailStatus = buf_size; 7884 EL(ha, "failed ResponseLen < buf_size, len passed=%xh\n", 7885 cmd->ResponseLen); 7886 return; 7887 } 7888 7889 /* Dump PCI config data. */ 7890 if ((ql_pci_dump(ha, (void *)(uintptr_t)(cmd->ResponseAdr), 7891 buf_size, mode)) != 0) { 7892 cmd->Status = EXT_STATUS_COPY_ERR; 7893 cmd->DetailStatus = 0; 7894 EL(ha, "failed, copy err pci_dump\n"); 7895 } else { 7896 cmd->Status = EXT_STATUS_OK; 7897 cmd->DetailStatus = buf_size; 7898 } 7899 7900 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 7901 } 7902 7903 /* 7904 * ql_pci_dump 7905 * Dumps PCI config data to application buffer. 7906 * 7907 * Input: 7908 * ha = adapter state pointer. 7909 * bp = user buffer address. 7910 * 7911 * Returns: 7912 * 7913 * Context: 7914 * Kernel context. 7915 */ 7916 int 7917 ql_pci_dump(ql_adapter_state_t *ha, uint32_t *bp, uint32_t pci_size, int mode) 7918 { 7919 uint32_t pci_os; 7920 uint32_t *ptr32, *org_ptr32; 7921 7922 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 7923 7924 ptr32 = kmem_zalloc(pci_size, KM_SLEEP); 7925 if (ptr32 == NULL) { 7926 EL(ha, "failed kmem_zalloc\n"); 7927 return (ENOMEM); 7928 } 7929 7930 /* store the initial value of ptr32 */ 7931 org_ptr32 = ptr32; 7932 for (pci_os = 0; pci_os < pci_size; pci_os += 4) { 7933 *ptr32 = (uint32_t)ql_pci_config_get32(ha, pci_os); 7934 LITTLE_ENDIAN_32(ptr32); 7935 ptr32++; 7936 } 7937 7938 if (ddi_copyout((void *)org_ptr32, (void *)bp, pci_size, mode) != 7939 0) { 7940 EL(ha, "failed ddi_copyout\n"); 7941 kmem_free(org_ptr32, pci_size); 7942 return (EFAULT); 7943 } 7944 7945 QL_DUMP_9(org_ptr32, 8, pci_size); 7946 7947 kmem_free(org_ptr32, pci_size); 7948 7949 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 7950 7951 return (0); 7952 } 7953 7954 /* 7955 * ql_menlo_reset 7956 * Reset Menlo 7957 * 7958 * Input: 7959 * ha: adapter state pointer. 7960 * bp: buffer address. 7961 * mode: flags 7962 * 7963 * Returns: 7964 * 7965 * Context: 7966 * Kernel context. 7967 */ 7968 static void 7969 ql_menlo_reset(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode) 7970 { 7971 EXT_MENLO_RESET rst; 7972 ql_mbx_data_t mr; 7973 int rval; 7974 7975 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 7976 7977 if ((CFG_IST(ha, CFG_CTRL_MENLO)) == 0) { 7978 EL(ha, "failed, invalid request for HBA\n"); 7979 cmd->Status = EXT_STATUS_INVALID_REQUEST; 7980 cmd->ResponseLen = 0; 7981 return; 7982 } 7983 7984 /* 7985 * TODO: only vp_index 0 can do this (?) 7986 */ 7987 7988 /* Verify the size of request structure. */ 7989 if (cmd->RequestLen < sizeof (EXT_MENLO_RESET)) { 7990 /* Return error */ 7991 EL(ha, "RequestLen=%d < %d\n", cmd->RequestLen, 7992 sizeof (EXT_MENLO_RESET)); 7993 cmd->Status = EXT_STATUS_INVALID_PARAM; 7994 cmd->DetailStatus = EXT_DSTATUS_REQUEST_LEN; 7995 cmd->ResponseLen = 0; 7996 return; 7997 } 7998 7999 /* Get reset request. */ 8000 if (ddi_copyin((void *)(uintptr_t)cmd->RequestAdr, 8001 (void *)&rst, sizeof (EXT_MENLO_RESET), mode) != 0) { 8002 EL(ha, "failed, ddi_copyin\n"); 8003 cmd->Status = EXT_STATUS_COPY_ERR; 8004 cmd->ResponseLen = 0; 8005 return; 8006 } 8007 8008 /* Wait for I/O to stop and daemon to stall. */ 8009 if (ql_suspend_hba(ha, 0) != QL_SUCCESS) { 8010 EL(ha, "ql_stall_driver failed\n"); 8011 ql_restart_hba(ha); 8012 cmd->Status = EXT_STATUS_BUSY; 8013 cmd->ResponseLen = 0; 8014 return; 8015 } 8016 8017 rval = ql_reset_menlo(ha, &mr, rst.Flags); 8018 if (rval != QL_SUCCESS) { 8019 EL(ha, "failed, status=%xh\n", rval); 8020 cmd->Status = EXT_STATUS_MAILBOX; 8021 cmd->DetailStatus = rval; 8022 cmd->ResponseLen = 0; 8023 } else if (mr.mb[1] != 0) { 8024 EL(ha, "failed, substatus=%d\n", mr.mb[1]); 8025 cmd->Status = EXT_STATUS_ERR; 8026 cmd->DetailStatus = mr.mb[1]; 8027 cmd->ResponseLen = 0; 8028 } 8029 8030 ql_restart_hba(ha); 8031 8032 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 8033 } 8034 8035 /* 8036 * ql_menlo_get_fw_version 8037 * Get Menlo firmware version. 8038 * 8039 * Input: 8040 * ha: adapter state pointer. 8041 * bp: buffer address. 8042 * mode: flags 8043 * 8044 * Returns: 8045 * 8046 * Context: 8047 * Kernel context. 8048 */ 8049 static void 8050 ql_menlo_get_fw_version(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode) 8051 { 8052 int rval; 8053 ql_mbx_iocb_t *pkt; 8054 EXT_MENLO_GET_FW_VERSION ver = {0}; 8055 8056 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 8057 8058 if ((CFG_IST(ha, CFG_CTRL_MENLO)) == 0) { 8059 EL(ha, "failed, invalid request for HBA\n"); 8060 cmd->Status = EXT_STATUS_INVALID_REQUEST; 8061 cmd->ResponseLen = 0; 8062 return; 8063 } 8064 8065 if (cmd->ResponseLen < sizeof (EXT_MENLO_GET_FW_VERSION)) { 8066 cmd->Status = EXT_STATUS_BUFFER_TOO_SMALL; 8067 cmd->DetailStatus = sizeof (EXT_MENLO_GET_FW_VERSION); 8068 EL(ha, "ResponseLen=%d < %d\n", cmd->ResponseLen, 8069 sizeof (EXT_MENLO_GET_FW_VERSION)); 8070 cmd->ResponseLen = 0; 8071 return; 8072 } 8073 8074 /* Allocate packet. */ 8075 pkt = kmem_zalloc(sizeof (ql_mbx_iocb_t), KM_SLEEP); 8076 if (pkt == NULL) { 8077 EL(ha, "failed, kmem_zalloc\n"); 8078 cmd->Status = EXT_STATUS_NO_MEMORY; 8079 cmd->ResponseLen = 0; 8080 return; 8081 } 8082 8083 pkt->mvfy.entry_type = VERIFY_MENLO_TYPE; 8084 pkt->mvfy.entry_count = 1; 8085 pkt->mvfy.options_status = LE_16(VMF_DO_NOT_UPDATE_FW); 8086 8087 rval = ql_issue_mbx_iocb(ha, (caddr_t)pkt, sizeof (ql_mbx_iocb_t)); 8088 LITTLE_ENDIAN_16(&pkt->mvfy.options_status); 8089 LITTLE_ENDIAN_16(&pkt->mvfy.failure_code); 8090 ver.FwVersion = LE_32(pkt->mvfy.fw_version); 8091 8092 if (rval != QL_SUCCESS || (pkt->mvfy.entry_status & 0x3c) != 0 || 8093 pkt->mvfy.options_status != CS_COMPLETE) { 8094 /* Command error */ 8095 EL(ha, "failed, status=%xh, es=%xh, cs=%xh, fc=%xh\n", rval, 8096 pkt->mvfy.entry_status & 0x3c, pkt->mvfy.options_status, 8097 pkt->mvfy.failure_code); 8098 cmd->Status = EXT_STATUS_ERR; 8099 cmd->DetailStatus = rval != QL_SUCCESS ? rval : 8100 QL_FUNCTION_FAILED; 8101 cmd->ResponseLen = 0; 8102 } else if (ddi_copyout((void *)&ver, 8103 (void *)(uintptr_t)cmd->ResponseAdr, 8104 sizeof (EXT_MENLO_GET_FW_VERSION), mode) != 0) { 8105 EL(ha, "failed, ddi_copyout\n"); 8106 cmd->Status = EXT_STATUS_COPY_ERR; 8107 cmd->ResponseLen = 0; 8108 } else { 8109 cmd->ResponseLen = sizeof (EXT_MENLO_GET_FW_VERSION); 8110 } 8111 8112 kmem_free(pkt, sizeof (ql_mbx_iocb_t)); 8113 8114 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 8115 } 8116 8117 /* 8118 * ql_menlo_update_fw 8119 * Get Menlo update firmware. 8120 * 8121 * Input: 8122 * ha: adapter state pointer. 8123 * bp: buffer address. 8124 * mode: flags 8125 * 8126 * Returns: 8127 * 8128 * Context: 8129 * Kernel context. 8130 */ 8131 static void 8132 ql_menlo_update_fw(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode) 8133 { 8134 ql_mbx_iocb_t *pkt; 8135 dma_mem_t *dma_mem; 8136 EXT_MENLO_UPDATE_FW fw; 8137 uint32_t *ptr32; 8138 int rval; 8139 8140 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 8141 8142 if ((CFG_IST(ha, CFG_CTRL_MENLO)) == 0) { 8143 EL(ha, "failed, invalid request for HBA\n"); 8144 cmd->Status = EXT_STATUS_INVALID_REQUEST; 8145 cmd->ResponseLen = 0; 8146 return; 8147 } 8148 8149 /* 8150 * TODO: only vp_index 0 can do this (?) 8151 */ 8152 8153 /* Verify the size of request structure. */ 8154 if (cmd->RequestLen < sizeof (EXT_MENLO_UPDATE_FW)) { 8155 /* Return error */ 8156 EL(ha, "RequestLen=%d < %d\n", cmd->RequestLen, 8157 sizeof (EXT_MENLO_UPDATE_FW)); 8158 cmd->Status = EXT_STATUS_INVALID_PARAM; 8159 cmd->DetailStatus = EXT_DSTATUS_REQUEST_LEN; 8160 cmd->ResponseLen = 0; 8161 return; 8162 } 8163 8164 /* Get update fw request. */ 8165 if (ddi_copyin((caddr_t)(uintptr_t)cmd->RequestAdr, (caddr_t)&fw, 8166 sizeof (EXT_MENLO_UPDATE_FW), mode) != 0) { 8167 EL(ha, "failed, ddi_copyin\n"); 8168 cmd->Status = EXT_STATUS_COPY_ERR; 8169 cmd->ResponseLen = 0; 8170 return; 8171 } 8172 8173 /* Wait for I/O to stop and daemon to stall. */ 8174 if (ql_suspend_hba(ha, 0) != QL_SUCCESS) { 8175 EL(ha, "ql_stall_driver failed\n"); 8176 ql_restart_hba(ha); 8177 cmd->Status = EXT_STATUS_BUSY; 8178 cmd->ResponseLen = 0; 8179 return; 8180 } 8181 8182 /* Allocate packet. */ 8183 dma_mem = (dma_mem_t *)kmem_zalloc(sizeof (dma_mem_t), KM_SLEEP); 8184 if (dma_mem == NULL) { 8185 EL(ha, "failed, kmem_zalloc\n"); 8186 cmd->Status = EXT_STATUS_NO_MEMORY; 8187 cmd->ResponseLen = 0; 8188 return; 8189 } 8190 pkt = kmem_zalloc(sizeof (ql_mbx_iocb_t), KM_SLEEP); 8191 if (pkt == NULL) { 8192 EL(ha, "failed, kmem_zalloc\n"); 8193 kmem_free(dma_mem, sizeof (dma_mem_t)); 8194 ql_restart_hba(ha); 8195 cmd->Status = EXT_STATUS_NO_MEMORY; 8196 cmd->ResponseLen = 0; 8197 return; 8198 } 8199 8200 /* Get DMA memory for the IOCB */ 8201 if (ql_get_dma_mem(ha, dma_mem, fw.TotalByteCount, LITTLE_ENDIAN_DMA, 8202 QL_DMA_DATA_ALIGN) != QL_SUCCESS) { 8203 cmn_err(CE_WARN, "%s(%d): request queue DMA memory " 8204 "alloc failed", QL_NAME, ha->instance); 8205 kmem_free(pkt, sizeof (ql_mbx_iocb_t)); 8206 kmem_free(dma_mem, sizeof (dma_mem_t)); 8207 ql_restart_hba(ha); 8208 cmd->Status = EXT_STATUS_MS_NO_RESPONSE; 8209 cmd->ResponseLen = 0; 8210 return; 8211 } 8212 8213 /* Get firmware data. */ 8214 if (ql_get_buffer_data((caddr_t)(uintptr_t)fw.pFwDataBytes, dma_mem->bp, 8215 fw.TotalByteCount, mode) != fw.TotalByteCount) { 8216 EL(ha, "failed, get_buffer_data\n"); 8217 ql_free_dma_resource(ha, dma_mem); 8218 kmem_free(pkt, sizeof (ql_mbx_iocb_t)); 8219 kmem_free(dma_mem, sizeof (dma_mem_t)); 8220 ql_restart_hba(ha); 8221 cmd->Status = EXT_STATUS_COPY_ERR; 8222 cmd->ResponseLen = 0; 8223 return; 8224 } 8225 8226 /* Sync DMA buffer. */ 8227 (void) ddi_dma_sync(dma_mem->dma_handle, 0, dma_mem->size, 8228 DDI_DMA_SYNC_FORDEV); 8229 8230 pkt->mvfy.entry_type = VERIFY_MENLO_TYPE; 8231 pkt->mvfy.entry_count = 1; 8232 pkt->mvfy.options_status = (uint16_t)LE_16(fw.Flags); 8233 ptr32 = dma_mem->bp; 8234 pkt->mvfy.fw_version = LE_32(ptr32[2]); 8235 pkt->mvfy.fw_size = LE_32(fw.TotalByteCount); 8236 pkt->mvfy.fw_sequence_size = LE_32(fw.TotalByteCount); 8237 pkt->mvfy.dseg_count = LE_16(1); 8238 pkt->mvfy.dseg_0_address[0] = (uint32_t) 8239 LE_32(LSD(dma_mem->cookie.dmac_laddress)); 8240 pkt->mvfy.dseg_0_address[1] = (uint32_t) 8241 LE_32(MSD(dma_mem->cookie.dmac_laddress)); 8242 pkt->mvfy.dseg_0_length = LE_32(fw.TotalByteCount); 8243 8244 rval = ql_issue_mbx_iocb(ha, (caddr_t)pkt, sizeof (ql_mbx_iocb_t)); 8245 LITTLE_ENDIAN_16(&pkt->mvfy.options_status); 8246 LITTLE_ENDIAN_16(&pkt->mvfy.failure_code); 8247 8248 if (rval != QL_SUCCESS || (pkt->mvfy.entry_status & 0x3c) != 0 || 8249 pkt->mvfy.options_status != CS_COMPLETE) { 8250 /* Command error */ 8251 EL(ha, "failed, status=%xh, es=%xh, cs=%xh, fc=%xh\n", rval, 8252 pkt->mvfy.entry_status & 0x3c, pkt->mvfy.options_status, 8253 pkt->mvfy.failure_code); 8254 cmd->Status = EXT_STATUS_ERR; 8255 cmd->DetailStatus = rval != QL_SUCCESS ? rval : 8256 QL_FUNCTION_FAILED; 8257 cmd->ResponseLen = 0; 8258 } 8259 8260 ql_free_dma_resource(ha, dma_mem); 8261 kmem_free(pkt, sizeof (ql_mbx_iocb_t)); 8262 kmem_free(dma_mem, sizeof (dma_mem_t)); 8263 ql_restart_hba(ha); 8264 8265 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 8266 } 8267 8268 /* 8269 * ql_menlo_manage_info 8270 * Get Menlo manage info. 8271 * 8272 * Input: 8273 * ha: adapter state pointer. 8274 * bp: buffer address. 8275 * mode: flags 8276 * 8277 * Returns: 8278 * 8279 * Context: 8280 * Kernel context. 8281 */ 8282 static void 8283 ql_menlo_manage_info(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode) 8284 { 8285 ql_mbx_iocb_t *pkt; 8286 dma_mem_t *dma_mem = NULL; 8287 EXT_MENLO_MANAGE_INFO info; 8288 int rval; 8289 8290 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 8291 8292 8293 /* The call is only supported for Schultz right now */ 8294 if (CFG_IST(ha, CFG_CTRL_8081)) { 8295 ql_get_xgmac_statistics(ha, cmd, mode); 8296 QL_PRINT_9(CE_CONT, "(%d): CFG_CTRL_81XX done\n", 8297 ha->instance); 8298 return; 8299 } 8300 8301 if (!CFG_IST(ha, CFG_CTRL_8081) || !CFG_IST(ha, CFG_CTRL_MENLO)) { 8302 EL(ha, "failed, invalid request for HBA\n"); 8303 cmd->Status = EXT_STATUS_INVALID_REQUEST; 8304 cmd->ResponseLen = 0; 8305 return; 8306 } 8307 8308 /* Verify the size of request structure. */ 8309 if (cmd->RequestLen < sizeof (EXT_MENLO_MANAGE_INFO)) { 8310 /* Return error */ 8311 EL(ha, "RequestLen=%d < %d\n", cmd->RequestLen, 8312 sizeof (EXT_MENLO_MANAGE_INFO)); 8313 cmd->Status = EXT_STATUS_INVALID_PARAM; 8314 cmd->DetailStatus = EXT_DSTATUS_REQUEST_LEN; 8315 cmd->ResponseLen = 0; 8316 return; 8317 } 8318 8319 /* Get manage info request. */ 8320 if (ddi_copyin((caddr_t)(uintptr_t)cmd->RequestAdr, 8321 (caddr_t)&info, sizeof (EXT_MENLO_MANAGE_INFO), mode) != 0) { 8322 EL(ha, "failed, ddi_copyin\n"); 8323 cmd->Status = EXT_STATUS_COPY_ERR; 8324 cmd->ResponseLen = 0; 8325 return; 8326 } 8327 8328 /* Allocate packet. */ 8329 pkt = kmem_zalloc(sizeof (ql_mbx_iocb_t), KM_SLEEP); 8330 if (pkt == NULL) { 8331 EL(ha, "failed, kmem_zalloc\n"); 8332 ql_restart_driver(ha); 8333 cmd->Status = EXT_STATUS_NO_MEMORY; 8334 cmd->ResponseLen = 0; 8335 return; 8336 } 8337 8338 pkt->mdata.entry_type = MENLO_DATA_TYPE; 8339 pkt->mdata.entry_count = 1; 8340 pkt->mdata.options_status = (uint16_t)LE_16(info.Operation); 8341 8342 /* Get DMA memory for the IOCB */ 8343 if (info.Operation == MENLO_OP_READ_MEM || 8344 info.Operation == MENLO_OP_WRITE_MEM) { 8345 pkt->mdata.total_byte_count = LE_32(info.TotalByteCount); 8346 pkt->mdata.parameter_1 = 8347 LE_32(info.Parameters.ap.MenloMemory.StartingAddr); 8348 dma_mem = (dma_mem_t *)kmem_zalloc(sizeof (dma_mem_t), 8349 KM_SLEEP); 8350 if (dma_mem == NULL) { 8351 EL(ha, "failed, kmem_zalloc\n"); 8352 kmem_free(pkt, sizeof (ql_mbx_iocb_t)); 8353 cmd->Status = EXT_STATUS_NO_MEMORY; 8354 cmd->ResponseLen = 0; 8355 return; 8356 } 8357 if (ql_get_dma_mem(ha, dma_mem, info.TotalByteCount, 8358 LITTLE_ENDIAN_DMA, QL_DMA_DATA_ALIGN) != QL_SUCCESS) { 8359 cmn_err(CE_WARN, "%s(%d): request queue DMA memory " 8360 "alloc failed", QL_NAME, ha->instance); 8361 kmem_free(dma_mem, sizeof (dma_mem_t)); 8362 kmem_free(pkt, sizeof (ql_mbx_iocb_t)); 8363 cmd->Status = EXT_STATUS_MS_NO_RESPONSE; 8364 cmd->ResponseLen = 0; 8365 return; 8366 } 8367 if (info.Operation == MENLO_OP_WRITE_MEM) { 8368 /* Get data. */ 8369 if (ql_get_buffer_data( 8370 (caddr_t)(uintptr_t)info.pDataBytes, 8371 dma_mem->bp, info.TotalByteCount, mode) != 8372 info.TotalByteCount) { 8373 EL(ha, "failed, get_buffer_data\n"); 8374 ql_free_dma_resource(ha, dma_mem); 8375 kmem_free(dma_mem, sizeof (dma_mem_t)); 8376 kmem_free(pkt, sizeof (ql_mbx_iocb_t)); 8377 cmd->Status = EXT_STATUS_COPY_ERR; 8378 cmd->ResponseLen = 0; 8379 return; 8380 } 8381 (void) ddi_dma_sync(dma_mem->dma_handle, 0, 8382 dma_mem->size, DDI_DMA_SYNC_FORDEV); 8383 } 8384 pkt->mdata.dseg_count = LE_16(1); 8385 pkt->mdata.dseg_0_address[0] = (uint32_t) 8386 LE_32(LSD(dma_mem->cookie.dmac_laddress)); 8387 pkt->mdata.dseg_0_address[1] = (uint32_t) 8388 LE_32(MSD(dma_mem->cookie.dmac_laddress)); 8389 pkt->mdata.dseg_0_length = LE_32(info.TotalByteCount); 8390 } else if (info.Operation & MENLO_OP_CHANGE_CONFIG) { 8391 pkt->mdata.parameter_1 = 8392 LE_32(info.Parameters.ap.MenloConfig.ConfigParamID); 8393 pkt->mdata.parameter_2 = 8394 LE_32(info.Parameters.ap.MenloConfig.ConfigParamData0); 8395 pkt->mdata.parameter_3 = 8396 LE_32(info.Parameters.ap.MenloConfig.ConfigParamData1); 8397 } else if (info.Operation & MENLO_OP_GET_INFO) { 8398 pkt->mdata.parameter_1 = 8399 LE_32(info.Parameters.ap.MenloInfo.InfoDataType); 8400 pkt->mdata.parameter_2 = 8401 LE_32(info.Parameters.ap.MenloInfo.InfoContext); 8402 } 8403 8404 rval = ql_issue_mbx_iocb(ha, (caddr_t)pkt, sizeof (ql_mbx_iocb_t)); 8405 LITTLE_ENDIAN_16(&pkt->mdata.options_status); 8406 LITTLE_ENDIAN_16(&pkt->mdata.failure_code); 8407 8408 if (rval != QL_SUCCESS || (pkt->mdata.entry_status & 0x3c) != 0 || 8409 pkt->mdata.options_status != CS_COMPLETE) { 8410 /* Command error */ 8411 EL(ha, "failed, status=%xh, es=%xh, cs=%xh, fc=%xh\n", rval, 8412 pkt->mdata.entry_status & 0x3c, pkt->mdata.options_status, 8413 pkt->mdata.failure_code); 8414 cmd->Status = EXT_STATUS_ERR; 8415 cmd->DetailStatus = rval != QL_SUCCESS ? rval : 8416 QL_FUNCTION_FAILED; 8417 cmd->ResponseLen = 0; 8418 } else if (info.Operation == MENLO_OP_READ_MEM) { 8419 (void) ddi_dma_sync(dma_mem->dma_handle, 0, dma_mem->size, 8420 DDI_DMA_SYNC_FORKERNEL); 8421 if (ql_send_buffer_data((caddr_t)(uintptr_t)info.pDataBytes, 8422 dma_mem->bp, info.TotalByteCount, mode) != 8423 info.TotalByteCount) { 8424 cmd->Status = EXT_STATUS_COPY_ERR; 8425 cmd->ResponseLen = 0; 8426 } 8427 } 8428 8429 ql_free_dma_resource(ha, dma_mem); 8430 kmem_free(dma_mem, sizeof (dma_mem_t)); 8431 kmem_free(pkt, sizeof (ql_mbx_iocb_t)); 8432 8433 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 8434 } 8435 8436 /* 8437 * ql_suspend_hba 8438 * Suspends all adapter ports. 8439 * 8440 * Input: 8441 * ha: adapter state pointer. 8442 * options: BIT_0 --> leave driver stalled on exit if 8443 * failed. 8444 * 8445 * Returns: 8446 * ql local function return status code. 8447 * 8448 * Context: 8449 * Kernel context. 8450 */ 8451 static int 8452 ql_suspend_hba(ql_adapter_state_t *ha, uint32_t opt) 8453 { 8454 ql_adapter_state_t *ha2; 8455 ql_link_t *link; 8456 int rval = QL_SUCCESS; 8457 8458 /* Quiesce I/O on all adapter ports */ 8459 for (link = ql_hba.first; link != NULL; link = link->next) { 8460 ha2 = link->base_address; 8461 8462 if (ha2->fru_hba_index != ha->fru_hba_index) { 8463 continue; 8464 } 8465 8466 if ((rval = ql_stall_driver(ha2, opt)) != QL_SUCCESS) { 8467 EL(ha, "ql_stall_driver status=%xh\n", rval); 8468 break; 8469 } 8470 } 8471 8472 return (rval); 8473 } 8474 8475 /* 8476 * ql_restart_hba 8477 * Restarts adapter. 8478 * 8479 * Input: 8480 * ha: adapter state pointer. 8481 * 8482 * Context: 8483 * Kernel context. 8484 */ 8485 static void 8486 ql_restart_hba(ql_adapter_state_t *ha) 8487 { 8488 ql_adapter_state_t *ha2; 8489 ql_link_t *link; 8490 8491 /* Resume I/O on all adapter ports */ 8492 for (link = ql_hba.first; link != NULL; link = link->next) { 8493 ha2 = link->base_address; 8494 8495 if (ha2->fru_hba_index != ha->fru_hba_index) { 8496 continue; 8497 } 8498 8499 ql_restart_driver(ha2); 8500 } 8501 } 8502 8503 /* 8504 * ql_get_vp_cnt_id 8505 * Retrieves pci config space data 8506 * 8507 * Input: 8508 * ha: adapter state pointer. 8509 * cmd: Local EXT_IOCTL cmd struct pointer. 8510 * mode: flags. 8511 * 8512 * Returns: 8513 * None, request status indicated in cmd->Status. 8514 * 8515 * Context: 8516 * Kernel context. 8517 * 8518 */ 8519 static void 8520 ql_get_vp_cnt_id(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode) 8521 { 8522 ql_adapter_state_t *vha; 8523 PEXT_VPORT_ID_CNT ptmp_vp; 8524 int id = 0; 8525 int rval; 8526 char name[MAXPATHLEN]; 8527 8528 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 8529 8530 /* 8531 * To be backward compatible with older API 8532 * check for the size of old EXT_VPORT_ID_CNT 8533 */ 8534 if (cmd->ResponseLen < sizeof (EXT_VPORT_ID_CNT) && 8535 (cmd->ResponseLen != EXT_OLD_VPORT_ID_CNT_SIZE)) { 8536 cmd->Status = EXT_STATUS_BUFFER_TOO_SMALL; 8537 cmd->DetailStatus = sizeof (EXT_VPORT_ID_CNT); 8538 EL(ha, "failed, ResponseLen < EXT_VPORT_ID_CNT, Len=%xh\n", 8539 cmd->ResponseLen); 8540 cmd->ResponseLen = 0; 8541 return; 8542 } 8543 8544 ptmp_vp = (EXT_VPORT_ID_CNT *) 8545 kmem_zalloc(sizeof (EXT_VPORT_ID_CNT), KM_SLEEP); 8546 if (ptmp_vp == NULL) { 8547 EL(ha, "failed, kmem_zalloc\n"); 8548 cmd->ResponseLen = 0; 8549 return; 8550 } 8551 vha = ha->vp_next; 8552 while (vha != NULL) { 8553 ptmp_vp->VpCnt++; 8554 ptmp_vp->VpId[id] = vha->vp_index; 8555 (void) ddi_pathname(vha->dip, name); 8556 (void) strcpy((char *)ptmp_vp->vp_path[id], name); 8557 ptmp_vp->VpDrvInst[id] = (int32_t)vha->instance; 8558 id++; 8559 vha = vha->vp_next; 8560 } 8561 rval = ddi_copyout((void *)ptmp_vp, 8562 (void *)(uintptr_t)(cmd->ResponseAdr), 8563 cmd->ResponseLen, mode); 8564 if (rval != 0) { 8565 cmd->Status = EXT_STATUS_COPY_ERR; 8566 cmd->ResponseLen = 0; 8567 EL(ha, "failed, ddi_copyout\n"); 8568 } else { 8569 cmd->ResponseLen = sizeof (EXT_VPORT_ID_CNT); 8570 QL_PRINT_9(CE_CONT, "(%d): done, vport_cnt=%d\n", 8571 ha->instance, ptmp_vp->VpCnt); 8572 } 8573 8574 } 8575 8576 /* 8577 * ql_vp_ioctl 8578 * Performs all EXT_CC_VPORT_CMD functions. 8579 * 8580 * Input: 8581 * ha: adapter state pointer. 8582 * cmd: Local EXT_IOCTL cmd struct pointer. 8583 * mode: flags. 8584 * 8585 * Returns: 8586 * None, request status indicated in cmd->Status. 8587 * 8588 * Context: 8589 * Kernel context. 8590 */ 8591 static void 8592 ql_vp_ioctl(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode) 8593 { 8594 QL_PRINT_9(CE_CONT, "(%d): started, cmd=%d\n", ha->instance, 8595 cmd->SubCode); 8596 8597 /* case off on command subcode */ 8598 switch (cmd->SubCode) { 8599 case EXT_VF_SC_VPORT_GETINFO: 8600 ql_qry_vport(ha, cmd, mode); 8601 break; 8602 default: 8603 /* function not supported. */ 8604 cmd->Status = EXT_STATUS_UNSUPPORTED_SUBCODE; 8605 EL(ha, "failed, Unsupported Subcode=%xh\n", 8606 cmd->SubCode); 8607 break; 8608 } 8609 8610 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 8611 } 8612 8613 /* 8614 * ql_qry_vport 8615 * Performs EXT_VF_SC_VPORT_GETINFO subfunction. 8616 * 8617 * Input: 8618 * ha: adapter state pointer. 8619 * cmd: EXT_IOCTL cmd struct pointer. 8620 * mode: flags. 8621 * 8622 * Returns: 8623 * None, request status indicated in cmd->Status. 8624 * 8625 * Context: 8626 * Kernel context. 8627 */ 8628 static void 8629 ql_qry_vport(ql_adapter_state_t *vha, EXT_IOCTL *cmd, int mode) 8630 { 8631 ql_adapter_state_t *tmp_vha; 8632 EXT_VPORT_INFO tmp_vport = {0}; 8633 int max_vport; 8634 8635 QL_PRINT_9(CE_CONT, "(%d): started\n", vha->instance); 8636 8637 if (cmd->ResponseLen < sizeof (EXT_VPORT_INFO)) { 8638 cmd->Status = EXT_STATUS_BUFFER_TOO_SMALL; 8639 cmd->DetailStatus = sizeof (EXT_VPORT_INFO); 8640 EL(vha, "failed, ResponseLen < EXT_VPORT_INFO, Len=%xh\n", 8641 cmd->ResponseLen); 8642 cmd->ResponseLen = 0; 8643 return; 8644 } 8645 8646 /* Fill in the vport information. */ 8647 bcopy(vha->loginparams.node_ww_name.raw_wwn, tmp_vport.wwnn, 8648 EXT_DEF_WWN_NAME_SIZE); 8649 bcopy(vha->loginparams.nport_ww_name.raw_wwn, tmp_vport.wwpn, 8650 EXT_DEF_WWN_NAME_SIZE); 8651 tmp_vport.state = vha->state; 8652 tmp_vport.id = vha->vp_index; 8653 8654 tmp_vha = vha->pha->vp_next; 8655 while (tmp_vha != NULL) { 8656 tmp_vport.used++; 8657 tmp_vha = tmp_vha->vp_next; 8658 } 8659 8660 max_vport = (CFG_IST(vha, CFG_CTRL_2422) ? MAX_24_VIRTUAL_PORTS : 8661 MAX_25_VIRTUAL_PORTS); 8662 if (max_vport > tmp_vport.used) { 8663 tmp_vport.free = max_vport - tmp_vport.used; 8664 } 8665 8666 if (ddi_copyout((void *)&tmp_vport, 8667 (void *)(uintptr_t)(cmd->ResponseAdr), 8668 sizeof (EXT_VPORT_INFO), mode) != 0) { 8669 cmd->Status = EXT_STATUS_COPY_ERR; 8670 cmd->ResponseLen = 0; 8671 EL(vha, "failed, ddi_copyout\n"); 8672 } else { 8673 cmd->ResponseLen = sizeof (EXT_VPORT_INFO); 8674 QL_PRINT_9(CE_CONT, "(%d): done\n", vha->instance); 8675 } 8676 } 8677 8678 /* 8679 * ql_access_flash 8680 * Performs all EXT_CC_ACCESS_FLASH_OS functions. 8681 * 8682 * Input: 8683 * pi: port info pointer. 8684 * cmd: Local EXT_IOCTL cmd struct pointer. 8685 * mode: flags. 8686 * 8687 * Returns: 8688 * None, request status indicated in cmd->Status. 8689 * 8690 * Context: 8691 * Kernel context. 8692 */ 8693 static void 8694 ql_access_flash(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode) 8695 { 8696 int rval; 8697 8698 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 8699 8700 switch (cmd->SubCode) { 8701 case EXT_SC_FLASH_READ: 8702 if ((rval = ql_flash_fcode_dump(ha, 8703 (void *)(uintptr_t)(cmd->ResponseAdr), 8704 (size_t)(cmd->ResponseLen), cmd->Reserved1, mode)) != 0) { 8705 cmd->Status = EXT_STATUS_COPY_ERR; 8706 cmd->ResponseLen = 0; 8707 EL(ha, "flash_fcode_dump status=%xh\n", rval); 8708 } 8709 break; 8710 case EXT_SC_FLASH_WRITE: 8711 if ((rval = ql_r_m_w_flash(ha, 8712 (void *)(uintptr_t)(cmd->RequestAdr), 8713 (size_t)(cmd->RequestLen), cmd->Reserved1, mode)) != 8714 QL_SUCCESS) { 8715 cmd->Status = EXT_STATUS_COPY_ERR; 8716 cmd->ResponseLen = 0; 8717 EL(ha, "r_m_w_flash status=%xh\n", rval); 8718 } else { 8719 /* Reset caches on all adapter instances. */ 8720 ql_update_flash_caches(ha); 8721 } 8722 break; 8723 default: 8724 EL(ha, "unknown subcode=%xh\n", cmd->SubCode); 8725 cmd->Status = EXT_STATUS_ERR; 8726 cmd->ResponseLen = 0; 8727 break; 8728 } 8729 8730 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 8731 } 8732 8733 /* 8734 * ql_reset_cmd 8735 * Performs all EXT_CC_RESET_FW_OS functions. 8736 * 8737 * Input: 8738 * ha: adapter state pointer. 8739 * cmd: Local EXT_IOCTL cmd struct pointer. 8740 * 8741 * Returns: 8742 * None, request status indicated in cmd->Status. 8743 * 8744 * Context: 8745 * Kernel context. 8746 */ 8747 static void 8748 ql_reset_cmd(ql_adapter_state_t *ha, EXT_IOCTL *cmd) 8749 { 8750 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 8751 8752 switch (cmd->SubCode) { 8753 case EXT_SC_RESET_FC_FW: 8754 EL(ha, "isp_abort_needed\n"); 8755 ql_awaken_task_daemon(ha, NULL, ISP_ABORT_NEEDED, 0); 8756 break; 8757 case EXT_SC_RESET_MPI_FW: 8758 if (!(CFG_IST(ha, CFG_CTRL_81XX))) { 8759 EL(ha, "invalid request for HBA\n"); 8760 cmd->Status = EXT_STATUS_INVALID_REQUEST; 8761 cmd->ResponseLen = 0; 8762 } else { 8763 /* Wait for I/O to stop and daemon to stall. */ 8764 if (ql_suspend_hba(ha, 0) != QL_SUCCESS) { 8765 EL(ha, "ql_suspend_hba failed\n"); 8766 cmd->Status = EXT_STATUS_BUSY; 8767 cmd->ResponseLen = 0; 8768 } else if (ql_restart_mpi(ha) != QL_SUCCESS) { 8769 cmd->Status = EXT_STATUS_ERR; 8770 cmd->ResponseLen = 0; 8771 } else { 8772 uint8_t timer; 8773 /* 8774 * While the restart_mpi mailbox cmd may be 8775 * done the MPI is not. Wait at least 6 sec. or 8776 * exit if the loop comes up. 8777 */ 8778 for (timer = 6; timer; timer--) { 8779 if (!(ha->task_daemon_flags & 8780 LOOP_DOWN)) { 8781 break; 8782 } 8783 /* Delay for 1 second. */ 8784 ql_delay(ha, 1000000); 8785 } 8786 } 8787 ql_restart_hba(ha); 8788 } 8789 break; 8790 default: 8791 EL(ha, "unknown subcode=%xh\n", cmd->SubCode); 8792 cmd->Status = EXT_STATUS_ERR; 8793 cmd->ResponseLen = 0; 8794 break; 8795 } 8796 8797 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 8798 } 8799 8800 /* 8801 * ql_get_dcbx_parameters 8802 * Get DCBX parameters. 8803 * 8804 * Input: 8805 * ha: adapter state pointer. 8806 * cmd: User space CT arguments pointer. 8807 * mode: flags. 8808 */ 8809 static void 8810 ql_get_dcbx_parameters(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode) 8811 { 8812 uint8_t *tmp_buf; 8813 int rval; 8814 8815 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 8816 8817 if (!(CFG_IST(ha, CFG_CTRL_8081))) { 8818 EL(ha, "invalid request for HBA\n"); 8819 cmd->Status = EXT_STATUS_INVALID_REQUEST; 8820 cmd->ResponseLen = 0; 8821 return; 8822 } 8823 8824 /* Allocate memory for command. */ 8825 tmp_buf = kmem_zalloc(EXT_DEF_DCBX_PARAM_BUF_SIZE, KM_SLEEP); 8826 if (tmp_buf == NULL) { 8827 EL(ha, "failed, kmem_zalloc\n"); 8828 cmd->Status = EXT_STATUS_NO_MEMORY; 8829 cmd->ResponseLen = 0; 8830 return; 8831 } 8832 /* Send command */ 8833 rval = ql_get_dcbx_params(ha, EXT_DEF_DCBX_PARAM_BUF_SIZE, 8834 (caddr_t)tmp_buf); 8835 if (rval != QL_SUCCESS) { 8836 /* error */ 8837 EL(ha, "failed, get_dcbx_params_mbx=%xh\n", rval); 8838 kmem_free(tmp_buf, EXT_DEF_DCBX_PARAM_BUF_SIZE); 8839 cmd->Status = EXT_STATUS_ERR; 8840 cmd->ResponseLen = 0; 8841 return; 8842 } 8843 8844 /* Copy the response */ 8845 if (ql_send_buffer_data((caddr_t)tmp_buf, 8846 (caddr_t)(uintptr_t)cmd->ResponseAdr, 8847 EXT_DEF_DCBX_PARAM_BUF_SIZE, mode) != EXT_DEF_DCBX_PARAM_BUF_SIZE) { 8848 EL(ha, "failed, ddi_copyout\n"); 8849 cmd->Status = EXT_STATUS_COPY_ERR; 8850 cmd->ResponseLen = 0; 8851 } else { 8852 cmd->ResponseLen = EXT_DEF_DCBX_PARAM_BUF_SIZE; 8853 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 8854 } 8855 kmem_free(tmp_buf, EXT_DEF_DCBX_PARAM_BUF_SIZE); 8856 8857 } 8858 8859 /* 8860 * ql_qry_cna_port 8861 * Performs EXT_SC_QUERY_CNA_PORT subfunction. 8862 * 8863 * Input: 8864 * ha: adapter state pointer. 8865 * cmd: EXT_IOCTL cmd struct pointer. 8866 * mode: flags. 8867 * 8868 * Returns: 8869 * None, request status indicated in cmd->Status. 8870 * 8871 * Context: 8872 * Kernel context. 8873 */ 8874 static void 8875 ql_qry_cna_port(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode) 8876 { 8877 EXT_CNA_PORT cna_port = {0}; 8878 8879 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 8880 8881 if (!(CFG_IST(ha, CFG_CTRL_8081))) { 8882 EL(ha, "invalid request for HBA\n"); 8883 cmd->Status = EXT_STATUS_INVALID_REQUEST; 8884 cmd->ResponseLen = 0; 8885 return; 8886 } 8887 8888 if (cmd->ResponseLen < sizeof (EXT_CNA_PORT)) { 8889 cmd->Status = EXT_STATUS_BUFFER_TOO_SMALL; 8890 cmd->DetailStatus = sizeof (EXT_CNA_PORT); 8891 EL(ha, "failed, ResponseLen < EXT_CNA_PORT, Len=%xh\n", 8892 cmd->ResponseLen); 8893 cmd->ResponseLen = 0; 8894 return; 8895 } 8896 8897 cna_port.VLanId = ha->fcoe_vlan_id; 8898 cna_port.FabricParam = ha->fabric_params; 8899 bcopy(ha->fcoe_vnport_mac, cna_port.VNPortMACAddress, 8900 EXT_DEF_MAC_ADDRESS_SIZE); 8901 8902 if (ddi_copyout((void *)&cna_port, 8903 (void *)(uintptr_t)(cmd->ResponseAdr), 8904 sizeof (EXT_CNA_PORT), mode) != 0) { 8905 cmd->Status = EXT_STATUS_COPY_ERR; 8906 cmd->ResponseLen = 0; 8907 EL(ha, "failed, ddi_copyout\n"); 8908 } else { 8909 cmd->ResponseLen = sizeof (EXT_CNA_PORT); 8910 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 8911 } 8912 } 8913 8914 /* 8915 * ql_qry_adapter_versions 8916 * Performs EXT_SC_QUERY_ADAPTER_VERSIONS subfunction. 8917 * 8918 * Input: 8919 * ha: adapter state pointer. 8920 * cmd: EXT_IOCTL cmd struct pointer. 8921 * mode: flags. 8922 * 8923 * Returns: 8924 * None, request status indicated in cmd->Status. 8925 * 8926 * Context: 8927 * Kernel context. 8928 */ 8929 static void 8930 ql_qry_adapter_versions(ql_adapter_state_t *ha, EXT_IOCTL *cmd, 8931 int mode) 8932 { 8933 uint8_t is_8142, mpi_cap; 8934 uint32_t ver_len, transfer_size; 8935 PEXT_ADAPTERREGIONVERSION padapter_ver = NULL; 8936 8937 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 8938 8939 /* 8142s do not have a EDC PHY firmware. */ 8940 mpi_cap = (uint8_t)(ha->mpi_capability_list >> 8); 8941 8942 is_8142 = 0; 8943 /* Sizeof (Length + Reserved) = 8 Bytes */ 8944 if (mpi_cap == 0x02 || mpi_cap == 0x04) { 8945 ver_len = (sizeof (EXT_REGIONVERSION) * (NO_OF_VERSIONS - 1)) 8946 + 8; 8947 is_8142 = 1; 8948 } else { 8949 ver_len = (sizeof (EXT_REGIONVERSION) * NO_OF_VERSIONS) + 8; 8950 } 8951 8952 /* Allocate local memory for EXT_ADAPTERREGIONVERSION */ 8953 padapter_ver = (EXT_ADAPTERREGIONVERSION *)kmem_zalloc(ver_len, 8954 KM_SLEEP); 8955 8956 if (padapter_ver == NULL) { 8957 EL(ha, "failed, kmem_zalloc\n"); 8958 cmd->Status = EXT_STATUS_NO_MEMORY; 8959 cmd->ResponseLen = 0; 8960 return; 8961 } 8962 8963 padapter_ver->Length = 1; 8964 /* Copy MPI version */ 8965 padapter_ver->RegionVersion[0].Region = 8966 EXT_OPT_ROM_REGION_MPI_RISC_FW; 8967 padapter_ver->RegionVersion[0].Version[0] = 8968 ha->mpi_fw_major_version; 8969 padapter_ver->RegionVersion[0].Version[1] = 8970 ha->mpi_fw_minor_version; 8971 padapter_ver->RegionVersion[0].Version[2] = 8972 ha->mpi_fw_subminor_version; 8973 padapter_ver->RegionVersion[0].VersionLength = 3; 8974 padapter_ver->RegionVersion[0].Location = RUNNING_VERSION; 8975 8976 if (!is_8142) { 8977 padapter_ver->RegionVersion[1].Region = 8978 EXT_OPT_ROM_REGION_EDC_PHY_FW; 8979 padapter_ver->RegionVersion[1].Version[0] = 8980 ha->phy_fw_major_version; 8981 padapter_ver->RegionVersion[1].Version[1] = 8982 ha->phy_fw_minor_version; 8983 padapter_ver->RegionVersion[1].Version[2] = 8984 ha->phy_fw_subminor_version; 8985 padapter_ver->RegionVersion[1].VersionLength = 3; 8986 padapter_ver->RegionVersion[1].Location = RUNNING_VERSION; 8987 padapter_ver->Length = NO_OF_VERSIONS; 8988 } 8989 8990 if (cmd->ResponseLen < ver_len) { 8991 EL(ha, "failed, ResponseLen < ver_len, ", 8992 "RespLen=%xh ver_len=%xh\n", cmd->ResponseLen, ver_len); 8993 /* Calculate the No. of valid versions being returned. */ 8994 padapter_ver->Length = (uint32_t) 8995 ((cmd->ResponseLen - 8) / sizeof (EXT_REGIONVERSION)); 8996 cmd->Status = EXT_STATUS_BUFFER_TOO_SMALL; 8997 cmd->DetailStatus = ver_len; 8998 transfer_size = cmd->ResponseLen; 8999 } else { 9000 transfer_size = ver_len; 9001 } 9002 9003 if (ddi_copyout((void *)padapter_ver, 9004 (void *)(uintptr_t)(cmd->ResponseAdr), 9005 transfer_size, mode) != 0) { 9006 cmd->Status = EXT_STATUS_COPY_ERR; 9007 cmd->ResponseLen = 0; 9008 EL(ha, "failed, ddi_copyout\n"); 9009 } else { 9010 cmd->ResponseLen = ver_len; 9011 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 9012 } 9013 9014 kmem_free(padapter_ver, ver_len); 9015 } 9016 9017 /* 9018 * ql_get_xgmac_statistics 9019 * Get XgMac information 9020 * 9021 * Input: 9022 * ha: adapter state pointer. 9023 * cmd: EXT_IOCTL cmd struct pointer. 9024 * mode: flags. 9025 * 9026 * Returns: 9027 * None, request status indicated in cmd->Status. 9028 * 9029 * Context: 9030 * Kernel context. 9031 */ 9032 static void 9033 ql_get_xgmac_statistics(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode) 9034 { 9035 int rval; 9036 uint32_t size; 9037 int8_t *tmp_buf; 9038 EXT_MENLO_MANAGE_INFO info; 9039 9040 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 9041 9042 /* Verify the size of request structure. */ 9043 if (cmd->RequestLen < sizeof (EXT_MENLO_MANAGE_INFO)) { 9044 /* Return error */ 9045 EL(ha, "RequestLen=%d < %d\n", cmd->RequestLen, 9046 sizeof (EXT_MENLO_MANAGE_INFO)); 9047 cmd->Status = EXT_STATUS_INVALID_PARAM; 9048 cmd->DetailStatus = EXT_DSTATUS_REQUEST_LEN; 9049 cmd->ResponseLen = 0; 9050 return; 9051 } 9052 9053 /* Get manage info request. */ 9054 if (ddi_copyin((caddr_t)(uintptr_t)cmd->RequestAdr, 9055 (caddr_t)&info, sizeof (EXT_MENLO_MANAGE_INFO), mode) != 0) { 9056 EL(ha, "failed, ddi_copyin\n"); 9057 cmd->Status = EXT_STATUS_COPY_ERR; 9058 cmd->ResponseLen = 0; 9059 return; 9060 } 9061 9062 size = info.TotalByteCount; 9063 if (!size) { 9064 /* parameter error */ 9065 cmd->Status = EXT_STATUS_INVALID_PARAM; 9066 cmd->DetailStatus = 0; 9067 EL(ha, "failed, size=%xh\n", size); 9068 cmd->ResponseLen = 0; 9069 return; 9070 } 9071 9072 /* Allocate memory for command. */ 9073 tmp_buf = kmem_zalloc(size, KM_SLEEP); 9074 if (tmp_buf == NULL) { 9075 EL(ha, "failed, kmem_zalloc\n"); 9076 cmd->Status = EXT_STATUS_NO_MEMORY; 9077 cmd->ResponseLen = 0; 9078 return; 9079 } 9080 9081 if (!(info.Operation & MENLO_OP_GET_INFO)) { 9082 EL(ha, "Invalid request for 81XX\n"); 9083 kmem_free(tmp_buf, size); 9084 cmd->Status = EXT_STATUS_ERR; 9085 cmd->ResponseLen = 0; 9086 return; 9087 } 9088 9089 rval = ql_get_xgmac_stats(ha, size, (caddr_t)tmp_buf); 9090 9091 if (rval != QL_SUCCESS) { 9092 /* error */ 9093 EL(ha, "failed, get_xgmac_stats =%xh\n", rval); 9094 kmem_free(tmp_buf, size); 9095 cmd->Status = EXT_STATUS_ERR; 9096 cmd->ResponseLen = 0; 9097 return; 9098 } 9099 9100 if (ql_send_buffer_data(tmp_buf, (caddr_t)(uintptr_t)info.pDataBytes, 9101 size, mode) != size) { 9102 EL(ha, "failed, ddi_copyout\n"); 9103 cmd->Status = EXT_STATUS_COPY_ERR; 9104 cmd->ResponseLen = 0; 9105 } else { 9106 cmd->ResponseLen = info.TotalByteCount; 9107 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 9108 } 9109 kmem_free(tmp_buf, size); 9110 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 9111 } 9112 9113 /* 9114 * ql_get_fcf_list 9115 * Get FCF list. 9116 * 9117 * Input: 9118 * ha: adapter state pointer. 9119 * cmd: User space CT arguments pointer. 9120 * mode: flags. 9121 */ 9122 static void 9123 ql_get_fcf_list(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode) 9124 { 9125 uint8_t *tmp_buf; 9126 int rval; 9127 EXT_FCF_LIST fcf_list = {0}; 9128 ql_fcf_list_desc_t mb_fcf_list = {0}; 9129 9130 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 9131 9132 if (!(CFG_IST(ha, CFG_CTRL_81XX))) { 9133 EL(ha, "invalid request for HBA\n"); 9134 cmd->Status = EXT_STATUS_INVALID_REQUEST; 9135 cmd->ResponseLen = 0; 9136 return; 9137 } 9138 /* Get manage info request. */ 9139 if (ddi_copyin((caddr_t)(uintptr_t)cmd->RequestAdr, 9140 (caddr_t)&fcf_list, sizeof (EXT_FCF_LIST), mode) != 0) { 9141 EL(ha, "failed, ddi_copyin\n"); 9142 cmd->Status = EXT_STATUS_COPY_ERR; 9143 cmd->ResponseLen = 0; 9144 return; 9145 } 9146 9147 if (!(fcf_list.BufSize)) { 9148 /* Return error */ 9149 EL(ha, "failed, fcf_list BufSize is=%xh\n", 9150 fcf_list.BufSize); 9151 cmd->Status = EXT_STATUS_INVALID_PARAM; 9152 cmd->ResponseLen = 0; 9153 return; 9154 } 9155 /* Allocate memory for command. */ 9156 tmp_buf = kmem_zalloc(fcf_list.BufSize, KM_SLEEP); 9157 if (tmp_buf == NULL) { 9158 EL(ha, "failed, kmem_zalloc\n"); 9159 cmd->Status = EXT_STATUS_NO_MEMORY; 9160 cmd->ResponseLen = 0; 9161 return; 9162 } 9163 /* build the descriptor */ 9164 if (fcf_list.Options) { 9165 mb_fcf_list.options = FCF_LIST_RETURN_ONE; 9166 } else { 9167 mb_fcf_list.options = FCF_LIST_RETURN_ALL; 9168 } 9169 mb_fcf_list.fcf_index = (uint16_t)fcf_list.FcfIndex; 9170 mb_fcf_list.buffer_size = fcf_list.BufSize; 9171 9172 /* Send command */ 9173 rval = ql_get_fcf_list_mbx(ha, &mb_fcf_list, (caddr_t)tmp_buf); 9174 if (rval != QL_SUCCESS) { 9175 /* error */ 9176 EL(ha, "failed, get_fcf_list_mbx=%xh\n", rval); 9177 kmem_free(tmp_buf, fcf_list.BufSize); 9178 cmd->Status = EXT_STATUS_ERR; 9179 cmd->ResponseLen = 0; 9180 return; 9181 } 9182 9183 /* Copy the response */ 9184 if (ql_send_buffer_data((caddr_t)tmp_buf, 9185 (caddr_t)(uintptr_t)cmd->ResponseAdr, 9186 fcf_list.BufSize, mode) != fcf_list.BufSize) { 9187 EL(ha, "failed, ddi_copyout\n"); 9188 cmd->Status = EXT_STATUS_COPY_ERR; 9189 cmd->ResponseLen = 0; 9190 } else { 9191 cmd->ResponseLen = mb_fcf_list.buffer_size; 9192 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 9193 } 9194 9195 kmem_free(tmp_buf, fcf_list.BufSize); 9196 } 9197 9198 /* 9199 * ql_get_resource_counts 9200 * Get Resource counts: 9201 * 9202 * Input: 9203 * ha: adapter state pointer. 9204 * cmd: User space CT arguments pointer. 9205 * mode: flags. 9206 */ 9207 static void 9208 ql_get_resource_counts(ql_adapter_state_t *ha, EXT_IOCTL *cmd, int mode) 9209 { 9210 int rval; 9211 ql_mbx_data_t mr; 9212 EXT_RESOURCE_CNTS tmp_rc_cnt = {0}; 9213 9214 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 9215 9216 if (!(CFG_IST(ha, CFG_CTRL_242581))) { 9217 EL(ha, "invalid request for HBA\n"); 9218 cmd->Status = EXT_STATUS_INVALID_REQUEST; 9219 cmd->ResponseLen = 0; 9220 return; 9221 } 9222 9223 if (cmd->ResponseLen < sizeof (EXT_RESOURCE_CNTS)) { 9224 cmd->Status = EXT_STATUS_BUFFER_TOO_SMALL; 9225 cmd->DetailStatus = sizeof (EXT_RESOURCE_CNTS); 9226 EL(ha, "failed, ResponseLen < EXT_RESOURCE_CNTS, " 9227 "Len=%xh\n", cmd->ResponseLen); 9228 cmd->ResponseLen = 0; 9229 return; 9230 } 9231 9232 rval = ql_get_resource_cnts(ha, &mr); 9233 if (rval != QL_SUCCESS) { 9234 EL(ha, "resource cnt mbx failed\n"); 9235 cmd->Status = EXT_STATUS_ERR; 9236 cmd->ResponseLen = 0; 9237 return; 9238 } 9239 9240 tmp_rc_cnt.OrgTgtXchgCtrlCnt = (uint32_t)mr.mb[1]; 9241 tmp_rc_cnt.CurTgtXchgCtrlCnt = (uint32_t)mr.mb[2]; 9242 tmp_rc_cnt.CurXchgCtrlCnt = (uint32_t)mr.mb[3]; 9243 tmp_rc_cnt.OrgXchgCtrlCnt = (uint32_t)mr.mb[6]; 9244 tmp_rc_cnt.CurIocbBufCnt = (uint32_t)mr.mb[7]; 9245 tmp_rc_cnt.OrgIocbBufCnt = (uint32_t)mr.mb[10]; 9246 tmp_rc_cnt.NoOfSupVPs = (uint32_t)mr.mb[11]; 9247 tmp_rc_cnt.NoOfSupFCFs = (uint32_t)mr.mb[12]; 9248 9249 rval = ddi_copyout((void *)&tmp_rc_cnt, 9250 (void *)(uintptr_t)(cmd->ResponseAdr), 9251 sizeof (EXT_RESOURCE_CNTS), mode); 9252 if (rval != 0) { 9253 cmd->Status = EXT_STATUS_COPY_ERR; 9254 cmd->ResponseLen = 0; 9255 EL(ha, "failed, ddi_copyout\n"); 9256 } else { 9257 cmd->ResponseLen = sizeof (EXT_RESOURCE_CNTS); 9258 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 9259 } 9260 }