1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2009 QLogic Corporation. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 29 * Use is subject to license terms. 30 */ 31 32 #include <sys/conf.h> 33 #include <sys/ddi.h> 34 #include <sys/stat.h> 35 #include <sys/pci.h> 36 #include <sys/sunddi.h> 37 #include <sys/modctl.h> 38 #include <sys/file.h> 39 #include <sys/cred.h> 40 #include <sys/byteorder.h> 41 #include <sys/atomic.h> 42 #include <sys/scsi/scsi.h> 43 44 #include <stmf_defines.h> 45 #include <fct_defines.h> 46 #include <stmf.h> 47 #include <portif.h> 48 #include <fct.h> 49 #include <qlt.h> 50 #include <qlt_dma.h> 51 #include <qlt_ioctl.h> 52 #include <qlt_open.h> 53 #include <stmf_ioctl.h> 54 55 static int qlt_attach(dev_info_t *dip, ddi_attach_cmd_t cmd); 56 static int qlt_detach(dev_info_t *dip, ddi_detach_cmd_t cmd); 57 static void qlt_enable_intr(qlt_state_t *); 58 static void qlt_disable_intr(qlt_state_t *); 59 static fct_status_t qlt_reset_chip(qlt_state_t *qlt); 60 static fct_status_t qlt_download_fw(qlt_state_t *qlt); 61 static fct_status_t qlt_load_risc_ram(qlt_state_t *qlt, uint32_t *host_addr, 62 uint32_t word_count, uint32_t risc_addr); 63 static fct_status_t qlt_raw_mailbox_command(qlt_state_t *qlt); 64 static mbox_cmd_t *qlt_alloc_mailbox_command(qlt_state_t *qlt, 65 uint32_t dma_size); 66 void qlt_free_mailbox_command(qlt_state_t *qlt, mbox_cmd_t *mcp); 67 static fct_status_t qlt_mailbox_command(qlt_state_t *qlt, mbox_cmd_t *mcp); 68 static uint_t qlt_isr(caddr_t arg, caddr_t arg2); 69 static fct_status_t qlt_firmware_dump(fct_local_port_t *port, 70 stmf_state_change_info_t *ssci); 71 static void qlt_handle_inot(qlt_state_t *qlt, uint8_t *inot); 72 static void qlt_handle_purex(qlt_state_t *qlt, uint8_t *resp); 73 static void qlt_handle_atio(qlt_state_t *qlt, uint8_t *atio); 74 static void qlt_handle_ctio_completion(qlt_state_t *qlt, uint8_t *rsp); 75 static void qlt_handle_sol_abort_completion(qlt_state_t *qlt, uint8_t *rsp); 76 static void qlt_handle_dereg_completion(qlt_state_t *qlt, uint8_t *rsp); 77 static void qlt_handle_unsol_els_completion(qlt_state_t *qlt, uint8_t *rsp); 78 static void qlt_handle_unsol_els_abort_completion(qlt_state_t *qlt, 79 uint8_t *rsp); 80 static void qlt_handle_sol_els_completion(qlt_state_t *qlt, uint8_t *rsp); 81 static void qlt_handle_rcvd_abts(qlt_state_t *qlt, uint8_t *resp); 82 static void qlt_handle_abts_completion(qlt_state_t *qlt, uint8_t *resp); 83 static fct_status_t qlt_read_nvram(qlt_state_t *qlt); 84 static void qlt_verify_fw(qlt_state_t *qlt); 85 static void qlt_handle_verify_fw_completion(qlt_state_t *qlt, uint8_t *rsp); 86 fct_status_t qlt_port_start(caddr_t arg); 87 fct_status_t qlt_port_stop(caddr_t arg); 88 fct_status_t qlt_port_online(qlt_state_t *qlt); 89 fct_status_t qlt_port_offline(qlt_state_t *qlt); 90 static fct_status_t qlt_get_link_info(fct_local_port_t *port, 91 fct_link_info_t *li); 92 static void qlt_ctl(struct fct_local_port *port, int cmd, void *arg); 93 static fct_status_t qlt_force_lip(qlt_state_t *); 94 static fct_status_t qlt_do_flogi(struct fct_local_port *port, 95 fct_flogi_xchg_t *fx); 96 void qlt_handle_atio_queue_update(qlt_state_t *qlt); 97 void qlt_handle_resp_queue_update(qlt_state_t *qlt); 98 fct_status_t qlt_register_remote_port(fct_local_port_t *port, 99 fct_remote_port_t *rp, fct_cmd_t *login); 100 fct_status_t qlt_deregister_remote_port(fct_local_port_t *port, 101 fct_remote_port_t *rp); 102 fct_status_t qlt_send_cmd_response(fct_cmd_t *cmd, uint32_t ioflags); 103 fct_status_t qlt_send_els_response(qlt_state_t *qlt, fct_cmd_t *cmd); 104 fct_status_t qlt_send_abts_response(qlt_state_t *qlt, 105 fct_cmd_t *cmd, int terminate); 106 static void qlt_handle_inot(qlt_state_t *qlt, uint8_t *inot); 107 int qlt_set_uniq_flag(uint16_t *ptr, uint16_t setf, uint16_t abortf); 108 fct_status_t qlt_abort_cmd(struct fct_local_port *port, 109 fct_cmd_t *cmd, uint32_t flags); 110 fct_status_t qlt_abort_sol_cmd(qlt_state_t *qlt, fct_cmd_t *cmd); 111 fct_status_t qlt_abort_purex(qlt_state_t *qlt, fct_cmd_t *cmd); 112 fct_status_t qlt_abort_unsol_scsi_cmd(qlt_state_t *qlt, fct_cmd_t *cmd); 113 fct_status_t qlt_send_cmd(fct_cmd_t *cmd); 114 fct_status_t qlt_send_els(qlt_state_t *qlt, fct_cmd_t *cmd); 115 fct_status_t qlt_send_status(qlt_state_t *qlt, fct_cmd_t *cmd); 116 fct_status_t qlt_xfer_scsi_data(fct_cmd_t *cmd, 117 stmf_data_buf_t *dbuf, uint32_t ioflags); 118 fct_status_t qlt_send_ct(qlt_state_t *qlt, fct_cmd_t *cmd); 119 static void qlt_handle_ct_completion(qlt_state_t *qlt, uint8_t *rsp); 120 static void qlt_release_intr(qlt_state_t *qlt); 121 static int qlt_setup_interrupts(qlt_state_t *qlt); 122 static void qlt_destroy_mutex(qlt_state_t *qlt); 123 124 static fct_status_t qlt_read_risc_ram(qlt_state_t *qlt, uint32_t addr, 125 uint32_t words); 126 static int qlt_dump_queue(qlt_state_t *qlt, caddr_t qadr, int entries, 127 caddr_t buf, uint_t size_left); 128 static int qlt_dump_risc_ram(qlt_state_t *qlt, uint32_t addr, uint32_t words, 129 caddr_t buf, uint_t size_left); 130 static int qlt_fwdump_dump_regs(qlt_state_t *qlt, caddr_t buf, int startaddr, 131 int count, uint_t size_left); 132 static int qlt_ioctl(dev_t dev, int cmd, intptr_t data, int mode, 133 cred_t *credp, int *rval); 134 static int qlt_open(dev_t *devp, int flag, int otype, cred_t *credp); 135 static int qlt_close(dev_t dev, int flag, int otype, cred_t *credp); 136 137 static int qlt_setup_msi(qlt_state_t *qlt); 138 static int qlt_setup_msix(qlt_state_t *qlt); 139 140 static int qlt_el_trace_desc_ctor(qlt_state_t *qlt); 141 static int qlt_el_trace_desc_dtor(qlt_state_t *qlt); 142 static int qlt_validate_trace_desc(qlt_state_t *qlt); 143 static char *qlt_find_trace_start(qlt_state_t *qlt); 144 145 static int qlt_read_int_prop(qlt_state_t *qlt, char *prop, int defval); 146 static int qlt_read_string_prop(qlt_state_t *qlt, char *prop, char **prop_val); 147 static int qlt_read_string_instance_prop(qlt_state_t *qlt, char *prop, 148 char **prop_val); 149 static int qlt_read_int_instance_prop(qlt_state_t *, char *, int); 150 static int qlt_convert_string_to_ull(char *prop, int radix, 151 u_longlong_t *result); 152 static boolean_t qlt_wwn_overload_prop(qlt_state_t *qlt); 153 static int qlt_quiesce(dev_info_t *dip); 154 static fct_status_t qlt_raw_wrt_risc_ram_word(qlt_state_t *qlt, uint32_t, 155 uint32_t); 156 static fct_status_t qlt_raw_rd_risc_ram_word(qlt_state_t *qlt, uint32_t, 157 uint32_t *); 158 static void qlt_mps_reset(qlt_state_t *qlt); 159 static void qlt_properties(qlt_state_t *qlt); 160 161 162 #define SETELSBIT(bmp, els) (bmp)[((els) >> 3) & 0x1F] = \ 163 (uint8_t)((bmp)[((els) >> 3) & 0x1F] | ((uint8_t)1) << ((els) & 7)) 164 165 int qlt_enable_msix = 0; 166 int qlt_enable_msi = 1; 167 168 169 string_table_t prop_status_tbl[] = DDI_PROP_STATUS(); 170 171 /* Array to quickly calculate next free buf index to use */ 172 #if 0 173 static int qlt_nfb[] = { 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 0xff }; 174 #endif 175 176 static struct cb_ops qlt_cb_ops = { 177 qlt_open, 178 qlt_close, 179 nodev, 180 nodev, 181 nodev, 182 nodev, 183 nodev, 184 qlt_ioctl, 185 nodev, 186 nodev, 187 nodev, 188 nochpoll, 189 ddi_prop_op, 190 0, 191 D_MP | D_NEW 192 }; 193 194 static struct dev_ops qlt_ops = { 195 DEVO_REV, 196 0, 197 nodev, 198 nulldev, 199 nulldev, 200 qlt_attach, 201 qlt_detach, 202 nodev, 203 &qlt_cb_ops, 204 NULL, 205 ddi_power, 206 qlt_quiesce 207 }; 208 209 #ifndef PORT_SPEED_10G 210 #define PORT_SPEED_10G 16 211 #endif 212 213 static struct modldrv modldrv = { 214 &mod_driverops, 215 QLT_NAME" "QLT_VERSION, 216 &qlt_ops, 217 }; 218 219 static struct modlinkage modlinkage = { 220 MODREV_1, &modldrv, NULL 221 }; 222 223 void *qlt_state = NULL; 224 kmutex_t qlt_global_lock; 225 static uint32_t qlt_loaded_counter = 0; 226 227 static char *pci_speeds[] = { " 33", "-X Mode 1 66", "-X Mode 1 100", 228 "-X Mode 1 133", "--Invalid--", 229 "-X Mode 2 66", "-X Mode 2 100", 230 "-X Mode 2 133", " 66" }; 231 232 /* Always use 64 bit DMA. */ 233 static ddi_dma_attr_t qlt_queue_dma_attr = { 234 DMA_ATTR_V0, /* dma_attr_version */ 235 0, /* low DMA address range */ 236 0xffffffffffffffff, /* high DMA address range */ 237 0xffffffff, /* DMA counter register */ 238 64, /* DMA address alignment */ 239 0xff, /* DMA burstsizes */ 240 1, /* min effective DMA size */ 241 0xffffffff, /* max DMA xfer size */ 242 0xffffffff, /* segment boundary */ 243 1, /* s/g list length */ 244 1, /* granularity of device */ 245 0 /* DMA transfer flags */ 246 }; 247 248 /* qlogic logging */ 249 int enable_extended_logging = 0; 250 251 static char qlt_provider_name[] = "qlt"; 252 static struct stmf_port_provider *qlt_pp; 253 254 int 255 _init(void) 256 { 257 int ret; 258 259 ret = ddi_soft_state_init(&qlt_state, sizeof (qlt_state_t), 0); 260 if (ret == 0) { 261 mutex_init(&qlt_global_lock, 0, MUTEX_DRIVER, 0); 262 qlt_pp = (stmf_port_provider_t *)stmf_alloc( 263 STMF_STRUCT_PORT_PROVIDER, 0, 0); 264 qlt_pp->pp_portif_rev = PORTIF_REV_1; 265 qlt_pp->pp_name = qlt_provider_name; 266 if (stmf_register_port_provider(qlt_pp) != STMF_SUCCESS) { 267 stmf_free(qlt_pp); 268 mutex_destroy(&qlt_global_lock); 269 ddi_soft_state_fini(&qlt_state); 270 return (EIO); 271 } 272 ret = mod_install(&modlinkage); 273 if (ret != 0) { 274 (void) stmf_deregister_port_provider(qlt_pp); 275 stmf_free(qlt_pp); 276 mutex_destroy(&qlt_global_lock); 277 ddi_soft_state_fini(&qlt_state); 278 } 279 } 280 return (ret); 281 } 282 283 int 284 _fini(void) 285 { 286 int ret; 287 288 if (qlt_loaded_counter) 289 return (EBUSY); 290 ret = mod_remove(&modlinkage); 291 if (ret == 0) { 292 (void) stmf_deregister_port_provider(qlt_pp); 293 stmf_free(qlt_pp); 294 mutex_destroy(&qlt_global_lock); 295 ddi_soft_state_fini(&qlt_state); 296 } 297 return (ret); 298 } 299 300 int 301 _info(struct modinfo *modinfop) 302 { 303 return (mod_info(&modlinkage, modinfop)); 304 } 305 306 307 static int 308 qlt_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 309 { 310 int instance; 311 qlt_state_t *qlt; 312 ddi_device_acc_attr_t dev_acc_attr; 313 uint16_t did; 314 uint16_t val; 315 uint16_t mr; 316 size_t discard; 317 uint_t ncookies; 318 int max_read_size; 319 int max_payload_size; 320 fct_status_t ret; 321 322 /* No support for suspend resume yet */ 323 if (cmd != DDI_ATTACH) 324 return (DDI_FAILURE); 325 instance = ddi_get_instance(dip); 326 327 if (ddi_soft_state_zalloc(qlt_state, instance) != DDI_SUCCESS) { 328 return (DDI_FAILURE); 329 } 330 331 if ((qlt = (qlt_state_t *)ddi_get_soft_state(qlt_state, instance)) == 332 NULL) { 333 goto attach_fail_1; 334 } 335 336 qlt->instance = instance; 337 338 qlt->nvram = (qlt_nvram_t *)kmem_zalloc(sizeof (qlt_nvram_t), KM_SLEEP); 339 qlt->dip = dip; 340 341 if (qlt_el_trace_desc_ctor(qlt) != DDI_SUCCESS) { 342 cmn_err(CE_WARN, "qlt(%d): can't setup el tracing", instance); 343 goto attach_fail_1; 344 } 345 346 EL(qlt, "instance=%d, ptr=%p\n", instance, (void *)qlt); 347 348 if (pci_config_setup(dip, &qlt->pcicfg_acc_handle) != DDI_SUCCESS) { 349 goto attach_fail_2; 350 } 351 did = PCICFG_RD16(qlt, PCI_CONF_DEVID); 352 if ((did != 0x2422) && (did != 0x2432) && 353 (did != 0x8432) && (did != 0x2532) && 354 (did != 0x8001)) { 355 cmn_err(CE_WARN, "qlt(%d): unknown devid(%x), failing attach", 356 instance, did); 357 goto attach_fail_4; 358 } 359 360 if ((did & 0xFF00) == 0x8000) 361 qlt->qlt_81xx_chip = 1; 362 else if ((did & 0xFF00) == 0x2500) 363 qlt->qlt_25xx_chip = 1; 364 365 dev_acc_attr.devacc_attr_version = DDI_DEVICE_ATTR_V0; 366 dev_acc_attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC; 367 dev_acc_attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC; 368 if (ddi_regs_map_setup(dip, 2, &qlt->regs, 0, 0x100, 369 &dev_acc_attr, &qlt->regs_acc_handle) != DDI_SUCCESS) { 370 goto attach_fail_4; 371 } 372 if (did == 0x2422) { 373 uint32_t pci_bits = REG_RD32(qlt, REG_CTRL_STATUS); 374 uint32_t slot = pci_bits & PCI_64_BIT_SLOT; 375 pci_bits >>= 8; 376 pci_bits &= 0xf; 377 if ((pci_bits == 3) || (pci_bits == 7)) { 378 cmn_err(CE_NOTE, 379 "!qlt(%d): HBA running at PCI%sMHz (%d)", 380 instance, pci_speeds[pci_bits], pci_bits); 381 } else { 382 cmn_err(CE_WARN, 383 "qlt(%d): HBA running at PCI%sMHz %s(%d)", 384 instance, (pci_bits <= 8) ? pci_speeds[pci_bits] : 385 "(Invalid)", ((pci_bits == 0) || 386 (pci_bits == 8)) ? (slot ? "64 bit slot " : 387 "32 bit slot ") : "", pci_bits); 388 } 389 } 390 if ((ret = qlt_read_nvram(qlt)) != QLT_SUCCESS) { 391 cmn_err(CE_WARN, "qlt(%d): read nvram failure %llx", instance, 392 (unsigned long long)ret); 393 goto attach_fail_5; 394 } 395 396 qlt_properties(qlt); 397 398 if (ddi_dma_alloc_handle(dip, &qlt_queue_dma_attr, DDI_DMA_SLEEP, 399 0, &qlt->queue_mem_dma_handle) != DDI_SUCCESS) { 400 goto attach_fail_5; 401 } 402 if (ddi_dma_mem_alloc(qlt->queue_mem_dma_handle, TOTAL_DMA_MEM_SIZE, 403 &dev_acc_attr, DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, 0, 404 &qlt->queue_mem_ptr, &discard, &qlt->queue_mem_acc_handle) != 405 DDI_SUCCESS) { 406 goto attach_fail_6; 407 } 408 if (ddi_dma_addr_bind_handle(qlt->queue_mem_dma_handle, NULL, 409 qlt->queue_mem_ptr, TOTAL_DMA_MEM_SIZE, 410 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, 0, 411 &qlt->queue_mem_cookie, &ncookies) != DDI_SUCCESS) { 412 goto attach_fail_7; 413 } 414 if (ncookies != 1) 415 goto attach_fail_8; 416 qlt->req_ptr = qlt->queue_mem_ptr + REQUEST_QUEUE_OFFSET; 417 qlt->resp_ptr = qlt->queue_mem_ptr + RESPONSE_QUEUE_OFFSET; 418 qlt->preq_ptr = qlt->queue_mem_ptr + PRIORITY_QUEUE_OFFSET; 419 qlt->atio_ptr = qlt->queue_mem_ptr + ATIO_QUEUE_OFFSET; 420 421 /* mutex are inited in this function */ 422 if (qlt_setup_interrupts(qlt) != DDI_SUCCESS) 423 goto attach_fail_8; 424 425 (void) snprintf(qlt->qlt_minor_name, sizeof (qlt->qlt_minor_name), 426 "qlt%d", instance); 427 (void) snprintf(qlt->qlt_port_alias, sizeof (qlt->qlt_port_alias), 428 "%s,0", qlt->qlt_minor_name); 429 430 if (ddi_create_minor_node(dip, qlt->qlt_minor_name, S_IFCHR, 431 instance, DDI_NT_STMF_PP, 0) != DDI_SUCCESS) { 432 goto attach_fail_9; 433 } 434 435 cv_init(&qlt->rp_dereg_cv, NULL, CV_DRIVER, NULL); 436 cv_init(&qlt->mbox_cv, NULL, CV_DRIVER, NULL); 437 mutex_init(&qlt->qlt_ioctl_lock, NULL, MUTEX_DRIVER, NULL); 438 439 /* Setup PCI cfg space registers */ 440 max_read_size = qlt_read_int_prop(qlt, "pci-max-read-request", 11); 441 if (max_read_size == 11) 442 goto over_max_read_xfer_setting; 443 if (did == 0x2422) { 444 if (max_read_size == 512) 445 val = 0; 446 else if (max_read_size == 1024) 447 val = 1; 448 else if (max_read_size == 2048) 449 val = 2; 450 else if (max_read_size == 4096) 451 val = 3; 452 else { 453 cmn_err(CE_WARN, "qlt(%d) malformed " 454 "pci-max-read-request in qlt.conf. Valid values " 455 "for this HBA are 512/1024/2048/4096", instance); 456 goto over_max_read_xfer_setting; 457 } 458 mr = (uint16_t)PCICFG_RD16(qlt, 0x4E); 459 mr = (uint16_t)(mr & 0xfff3); 460 mr = (uint16_t)(mr | (val << 2)); 461 PCICFG_WR16(qlt, 0x4E, mr); 462 } else if ((did == 0x2432) || (did == 0x8432) || 463 (did == 0x2532) || (did == 0x8001)) { 464 if (max_read_size == 128) 465 val = 0; 466 else if (max_read_size == 256) 467 val = 1; 468 else if (max_read_size == 512) 469 val = 2; 470 else if (max_read_size == 1024) 471 val = 3; 472 else if (max_read_size == 2048) 473 val = 4; 474 else if (max_read_size == 4096) 475 val = 5; 476 else { 477 cmn_err(CE_WARN, "qlt(%d) malformed " 478 "pci-max-read-request in qlt.conf. Valid values " 479 "for this HBA are 128/256/512/1024/2048/4096", 480 instance); 481 goto over_max_read_xfer_setting; 482 } 483 mr = (uint16_t)PCICFG_RD16(qlt, 0x54); 484 mr = (uint16_t)(mr & 0x8fff); 485 mr = (uint16_t)(mr | (val << 12)); 486 PCICFG_WR16(qlt, 0x54, mr); 487 } else { 488 cmn_err(CE_WARN, "qlt(%d): dont know how to set " 489 "pci-max-read-request for this device (%x)", 490 instance, did); 491 } 492 over_max_read_xfer_setting:; 493 494 max_payload_size = qlt_read_int_prop(qlt, "pcie-max-payload-size", 11); 495 if (max_payload_size == 11) 496 goto over_max_payload_setting; 497 if ((did == 0x2432) || (did == 0x8432) || 498 (did == 0x2532) || (did == 0x8001)) { 499 if (max_payload_size == 128) 500 val = 0; 501 else if (max_payload_size == 256) 502 val = 1; 503 else if (max_payload_size == 512) 504 val = 2; 505 else if (max_payload_size == 1024) 506 val = 3; 507 else { 508 cmn_err(CE_WARN, "qlt(%d) malformed " 509 "pcie-max-payload-size in qlt.conf. Valid values " 510 "for this HBA are 128/256/512/1024", 511 instance); 512 goto over_max_payload_setting; 513 } 514 mr = (uint16_t)PCICFG_RD16(qlt, 0x54); 515 mr = (uint16_t)(mr & 0xff1f); 516 mr = (uint16_t)(mr | (val << 5)); 517 PCICFG_WR16(qlt, 0x54, mr); 518 } else { 519 cmn_err(CE_WARN, "qlt(%d): dont know how to set " 520 "pcie-max-payload-size for this device (%x)", 521 instance, did); 522 } 523 524 over_max_payload_setting:; 525 526 qlt_enable_intr(qlt); 527 528 if (qlt_port_start((caddr_t)qlt) != QLT_SUCCESS) 529 goto attach_fail_10; 530 531 ddi_report_dev(dip); 532 return (DDI_SUCCESS); 533 534 attach_fail_10:; 535 mutex_destroy(&qlt->qlt_ioctl_lock); 536 cv_destroy(&qlt->mbox_cv); 537 cv_destroy(&qlt->rp_dereg_cv); 538 ddi_remove_minor_node(dip, qlt->qlt_minor_name); 539 attach_fail_9:; 540 qlt_destroy_mutex(qlt); 541 qlt_release_intr(qlt); 542 attach_fail_8:; 543 (void) ddi_dma_unbind_handle(qlt->queue_mem_dma_handle); 544 attach_fail_7:; 545 ddi_dma_mem_free(&qlt->queue_mem_acc_handle); 546 attach_fail_6:; 547 ddi_dma_free_handle(&qlt->queue_mem_dma_handle); 548 attach_fail_5:; 549 ddi_regs_map_free(&qlt->regs_acc_handle); 550 attach_fail_4:; 551 pci_config_teardown(&qlt->pcicfg_acc_handle); 552 kmem_free(qlt->nvram, sizeof (qlt_nvram_t)); 553 (void) qlt_el_trace_desc_dtor(qlt); 554 attach_fail_2:; 555 attach_fail_1:; 556 ddi_soft_state_free(qlt_state, instance); 557 return (DDI_FAILURE); 558 } 559 560 #define FCT_I_EVENT_BRING_PORT_OFFLINE 0x83 561 562 /* ARGSUSED */ 563 static int 564 qlt_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 565 { 566 qlt_state_t *qlt; 567 568 int instance; 569 570 instance = ddi_get_instance(dip); 571 if ((qlt = (qlt_state_t *)ddi_get_soft_state(qlt_state, instance)) == 572 NULL) { 573 return (DDI_FAILURE); 574 } 575 576 if (qlt->fw_code01) { 577 return (DDI_FAILURE); 578 } 579 580 if ((qlt->qlt_state != FCT_STATE_OFFLINE) || 581 qlt->qlt_state_not_acked) { 582 return (DDI_FAILURE); 583 } 584 if (qlt_port_stop((caddr_t)qlt) != FCT_SUCCESS) { 585 return (DDI_FAILURE); 586 } 587 588 qlt_disable_intr(qlt); 589 590 ddi_remove_minor_node(dip, qlt->qlt_minor_name); 591 qlt_destroy_mutex(qlt); 592 qlt_release_intr(qlt); 593 (void) ddi_dma_unbind_handle(qlt->queue_mem_dma_handle); 594 ddi_dma_mem_free(&qlt->queue_mem_acc_handle); 595 ddi_dma_free_handle(&qlt->queue_mem_dma_handle); 596 ddi_regs_map_free(&qlt->regs_acc_handle); 597 pci_config_teardown(&qlt->pcicfg_acc_handle); 598 kmem_free(qlt->nvram, sizeof (qlt_nvram_t)); 599 cv_destroy(&qlt->mbox_cv); 600 cv_destroy(&qlt->rp_dereg_cv); 601 (void) qlt_el_trace_desc_dtor(qlt); 602 ddi_soft_state_free(qlt_state, instance); 603 604 return (DDI_SUCCESS); 605 } 606 607 /* 608 * qlt_quiesce quiesce a device attached to the system. 609 */ 610 static int 611 qlt_quiesce(dev_info_t *dip) 612 { 613 qlt_state_t *qlt; 614 uint32_t timer; 615 uint32_t stat; 616 617 qlt = ddi_get_soft_state(qlt_state, ddi_get_instance(dip)); 618 if (qlt == NULL) { 619 /* Oh well.... */ 620 return (DDI_SUCCESS); 621 } 622 623 REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_HOST_TO_RISC_INTR)); 624 REG_WR16(qlt, REG_MBOX0, MBC_STOP_FIRMWARE); 625 REG_WR32(qlt, REG_HCCR, HCCR_CMD(SET_HOST_TO_RISC_INTR)); 626 for (timer = 0; timer < 30000; timer++) { 627 stat = REG_RD32(qlt, REG_RISC_STATUS); 628 if (stat & RISC_HOST_INTR_REQUEST) { 629 if ((stat & FW_INTR_STATUS_MASK) < 0x12) { 630 REG_WR32(qlt, REG_HCCR, 631 HCCR_CMD(CLEAR_RISC_PAUSE)); 632 break; 633 } 634 REG_WR32(qlt, REG_HCCR, 635 HCCR_CMD(CLEAR_HOST_TO_RISC_INTR)); 636 } 637 drv_usecwait(100); 638 } 639 /* Reset the chip. */ 640 REG_WR32(qlt, REG_CTRL_STATUS, CHIP_SOFT_RESET | DMA_SHUTDOWN_CTRL | 641 PCI_X_XFER_CTRL); 642 drv_usecwait(100); 643 644 qlt_disable_intr(qlt); 645 646 return (DDI_SUCCESS); 647 } 648 649 static void 650 qlt_enable_intr(qlt_state_t *qlt) 651 { 652 if (qlt->intr_cap & DDI_INTR_FLAG_BLOCK) { 653 (void) ddi_intr_block_enable(qlt->htable, qlt->intr_cnt); 654 } else { 655 int i; 656 for (i = 0; i < qlt->intr_cnt; i++) 657 (void) ddi_intr_enable(qlt->htable[i]); 658 } 659 qlt->qlt_intr_enabled = 1; 660 } 661 662 static void 663 qlt_disable_intr(qlt_state_t *qlt) 664 { 665 if (qlt->intr_cap & DDI_INTR_FLAG_BLOCK) { 666 (void) ddi_intr_block_disable(qlt->htable, qlt->intr_cnt); 667 } else { 668 int i; 669 for (i = 0; i < qlt->intr_cnt; i++) 670 (void) ddi_intr_disable(qlt->htable[i]); 671 } 672 qlt->qlt_intr_enabled = 0; 673 } 674 675 static void 676 qlt_release_intr(qlt_state_t *qlt) 677 { 678 if (qlt->htable) { 679 int i; 680 for (i = 0; i < qlt->intr_cnt; i++) { 681 (void) ddi_intr_remove_handler(qlt->htable[i]); 682 (void) ddi_intr_free(qlt->htable[i]); 683 } 684 kmem_free(qlt->htable, (uint_t)qlt->intr_size); 685 } 686 qlt->htable = NULL; 687 qlt->intr_pri = 0; 688 qlt->intr_cnt = 0; 689 qlt->intr_size = 0; 690 qlt->intr_cap = 0; 691 } 692 693 694 static void 695 qlt_init_mutex(qlt_state_t *qlt) 696 { 697 mutex_init(&qlt->req_lock, 0, MUTEX_DRIVER, 698 INT2PTR(qlt->intr_pri, void *)); 699 mutex_init(&qlt->preq_lock, 0, MUTEX_DRIVER, 700 INT2PTR(qlt->intr_pri, void *)); 701 mutex_init(&qlt->mbox_lock, NULL, MUTEX_DRIVER, 702 INT2PTR(qlt->intr_pri, void *)); 703 mutex_init(&qlt->intr_lock, NULL, MUTEX_DRIVER, 704 INT2PTR(qlt->intr_pri, void *)); 705 } 706 707 static void 708 qlt_destroy_mutex(qlt_state_t *qlt) 709 { 710 mutex_destroy(&qlt->req_lock); 711 mutex_destroy(&qlt->preq_lock); 712 mutex_destroy(&qlt->mbox_lock); 713 mutex_destroy(&qlt->intr_lock); 714 } 715 716 717 static int 718 qlt_setup_msix(qlt_state_t *qlt) 719 { 720 int count, avail, actual; 721 int ret; 722 int itype = DDI_INTR_TYPE_MSIX; 723 int i; 724 725 ret = ddi_intr_get_nintrs(qlt->dip, itype, &count); 726 if (ret != DDI_SUCCESS || count == 0) { 727 EL(qlt, "ddi_intr_get_nintrs status=%xh, count=%d\n", ret, 728 count); 729 return (DDI_FAILURE); 730 } 731 ret = ddi_intr_get_navail(qlt->dip, itype, &avail); 732 if (ret != DDI_SUCCESS || avail == 0) { 733 EL(qlt, "ddi_intr_get_navail status=%xh, avail=%d\n", ret, 734 avail); 735 return (DDI_FAILURE); 736 } 737 if (avail < count) { 738 stmf_trace(qlt->qlt_port_alias, 739 "qlt_setup_msix: nintrs=%d,avail=%d", count, avail); 740 } 741 742 qlt->intr_size = (int)(count * (int)sizeof (ddi_intr_handle_t)); 743 qlt->htable = kmem_zalloc((uint_t)qlt->intr_size, KM_SLEEP); 744 ret = ddi_intr_alloc(qlt->dip, qlt->htable, itype, 745 DDI_INTR_ALLOC_NORMAL, count, &actual, 0); 746 /* we need at least 2 interrupt vectors */ 747 if (ret != DDI_SUCCESS || actual < 2) { 748 EL(qlt, "ddi_intr_alloc status=%xh, actual=%d\n", ret, 749 actual); 750 ret = DDI_FAILURE; 751 goto release_intr; 752 } 753 if (actual < count) { 754 EL(qlt, "requested: %d, received: %d\n", count, actual); 755 } 756 757 qlt->intr_cnt = actual; 758 ret = ddi_intr_get_pri(qlt->htable[0], &qlt->intr_pri); 759 if (ret != DDI_SUCCESS) { 760 EL(qlt, "ddi_intr_get_pri status=%xh\n", ret); 761 ret = DDI_FAILURE; 762 goto release_intr; 763 } 764 qlt_init_mutex(qlt); 765 for (i = 0; i < actual; i++) { 766 ret = ddi_intr_add_handler(qlt->htable[i], qlt_isr, 767 qlt, INT2PTR((uint_t)i, void *)); 768 if (ret != DDI_SUCCESS) { 769 EL(qlt, "ddi_intr_add_handler status=%xh\n", ret); 770 goto release_mutex; 771 } 772 } 773 774 (void) ddi_intr_get_cap(qlt->htable[0], &qlt->intr_cap); 775 qlt->intr_flags |= QLT_INTR_MSIX; 776 return (DDI_SUCCESS); 777 778 release_mutex: 779 qlt_destroy_mutex(qlt); 780 release_intr: 781 for (i = 0; i < actual; i++) 782 (void) ddi_intr_free(qlt->htable[i]); 783 #if 0 784 free_mem: 785 #endif 786 kmem_free(qlt->htable, (uint_t)qlt->intr_size); 787 qlt->htable = NULL; 788 qlt_release_intr(qlt); 789 return (ret); 790 } 791 792 793 static int 794 qlt_setup_msi(qlt_state_t *qlt) 795 { 796 int count, avail, actual; 797 int itype = DDI_INTR_TYPE_MSI; 798 int ret; 799 int i; 800 801 /* get the # of interrupts */ 802 ret = ddi_intr_get_nintrs(qlt->dip, itype, &count); 803 if (ret != DDI_SUCCESS || count == 0) { 804 EL(qlt, "ddi_intr_get_nintrs status=%xh, count=%d\n", ret, 805 count); 806 return (DDI_FAILURE); 807 } 808 ret = ddi_intr_get_navail(qlt->dip, itype, &avail); 809 if (ret != DDI_SUCCESS || avail == 0) { 810 EL(qlt, "ddi_intr_get_navail status=%xh, avail=%d\n", ret, 811 avail); 812 return (DDI_FAILURE); 813 } 814 if (avail < count) { 815 EL(qlt, "nintrs=%d, avail=%d\n", count, avail); 816 } 817 /* MSI requires only 1 interrupt. */ 818 count = 1; 819 820 /* allocate interrupt */ 821 qlt->intr_size = (int)(count * (int)sizeof (ddi_intr_handle_t)); 822 qlt->htable = kmem_zalloc((uint_t)qlt->intr_size, KM_SLEEP); 823 ret = ddi_intr_alloc(qlt->dip, qlt->htable, itype, 824 0, count, &actual, DDI_INTR_ALLOC_NORMAL); 825 if (ret != DDI_SUCCESS || actual == 0) { 826 EL(qlt, "ddi_intr_alloc status=%xh, actual=%d\n", ret, 827 actual); 828 ret = DDI_FAILURE; 829 goto free_mem; 830 } 831 if (actual < count) { 832 EL(qlt, "requested: %d, received: %d\n", count, actual); 833 } 834 qlt->intr_cnt = actual; 835 836 /* 837 * Get priority for first msi, assume remaining are all the same. 838 */ 839 ret = ddi_intr_get_pri(qlt->htable[0], &qlt->intr_pri); 840 if (ret != DDI_SUCCESS) { 841 EL(qlt, "ddi_intr_get_pri status=%xh\n", ret); 842 ret = DDI_FAILURE; 843 goto release_intr; 844 } 845 qlt_init_mutex(qlt); 846 847 /* add handler */ 848 for (i = 0; i < actual; i++) { 849 ret = ddi_intr_add_handler(qlt->htable[i], qlt_isr, 850 qlt, INT2PTR((uint_t)i, void *)); 851 if (ret != DDI_SUCCESS) { 852 EL(qlt, "ddi_intr_add_handler status=%xh\n", ret); 853 goto release_mutex; 854 } 855 } 856 857 (void) ddi_intr_get_cap(qlt->htable[0], &qlt->intr_cap); 858 qlt->intr_flags |= QLT_INTR_MSI; 859 return (DDI_SUCCESS); 860 861 release_mutex: 862 qlt_destroy_mutex(qlt); 863 release_intr: 864 for (i = 0; i < actual; i++) 865 (void) ddi_intr_free(qlt->htable[i]); 866 free_mem: 867 kmem_free(qlt->htable, (uint_t)qlt->intr_size); 868 qlt->htable = NULL; 869 qlt_release_intr(qlt); 870 return (ret); 871 } 872 873 static int 874 qlt_setup_fixed(qlt_state_t *qlt) 875 { 876 int count; 877 int actual; 878 int ret; 879 int itype = DDI_INTR_TYPE_FIXED; 880 881 ret = ddi_intr_get_nintrs(qlt->dip, itype, &count); 882 /* Fixed interrupts can only have one interrupt. */ 883 if (ret != DDI_SUCCESS || count != 1) { 884 EL(qlt, "ddi_intr_get_nintrs status=%xh, count=%d\n", ret, 885 count); 886 return (DDI_FAILURE); 887 } 888 889 qlt->intr_size = sizeof (ddi_intr_handle_t); 890 qlt->htable = kmem_zalloc((uint_t)qlt->intr_size, KM_SLEEP); 891 ret = ddi_intr_alloc(qlt->dip, qlt->htable, itype, 892 DDI_INTR_ALLOC_NORMAL, count, &actual, 0); 893 if (ret != DDI_SUCCESS || actual != 1) { 894 EL(qlt, "ddi_intr_alloc status=%xh, actual=%d\n", ret, 895 actual); 896 ret = DDI_FAILURE; 897 goto free_mem; 898 } 899 900 qlt->intr_cnt = actual; 901 ret = ddi_intr_get_pri(qlt->htable[0], &qlt->intr_pri); 902 if (ret != DDI_SUCCESS) { 903 EL(qlt, "ddi_intr_get_pri status=%xh\n", ret); 904 ret = DDI_FAILURE; 905 goto release_intr; 906 } 907 qlt_init_mutex(qlt); 908 ret = ddi_intr_add_handler(qlt->htable[0], qlt_isr, qlt, 0); 909 if (ret != DDI_SUCCESS) { 910 EL(qlt, "ddi_intr_add_handler status=%xh\n", ret); 911 goto release_mutex; 912 } 913 914 qlt->intr_flags |= QLT_INTR_FIXED; 915 return (DDI_SUCCESS); 916 917 release_mutex: 918 qlt_destroy_mutex(qlt); 919 release_intr: 920 (void) ddi_intr_free(qlt->htable[0]); 921 free_mem: 922 kmem_free(qlt->htable, (uint_t)qlt->intr_size); 923 qlt->htable = NULL; 924 qlt_release_intr(qlt); 925 return (ret); 926 } 927 928 static int 929 qlt_setup_interrupts(qlt_state_t *qlt) 930 { 931 int itypes = 0; 932 933 /* 934 * x86 has a bug in the ddi_intr_block_enable/disable area (6562198). 935 */ 936 #ifndef __sparc 937 if (qlt_enable_msi != 0) { 938 #endif 939 if (ddi_intr_get_supported_types(qlt->dip, &itypes) != DDI_SUCCESS) { 940 itypes = DDI_INTR_TYPE_FIXED; 941 } 942 943 if (qlt_enable_msix && (itypes & DDI_INTR_TYPE_MSIX)) { 944 if (qlt_setup_msix(qlt) == DDI_SUCCESS) 945 return (DDI_SUCCESS); 946 } 947 948 if (itypes & DDI_INTR_TYPE_MSI) { 949 if (qlt_setup_msi(qlt) == DDI_SUCCESS) 950 return (DDI_SUCCESS); 951 } 952 #ifndef __sparc 953 } 954 #endif 955 return (qlt_setup_fixed(qlt)); 956 } 957 958 /* 959 * Filling the hba attributes 960 */ 961 void 962 qlt_populate_hba_fru_details(struct fct_local_port *port, 963 struct fct_port_attrs *port_attrs) 964 { 965 caddr_t bufp; 966 int len; 967 qlt_state_t *qlt = (qlt_state_t *)port->port_fca_private; 968 969 (void) snprintf(port_attrs->manufacturer, FCHBA_MANUFACTURER_LEN, 970 "QLogic Corp."); 971 (void) snprintf(port_attrs->driver_name, FCHBA_DRIVER_NAME_LEN, 972 "%s", QLT_NAME); 973 (void) snprintf(port_attrs->driver_version, FCHBA_DRIVER_VERSION_LEN, 974 "%s", QLT_VERSION); 975 port_attrs->serial_number[0] = '\0'; 976 port_attrs->hardware_version[0] = '\0'; 977 978 (void) snprintf(port_attrs->firmware_version, 979 FCHBA_FIRMWARE_VERSION_LEN, "%d.%d.%d", qlt->fw_major, 980 qlt->fw_minor, qlt->fw_subminor); 981 982 /* Get FCode version */ 983 if (ddi_getlongprop(DDI_DEV_T_ANY, qlt->dip, PROP_LEN_AND_VAL_ALLOC | 984 DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, "version", (caddr_t)&bufp, 985 (int *)&len) == DDI_PROP_SUCCESS) { 986 (void) snprintf(port_attrs->option_rom_version, 987 FCHBA_OPTION_ROM_VERSION_LEN, "%s", bufp); 988 kmem_free(bufp, (uint_t)len); 989 bufp = NULL; 990 } else { 991 #ifdef __sparc 992 (void) snprintf(port_attrs->option_rom_version, 993 FCHBA_OPTION_ROM_VERSION_LEN, "No Fcode found"); 994 #else 995 (void) snprintf(port_attrs->option_rom_version, 996 FCHBA_OPTION_ROM_VERSION_LEN, "N/A"); 997 #endif 998 } 999 port_attrs->vendor_specific_id = qlt->nvram->subsystem_vendor_id[0] | 1000 qlt->nvram->subsystem_vendor_id[1] << 8; 1001 1002 port_attrs->max_frame_size = qlt->nvram->max_frame_length[1] << 8 | 1003 qlt->nvram->max_frame_length[0]; 1004 1005 port_attrs->supported_cos = 0x10000000; 1006 port_attrs->supported_speed = PORT_SPEED_1G | 1007 PORT_SPEED_2G | PORT_SPEED_4G; 1008 if (qlt->qlt_25xx_chip) 1009 port_attrs->supported_speed |= PORT_SPEED_8G; 1010 if (qlt->qlt_81xx_chip) 1011 port_attrs->supported_speed = PORT_SPEED_10G; 1012 1013 /* limit string length to nvr model_name length */ 1014 len = (qlt->qlt_81xx_chip) ? 16 : 8; 1015 (void) snprintf(port_attrs->model, 1016 (uint_t)(len < FCHBA_MODEL_LEN ? len : FCHBA_MODEL_LEN), 1017 "%s", qlt->nvram->model_name); 1018 1019 (void) snprintf(port_attrs->model_description, 1020 (uint_t)(len < FCHBA_MODEL_DESCRIPTION_LEN ? len : 1021 FCHBA_MODEL_DESCRIPTION_LEN), 1022 "%s", qlt->nvram->model_name); 1023 } 1024 1025 /* ARGSUSED */ 1026 fct_status_t 1027 qlt_info(uint32_t cmd, fct_local_port_t *port, 1028 void *arg, uint8_t *buf, uint32_t *bufsizep) 1029 { 1030 qlt_state_t *qlt = (qlt_state_t *)port->port_fca_private; 1031 mbox_cmd_t *mcp; 1032 fct_status_t ret = FCT_SUCCESS; 1033 uint8_t *p; 1034 fct_port_link_status_t *link_status; 1035 1036 switch (cmd) { 1037 case FC_TGT_PORT_RLS: 1038 if ((*bufsizep) < sizeof (fct_port_link_status_t)) { 1039 EL(qlt, "FC_TGT_PORT_RLS bufsizep=%xh < " 1040 "fct_port_link_status_t=%xh\n", *bufsizep, 1041 sizeof (fct_port_link_status_t)); 1042 ret = FCT_FAILURE; 1043 break; 1044 } 1045 /* send mailbox command to get link status */ 1046 mcp = qlt_alloc_mailbox_command(qlt, 156); 1047 if (mcp == NULL) { 1048 EL(qlt, "qlt_alloc_mailbox_command mcp=null\n"); 1049 ret = FCT_ALLOC_FAILURE; 1050 break; 1051 } 1052 1053 /* GET LINK STATUS count */ 1054 mcp->to_fw[0] = MBC_GET_STATUS_COUNTS; 1055 mcp->to_fw[8] = 156/4; 1056 mcp->to_fw_mask |= BIT_1 | BIT_8; 1057 mcp->from_fw_mask |= BIT_1 | BIT_2; 1058 1059 ret = qlt_mailbox_command(qlt, mcp); 1060 if (ret != QLT_SUCCESS) { 1061 EL(qlt, "qlt_mailbox_command=6dh status=%llxh\n", ret); 1062 qlt_free_mailbox_command(qlt, mcp); 1063 break; 1064 } 1065 qlt_dmem_dma_sync(mcp->dbuf, DDI_DMA_SYNC_FORCPU); 1066 1067 p = mcp->dbuf->db_sglist[0].seg_addr; 1068 link_status = (fct_port_link_status_t *)buf; 1069 link_status->LinkFailureCount = LE_32(*((uint32_t *)p)); 1070 link_status->LossOfSyncCount = LE_32(*((uint32_t *)(p + 4))); 1071 link_status->LossOfSignalsCount = LE_32(*((uint32_t *)(p + 8))); 1072 link_status->PrimitiveSeqProtocolErrorCount = 1073 LE_32(*((uint32_t *)(p + 12))); 1074 link_status->InvalidTransmissionWordCount = 1075 LE_32(*((uint32_t *)(p + 16))); 1076 link_status->InvalidCRCCount = 1077 LE_32(*((uint32_t *)(p + 20))); 1078 1079 qlt_free_mailbox_command(qlt, mcp); 1080 break; 1081 default: 1082 EL(qlt, "Unknown cmd=%xh\n", cmd); 1083 ret = FCT_FAILURE; 1084 break; 1085 } 1086 return (ret); 1087 } 1088 1089 fct_status_t 1090 qlt_port_start(caddr_t arg) 1091 { 1092 qlt_state_t *qlt = (qlt_state_t *)arg; 1093 fct_local_port_t *port; 1094 fct_dbuf_store_t *fds; 1095 fct_status_t ret; 1096 1097 if (qlt_dmem_init(qlt) != QLT_SUCCESS) { 1098 return (FCT_FAILURE); 1099 } 1100 port = (fct_local_port_t *)fct_alloc(FCT_STRUCT_LOCAL_PORT, 0, 0); 1101 if (port == NULL) { 1102 goto qlt_pstart_fail_1; 1103 } 1104 fds = (fct_dbuf_store_t *)fct_alloc(FCT_STRUCT_DBUF_STORE, 0, 0); 1105 if (fds == NULL) { 1106 goto qlt_pstart_fail_2; 1107 } 1108 qlt->qlt_port = port; 1109 fds->fds_alloc_data_buf = qlt_dmem_alloc; 1110 fds->fds_free_data_buf = qlt_dmem_free; 1111 fds->fds_fca_private = (void *)qlt; 1112 /* 1113 * Since we keep everything in the state struct and dont allocate any 1114 * port private area, just use that pointer to point to the 1115 * state struct. 1116 */ 1117 port->port_fca_private = qlt; 1118 port->port_fca_abort_timeout = 5 * 1000; /* 5 seconds */ 1119 bcopy(qlt->nvram->node_name, port->port_nwwn, 8); 1120 bcopy(qlt->nvram->port_name, port->port_pwwn, 8); 1121 fct_wwn_to_str(port->port_nwwn_str, port->port_nwwn); 1122 fct_wwn_to_str(port->port_pwwn_str, port->port_pwwn); 1123 port->port_default_alias = qlt->qlt_port_alias; 1124 port->port_pp = qlt_pp; 1125 port->port_fds = fds; 1126 port->port_max_logins = QLT_MAX_LOGINS; 1127 port->port_max_xchges = QLT_MAX_XCHGES; 1128 port->port_fca_fcp_cmd_size = sizeof (qlt_cmd_t); 1129 port->port_fca_rp_private_size = sizeof (qlt_remote_port_t); 1130 port->port_fca_sol_els_private_size = sizeof (qlt_cmd_t); 1131 port->port_fca_sol_ct_private_size = sizeof (qlt_cmd_t); 1132 port->port_get_link_info = qlt_get_link_info; 1133 port->port_register_remote_port = qlt_register_remote_port; 1134 port->port_deregister_remote_port = qlt_deregister_remote_port; 1135 port->port_send_cmd = qlt_send_cmd; 1136 port->port_xfer_scsi_data = qlt_xfer_scsi_data; 1137 port->port_send_cmd_response = qlt_send_cmd_response; 1138 port->port_abort_cmd = qlt_abort_cmd; 1139 port->port_ctl = qlt_ctl; 1140 port->port_flogi_xchg = qlt_do_flogi; 1141 port->port_populate_hba_details = qlt_populate_hba_fru_details; 1142 port->port_info = qlt_info; 1143 port->port_fca_version = FCT_FCA_MODREV_1; 1144 1145 if ((ret = fct_register_local_port(port)) != FCT_SUCCESS) { 1146 EL(qlt, "fct_register_local_port status=%llxh\n", ret); 1147 goto qlt_pstart_fail_2_5; 1148 } 1149 1150 return (QLT_SUCCESS); 1151 #if 0 1152 qlt_pstart_fail_3: 1153 (void) fct_deregister_local_port(port); 1154 #endif 1155 qlt_pstart_fail_2_5: 1156 fct_free(fds); 1157 qlt_pstart_fail_2: 1158 fct_free(port); 1159 qlt->qlt_port = NULL; 1160 qlt_pstart_fail_1: 1161 qlt_dmem_fini(qlt); 1162 return (QLT_FAILURE); 1163 } 1164 1165 fct_status_t 1166 qlt_port_stop(caddr_t arg) 1167 { 1168 qlt_state_t *qlt = (qlt_state_t *)arg; 1169 fct_status_t ret; 1170 1171 if ((ret = fct_deregister_local_port(qlt->qlt_port)) != FCT_SUCCESS) { 1172 EL(qlt, "fct_register_local_port status=%llxh\n", ret); 1173 return (QLT_FAILURE); 1174 } 1175 fct_free(qlt->qlt_port->port_fds); 1176 fct_free(qlt->qlt_port); 1177 qlt->qlt_port = NULL; 1178 qlt_dmem_fini(qlt); 1179 return (QLT_SUCCESS); 1180 } 1181 1182 /* 1183 * Called by framework to init the HBA. 1184 * Can be called in the middle of I/O. (Why ??) 1185 * Should make sure sane state both before and after the initialization 1186 */ 1187 fct_status_t 1188 qlt_port_online(qlt_state_t *qlt) 1189 { 1190 uint64_t da; 1191 int instance, i; 1192 fct_status_t ret; 1193 uint16_t rcount; 1194 caddr_t icb; 1195 mbox_cmd_t *mcp; 1196 uint8_t *elsbmp; 1197 1198 instance = ddi_get_instance(qlt->dip); 1199 1200 /* XXX Make sure a sane state */ 1201 1202 if ((ret = qlt_download_fw(qlt)) != QLT_SUCCESS) { 1203 cmn_err(CE_NOTE, "reset chip failed %llx", (long long)ret); 1204 return (ret); 1205 } 1206 1207 bzero(qlt->queue_mem_ptr, TOTAL_DMA_MEM_SIZE); 1208 1209 /* Get resource count */ 1210 REG_WR16(qlt, REG_MBOX(0), MBC_GET_RESOURCE_COUNTS); 1211 ret = qlt_raw_mailbox_command(qlt); 1212 rcount = REG_RD16(qlt, REG_MBOX(3)); 1213 REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR)); 1214 if (ret != QLT_SUCCESS) { 1215 EL(qlt, "qlt_raw_mailbox_command=42h status=%llxh\n", ret); 1216 return (ret); 1217 } 1218 1219 /* Enable PUREX */ 1220 REG_WR16(qlt, REG_MBOX(0), MBC_SET_ADDITIONAL_FIRMWARE_OPT); 1221 REG_WR16(qlt, REG_MBOX(1), OPT_PUREX_ENABLE); 1222 REG_WR16(qlt, REG_MBOX(2), 0x0); 1223 REG_WR16(qlt, REG_MBOX(3), 0x0); 1224 ret = qlt_raw_mailbox_command(qlt); 1225 REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR)); 1226 if (ret != QLT_SUCCESS) { 1227 EL(qlt, "qlt_raw_mailbox_command=38h status=%llxh\n", ret); 1228 cmn_err(CE_NOTE, "Enable PUREX failed"); 1229 return (ret); 1230 } 1231 1232 /* Pass ELS bitmap to fw */ 1233 REG_WR16(qlt, REG_MBOX(0), MBC_SET_PARAMETERS); 1234 REG_WR16(qlt, REG_MBOX(1), PARAM_TYPE(PUREX_ELS_CMDS)); 1235 elsbmp = (uint8_t *)qlt->queue_mem_ptr + MBOX_DMA_MEM_OFFSET; 1236 bzero(elsbmp, 32); 1237 da = qlt->queue_mem_cookie.dmac_laddress; 1238 da += MBOX_DMA_MEM_OFFSET; 1239 REG_WR16(qlt, REG_MBOX(3), LSW(LSD(da))); 1240 REG_WR16(qlt, REG_MBOX(2), MSW(LSD(da))); 1241 REG_WR16(qlt, REG_MBOX(7), LSW(MSD(da))); 1242 REG_WR16(qlt, REG_MBOX(6), MSW(MSD(da))); 1243 SETELSBIT(elsbmp, ELS_OP_PLOGI); 1244 SETELSBIT(elsbmp, ELS_OP_LOGO); 1245 SETELSBIT(elsbmp, ELS_OP_ABTX); 1246 SETELSBIT(elsbmp, ELS_OP_ECHO); 1247 SETELSBIT(elsbmp, ELS_OP_PRLI); 1248 SETELSBIT(elsbmp, ELS_OP_PRLO); 1249 SETELSBIT(elsbmp, ELS_OP_SCN); 1250 SETELSBIT(elsbmp, ELS_OP_TPRLO); 1251 SETELSBIT(elsbmp, ELS_OP_PDISC); 1252 SETELSBIT(elsbmp, ELS_OP_ADISC); 1253 SETELSBIT(elsbmp, ELS_OP_RSCN); 1254 SETELSBIT(elsbmp, ELS_OP_RNID); 1255 (void) ddi_dma_sync(qlt->queue_mem_dma_handle, MBOX_DMA_MEM_OFFSET, 32, 1256 DDI_DMA_SYNC_FORDEV); 1257 ret = qlt_raw_mailbox_command(qlt); 1258 REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR)); 1259 if (ret != QLT_SUCCESS) { 1260 EL(qlt, "qlt_raw_mailbox_command=59h status=llxh\n", ret); 1261 cmn_err(CE_NOTE, "Set ELS Bitmap failed ret=%llx, " 1262 "elsbmp0=%x elabmp1=%x", (long long)ret, elsbmp[0], 1263 elsbmp[1]); 1264 return (ret); 1265 } 1266 1267 /* Init queue pointers */ 1268 REG_WR32(qlt, REG_REQ_IN_PTR, 0); 1269 REG_WR32(qlt, REG_REQ_OUT_PTR, 0); 1270 REG_WR32(qlt, REG_RESP_IN_PTR, 0); 1271 REG_WR32(qlt, REG_RESP_OUT_PTR, 0); 1272 REG_WR32(qlt, REG_PREQ_IN_PTR, 0); 1273 REG_WR32(qlt, REG_PREQ_OUT_PTR, 0); 1274 REG_WR32(qlt, REG_ATIO_IN_PTR, 0); 1275 REG_WR32(qlt, REG_ATIO_OUT_PTR, 0); 1276 qlt->req_ndx_to_fw = qlt->req_ndx_from_fw = 0; 1277 qlt->req_available = REQUEST_QUEUE_ENTRIES - 1; 1278 qlt->resp_ndx_to_fw = qlt->resp_ndx_from_fw = 0; 1279 qlt->preq_ndx_to_fw = qlt->preq_ndx_from_fw = 0; 1280 qlt->atio_ndx_to_fw = qlt->atio_ndx_from_fw = 0; 1281 1282 /* 1283 * XXX support for tunables. Also should we cache icb ? 1284 */ 1285 if (qlt->qlt_81xx_chip) { 1286 /* allocate extra 64 bytes for Extended init control block */ 1287 mcp = qlt_alloc_mailbox_command(qlt, 0xC0); 1288 } else { 1289 mcp = qlt_alloc_mailbox_command(qlt, 0x80); 1290 } 1291 if (mcp == NULL) { 1292 EL(qlt, "qlt_alloc_mailbox_command mcp=null\n"); 1293 return (STMF_ALLOC_FAILURE); 1294 } 1295 icb = (caddr_t)mcp->dbuf->db_sglist[0].seg_addr; 1296 if (qlt->qlt_81xx_chip) { 1297 bzero(icb, 0xC0); 1298 } else { 1299 bzero(icb, 0x80); 1300 } 1301 da = qlt->queue_mem_cookie.dmac_laddress; 1302 DMEM_WR16(qlt, icb, 1); /* Version */ 1303 DMEM_WR16(qlt, icb+4, 2112); /* Max frame length */ 1304 DMEM_WR16(qlt, icb+6, 16); /* Execution throttle */ 1305 DMEM_WR16(qlt, icb+8, rcount); /* Xchg count */ 1306 DMEM_WR16(qlt, icb+0x0a, 0x00); /* Hard address (not used) */ 1307 bcopy(qlt->qlt_port->port_pwwn, icb+0x0c, 8); 1308 bcopy(qlt->qlt_port->port_nwwn, icb+0x14, 8); 1309 DMEM_WR16(qlt, icb+0x20, 3); /* Login retry count */ 1310 DMEM_WR16(qlt, icb+0x24, RESPONSE_QUEUE_ENTRIES); 1311 DMEM_WR16(qlt, icb+0x26, REQUEST_QUEUE_ENTRIES); 1312 if (!qlt->qlt_81xx_chip) { 1313 DMEM_WR16(qlt, icb+0x28, 100); /* ms of NOS/OLS for Link down */ 1314 } 1315 DMEM_WR16(qlt, icb+0x2a, PRIORITY_QUEUE_ENTRIES); 1316 DMEM_WR64(qlt, icb+0x2c, (da+REQUEST_QUEUE_OFFSET)); 1317 DMEM_WR64(qlt, icb+0x34, (da+RESPONSE_QUEUE_OFFSET)); 1318 DMEM_WR64(qlt, icb+0x3c, (da+PRIORITY_QUEUE_OFFSET)); 1319 DMEM_WR16(qlt, icb+0x4e, ATIO_QUEUE_ENTRIES); 1320 DMEM_WR64(qlt, icb+0x50, (da+ATIO_QUEUE_OFFSET)); 1321 DMEM_WR16(qlt, icb+0x58, 2); /* Interrupt delay Timer */ 1322 DMEM_WR16(qlt, icb+0x5a, 4); /* Login timeout (secs) */ 1323 if (qlt->qlt_81xx_chip) { 1324 qlt_nvram_81xx_t *qlt81nvr = (qlt_nvram_81xx_t *)qlt->nvram; 1325 1326 DMEM_WR32(qlt, icb+0x5c, BIT_5 | BIT_4); /* fw options 1 */ 1327 DMEM_WR32(qlt, icb+0x64, BIT_20 | BIT_4); /* fw options 3 */ 1328 DMEM_WR32(qlt, icb+0x70, 1329 qlt81nvr->enode_mac[0] | 1330 (qlt81nvr->enode_mac[1] << 8) | 1331 (qlt81nvr->enode_mac[2] << 16) | 1332 (qlt81nvr->enode_mac[3] << 24)); 1333 DMEM_WR16(qlt, icb+0x74, 1334 qlt81nvr->enode_mac[4] | 1335 (qlt81nvr->enode_mac[5] << 8)); 1336 } else { 1337 DMEM_WR32(qlt, icb+0x5c, BIT_11 | BIT_5 | BIT_4 | 1338 BIT_2 | BIT_1 | BIT_0); 1339 DMEM_WR32(qlt, icb+0x60, BIT_5); 1340 DMEM_WR32(qlt, icb+0x64, BIT_14 | BIT_8 | BIT_7 | 1341 BIT_4); 1342 } 1343 1344 if (qlt->qlt_81xx_chip) { 1345 qlt_dmem_bctl_t *bctl; 1346 uint32_t index; 1347 caddr_t src; 1348 caddr_t dst; 1349 qlt_nvram_81xx_t *qlt81nvr; 1350 1351 dst = icb+0x80; 1352 qlt81nvr = (qlt_nvram_81xx_t *)qlt->nvram; 1353 src = (caddr_t)&qlt81nvr->ext_blk; 1354 index = sizeof (qlt_ext_icb_81xx_t); 1355 1356 /* Use defaults for cases where we find nothing in NVR */ 1357 if (*src == 0) { 1358 EL(qlt, "nvram eicb=null\n"); 1359 cmn_err(CE_NOTE, "qlt(%d) NVR eicb is zeroed", 1360 instance); 1361 qlt81nvr->ext_blk.version[0] = 1; 1362 /* 1363 * not yet, for !FIP firmware at least 1364 * 1365 * qlt81nvr->ext_blk.fcf_vlan_match = 0x81; 1366 */ 1367 #ifdef _LITTLE_ENDIAN 1368 qlt81nvr->ext_blk.fcf_vlan_id[0] = 0xEA; 1369 qlt81nvr->ext_blk.fcf_vlan_id[1] = 0x03; 1370 #else 1371 qlt81nvr->ext_blk.fcf_vlan_id[1] = 0xEA; 1372 qlt81nvr->ext_blk.fcf_vlan_id[0] = 0x03; 1373 #endif 1374 } 1375 1376 while (index--) { 1377 *dst++ = *src++; 1378 } 1379 1380 bctl = (qlt_dmem_bctl_t *)mcp->dbuf->db_port_private; 1381 da = bctl->bctl_dev_addr + 0x80; /* base addr of eicb (phys) */ 1382 1383 mcp->to_fw[11] = LSW(LSD(da)); 1384 mcp->to_fw[10] = MSW(LSD(da)); 1385 mcp->to_fw[13] = LSW(MSD(da)); 1386 mcp->to_fw[12] = MSW(MSD(da)); 1387 mcp->to_fw[14] = (uint16_t)(sizeof (qlt_ext_icb_81xx_t) & 1388 0xffff); 1389 1390 /* eicb enable */ 1391 mcp->to_fw[1] = (uint16_t)(mcp->to_fw[1] | BIT_0); 1392 mcp->to_fw_mask |= BIT_14 | BIT_13 | BIT_12 | BIT_11 | BIT_10 | 1393 BIT_1; 1394 } 1395 1396 qlt_dmem_dma_sync(mcp->dbuf, DDI_DMA_SYNC_FORDEV); 1397 mcp->to_fw[0] = MBC_INITIALIZE_FIRMWARE; 1398 1399 /* 1400 * This is the 1st command after adapter initialize which will 1401 * use interrupts and regular mailbox interface. 1402 */ 1403 qlt->mbox_io_state = MBOX_STATE_READY; 1404 REG_WR32(qlt, REG_INTR_CTRL, ENABLE_RISC_INTR); 1405 /* Issue mailbox to firmware */ 1406 ret = qlt_mailbox_command(qlt, mcp); 1407 if (ret != QLT_SUCCESS) { 1408 EL(qlt, "qlt_mailbox_command=60h status=%llxh\n", ret); 1409 cmn_err(CE_NOTE, "qlt(%d) init fw failed %llx, intr status %x", 1410 instance, (long long)ret, REG_RD32(qlt, REG_INTR_STATUS)); 1411 } 1412 1413 mcp->to_fw_mask = BIT_0; 1414 mcp->from_fw_mask = BIT_0 | BIT_1; 1415 mcp->to_fw[0] = 0x28; 1416 ret = qlt_mailbox_command(qlt, mcp); 1417 if (ret != QLT_SUCCESS) { 1418 EL(qlt, "qlt_mailbox_command=28h status=%llxh\n", ret); 1419 cmn_err(CE_NOTE, "qlt(%d) get_fw_options %llx", instance, 1420 (long long)ret); 1421 } 1422 1423 /* 1424 * Report FW versions for 81xx - MPI rev is useful 1425 */ 1426 if (qlt->qlt_81xx_chip) { 1427 mcp->to_fw_mask = BIT_0; 1428 mcp->from_fw_mask = BIT_11 | BIT_10 | BIT_3 | BIT_2 | BIT_1 | 1429 BIT_0; 1430 mcp->to_fw[0] = 0x8; 1431 ret = qlt_mailbox_command(qlt, mcp); 1432 if (ret != QLT_SUCCESS) { 1433 EL(qlt, "about fw failed: %llx\n", (long long)ret); 1434 } else { 1435 EL(qlt, "Firmware version %d.%d.%d, MPI: %d.%d.%d\n", 1436 mcp->from_fw[1], mcp->from_fw[2], mcp->from_fw[3], 1437 mcp->from_fw[10] & 0xff, mcp->from_fw[11] >> 8, 1438 mcp->from_fw[11] & 0xff); 1439 } 1440 } 1441 1442 qlt_free_mailbox_command(qlt, mcp); 1443 1444 for (i = 0; i < 5; i++) { 1445 qlt->qlt_bufref[i] = 0; 1446 qlt->qlt_nullbufref[i] = 0; 1447 } 1448 qlt->qlt_bumpbucket = 0; 1449 1450 if (ret != QLT_SUCCESS) 1451 return (ret); 1452 return (FCT_SUCCESS); 1453 } 1454 1455 fct_status_t 1456 qlt_port_offline(qlt_state_t *qlt) 1457 { 1458 int retries; 1459 1460 mutex_enter(&qlt->mbox_lock); 1461 1462 if (qlt->mbox_io_state == MBOX_STATE_UNKNOWN) { 1463 mutex_exit(&qlt->mbox_lock); 1464 goto poff_mbox_done; 1465 } 1466 1467 /* Wait to grab the mailboxes */ 1468 for (retries = 0; qlt->mbox_io_state != MBOX_STATE_READY; 1469 retries++) { 1470 cv_wait(&qlt->mbox_cv, &qlt->mbox_lock); 1471 if ((retries > 5) || 1472 (qlt->mbox_io_state == MBOX_STATE_UNKNOWN)) { 1473 qlt->mbox_io_state = MBOX_STATE_UNKNOWN; 1474 mutex_exit(&qlt->mbox_lock); 1475 goto poff_mbox_done; 1476 } 1477 } 1478 qlt->mbox_io_state = MBOX_STATE_UNKNOWN; 1479 mutex_exit(&qlt->mbox_lock); 1480 poff_mbox_done:; 1481 qlt->intr_sneak_counter = 10; 1482 mutex_enter(&qlt->intr_lock); 1483 (void) qlt_reset_chip(qlt); 1484 drv_usecwait(20); 1485 qlt->intr_sneak_counter = 0; 1486 mutex_exit(&qlt->intr_lock); 1487 1488 return (FCT_SUCCESS); 1489 } 1490 1491 static fct_status_t 1492 qlt_get_link_info(fct_local_port_t *port, fct_link_info_t *li) 1493 { 1494 qlt_state_t *qlt = (qlt_state_t *)port->port_fca_private; 1495 mbox_cmd_t *mcp; 1496 fct_status_t fc_ret; 1497 fct_status_t ret; 1498 clock_t et; 1499 1500 et = ddi_get_lbolt() + drv_usectohz(5000000); 1501 mcp = qlt_alloc_mailbox_command(qlt, 0); 1502 link_info_retry: 1503 mcp->to_fw[0] = MBC_GET_ID; 1504 mcp->to_fw[9] = 0; 1505 mcp->to_fw_mask |= BIT_0 | BIT_9; 1506 mcp->from_fw_mask |= BIT_0 | BIT_1 | BIT_2 | BIT_3 | BIT_6 | BIT_7; 1507 /* Issue mailbox to firmware */ 1508 ret = qlt_mailbox_command(qlt, mcp); 1509 if (ret != QLT_SUCCESS) { 1510 EL(qlt, "qlt_mailbox_command=20h status=%llxh\n", ret); 1511 if ((mcp->from_fw[0] == 0x4005) && (mcp->from_fw[1] == 7)) { 1512 /* Firmware is not ready */ 1513 if (ddi_get_lbolt() < et) { 1514 delay(drv_usectohz(50000)); 1515 goto link_info_retry; 1516 } 1517 } 1518 stmf_trace(qlt->qlt_port_alias, "GET ID mbox failed, ret=%llx " 1519 "mb0=%x mb1=%x", ret, mcp->from_fw[0], mcp->from_fw[1]); 1520 fc_ret = FCT_FAILURE; 1521 } else { 1522 li->portid = ((uint32_t)(mcp->from_fw[2])) | 1523 (((uint32_t)(mcp->from_fw[3])) << 16); 1524 1525 li->port_speed = qlt->link_speed; 1526 switch (mcp->from_fw[6]) { 1527 case 1: 1528 li->port_topology = PORT_TOPOLOGY_PUBLIC_LOOP; 1529 li->port_fca_flogi_done = 1; 1530 break; 1531 case 0: 1532 li->port_topology = PORT_TOPOLOGY_PRIVATE_LOOP; 1533 li->port_no_fct_flogi = 1; 1534 break; 1535 case 3: 1536 li->port_topology = PORT_TOPOLOGY_FABRIC_PT_TO_PT; 1537 li->port_fca_flogi_done = 1; 1538 break; 1539 case 2: /*FALLTHROUGH*/ 1540 case 4: 1541 li->port_topology = PORT_TOPOLOGY_PT_TO_PT; 1542 li->port_fca_flogi_done = 1; 1543 break; 1544 default: 1545 li->port_topology = PORT_TOPOLOGY_UNKNOWN; 1546 EL(qlt, "Unknown topology=%xh\n", mcp->from_fw[6]); 1547 } 1548 qlt->cur_topology = li->port_topology; 1549 fc_ret = FCT_SUCCESS; 1550 } 1551 qlt_free_mailbox_command(qlt, mcp); 1552 1553 if ((fc_ret == FCT_SUCCESS) && (li->port_fca_flogi_done)) { 1554 mcp = qlt_alloc_mailbox_command(qlt, 64); 1555 mcp->to_fw[0] = MBC_GET_PORT_DATABASE; 1556 mcp->to_fw[1] = 0x7FE; 1557 mcp->to_fw[9] = 0; 1558 mcp->to_fw[10] = 0; 1559 mcp->to_fw_mask |= BIT_0 | BIT_1 | BIT_9 | BIT_10; 1560 fc_ret = qlt_mailbox_command(qlt, mcp); 1561 if (fc_ret != QLT_SUCCESS) { 1562 EL(qlt, "qlt_mailbox_command=64h status=%llxh\n", 1563 fc_ret); 1564 stmf_trace(qlt->qlt_port_alias, "Attempt to get port " 1565 "database for F_port failed, ret = %llx", fc_ret); 1566 } else { 1567 uint8_t *p; 1568 1569 qlt_dmem_dma_sync(mcp->dbuf, DDI_DMA_SYNC_FORCPU); 1570 p = mcp->dbuf->db_sglist[0].seg_addr; 1571 bcopy(p + 0x18, li->port_rpwwn, 8); 1572 bcopy(p + 0x20, li->port_rnwwn, 8); 1573 } 1574 qlt_free_mailbox_command(qlt, mcp); 1575 } 1576 return (fc_ret); 1577 } 1578 1579 static int 1580 qlt_open(dev_t *devp, int flag, int otype, cred_t *credp) 1581 { 1582 int instance; 1583 qlt_state_t *qlt; 1584 1585 if (otype != OTYP_CHR) { 1586 return (EINVAL); 1587 } 1588 1589 /* 1590 * Since this is for debugging only, only allow root to issue ioctl now 1591 */ 1592 if (drv_priv(credp)) { 1593 return (EPERM); 1594 } 1595 1596 instance = (int)getminor(*devp); 1597 qlt = ddi_get_soft_state(qlt_state, instance); 1598 if (qlt == NULL) { 1599 return (ENXIO); 1600 } 1601 1602 mutex_enter(&qlt->qlt_ioctl_lock); 1603 if (qlt->qlt_ioctl_flags & QLT_IOCTL_FLAG_EXCL) { 1604 /* 1605 * It is already open for exclusive access. 1606 * So shut the door on this caller. 1607 */ 1608 mutex_exit(&qlt->qlt_ioctl_lock); 1609 return (EBUSY); 1610 } 1611 1612 if (flag & FEXCL) { 1613 if (qlt->qlt_ioctl_flags & QLT_IOCTL_FLAG_OPEN) { 1614 /* 1615 * Exclusive operation not possible 1616 * as it is already opened 1617 */ 1618 mutex_exit(&qlt->qlt_ioctl_lock); 1619 return (EBUSY); 1620 } 1621 qlt->qlt_ioctl_flags |= QLT_IOCTL_FLAG_EXCL; 1622 } 1623 qlt->qlt_ioctl_flags |= QLT_IOCTL_FLAG_OPEN; 1624 mutex_exit(&qlt->qlt_ioctl_lock); 1625 1626 return (0); 1627 } 1628 1629 /* ARGSUSED */ 1630 static int 1631 qlt_close(dev_t dev, int flag, int otype, cred_t *credp) 1632 { 1633 int instance; 1634 qlt_state_t *qlt; 1635 1636 if (otype != OTYP_CHR) { 1637 return (EINVAL); 1638 } 1639 1640 instance = (int)getminor(dev); 1641 qlt = ddi_get_soft_state(qlt_state, instance); 1642 if (qlt == NULL) { 1643 return (ENXIO); 1644 } 1645 1646 mutex_enter(&qlt->qlt_ioctl_lock); 1647 if ((qlt->qlt_ioctl_flags & QLT_IOCTL_FLAG_OPEN) == 0) { 1648 mutex_exit(&qlt->qlt_ioctl_lock); 1649 return (ENODEV); 1650 } 1651 1652 /* 1653 * It looks there's one hole here, maybe there could several concurrent 1654 * shareed open session, but we never check this case. 1655 * But it will not hurt too much, disregard it now. 1656 */ 1657 qlt->qlt_ioctl_flags &= ~QLT_IOCTL_FLAG_MASK; 1658 mutex_exit(&qlt->qlt_ioctl_lock); 1659 1660 return (0); 1661 } 1662 1663 /* 1664 * All of these ioctls are unstable interfaces which are meant to be used 1665 * in a controlled lab env. No formal testing will be (or needs to be) done 1666 * for these ioctls. Specially note that running with an additional 1667 * uploaded firmware is not supported and is provided here for test 1668 * purposes only. 1669 */ 1670 /* ARGSUSED */ 1671 static int 1672 qlt_ioctl(dev_t dev, int cmd, intptr_t data, int mode, 1673 cred_t *credp, int *rval) 1674 { 1675 qlt_state_t *qlt; 1676 int ret = 0; 1677 #ifdef _LITTLE_ENDIAN 1678 int i; 1679 #endif 1680 stmf_iocdata_t *iocd; 1681 void *ibuf = NULL; 1682 void *obuf = NULL; 1683 uint32_t *intp; 1684 qlt_fw_info_t *fwi; 1685 mbox_cmd_t *mcp; 1686 fct_status_t st; 1687 char info[80]; 1688 fct_status_t ret2; 1689 1690 if (drv_priv(credp) != 0) 1691 return (EPERM); 1692 1693 qlt = ddi_get_soft_state(qlt_state, (int32_t)getminor(dev)); 1694 ret = stmf_copyin_iocdata(data, mode, &iocd, &ibuf, &obuf); 1695 if (ret) 1696 return (ret); 1697 iocd->stmf_error = 0; 1698 1699 switch (cmd) { 1700 case QLT_IOCTL_FETCH_FWDUMP: 1701 if (iocd->stmf_obuf_size < QLT_FWDUMP_BUFSIZE) { 1702 EL(qlt, "FETCH_FWDUMP obuf_size=%d < %d\n", 1703 iocd->stmf_obuf_size, QLT_FWDUMP_BUFSIZE); 1704 ret = EINVAL; 1705 break; 1706 } 1707 mutex_enter(&qlt->qlt_ioctl_lock); 1708 if (!(qlt->qlt_ioctl_flags & QLT_FWDUMP_ISVALID)) { 1709 mutex_exit(&qlt->qlt_ioctl_lock); 1710 ret = ENODATA; 1711 EL(qlt, "no fwdump\n"); 1712 iocd->stmf_error = QLTIO_NO_DUMP; 1713 break; 1714 } 1715 if (qlt->qlt_ioctl_flags & QLT_FWDUMP_INPROGRESS) { 1716 mutex_exit(&qlt->qlt_ioctl_lock); 1717 ret = EBUSY; 1718 EL(qlt, "fwdump inprogress\n"); 1719 iocd->stmf_error = QLTIO_DUMP_INPROGRESS; 1720 break; 1721 } 1722 if (qlt->qlt_ioctl_flags & QLT_FWDUMP_FETCHED_BY_USER) { 1723 mutex_exit(&qlt->qlt_ioctl_lock); 1724 ret = EEXIST; 1725 EL(qlt, "fwdump already fetched\n"); 1726 iocd->stmf_error = QLTIO_ALREADY_FETCHED; 1727 break; 1728 } 1729 bcopy(qlt->qlt_fwdump_buf, obuf, QLT_FWDUMP_BUFSIZE); 1730 qlt->qlt_ioctl_flags |= QLT_FWDUMP_FETCHED_BY_USER; 1731 mutex_exit(&qlt->qlt_ioctl_lock); 1732 1733 break; 1734 1735 case QLT_IOCTL_TRIGGER_FWDUMP: 1736 if (qlt->qlt_state != FCT_STATE_ONLINE) { 1737 ret = EACCES; 1738 iocd->stmf_error = QLTIO_NOT_ONLINE; 1739 break; 1740 } 1741 (void) snprintf(info, 80, "qlt_ioctl: qlt-%p, " 1742 "user triggered FWDUMP with RFLAG_RESET", (void *)qlt); 1743 info[79] = 0; 1744 if ((ret2 = fct_port_shutdown(qlt->qlt_port, 1745 STMF_RFLAG_USER_REQUEST | STMF_RFLAG_RESET | 1746 STMF_RFLAG_COLLECT_DEBUG_DUMP, info)) != FCT_SUCCESS) { 1747 EL(qlt, "TRIGGER_FWDUMP fct_port_shutdown status=" 1748 "%llxh\n", ret2); 1749 ret = EIO; 1750 } 1751 break; 1752 case QLT_IOCTL_UPLOAD_FW: 1753 if ((iocd->stmf_ibuf_size < 1024) || 1754 (iocd->stmf_ibuf_size & 3)) { 1755 EL(qlt, "UPLOAD_FW ibuf_size=%d < 1024\n", 1756 iocd->stmf_ibuf_size); 1757 ret = EINVAL; 1758 iocd->stmf_error = QLTIO_INVALID_FW_SIZE; 1759 break; 1760 } 1761 intp = (uint32_t *)ibuf; 1762 #ifdef _LITTLE_ENDIAN 1763 for (i = 0; (i << 2) < iocd->stmf_ibuf_size; i++) { 1764 intp[i] = BSWAP_32(intp[i]); 1765 } 1766 #endif 1767 if (((intp[3] << 2) >= iocd->stmf_ibuf_size) || 1768 (((intp[intp[3] + 3] + intp[3]) << 2) != 1769 iocd->stmf_ibuf_size)) { 1770 EL(qlt, "UPLOAD_FW fw_size=%d >= %d\n", intp[3] << 2, 1771 iocd->stmf_ibuf_size); 1772 ret = EINVAL; 1773 iocd->stmf_error = QLTIO_INVALID_FW_SIZE; 1774 break; 1775 } 1776 if ((qlt->qlt_81xx_chip && ((intp[8] & 8) == 0)) || 1777 (qlt->qlt_25xx_chip && ((intp[8] & 4) == 0)) || 1778 (!qlt->qlt_25xx_chip && !qlt->qlt_81xx_chip && 1779 ((intp[8] & 3) == 0))) { 1780 EL(qlt, "UPLOAD_FW fw_type=%d\n", intp[8]); 1781 ret = EACCES; 1782 iocd->stmf_error = QLTIO_INVALID_FW_TYPE; 1783 break; 1784 } 1785 1786 /* Everything looks ok, lets copy this firmware */ 1787 if (qlt->fw_code01) { 1788 kmem_free(qlt->fw_code01, (qlt->fw_length01 + 1789 qlt->fw_length02) << 2); 1790 qlt->fw_code01 = NULL; 1791 } else { 1792 atomic_add_32(&qlt_loaded_counter, 1); 1793 } 1794 qlt->fw_length01 = intp[3]; 1795 qlt->fw_code01 = (uint32_t *)kmem_alloc(iocd->stmf_ibuf_size, 1796 KM_SLEEP); 1797 bcopy(intp, qlt->fw_code01, iocd->stmf_ibuf_size); 1798 qlt->fw_addr01 = intp[2]; 1799 qlt->fw_code02 = &qlt->fw_code01[intp[3]]; 1800 qlt->fw_addr02 = qlt->fw_code02[2]; 1801 qlt->fw_length02 = qlt->fw_code02[3]; 1802 break; 1803 1804 case QLT_IOCTL_CLEAR_FW: 1805 if (qlt->fw_code01) { 1806 kmem_free(qlt->fw_code01, (qlt->fw_length01 + 1807 qlt->fw_length02) << 2); 1808 qlt->fw_code01 = NULL; 1809 atomic_add_32(&qlt_loaded_counter, -1); 1810 } 1811 break; 1812 1813 case QLT_IOCTL_GET_FW_INFO: 1814 if (iocd->stmf_obuf_size != sizeof (qlt_fw_info_t)) { 1815 EL(qlt, "GET_FW_INFO obuf_size=%d != %d\n", 1816 iocd->stmf_obuf_size, sizeof (qlt_fw_info_t)); 1817 ret = EINVAL; 1818 break; 1819 } 1820 fwi = (qlt_fw_info_t *)obuf; 1821 if (qlt->qlt_stay_offline) { 1822 fwi->fwi_stay_offline = 1; 1823 } 1824 if (qlt->qlt_state == FCT_STATE_ONLINE) { 1825 fwi->fwi_port_active = 1; 1826 } 1827 fwi->fwi_active_major = qlt->fw_major; 1828 fwi->fwi_active_minor = qlt->fw_minor; 1829 fwi->fwi_active_subminor = qlt->fw_subminor; 1830 fwi->fwi_active_attr = qlt->fw_attr; 1831 if (qlt->fw_code01) { 1832 fwi->fwi_fw_uploaded = 1; 1833 fwi->fwi_loaded_major = (uint16_t)qlt->fw_code01[4]; 1834 fwi->fwi_loaded_minor = (uint16_t)qlt->fw_code01[5]; 1835 fwi->fwi_loaded_subminor = (uint16_t)qlt->fw_code01[6]; 1836 fwi->fwi_loaded_attr = (uint16_t)qlt->fw_code01[7]; 1837 } 1838 if (qlt->qlt_81xx_chip) { 1839 fwi->fwi_default_major = (uint16_t)fw8100_code01[4]; 1840 fwi->fwi_default_minor = (uint16_t)fw8100_code01[5]; 1841 fwi->fwi_default_subminor = (uint16_t)fw8100_code01[6]; 1842 fwi->fwi_default_attr = (uint16_t)fw8100_code01[7]; 1843 } else if (qlt->qlt_25xx_chip) { 1844 fwi->fwi_default_major = (uint16_t)fw2500_code01[4]; 1845 fwi->fwi_default_minor = (uint16_t)fw2500_code01[5]; 1846 fwi->fwi_default_subminor = (uint16_t)fw2500_code01[6]; 1847 fwi->fwi_default_attr = (uint16_t)fw2500_code01[7]; 1848 } else { 1849 fwi->fwi_default_major = (uint16_t)fw2400_code01[4]; 1850 fwi->fwi_default_minor = (uint16_t)fw2400_code01[5]; 1851 fwi->fwi_default_subminor = (uint16_t)fw2400_code01[6]; 1852 fwi->fwi_default_attr = (uint16_t)fw2400_code01[7]; 1853 } 1854 break; 1855 1856 case QLT_IOCTL_STAY_OFFLINE: 1857 if (!iocd->stmf_ibuf_size) { 1858 EL(qlt, "STAY_OFFLINE ibuf_size=%d\n", 1859 iocd->stmf_ibuf_size); 1860 ret = EINVAL; 1861 break; 1862 } 1863 if (*((char *)ibuf)) { 1864 qlt->qlt_stay_offline = 1; 1865 } else { 1866 qlt->qlt_stay_offline = 0; 1867 } 1868 break; 1869 1870 case QLT_IOCTL_MBOX: 1871 if ((iocd->stmf_ibuf_size < sizeof (qlt_ioctl_mbox_t)) || 1872 (iocd->stmf_obuf_size < sizeof (qlt_ioctl_mbox_t))) { 1873 EL(qlt, "IOCTL_MBOX ibuf_size=%d, obuf_size=%d\n", 1874 iocd->stmf_ibuf_size, iocd->stmf_obuf_size); 1875 ret = EINVAL; 1876 break; 1877 } 1878 mcp = qlt_alloc_mailbox_command(qlt, 0); 1879 if (mcp == NULL) { 1880 EL(qlt, "IOCTL_MBOX mcp == NULL\n"); 1881 ret = ENOMEM; 1882 break; 1883 } 1884 bcopy(ibuf, mcp, sizeof (qlt_ioctl_mbox_t)); 1885 st = qlt_mailbox_command(qlt, mcp); 1886 bcopy(mcp, obuf, sizeof (qlt_ioctl_mbox_t)); 1887 qlt_free_mailbox_command(qlt, mcp); 1888 if (st != QLT_SUCCESS) { 1889 if ((st & (~((uint64_t)(0xFFFF)))) == QLT_MBOX_FAILED) 1890 st = QLT_SUCCESS; 1891 } 1892 if (st != QLT_SUCCESS) { 1893 EL(qlt, "IOCTL_MBOX status=%xh\n", st); 1894 ret = EIO; 1895 switch (st) { 1896 case QLT_MBOX_NOT_INITIALIZED: 1897 iocd->stmf_error = QLTIO_MBOX_NOT_INITIALIZED; 1898 break; 1899 case QLT_MBOX_BUSY: 1900 iocd->stmf_error = QLTIO_CANT_GET_MBOXES; 1901 break; 1902 case QLT_MBOX_TIMEOUT: 1903 iocd->stmf_error = QLTIO_MBOX_TIMED_OUT; 1904 break; 1905 case QLT_MBOX_ABORTED: 1906 iocd->stmf_error = QLTIO_MBOX_ABORTED; 1907 break; 1908 } 1909 } 1910 break; 1911 1912 case QLT_IOCTL_ELOG: 1913 qlt_dump_el_trace_buffer(qlt); 1914 break; 1915 1916 default: 1917 EL(qlt, "Unknown ioctl-%xh\n", cmd); 1918 ret = ENOTTY; 1919 } 1920 1921 if (ret == 0) { 1922 ret = stmf_copyout_iocdata(data, mode, iocd, obuf); 1923 } else if (iocd->stmf_error) { 1924 (void) stmf_copyout_iocdata(data, mode, iocd, obuf); 1925 } 1926 if (obuf) { 1927 kmem_free(obuf, iocd->stmf_obuf_size); 1928 obuf = NULL; 1929 } 1930 if (ibuf) { 1931 kmem_free(ibuf, iocd->stmf_ibuf_size); 1932 ibuf = NULL; 1933 } 1934 kmem_free(iocd, sizeof (stmf_iocdata_t)); 1935 return (ret); 1936 } 1937 1938 static fct_status_t 1939 qlt_force_lip(qlt_state_t *qlt) 1940 { 1941 mbox_cmd_t *mcp; 1942 fct_status_t rval; 1943 1944 mcp = qlt_alloc_mailbox_command(qlt, 0); 1945 mcp->to_fw[0] = 0x0072; 1946 mcp->to_fw[1] = BIT_4; 1947 mcp->to_fw[3] = 1; 1948 mcp->to_fw_mask |= BIT_1 | BIT_3; 1949 rval = qlt_mailbox_command(qlt, mcp); 1950 if (rval != FCT_SUCCESS) { 1951 EL(qlt, "qlt force lip MB failed: rval=%x", rval); 1952 } else { 1953 if (mcp->from_fw[0] != 0x4000) { 1954 QLT_LOG(qlt->qlt_port_alias, "qlt FLIP: fw[0]=%x", 1955 mcp->from_fw[0]); 1956 rval = FCT_FAILURE; 1957 } 1958 } 1959 qlt_free_mailbox_command(qlt, mcp); 1960 return (rval); 1961 } 1962 1963 static void 1964 qlt_ctl(struct fct_local_port *port, int cmd, void *arg) 1965 { 1966 stmf_change_status_t st; 1967 stmf_state_change_info_t *ssci = (stmf_state_change_info_t *)arg; 1968 qlt_state_t *qlt; 1969 fct_status_t ret; 1970 1971 ASSERT((cmd == FCT_CMD_PORT_ONLINE) || 1972 (cmd == FCT_CMD_PORT_OFFLINE) || 1973 (cmd == FCT_CMD_FORCE_LIP) || 1974 (cmd == FCT_ACK_PORT_ONLINE_COMPLETE) || 1975 (cmd == FCT_ACK_PORT_OFFLINE_COMPLETE)); 1976 1977 qlt = (qlt_state_t *)port->port_fca_private; 1978 st.st_completion_status = FCT_SUCCESS; 1979 st.st_additional_info = NULL; 1980 1981 switch (cmd) { 1982 case FCT_CMD_PORT_ONLINE: 1983 if (qlt->qlt_state == FCT_STATE_ONLINE) 1984 st.st_completion_status = STMF_ALREADY; 1985 else if (qlt->qlt_state != FCT_STATE_OFFLINE) 1986 st.st_completion_status = FCT_FAILURE; 1987 if (st.st_completion_status == FCT_SUCCESS) { 1988 qlt->qlt_state = FCT_STATE_ONLINING; 1989 qlt->qlt_state_not_acked = 1; 1990 st.st_completion_status = qlt_port_online(qlt); 1991 if (st.st_completion_status != STMF_SUCCESS) { 1992 EL(qlt, "PORT_ONLINE status=%xh\n", 1993 st.st_completion_status); 1994 qlt->qlt_state = FCT_STATE_OFFLINE; 1995 qlt->qlt_state_not_acked = 0; 1996 } else { 1997 qlt->qlt_state = FCT_STATE_ONLINE; 1998 } 1999 } 2000 fct_ctl(port->port_lport, FCT_CMD_PORT_ONLINE_COMPLETE, &st); 2001 qlt->qlt_change_state_flags = 0; 2002 break; 2003 2004 case FCT_CMD_PORT_OFFLINE: 2005 if (qlt->qlt_state == FCT_STATE_OFFLINE) { 2006 st.st_completion_status = STMF_ALREADY; 2007 } else if (qlt->qlt_state != FCT_STATE_ONLINE) { 2008 st.st_completion_status = FCT_FAILURE; 2009 } 2010 if (st.st_completion_status == FCT_SUCCESS) { 2011 qlt->qlt_state = FCT_STATE_OFFLINING; 2012 qlt->qlt_state_not_acked = 1; 2013 2014 if (ssci->st_rflags & STMF_RFLAG_COLLECT_DEBUG_DUMP) { 2015 (void) qlt_firmware_dump(port, ssci); 2016 } 2017 qlt->qlt_change_state_flags = (uint32_t)ssci->st_rflags; 2018 st.st_completion_status = qlt_port_offline(qlt); 2019 if (st.st_completion_status != STMF_SUCCESS) { 2020 EL(qlt, "PORT_OFFLINE status=%xh\n", 2021 st.st_completion_status); 2022 qlt->qlt_state = FCT_STATE_ONLINE; 2023 qlt->qlt_state_not_acked = 0; 2024 } else { 2025 qlt->qlt_state = FCT_STATE_OFFLINE; 2026 } 2027 } 2028 fct_ctl(port->port_lport, FCT_CMD_PORT_OFFLINE_COMPLETE, &st); 2029 break; 2030 2031 case FCT_ACK_PORT_ONLINE_COMPLETE: 2032 qlt->qlt_state_not_acked = 0; 2033 break; 2034 2035 case FCT_ACK_PORT_OFFLINE_COMPLETE: 2036 qlt->qlt_state_not_acked = 0; 2037 if ((qlt->qlt_change_state_flags & STMF_RFLAG_RESET) && 2038 (qlt->qlt_stay_offline == 0)) { 2039 if ((ret = fct_port_initialize(port, 2040 qlt->qlt_change_state_flags, 2041 "qlt_ctl FCT_ACK_PORT_OFFLINE_COMPLETE " 2042 "with RLFLAG_RESET")) != FCT_SUCCESS) { 2043 EL(qlt, "fct_port_initialize status=%llxh\n", 2044 ret); 2045 cmn_err(CE_WARN, "qlt_ctl: " 2046 "fct_port_initialize failed, please use " 2047 "stmfstate to start the port-%s manualy", 2048 qlt->qlt_port_alias); 2049 } 2050 } 2051 break; 2052 2053 case FCT_CMD_FORCE_LIP: 2054 if (qlt->qlt_81xx_chip) { 2055 EL(qlt, "force lip is an unsupported command " 2056 "for this adapter type\n"); 2057 } else { 2058 *((fct_status_t *)arg) = qlt_force_lip(qlt); 2059 EL(qlt, "forcelip done\n"); 2060 } 2061 break; 2062 2063 default: 2064 EL(qlt, "unsupport cmd - 0x%02X", cmd); 2065 break; 2066 } 2067 } 2068 2069 /* ARGSUSED */ 2070 static fct_status_t 2071 qlt_do_flogi(fct_local_port_t *port, fct_flogi_xchg_t *fx) 2072 { 2073 qlt_state_t *qlt = (qlt_state_t *)port->port_fca_private; 2074 2075 EL(qlt, "FLOGI requested not supported\n"); 2076 cmn_err(CE_WARN, "qlt: FLOGI requested (not supported)"); 2077 return (FCT_FAILURE); 2078 } 2079 2080 /* 2081 * Return a pointer to n entries in the request queue. Assumes that 2082 * request queue lock is held. Does a very short busy wait if 2083 * less/zero entries are available. Retuns NULL if it still cannot 2084 * fullfill the request. 2085 * **CALL qlt_submit_req_entries() BEFORE DROPPING THE LOCK** 2086 */ 2087 caddr_t 2088 qlt_get_req_entries(qlt_state_t *qlt, uint32_t n) 2089 { 2090 int try = 0; 2091 2092 while (qlt->req_available < n) { 2093 uint32_t val1, val2, val3; 2094 val1 = REG_RD32(qlt, REG_REQ_OUT_PTR); 2095 val2 = REG_RD32(qlt, REG_REQ_OUT_PTR); 2096 val3 = REG_RD32(qlt, REG_REQ_OUT_PTR); 2097 if ((val1 != val2) || (val2 != val3)) 2098 continue; 2099 2100 qlt->req_ndx_from_fw = val1; 2101 qlt->req_available = REQUEST_QUEUE_ENTRIES - 1 - 2102 ((qlt->req_ndx_to_fw - qlt->req_ndx_from_fw) & 2103 (REQUEST_QUEUE_ENTRIES - 1)); 2104 if (qlt->req_available < n) { 2105 if (try < 2) { 2106 drv_usecwait(100); 2107 try++; 2108 continue; 2109 } else { 2110 stmf_trace(qlt->qlt_port_alias, 2111 "Req Q is full"); 2112 return (NULL); 2113 } 2114 } 2115 break; 2116 } 2117 /* We dont change anything until the entries are sumitted */ 2118 return (&qlt->req_ptr[qlt->req_ndx_to_fw << 6]); 2119 } 2120 2121 /* 2122 * updates the req in ptr to fw. Assumes that req lock is held. 2123 */ 2124 void 2125 qlt_submit_req_entries(qlt_state_t *qlt, uint32_t n) 2126 { 2127 ASSERT(n >= 1); 2128 qlt->req_ndx_to_fw += n; 2129 qlt->req_ndx_to_fw &= REQUEST_QUEUE_ENTRIES - 1; 2130 qlt->req_available -= n; 2131 REG_WR32(qlt, REG_REQ_IN_PTR, qlt->req_ndx_to_fw); 2132 } 2133 2134 2135 /* 2136 * Return a pointer to n entries in the priority request queue. Assumes that 2137 * priority request queue lock is held. Does a very short busy wait if 2138 * less/zero entries are available. Retuns NULL if it still cannot 2139 * fullfill the request. 2140 * **CALL qlt_submit_preq_entries() BEFORE DROPPING THE LOCK** 2141 */ 2142 caddr_t 2143 qlt_get_preq_entries(qlt_state_t *qlt, uint32_t n) 2144 { 2145 int try = 0; 2146 uint32_t req_available = PRIORITY_QUEUE_ENTRIES - 1 - 2147 ((qlt->preq_ndx_to_fw - qlt->preq_ndx_from_fw) & 2148 (PRIORITY_QUEUE_ENTRIES - 1)); 2149 2150 while (req_available < n) { 2151 uint32_t val1, val2, val3; 2152 val1 = REG_RD32(qlt, REG_PREQ_OUT_PTR); 2153 val2 = REG_RD32(qlt, REG_PREQ_OUT_PTR); 2154 val3 = REG_RD32(qlt, REG_PREQ_OUT_PTR); 2155 if ((val1 != val2) || (val2 != val3)) 2156 continue; 2157 2158 qlt->preq_ndx_from_fw = val1; 2159 req_available = PRIORITY_QUEUE_ENTRIES - 1 - 2160 ((qlt->preq_ndx_to_fw - qlt->preq_ndx_from_fw) & 2161 (PRIORITY_QUEUE_ENTRIES - 1)); 2162 if (req_available < n) { 2163 if (try < 2) { 2164 drv_usecwait(100); 2165 try++; 2166 continue; 2167 } else { 2168 return (NULL); 2169 } 2170 } 2171 break; 2172 } 2173 /* We dont change anything until the entries are sumitted */ 2174 return (&qlt->preq_ptr[qlt->preq_ndx_to_fw << 6]); 2175 } 2176 2177 /* 2178 * updates the req in ptr to fw. Assumes that req lock is held. 2179 */ 2180 void 2181 qlt_submit_preq_entries(qlt_state_t *qlt, uint32_t n) 2182 { 2183 ASSERT(n >= 1); 2184 qlt->preq_ndx_to_fw += n; 2185 qlt->preq_ndx_to_fw &= PRIORITY_QUEUE_ENTRIES - 1; 2186 REG_WR32(qlt, REG_PREQ_IN_PTR, qlt->preq_ndx_to_fw); 2187 } 2188 2189 /* 2190 * - Should not be called from Interrupt. 2191 * - A very hardware specific function. Does not touch driver state. 2192 * - Assumes that interrupts are disabled or not there. 2193 * - Expects that the caller makes sure that all activity has stopped 2194 * and its ok now to go ahead and reset the chip. Also the caller 2195 * takes care of post reset damage control. 2196 * - called by initialize adapter() and dump_fw(for reset only). 2197 * - During attach() nothing much is happening and during initialize_adapter() 2198 * the function (caller) does all the housekeeping so that this function 2199 * can execute in peace. 2200 * - Returns 0 on success. 2201 */ 2202 static fct_status_t 2203 qlt_reset_chip(qlt_state_t *qlt) 2204 { 2205 int cntr; 2206 2207 EL(qlt, "initiated\n"); 2208 2209 /* XXX: Switch off LEDs */ 2210 2211 /* Disable Interrupts */ 2212 REG_WR32(qlt, REG_INTR_CTRL, 0); 2213 (void) REG_RD32(qlt, REG_INTR_CTRL); 2214 /* Stop DMA */ 2215 REG_WR32(qlt, REG_CTRL_STATUS, DMA_SHUTDOWN_CTRL | PCI_X_XFER_CTRL); 2216 2217 /* Wait for DMA to be stopped */ 2218 cntr = 0; 2219 while (REG_RD32(qlt, REG_CTRL_STATUS) & DMA_ACTIVE_STATUS) { 2220 delay(drv_usectohz(10000)); /* mostly 10ms is 1 tick */ 2221 cntr++; 2222 /* 3 sec should be more than enough */ 2223 if (cntr == 300) 2224 return (QLT_DMA_STUCK); 2225 } 2226 2227 /* Reset the Chip */ 2228 REG_WR32(qlt, REG_CTRL_STATUS, 2229 DMA_SHUTDOWN_CTRL | PCI_X_XFER_CTRL | CHIP_SOFT_RESET); 2230 2231 qlt->qlt_link_up = 0; 2232 2233 drv_usecwait(100); 2234 2235 /* Wait for ROM firmware to initialize (0x0000) in mailbox 0 */ 2236 cntr = 0; 2237 while (REG_RD16(qlt, REG_MBOX(0)) != 0) { 2238 delay(drv_usectohz(10000)); 2239 cntr++; 2240 /* 3 sec should be more than enough */ 2241 if (cntr == 300) 2242 return (QLT_ROM_STUCK); 2243 } 2244 /* Disable Interrupts (Probably not needed) */ 2245 REG_WR32(qlt, REG_INTR_CTRL, 0); 2246 2247 return (QLT_SUCCESS); 2248 } 2249 /* 2250 * - Should not be called from Interrupt. 2251 * - A very hardware specific function. Does not touch driver state. 2252 * - Assumes that interrupts are disabled or not there. 2253 * - Expects that the caller makes sure that all activity has stopped 2254 * and its ok now to go ahead and reset the chip. Also the caller 2255 * takes care of post reset damage control. 2256 * - called by initialize adapter() and dump_fw(for reset only). 2257 * - During attach() nothing much is happening and during initialize_adapter() 2258 * the function (caller) does all the housekeeping so that this function 2259 * can execute in peace. 2260 * - Returns 0 on success. 2261 */ 2262 static fct_status_t 2263 qlt_download_fw(qlt_state_t *qlt) 2264 { 2265 uint32_t start_addr; 2266 fct_status_t ret; 2267 2268 EL(qlt, "initiated\n"); 2269 2270 (void) qlt_reset_chip(qlt); 2271 2272 if (qlt->qlt_81xx_chip) { 2273 qlt_mps_reset(qlt); 2274 } 2275 2276 /* Load the two segments */ 2277 if (qlt->fw_code01 != NULL) { 2278 ret = qlt_load_risc_ram(qlt, qlt->fw_code01, qlt->fw_length01, 2279 qlt->fw_addr01); 2280 if (ret == QLT_SUCCESS) { 2281 ret = qlt_load_risc_ram(qlt, qlt->fw_code02, 2282 qlt->fw_length02, qlt->fw_addr02); 2283 } 2284 start_addr = qlt->fw_addr01; 2285 } else if (qlt->qlt_81xx_chip) { 2286 ret = qlt_load_risc_ram(qlt, fw8100_code01, fw8100_length01, 2287 fw8100_addr01); 2288 if (ret == QLT_SUCCESS) { 2289 ret = qlt_load_risc_ram(qlt, fw8100_code02, 2290 fw8100_length02, fw8100_addr02); 2291 } 2292 start_addr = fw8100_addr01; 2293 } else if (qlt->qlt_25xx_chip) { 2294 ret = qlt_load_risc_ram(qlt, fw2500_code01, fw2500_length01, 2295 fw2500_addr01); 2296 if (ret == QLT_SUCCESS) { 2297 ret = qlt_load_risc_ram(qlt, fw2500_code02, 2298 fw2500_length02, fw2500_addr02); 2299 } 2300 start_addr = fw2500_addr01; 2301 } else { 2302 ret = qlt_load_risc_ram(qlt, fw2400_code01, fw2400_length01, 2303 fw2400_addr01); 2304 if (ret == QLT_SUCCESS) { 2305 ret = qlt_load_risc_ram(qlt, fw2400_code02, 2306 fw2400_length02, fw2400_addr02); 2307 } 2308 start_addr = fw2400_addr01; 2309 } 2310 if (ret != QLT_SUCCESS) { 2311 EL(qlt, "qlt_load_risc_ram status=%llxh\n", ret); 2312 return (ret); 2313 } 2314 2315 /* Verify Checksum */ 2316 REG_WR16(qlt, REG_MBOX(0), MBC_VERIFY_CHECKSUM); 2317 REG_WR16(qlt, REG_MBOX(1), MSW(start_addr)); 2318 REG_WR16(qlt, REG_MBOX(2), LSW(start_addr)); 2319 ret = qlt_raw_mailbox_command(qlt); 2320 REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR)); 2321 if (ret != QLT_SUCCESS) { 2322 EL(qlt, "qlt_raw_mailbox_command=7h status=%llxh\n", ret); 2323 return (ret); 2324 } 2325 2326 /* Execute firmware */ 2327 REG_WR16(qlt, REG_MBOX(0), MBC_EXECUTE_FIRMWARE); 2328 REG_WR16(qlt, REG_MBOX(1), MSW(start_addr)); 2329 REG_WR16(qlt, REG_MBOX(2), LSW(start_addr)); 2330 REG_WR16(qlt, REG_MBOX(3), 0); 2331 REG_WR16(qlt, REG_MBOX(4), 1); /* 25xx enable additional credits */ 2332 ret = qlt_raw_mailbox_command(qlt); 2333 REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR)); 2334 if (ret != QLT_SUCCESS) { 2335 EL(qlt, "qlt_raw_mailbox_command=2h status=%llxh\n", ret); 2336 return (ret); 2337 } 2338 2339 /* Get revisions (About Firmware) */ 2340 REG_WR16(qlt, REG_MBOX(0), MBC_ABOUT_FIRMWARE); 2341 ret = qlt_raw_mailbox_command(qlt); 2342 qlt->fw_major = REG_RD16(qlt, REG_MBOX(1)); 2343 qlt->fw_minor = REG_RD16(qlt, REG_MBOX(2)); 2344 qlt->fw_subminor = REG_RD16(qlt, REG_MBOX(3)); 2345 qlt->fw_endaddrlo = REG_RD16(qlt, REG_MBOX(4)); 2346 qlt->fw_endaddrhi = REG_RD16(qlt, REG_MBOX(5)); 2347 qlt->fw_attr = REG_RD16(qlt, REG_MBOX(6)); 2348 REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR)); 2349 if (ret != QLT_SUCCESS) { 2350 EL(qlt, "qlt_raw_mailbox_command=8h status=%llxh\n", ret); 2351 return (ret); 2352 } 2353 2354 return (QLT_SUCCESS); 2355 } 2356 2357 /* 2358 * Used only from qlt_download_fw(). 2359 */ 2360 static fct_status_t 2361 qlt_load_risc_ram(qlt_state_t *qlt, uint32_t *host_addr, 2362 uint32_t word_count, uint32_t risc_addr) 2363 { 2364 uint32_t words_sent = 0; 2365 uint32_t words_being_sent; 2366 uint32_t *cur_host_addr; 2367 uint32_t cur_risc_addr; 2368 uint64_t da; 2369 fct_status_t ret; 2370 2371 while (words_sent < word_count) { 2372 cur_host_addr = &(host_addr[words_sent]); 2373 cur_risc_addr = risc_addr + (words_sent << 2); 2374 words_being_sent = min(word_count - words_sent, 2375 TOTAL_DMA_MEM_SIZE >> 2); 2376 ddi_rep_put32(qlt->queue_mem_acc_handle, cur_host_addr, 2377 (uint32_t *)qlt->queue_mem_ptr, words_being_sent, 2378 DDI_DEV_AUTOINCR); 2379 (void) ddi_dma_sync(qlt->queue_mem_dma_handle, 0, 2380 words_being_sent << 2, DDI_DMA_SYNC_FORDEV); 2381 da = qlt->queue_mem_cookie.dmac_laddress; 2382 REG_WR16(qlt, REG_MBOX(0), MBC_LOAD_RAM_EXTENDED); 2383 REG_WR16(qlt, REG_MBOX(1), LSW(risc_addr)); 2384 REG_WR16(qlt, REG_MBOX(8), MSW(cur_risc_addr)); 2385 REG_WR16(qlt, REG_MBOX(3), LSW(LSD(da))); 2386 REG_WR16(qlt, REG_MBOX(2), MSW(LSD(da))); 2387 REG_WR16(qlt, REG_MBOX(7), LSW(MSD(da))); 2388 REG_WR16(qlt, REG_MBOX(6), MSW(MSD(da))); 2389 REG_WR16(qlt, REG_MBOX(5), LSW(words_being_sent)); 2390 REG_WR16(qlt, REG_MBOX(4), MSW(words_being_sent)); 2391 ret = qlt_raw_mailbox_command(qlt); 2392 REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR)); 2393 if (ret != QLT_SUCCESS) { 2394 EL(qlt, "qlt_raw_mailbox_command=0Bh status=%llxh\n", 2395 ret); 2396 return (ret); 2397 } 2398 words_sent += words_being_sent; 2399 } 2400 return (QLT_SUCCESS); 2401 } 2402 2403 /* 2404 * Not used during normal operation. Only during driver init. 2405 * Assumes that interrupts are disabled and mailboxes are loaded. 2406 * Just triggers the mailbox command an waits for the completion. 2407 * Also expects that There is nothing else going on and we will only 2408 * get back a mailbox completion from firmware. 2409 * ---DOES NOT CLEAR INTERRUPT--- 2410 * Used only from the code path originating from 2411 * qlt_reset_chip_and_download_fw() 2412 */ 2413 static fct_status_t 2414 qlt_raw_mailbox_command(qlt_state_t *qlt) 2415 { 2416 int cntr = 0; 2417 uint32_t status; 2418 2419 REG_WR32(qlt, REG_HCCR, HCCR_CMD(SET_HOST_TO_RISC_INTR)); 2420 while ((REG_RD32(qlt, REG_INTR_STATUS) & RISC_PCI_INTR_REQUEST) == 0) { 2421 cntr++; 2422 if (cntr == 100) { 2423 return (QLT_MAILBOX_STUCK); 2424 } 2425 delay(drv_usectohz(10000)); 2426 } 2427 status = (REG_RD32(qlt, REG_RISC_STATUS) & FW_INTR_STATUS_MASK); 2428 2429 if ((status == ROM_MBX_CMD_SUCCESSFUL) || 2430 (status == ROM_MBX_CMD_NOT_SUCCESSFUL) || 2431 (status == MBX_CMD_SUCCESSFUL) || 2432 (status == MBX_CMD_NOT_SUCCESSFUL)) { 2433 uint16_t mbox0 = REG_RD16(qlt, REG_MBOX(0)); 2434 if (mbox0 == QLT_MBX_CMD_SUCCESS) { 2435 return (QLT_SUCCESS); 2436 } else { 2437 return (QLT_MBOX_FAILED | mbox0); 2438 } 2439 } 2440 /* This is unexpected, dump a message */ 2441 cmn_err(CE_WARN, "qlt(%d): Unexpect intr status %llx", 2442 ddi_get_instance(qlt->dip), (unsigned long long)status); 2443 return (QLT_UNEXPECTED_RESPONSE); 2444 } 2445 2446 static mbox_cmd_t * 2447 qlt_alloc_mailbox_command(qlt_state_t *qlt, uint32_t dma_size) 2448 { 2449 mbox_cmd_t *mcp; 2450 2451 mcp = (mbox_cmd_t *)kmem_zalloc(sizeof (mbox_cmd_t), KM_SLEEP); 2452 if (dma_size) { 2453 qlt_dmem_bctl_t *bctl; 2454 uint64_t da; 2455 2456 mcp->dbuf = qlt_i_dmem_alloc(qlt, dma_size, &dma_size, 0); 2457 if (mcp->dbuf == NULL) { 2458 kmem_free(mcp, sizeof (*mcp)); 2459 return (NULL); 2460 } 2461 mcp->dbuf->db_data_size = dma_size; 2462 ASSERT(mcp->dbuf->db_sglist_length == 1); 2463 2464 bctl = (qlt_dmem_bctl_t *)mcp->dbuf->db_port_private; 2465 da = bctl->bctl_dev_addr; 2466 /* This is the most common initialization of dma ptrs */ 2467 mcp->to_fw[3] = LSW(LSD(da)); 2468 mcp->to_fw[2] = MSW(LSD(da)); 2469 mcp->to_fw[7] = LSW(MSD(da)); 2470 mcp->to_fw[6] = MSW(MSD(da)); 2471 mcp->to_fw_mask |= BIT_2 | BIT_3 | BIT_7 | BIT_6; 2472 } 2473 mcp->to_fw_mask |= BIT_0; 2474 mcp->from_fw_mask |= BIT_0; 2475 return (mcp); 2476 } 2477 2478 void 2479 qlt_free_mailbox_command(qlt_state_t *qlt, mbox_cmd_t *mcp) 2480 { 2481 if (mcp->dbuf) 2482 qlt_i_dmem_free(qlt, mcp->dbuf); 2483 kmem_free(mcp, sizeof (*mcp)); 2484 } 2485 2486 /* 2487 * This can sleep. Should never be called from interrupt context. 2488 */ 2489 static fct_status_t 2490 qlt_mailbox_command(qlt_state_t *qlt, mbox_cmd_t *mcp) 2491 { 2492 int retries; 2493 int i; 2494 char info[80]; 2495 2496 if (curthread->t_flag & T_INTR_THREAD) { 2497 ASSERT(0); 2498 return (QLT_MBOX_FAILED); 2499 } 2500 2501 mutex_enter(&qlt->mbox_lock); 2502 /* See if mailboxes are still uninitialized */ 2503 if (qlt->mbox_io_state == MBOX_STATE_UNKNOWN) { 2504 mutex_exit(&qlt->mbox_lock); 2505 return (QLT_MBOX_NOT_INITIALIZED); 2506 } 2507 2508 /* Wait to grab the mailboxes */ 2509 for (retries = 0; qlt->mbox_io_state != MBOX_STATE_READY; 2510 retries++) { 2511 cv_wait(&qlt->mbox_cv, &qlt->mbox_lock); 2512 if ((retries > 5) || 2513 (qlt->mbox_io_state == MBOX_STATE_UNKNOWN)) { 2514 mutex_exit(&qlt->mbox_lock); 2515 return (QLT_MBOX_BUSY); 2516 } 2517 } 2518 /* Make sure we always ask for mailbox 0 */ 2519 mcp->from_fw_mask |= BIT_0; 2520 2521 /* Load mailboxes, set state and generate RISC interrupt */ 2522 qlt->mbox_io_state = MBOX_STATE_CMD_RUNNING; 2523 qlt->mcp = mcp; 2524 for (i = 0; i < MAX_MBOXES; i++) { 2525 if (mcp->to_fw_mask & ((uint32_t)1 << i)) 2526 REG_WR16(qlt, REG_MBOX(i), mcp->to_fw[i]); 2527 } 2528 REG_WR32(qlt, REG_HCCR, HCCR_CMD(SET_HOST_TO_RISC_INTR)); 2529 2530 qlt_mbox_wait_loop:; 2531 /* Wait for mailbox command completion */ 2532 if (cv_timedwait(&qlt->mbox_cv, &qlt->mbox_lock, ddi_get_lbolt() 2533 + drv_usectohz(MBOX_TIMEOUT)) < 0) { 2534 (void) snprintf(info, 80, "qlt_mailbox_command: qlt-%p, " 2535 "cmd-0x%02X timed out", (void *)qlt, qlt->mcp->to_fw[0]); 2536 info[79] = 0; 2537 qlt->mcp = NULL; 2538 qlt->mbox_io_state = MBOX_STATE_UNKNOWN; 2539 mutex_exit(&qlt->mbox_lock); 2540 2541 /* 2542 * XXX Throw HBA fatal error event 2543 */ 2544 (void) fct_port_shutdown(qlt->qlt_port, STMF_RFLAG_FATAL_ERROR | 2545 STMF_RFLAG_RESET | STMF_RFLAG_COLLECT_DEBUG_DUMP, info); 2546 return (QLT_MBOX_TIMEOUT); 2547 } 2548 if (qlt->mbox_io_state == MBOX_STATE_CMD_RUNNING) 2549 goto qlt_mbox_wait_loop; 2550 2551 qlt->mcp = NULL; 2552 2553 /* Make sure its a completion */ 2554 if (qlt->mbox_io_state != MBOX_STATE_CMD_DONE) { 2555 ASSERT(qlt->mbox_io_state == MBOX_STATE_UNKNOWN); 2556 mutex_exit(&qlt->mbox_lock); 2557 return (QLT_MBOX_ABORTED); 2558 } 2559 2560 /* MBox command completed. Clear state, retuen based on mbox 0 */ 2561 /* Mailboxes are already loaded by interrupt routine */ 2562 qlt->mbox_io_state = MBOX_STATE_READY; 2563 mutex_exit(&qlt->mbox_lock); 2564 if (mcp->from_fw[0] != QLT_MBX_CMD_SUCCESS) 2565 return (QLT_MBOX_FAILED | mcp->from_fw[0]); 2566 2567 return (QLT_SUCCESS); 2568 } 2569 2570 /* 2571 * **SHOULD ONLY BE CALLED FROM INTERRUPT CONTEXT. DO NOT CALL ELSEWHERE** 2572 */ 2573 /* ARGSUSED */ 2574 static uint_t 2575 qlt_isr(caddr_t arg, caddr_t arg2) 2576 { 2577 qlt_state_t *qlt = (qlt_state_t *)arg; 2578 uint32_t risc_status, intr_type; 2579 int i; 2580 int intr_loop_count; 2581 char info[80]; 2582 2583 risc_status = REG_RD32(qlt, REG_RISC_STATUS); 2584 if (!mutex_tryenter(&qlt->intr_lock)) { 2585 /* 2586 * Normally we will always get this lock. If tryenter is 2587 * failing then it means that driver is trying to do 2588 * some cleanup and is masking the intr but some intr 2589 * has sneaked in between. See if our device has generated 2590 * this intr. If so then wait a bit and return claimed. 2591 * If not then return claimed if this is the 1st instance 2592 * of a interrupt after driver has grabbed the lock. 2593 */ 2594 if (risc_status & BIT_15) { 2595 drv_usecwait(10); 2596 return (DDI_INTR_CLAIMED); 2597 } else if (qlt->intr_sneak_counter) { 2598 qlt->intr_sneak_counter--; 2599 return (DDI_INTR_CLAIMED); 2600 } else { 2601 return (DDI_INTR_UNCLAIMED); 2602 } 2603 } 2604 if (((risc_status & BIT_15) == 0) || 2605 (qlt->qlt_intr_enabled == 0)) { 2606 /* 2607 * This might be a pure coincedence that we are operating 2608 * in a interrupt disabled mode and another device 2609 * sharing the interrupt line has generated an interrupt 2610 * while an interrupt from our device might be pending. Just 2611 * ignore it and let the code handling the interrupt 2612 * disabled mode handle it. 2613 */ 2614 mutex_exit(&qlt->intr_lock); 2615 return (DDI_INTR_UNCLAIMED); 2616 } 2617 2618 /* 2619 * XXX take care for MSI case. disable intrs 2620 * Its gonna be complicated because of the max iterations. 2621 * as hba will have posted the intr which did not go on PCI 2622 * but we did not service it either because of max iterations. 2623 * Maybe offload the intr on a different thread. 2624 */ 2625 intr_loop_count = 0; 2626 2627 REG_WR32(qlt, REG_INTR_CTRL, 0); 2628 2629 intr_again:; 2630 2631 /* check for risc pause */ 2632 if (risc_status & BIT_8) { 2633 EL(qlt, "Risc Pause status=%xh\n", risc_status); 2634 cmn_err(CE_WARN, "qlt(%d): Risc Pause %08x", 2635 qlt->instance, risc_status); 2636 (void) snprintf(info, 80, "Risc Pause %08x", risc_status); 2637 info[79] = 0; 2638 (void) fct_port_shutdown(qlt->qlt_port, 2639 STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET | 2640 STMF_RFLAG_COLLECT_DEBUG_DUMP, info); 2641 } 2642 2643 /* First check for high performance path */ 2644 intr_type = risc_status & 0xff; 2645 if (intr_type == 0x1D) { 2646 qlt->atio_ndx_from_fw = (uint16_t) 2647 REG_RD32(qlt, REG_ATIO_IN_PTR); 2648 REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR)); 2649 qlt->resp_ndx_from_fw = risc_status >> 16; 2650 qlt_handle_atio_queue_update(qlt); 2651 qlt_handle_resp_queue_update(qlt); 2652 } else if (intr_type == 0x1C) { 2653 REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR)); 2654 qlt->atio_ndx_from_fw = (uint16_t)(risc_status >> 16); 2655 qlt_handle_atio_queue_update(qlt); 2656 } else if (intr_type == 0x13) { 2657 REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR)); 2658 qlt->resp_ndx_from_fw = risc_status >> 16; 2659 qlt_handle_resp_queue_update(qlt); 2660 } else if (intr_type == 0x12) { 2661 uint16_t code = (uint16_t)(risc_status >> 16); 2662 uint16_t mbox1 = REG_RD16(qlt, REG_MBOX(1)); 2663 uint16_t mbox2 = REG_RD16(qlt, REG_MBOX(2)); 2664 uint16_t mbox3 = REG_RD16(qlt, REG_MBOX(3)); 2665 uint16_t mbox4 = REG_RD16(qlt, REG_MBOX(4)); 2666 uint16_t mbox5 = REG_RD16(qlt, REG_MBOX(5)); 2667 uint16_t mbox6 = REG_RD16(qlt, REG_MBOX(6)); 2668 2669 REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR)); 2670 stmf_trace(qlt->qlt_port_alias, "Async event %x mb1=%x mb2=%x," 2671 " mb3=%x, mb5=%x, mb6=%x", code, mbox1, mbox2, mbox3, 2672 mbox5, mbox6); 2673 EL(qlt, "Async event %x mb1=%x mb2=%x, mb3=%x, mb5=%x, mb6=%x", 2674 code, mbox1, mbox2, mbox3, mbox5, mbox6); 2675 2676 if ((code == 0x8030) || (code == 0x8010) || (code == 0x8013)) { 2677 if (qlt->qlt_link_up) { 2678 fct_handle_event(qlt->qlt_port, 2679 FCT_EVENT_LINK_RESET, 0, 0); 2680 } 2681 } else if (code == 0x8012) { 2682 qlt->qlt_link_up = 0; 2683 fct_handle_event(qlt->qlt_port, FCT_EVENT_LINK_DOWN, 2684 0, 0); 2685 } else if (code == 0x8011) { 2686 switch (mbox1) { 2687 case 0: qlt->link_speed = PORT_SPEED_1G; 2688 break; 2689 case 1: qlt->link_speed = PORT_SPEED_2G; 2690 break; 2691 case 3: qlt->link_speed = PORT_SPEED_4G; 2692 break; 2693 case 4: qlt->link_speed = PORT_SPEED_8G; 2694 break; 2695 case 0x13: qlt->link_speed = PORT_SPEED_10G; 2696 break; 2697 default: 2698 qlt->link_speed = PORT_SPEED_UNKNOWN; 2699 } 2700 qlt->qlt_link_up = 1; 2701 fct_handle_event(qlt->qlt_port, FCT_EVENT_LINK_UP, 2702 0, 0); 2703 } else if ((code == 0x8002) || (code == 0x8003) || 2704 (code == 0x8004) || (code == 0x8005)) { 2705 (void) snprintf(info, 80, 2706 "Got %04x, mb1=%x mb2=%x mb5=%x mb6=%x", 2707 code, mbox1, mbox2, mbox5, mbox6); 2708 info[79] = 0; 2709 (void) fct_port_shutdown(qlt->qlt_port, 2710 STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET | 2711 STMF_RFLAG_COLLECT_DEBUG_DUMP, info); 2712 } else if (code == 0x800F) { 2713 (void) snprintf(info, 80, 2714 "Got 800F, mb1=%x mb2=%x mb3=%x", 2715 mbox1, mbox2, mbox3); 2716 2717 if (mbox1 != 1) { 2718 /* issue "verify fw" */ 2719 qlt_verify_fw(qlt); 2720 } 2721 } else if (code == 0x8101) { 2722 (void) snprintf(info, 80, 2723 "IDC Req Rcvd:%04x, mb1=%x mb2=%x mb3=%x", 2724 code, mbox1, mbox2, mbox3); 2725 info[79] = 0; 2726 2727 /* check if "ACK" is required (timeout != 0) */ 2728 if (mbox1 & 0x0f00) { 2729 caddr_t req; 2730 2731 /* 2732 * Ack the request (queue work to do it?) 2733 * using a mailbox iocb 2734 */ 2735 mutex_enter(&qlt->req_lock); 2736 req = qlt_get_req_entries(qlt, 1); 2737 if (req) { 2738 bzero(req, IOCB_SIZE); 2739 req[0] = 0x39; req[1] = 1; 2740 QMEM_WR16(qlt, req+8, 0x101); 2741 QMEM_WR16(qlt, req+10, mbox1); 2742 QMEM_WR16(qlt, req+12, mbox2); 2743 QMEM_WR16(qlt, req+14, mbox3); 2744 QMEM_WR16(qlt, req+16, mbox4); 2745 QMEM_WR16(qlt, req+18, mbox5); 2746 QMEM_WR16(qlt, req+20, mbox6); 2747 qlt_submit_req_entries(qlt, 1); 2748 } else { 2749 (void) snprintf(info, 80, 2750 "IDC ACK failed"); 2751 info[79] = 0; 2752 } 2753 mutex_exit(&qlt->req_lock); 2754 } 2755 } 2756 } else if ((intr_type == 0x10) || (intr_type == 0x11)) { 2757 /* Handle mailbox completion */ 2758 mutex_enter(&qlt->mbox_lock); 2759 if (qlt->mbox_io_state != MBOX_STATE_CMD_RUNNING) { 2760 cmn_err(CE_WARN, "qlt(%d): mailbox completion received" 2761 " when driver wasn't waiting for it %d", 2762 qlt->instance, qlt->mbox_io_state); 2763 } else { 2764 for (i = 0; i < MAX_MBOXES; i++) { 2765 if (qlt->mcp->from_fw_mask & 2766 (((uint32_t)1) << i)) { 2767 qlt->mcp->from_fw[i] = 2768 REG_RD16(qlt, REG_MBOX(i)); 2769 } 2770 } 2771 qlt->mbox_io_state = MBOX_STATE_CMD_DONE; 2772 } 2773 REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR)); 2774 cv_broadcast(&qlt->mbox_cv); 2775 mutex_exit(&qlt->mbox_lock); 2776 } else { 2777 cmn_err(CE_WARN, "qlt(%d): Unknown intr type 0x%x", 2778 qlt->instance, intr_type); 2779 REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR)); 2780 } 2781 2782 (void) REG_RD32(qlt, REG_HCCR); /* PCI Posting */ 2783 risc_status = REG_RD32(qlt, REG_RISC_STATUS); 2784 if ((risc_status & BIT_15) && 2785 (++intr_loop_count < QLT_MAX_ITERATIONS_PER_INTR)) { 2786 goto intr_again; 2787 } 2788 2789 REG_WR32(qlt, REG_INTR_CTRL, ENABLE_RISC_INTR); 2790 2791 mutex_exit(&qlt->intr_lock); 2792 return (DDI_INTR_CLAIMED); 2793 } 2794 2795 /* **************** NVRAM Functions ********************** */ 2796 2797 fct_status_t 2798 qlt_read_flash_word(qlt_state_t *qlt, uint32_t faddr, uint32_t *bp) 2799 { 2800 uint32_t timer; 2801 2802 /* Clear access error flag */ 2803 REG_WR32(qlt, REG_CTRL_STATUS, 2804 REG_RD32(qlt, REG_CTRL_STATUS) | FLASH_ERROR); 2805 2806 REG_WR32(qlt, REG_FLASH_ADDR, faddr & ~BIT_31); 2807 2808 /* Wait for READ cycle to complete. */ 2809 for (timer = 3000; timer; timer--) { 2810 if (REG_RD32(qlt, REG_FLASH_ADDR) & BIT_31) { 2811 break; 2812 } 2813 drv_usecwait(10); 2814 } 2815 if (timer == 0) { 2816 EL(qlt, "flash timeout\n"); 2817 return (QLT_FLASH_TIMEOUT); 2818 } else if (REG_RD32(qlt, REG_CTRL_STATUS) & FLASH_ERROR) { 2819 EL(qlt, "flash access error\n"); 2820 return (QLT_FLASH_ACCESS_ERROR); 2821 } 2822 2823 *bp = REG_RD32(qlt, REG_FLASH_DATA); 2824 2825 return (QLT_SUCCESS); 2826 } 2827 2828 fct_status_t 2829 qlt_read_nvram(qlt_state_t *qlt) 2830 { 2831 uint32_t index, addr, chksum; 2832 uint32_t val, *ptr; 2833 fct_status_t ret; 2834 qlt_nvram_t *nv; 2835 uint64_t empty_node_name = 0; 2836 2837 if (qlt->qlt_81xx_chip) { 2838 addr = REG_RD32(qlt, REG_CTRL_STATUS) & BIT_12 ? 2839 QLT81_NVRAM_FUNC1_ADDR : QLT81_NVRAM_FUNC0_ADDR; 2840 } else if (qlt->qlt_25xx_chip) { 2841 addr = REG_RD32(qlt, REG_CTRL_STATUS) & FUNCTION_NUMBER ? 2842 QLT25_NVRAM_FUNC1_ADDR : QLT25_NVRAM_FUNC0_ADDR; 2843 } else { 2844 addr = REG_RD32(qlt, REG_CTRL_STATUS) & FUNCTION_NUMBER ? 2845 NVRAM_FUNC1_ADDR : NVRAM_FUNC0_ADDR; 2846 } 2847 mutex_enter(&qlt_global_lock); 2848 2849 /* Pause RISC. */ 2850 REG_WR32(qlt, REG_HCCR, HCCR_CMD(SET_RISC_PAUSE)); 2851 (void) REG_RD32(qlt, REG_HCCR); /* PCI Posting. */ 2852 2853 /* Get NVRAM data and calculate checksum. */ 2854 ptr = (uint32_t *)qlt->nvram; 2855 chksum = 0; 2856 for (index = 0; index < sizeof (qlt_nvram_t) / 4; index++) { 2857 ret = qlt_read_flash_word(qlt, addr++, &val); 2858 if (ret != QLT_SUCCESS) { 2859 EL(qlt, "qlt_read_flash_word, status=%llxh\n", ret); 2860 mutex_exit(&qlt_global_lock); 2861 return (ret); 2862 } 2863 chksum += val; 2864 *ptr = LE_32(val); 2865 ptr++; 2866 } 2867 2868 /* Release RISC Pause */ 2869 REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_PAUSE)); 2870 (void) REG_RD32(qlt, REG_HCCR); /* PCI Posting. */ 2871 2872 mutex_exit(&qlt_global_lock); 2873 2874 /* Sanity check NVRAM Data */ 2875 nv = qlt->nvram; 2876 if (chksum || nv->id[0] != 'I' || nv->id[1] != 'S' || 2877 nv->id[2] != 'P' || nv->id[3] != ' ' || 2878 (nv->nvram_version[0] | nv->nvram_version[1]) == 0) { 2879 EL(qlt, "chksum=%xh, id=%c%c%c%c, ver=%02d%02d\n", chksum, 2880 nv->id[0], nv->id[1], nv->id[2], nv->id[3], 2881 nv->nvram_version[1], nv->nvram_version[0]); 2882 return (QLT_BAD_NVRAM_DATA); 2883 } 2884 2885 /* If node name is zero, hand craft it from port name */ 2886 if (bcmp(nv->node_name, &empty_node_name, 8) == 0) { 2887 bcopy(nv->port_name, nv->node_name, 8); 2888 nv->node_name[0] = (uint8_t)(nv->node_name[0] & ~BIT_0); 2889 nv->port_name[0] = (uint8_t)(nv->node_name[0] | BIT_0); 2890 } 2891 2892 return (QLT_SUCCESS); 2893 } 2894 2895 uint32_t 2896 qlt_sync_atio_queue(qlt_state_t *qlt) 2897 { 2898 uint32_t total_ent; 2899 2900 if (qlt->atio_ndx_from_fw > qlt->atio_ndx_to_fw) { 2901 total_ent = qlt->atio_ndx_from_fw - qlt->atio_ndx_to_fw; 2902 (void) ddi_dma_sync(qlt->queue_mem_dma_handle, ATIO_QUEUE_OFFSET 2903 + (qlt->atio_ndx_to_fw << 6), total_ent << 6, 2904 DDI_DMA_SYNC_FORCPU); 2905 } else { 2906 total_ent = ATIO_QUEUE_ENTRIES - qlt->atio_ndx_to_fw + 2907 qlt->atio_ndx_from_fw; 2908 (void) ddi_dma_sync(qlt->queue_mem_dma_handle, ATIO_QUEUE_OFFSET 2909 + (qlt->atio_ndx_to_fw << 6), (uint_t)(ATIO_QUEUE_ENTRIES - 2910 qlt->atio_ndx_to_fw) << 6, DDI_DMA_SYNC_FORCPU); 2911 (void) ddi_dma_sync(qlt->queue_mem_dma_handle, 2912 ATIO_QUEUE_OFFSET, (uint_t)(qlt->atio_ndx_from_fw << 6), 2913 DDI_DMA_SYNC_FORCPU); 2914 } 2915 return (total_ent); 2916 } 2917 2918 void 2919 qlt_handle_atio_queue_update(qlt_state_t *qlt) 2920 { 2921 uint32_t total_ent; 2922 2923 if (qlt->atio_ndx_to_fw == qlt->atio_ndx_from_fw) 2924 return; 2925 2926 total_ent = qlt_sync_atio_queue(qlt); 2927 2928 do { 2929 uint8_t *atio = (uint8_t *)&qlt->atio_ptr[ 2930 qlt->atio_ndx_to_fw << 6]; 2931 uint32_t ent_cnt; 2932 2933 ent_cnt = (uint32_t)(atio[1]); 2934 if (ent_cnt > total_ent) { 2935 break; 2936 } 2937 switch ((uint8_t)(atio[0])) { 2938 case 0x0d: /* INOT */ 2939 qlt_handle_inot(qlt, atio); 2940 break; 2941 case 0x06: /* ATIO */ 2942 qlt_handle_atio(qlt, atio); 2943 break; 2944 default: 2945 EL(qlt, "atio_queue_update atio[0]=%xh\n", atio[0]); 2946 cmn_err(CE_WARN, "qlt_handle_atio_queue_update: " 2947 "atio[0] is %x, qlt-%p", atio[0], (void *)qlt); 2948 break; 2949 } 2950 qlt->atio_ndx_to_fw = (uint16_t)( 2951 (qlt->atio_ndx_to_fw + ent_cnt) & (ATIO_QUEUE_ENTRIES - 1)); 2952 total_ent -= ent_cnt; 2953 } while (total_ent > 0); 2954 REG_WR32(qlt, REG_ATIO_OUT_PTR, qlt->atio_ndx_to_fw); 2955 } 2956 2957 uint32_t 2958 qlt_sync_resp_queue(qlt_state_t *qlt) 2959 { 2960 uint32_t total_ent; 2961 2962 if (qlt->resp_ndx_from_fw > qlt->resp_ndx_to_fw) { 2963 total_ent = qlt->resp_ndx_from_fw - qlt->resp_ndx_to_fw; 2964 (void) ddi_dma_sync(qlt->queue_mem_dma_handle, 2965 RESPONSE_QUEUE_OFFSET 2966 + (qlt->resp_ndx_to_fw << 6), total_ent << 6, 2967 DDI_DMA_SYNC_FORCPU); 2968 } else { 2969 total_ent = RESPONSE_QUEUE_ENTRIES - qlt->resp_ndx_to_fw + 2970 qlt->resp_ndx_from_fw; 2971 (void) ddi_dma_sync(qlt->queue_mem_dma_handle, 2972 RESPONSE_QUEUE_OFFSET 2973 + (qlt->resp_ndx_to_fw << 6), (RESPONSE_QUEUE_ENTRIES - 2974 qlt->resp_ndx_to_fw) << 6, DDI_DMA_SYNC_FORCPU); 2975 (void) ddi_dma_sync(qlt->queue_mem_dma_handle, 2976 RESPONSE_QUEUE_OFFSET, 2977 qlt->resp_ndx_from_fw << 6, DDI_DMA_SYNC_FORCPU); 2978 } 2979 return (total_ent); 2980 } 2981 2982 void 2983 qlt_handle_resp_queue_update(qlt_state_t *qlt) 2984 { 2985 uint32_t total_ent; 2986 uint8_t c; 2987 2988 if (qlt->resp_ndx_to_fw == qlt->resp_ndx_from_fw) 2989 return; 2990 2991 total_ent = qlt_sync_resp_queue(qlt); 2992 2993 do { 2994 caddr_t resp = &qlt->resp_ptr[qlt->resp_ndx_to_fw << 6]; 2995 uint32_t ent_cnt; 2996 2997 ent_cnt = (uint32_t)(resp[1]); 2998 if (ent_cnt > total_ent) { 2999 break; 3000 } 3001 switch ((uint8_t)(resp[0])) { 3002 case 0x12: /* CTIO completion */ 3003 qlt_handle_ctio_completion(qlt, (uint8_t *)resp); 3004 break; 3005 case 0x0e: /* NACK */ 3006 /* Do Nothing */ 3007 break; 3008 case 0x1b: /* Verify FW */ 3009 qlt_handle_verify_fw_completion(qlt, (uint8_t *)resp); 3010 break; 3011 case 0x29: /* CT PassThrough */ 3012 qlt_handle_ct_completion(qlt, (uint8_t *)resp); 3013 break; 3014 case 0x33: /* Abort IO IOCB completion */ 3015 qlt_handle_sol_abort_completion(qlt, (uint8_t *)resp); 3016 break; 3017 case 0x51: /* PUREX */ 3018 qlt_handle_purex(qlt, (uint8_t *)resp); 3019 break; 3020 case 0x52: 3021 qlt_handle_dereg_completion(qlt, (uint8_t *)resp); 3022 break; 3023 case 0x53: /* ELS passthrough */ 3024 c = (uint8_t)(((uint8_t)resp[0x1f]) >> 5); 3025 if (c == 0) { 3026 qlt_handle_sol_els_completion(qlt, 3027 (uint8_t *)resp); 3028 } else if (c == 3) { 3029 qlt_handle_unsol_els_abort_completion(qlt, 3030 (uint8_t *)resp); 3031 } else { 3032 qlt_handle_unsol_els_completion(qlt, 3033 (uint8_t *)resp); 3034 } 3035 break; 3036 case 0x54: /* ABTS received */ 3037 qlt_handle_rcvd_abts(qlt, (uint8_t *)resp); 3038 break; 3039 case 0x55: /* ABTS completion */ 3040 qlt_handle_abts_completion(qlt, (uint8_t *)resp); 3041 break; 3042 default: 3043 EL(qlt, "response entry=%xh\n", resp[0]); 3044 break; 3045 } 3046 qlt->resp_ndx_to_fw = (qlt->resp_ndx_to_fw + ent_cnt) & 3047 (RESPONSE_QUEUE_ENTRIES - 1); 3048 total_ent -= ent_cnt; 3049 } while (total_ent > 0); 3050 REG_WR32(qlt, REG_RESP_OUT_PTR, qlt->resp_ndx_to_fw); 3051 } 3052 3053 fct_status_t 3054 qlt_portid_to_handle(qlt_state_t *qlt, uint32_t id, uint16_t cmd_handle, 3055 uint16_t *ret_handle) 3056 { 3057 fct_status_t ret; 3058 mbox_cmd_t *mcp; 3059 uint16_t n; 3060 uint16_t h; 3061 uint32_t ent_id; 3062 uint8_t *p; 3063 int found = 0; 3064 3065 mcp = qlt_alloc_mailbox_command(qlt, 2048 * 8); 3066 if (mcp == NULL) { 3067 return (STMF_ALLOC_FAILURE); 3068 } 3069 mcp->to_fw[0] = MBC_GET_ID_LIST; 3070 mcp->to_fw[8] = 2048 * 8; 3071 mcp->to_fw[9] = 0; 3072 mcp->to_fw_mask |= BIT_9 | BIT_8; 3073 mcp->from_fw_mask |= BIT_1 | BIT_2; 3074 3075 ret = qlt_mailbox_command(qlt, mcp); 3076 if (ret != QLT_SUCCESS) { 3077 EL(qlt, "qlt_mailbox_command=7Ch status=%llxh\n", ret); 3078 cmn_err(CE_WARN, "GET ID list failed, ret = %llx, mb0=%x, " 3079 "mb1=%x, mb2=%x", (long long)ret, mcp->from_fw[0], 3080 mcp->from_fw[1], mcp->from_fw[2]); 3081 qlt_free_mailbox_command(qlt, mcp); 3082 return (ret); 3083 } 3084 qlt_dmem_dma_sync(mcp->dbuf, DDI_DMA_SYNC_FORCPU); 3085 p = mcp->dbuf->db_sglist[0].seg_addr; 3086 for (n = 0; n < mcp->from_fw[1]; n++) { 3087 ent_id = LE_32(*((uint32_t *)p)) & 0xFFFFFF; 3088 h = (uint16_t)((uint16_t)p[4] | (((uint16_t)p[5]) << 8)); 3089 if (ent_id == id) { 3090 found = 1; 3091 *ret_handle = h; 3092 if ((cmd_handle != FCT_HANDLE_NONE) && 3093 (cmd_handle != h)) { 3094 cmn_err(CE_WARN, "login for portid %x came in " 3095 "with handle %x, while the portid was " 3096 "already using a different handle %x", 3097 id, cmd_handle, h); 3098 qlt_free_mailbox_command(qlt, mcp); 3099 return (QLT_FAILURE); 3100 } 3101 break; 3102 } 3103 if ((cmd_handle != FCT_HANDLE_NONE) && (h == cmd_handle)) { 3104 cmn_err(CE_WARN, "login for portid %x came in with " 3105 "handle %x, while the handle was already in use " 3106 "for portid %x", id, cmd_handle, ent_id); 3107 qlt_free_mailbox_command(qlt, mcp); 3108 return (QLT_FAILURE); 3109 } 3110 p += 8; 3111 } 3112 if (!found) { 3113 *ret_handle = cmd_handle; 3114 } 3115 qlt_free_mailbox_command(qlt, mcp); 3116 return (FCT_SUCCESS); 3117 } 3118 3119 /* ARGSUSED */ 3120 fct_status_t 3121 qlt_fill_plogi_req(fct_local_port_t *port, fct_remote_port_t *rp, 3122 fct_cmd_t *login) 3123 { 3124 uint8_t *p; 3125 3126 p = ((fct_els_t *)login->cmd_specific)->els_req_payload; 3127 p[0] = ELS_OP_PLOGI; 3128 *((uint16_t *)(&p[4])) = 0x2020; 3129 p[7] = 3; 3130 p[8] = 0x88; 3131 p[10] = 8; 3132 p[13] = 0xff; p[15] = 0x1f; 3133 p[18] = 7; p[19] = 0xd0; 3134 3135 bcopy(port->port_pwwn, p + 20, 8); 3136 bcopy(port->port_nwwn, p + 28, 8); 3137 3138 p[68] = 0x80; 3139 p[74] = 8; 3140 p[77] = 0xff; 3141 p[81] = 1; 3142 3143 return (FCT_SUCCESS); 3144 } 3145 3146 /* ARGSUSED */ 3147 fct_status_t 3148 qlt_fill_plogi_resp(fct_local_port_t *port, fct_remote_port_t *rp, 3149 fct_cmd_t *login) 3150 { 3151 return (FCT_SUCCESS); 3152 } 3153 3154 fct_status_t 3155 qlt_register_remote_port(fct_local_port_t *port, fct_remote_port_t *rp, 3156 fct_cmd_t *login) 3157 { 3158 uint16_t h; 3159 fct_status_t ret; 3160 qlt_state_t *qlt = (qlt_state_t *)port->port_fca_private; 3161 3162 switch (rp->rp_id) { 3163 case 0xFFFFFC: h = 0x7FC; break; 3164 case 0xFFFFFD: h = 0x7FD; break; 3165 case 0xFFFFFE: h = 0x7FE; break; 3166 case 0xFFFFFF: h = 0x7FF; break; 3167 default: 3168 ret = qlt_portid_to_handle(qlt, rp->rp_id, 3169 login->cmd_rp_handle, &h); 3170 if (ret != FCT_SUCCESS) { 3171 EL(qlt, "qlt_portid_to_handle, status=%llxh\n", ret); 3172 return (ret); 3173 } 3174 } 3175 3176 if (login->cmd_type == FCT_CMD_SOL_ELS) { 3177 ret = qlt_fill_plogi_req(port, rp, login); 3178 } else { 3179 ret = qlt_fill_plogi_resp(port, rp, login); 3180 } 3181 3182 if (ret != FCT_SUCCESS) { 3183 EL(qlt, "qlt_fill_plogi, status=%llxh\n", ret); 3184 return (ret); 3185 } 3186 3187 if (h == FCT_HANDLE_NONE) 3188 return (FCT_SUCCESS); 3189 3190 if (rp->rp_handle == FCT_HANDLE_NONE) { 3191 rp->rp_handle = h; 3192 return (FCT_SUCCESS); 3193 } 3194 3195 if (rp->rp_handle == h) 3196 return (FCT_SUCCESS); 3197 3198 EL(qlt, "rp_handle=%xh != h=%xh\n", rp->rp_handle, h); 3199 return (FCT_FAILURE); 3200 } 3201 /* invoked in single thread */ 3202 fct_status_t 3203 qlt_deregister_remote_port(fct_local_port_t *port, fct_remote_port_t *rp) 3204 { 3205 uint8_t *req; 3206 qlt_state_t *qlt; 3207 clock_t dereg_req_timer; 3208 fct_status_t ret; 3209 3210 qlt = (qlt_state_t *)port->port_fca_private; 3211 3212 if ((qlt->qlt_state == FCT_STATE_OFFLINE) || 3213 (qlt->qlt_state == FCT_STATE_OFFLINING)) 3214 return (FCT_SUCCESS); 3215 ASSERT(qlt->rp_id_in_dereg == 0); 3216 3217 mutex_enter(&qlt->preq_lock); 3218 req = (uint8_t *)qlt_get_preq_entries(qlt, 1); 3219 if (req == NULL) { 3220 mutex_exit(&qlt->preq_lock); 3221 return (FCT_BUSY); 3222 } 3223 bzero(req, IOCB_SIZE); 3224 req[0] = 0x52; req[1] = 1; 3225 /* QMEM_WR32(qlt, (&req[4]), 0xffffffff); */ 3226 QMEM_WR16(qlt, (&req[0xA]), rp->rp_handle); 3227 QMEM_WR16(qlt, (&req[0xC]), 0x98); /* implicit logo */ 3228 QMEM_WR32(qlt, (&req[0x10]), rp->rp_id); 3229 qlt->rp_id_in_dereg = rp->rp_id; 3230 qlt_submit_preq_entries(qlt, 1); 3231 3232 dereg_req_timer = ddi_get_lbolt() + drv_usectohz(DEREG_RP_TIMEOUT); 3233 if (cv_timedwait(&qlt->rp_dereg_cv, 3234 &qlt->preq_lock, dereg_req_timer) > 0) { 3235 ret = qlt->rp_dereg_status; 3236 } else { 3237 ret = FCT_BUSY; 3238 } 3239 qlt->rp_dereg_status = 0; 3240 qlt->rp_id_in_dereg = 0; 3241 mutex_exit(&qlt->preq_lock); 3242 return (ret); 3243 } 3244 3245 /* 3246 * Pass received ELS up to framework. 3247 */ 3248 static void 3249 qlt_handle_purex(qlt_state_t *qlt, uint8_t *resp) 3250 { 3251 fct_cmd_t *cmd; 3252 fct_els_t *els; 3253 qlt_cmd_t *qcmd; 3254 uint32_t payload_size; 3255 uint32_t remote_portid; 3256 uint8_t *pldptr, *bndrptr; 3257 int i, off; 3258 uint16_t iocb_flags; 3259 char info[160]; 3260 3261 remote_portid = ((uint32_t)(QMEM_RD16(qlt, (&resp[0x18])))) | 3262 ((uint32_t)(resp[0x1A])) << 16; 3263 iocb_flags = QMEM_RD16(qlt, (&resp[8])); 3264 if (iocb_flags & BIT_15) { 3265 payload_size = (QMEM_RD16(qlt, (&resp[0x0e])) & 0xfff) - 24; 3266 } else { 3267 payload_size = QMEM_RD16(qlt, (&resp[0x0c])) - 24; 3268 } 3269 3270 if (payload_size > ((uint32_t)resp[1] * IOCB_SIZE - 0x2C)) { 3271 EL(qlt, "payload is too large = %xh\n", payload_size); 3272 cmn_err(CE_WARN, "handle_purex: payload is too large"); 3273 goto cmd_null; 3274 } 3275 3276 cmd = (fct_cmd_t *)fct_alloc(FCT_STRUCT_CMD_RCVD_ELS, 3277 (int)(payload_size + GET_STRUCT_SIZE(qlt_cmd_t)), 0); 3278 if (cmd == NULL) { 3279 EL(qlt, "fct_alloc cmd==NULL\n"); 3280 cmd_null:; 3281 (void) snprintf(info, 160, "qlt_handle_purex: qlt-%p, can't " 3282 "allocate space for fct_cmd", (void *)qlt); 3283 info[159] = 0; 3284 (void) fct_port_shutdown(qlt->qlt_port, 3285 STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info); 3286 return; 3287 } 3288 3289 cmd->cmd_port = qlt->qlt_port; 3290 cmd->cmd_rp_handle = QMEM_RD16(qlt, resp+0xa); 3291 if (cmd->cmd_rp_handle == 0xFFFF) { 3292 cmd->cmd_rp_handle = FCT_HANDLE_NONE; 3293 } 3294 3295 els = (fct_els_t *)cmd->cmd_specific; 3296 qcmd = (qlt_cmd_t *)cmd->cmd_fca_private; 3297 els->els_req_size = (uint16_t)payload_size; 3298 els->els_req_payload = GET_BYTE_OFFSET(qcmd, 3299 GET_STRUCT_SIZE(qlt_cmd_t)); 3300 qcmd->fw_xchg_addr = QMEM_RD32(qlt, (&resp[0x10])); 3301 cmd->cmd_rportid = remote_portid; 3302 cmd->cmd_lportid = ((uint32_t)(QMEM_RD16(qlt, (&resp[0x14])))) | 3303 ((uint32_t)(resp[0x16])) << 16; 3304 cmd->cmd_oxid = QMEM_RD16(qlt, (&resp[0x26])); 3305 cmd->cmd_rxid = QMEM_RD16(qlt, (&resp[0x24])); 3306 pldptr = &resp[0x2C]; 3307 bndrptr = (uint8_t *)(qlt->resp_ptr + (RESPONSE_QUEUE_ENTRIES << 6)); 3308 for (i = 0, off = 0x2c; i < payload_size; i += 4) { 3309 /* Take care of fw's swapping of payload */ 3310 els->els_req_payload[i] = pldptr[3]; 3311 els->els_req_payload[i+1] = pldptr[2]; 3312 els->els_req_payload[i+2] = pldptr[1]; 3313 els->els_req_payload[i+3] = pldptr[0]; 3314 pldptr += 4; 3315 if (pldptr == bndrptr) 3316 pldptr = (uint8_t *)qlt->resp_ptr; 3317 off += 4; 3318 if (off >= IOCB_SIZE) { 3319 off = 4; 3320 pldptr += 4; 3321 } 3322 } 3323 fct_post_rcvd_cmd(cmd, 0); 3324 } 3325 3326 fct_status_t 3327 qlt_send_cmd_response(fct_cmd_t *cmd, uint32_t ioflags) 3328 { 3329 qlt_state_t *qlt; 3330 char info[160]; 3331 3332 qlt = (qlt_state_t *)cmd->cmd_port->port_fca_private; 3333 3334 if (cmd->cmd_type == FCT_CMD_FCP_XCHG) { 3335 if (ioflags & FCT_IOF_FORCE_FCA_DONE) { 3336 EL(qlt, "ioflags = %xh\n", ioflags); 3337 goto fatal_panic; 3338 } else { 3339 return (qlt_send_status(qlt, cmd)); 3340 } 3341 } 3342 3343 if (cmd->cmd_type == FCT_CMD_RCVD_ELS) { 3344 if (ioflags & FCT_IOF_FORCE_FCA_DONE) { 3345 goto fatal_panic; 3346 } else { 3347 return (qlt_send_els_response(qlt, cmd)); 3348 } 3349 } 3350 3351 if (ioflags & FCT_IOF_FORCE_FCA_DONE) { 3352 cmd->cmd_handle = 0; 3353 } 3354 3355 if (cmd->cmd_type == FCT_CMD_RCVD_ABTS) { 3356 return (qlt_send_abts_response(qlt, cmd, 0)); 3357 } else { 3358 EL(qlt, "cmd->cmd_type=%xh\n", cmd->cmd_type); 3359 ASSERT(0); 3360 return (FCT_FAILURE); 3361 } 3362 3363 fatal_panic:; 3364 (void) snprintf(info, 160, "qlt_send_cmd_response: can not handle " 3365 "FCT_IOF_FORCE_FCA_DONE for cmd %p, ioflags-%x", (void *)cmd, 3366 ioflags); 3367 info[159] = 0; 3368 (void) fct_port_shutdown(qlt->qlt_port, 3369 STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info); 3370 return (FCT_FAILURE); 3371 } 3372 3373 /* ARGSUSED */ 3374 fct_status_t 3375 qlt_xfer_scsi_data(fct_cmd_t *cmd, stmf_data_buf_t *dbuf, uint32_t ioflags) 3376 { 3377 qlt_dmem_bctl_t *bctl = (qlt_dmem_bctl_t *)dbuf->db_port_private; 3378 qlt_state_t *qlt = (qlt_state_t *)cmd->cmd_port->port_fca_private; 3379 qlt_cmd_t *qcmd = (qlt_cmd_t *)cmd->cmd_fca_private; 3380 uint8_t *req; 3381 uint16_t flags; 3382 3383 if (dbuf->db_handle == 0) 3384 qcmd->dbuf = dbuf; 3385 flags = (uint16_t)(((uint16_t)qcmd->param.atio_byte3 & 0xf0) << 5); 3386 if (dbuf->db_flags & DB_DIRECTION_TO_RPORT) { 3387 flags = (uint16_t)(flags | 2); 3388 qlt_dmem_dma_sync(dbuf, DDI_DMA_SYNC_FORDEV); 3389 } else { 3390 flags = (uint16_t)(flags | 1); 3391 } 3392 3393 if (dbuf->db_flags & DB_SEND_STATUS_GOOD) 3394 flags = (uint16_t)(flags | BIT_15); 3395 3396 mutex_enter(&qlt->req_lock); 3397 req = (uint8_t *)qlt_get_req_entries(qlt, 1); 3398 if (req == NULL) { 3399 mutex_exit(&qlt->req_lock); 3400 return (FCT_BUSY); 3401 } 3402 bzero(req, IOCB_SIZE); 3403 req[0] = 0x12; req[1] = 0x1; 3404 req[2] = dbuf->db_handle; 3405 QMEM_WR32(qlt, req+4, cmd->cmd_handle); 3406 QMEM_WR16(qlt, req+8, cmd->cmd_rp->rp_handle); 3407 QMEM_WR16(qlt, req+10, 60); /* 60 seconds timeout */ 3408 req[12] = 1; 3409 QMEM_WR32(qlt, req+0x10, cmd->cmd_rportid); 3410 QMEM_WR32(qlt, req+0x14, qcmd->fw_xchg_addr); 3411 QMEM_WR16(qlt, req+0x1A, flags); 3412 QMEM_WR16(qlt, req+0x20, cmd->cmd_oxid); 3413 QMEM_WR32(qlt, req+0x24, dbuf->db_relative_offset); 3414 QMEM_WR32(qlt, req+0x2C, dbuf->db_data_size); 3415 QMEM_WR64(qlt, req+0x34, bctl->bctl_dev_addr); 3416 QMEM_WR32(qlt, req+0x34+8, dbuf->db_data_size); 3417 qlt_submit_req_entries(qlt, 1); 3418 mutex_exit(&qlt->req_lock); 3419 3420 return (STMF_SUCCESS); 3421 } 3422 3423 /* 3424 * We must construct proper FCP_RSP_IU now. Here we only focus on 3425 * the handling of FCP_SNS_INFO. If there's protocol failures (FCP_RSP_INFO), 3426 * we could have catched them before we enter here. 3427 */ 3428 fct_status_t 3429 qlt_send_status(qlt_state_t *qlt, fct_cmd_t *cmd) 3430 { 3431 qlt_cmd_t *qcmd = (qlt_cmd_t *)cmd->cmd_fca_private; 3432 scsi_task_t *task = (scsi_task_t *)cmd->cmd_specific; 3433 qlt_dmem_bctl_t *bctl; 3434 uint32_t size; 3435 uint8_t *req, *fcp_rsp_iu; 3436 uint8_t *psd, sensbuf[24]; /* sense data */ 3437 uint16_t flags; 3438 uint16_t scsi_status; 3439 int use_mode2; 3440 int ndx; 3441 3442 /* 3443 * Enter fast channel for non check condition 3444 */ 3445 if (task->task_scsi_status != STATUS_CHECK) { 3446 /* 3447 * We will use mode1 3448 */ 3449 flags = (uint16_t)(BIT_6 | BIT_15 | 3450 (((uint16_t)qcmd->param.atio_byte3 & 0xf0) << 5)); 3451 scsi_status = (uint16_t)task->task_scsi_status; 3452 if (task->task_status_ctrl == TASK_SCTRL_OVER) { 3453 scsi_status = (uint16_t)(scsi_status | BIT_10); 3454 } else if (task->task_status_ctrl == TASK_SCTRL_UNDER) { 3455 scsi_status = (uint16_t)(scsi_status | BIT_11); 3456 } 3457 qcmd->dbuf_rsp_iu = NULL; 3458 3459 /* 3460 * Fillout CTIO type 7 IOCB 3461 */ 3462 mutex_enter(&qlt->req_lock); 3463 req = (uint8_t *)qlt_get_req_entries(qlt, 1); 3464 if (req == NULL) { 3465 mutex_exit(&qlt->req_lock); 3466 return (FCT_BUSY); 3467 } 3468 3469 /* 3470 * Common fields 3471 */ 3472 bzero(req, IOCB_SIZE); 3473 req[0x00] = 0x12; 3474 req[0x01] = 0x1; 3475 req[0x02] = BIT_7; /* indicate if it's a pure status req */ 3476 QMEM_WR32(qlt, req + 0x04, cmd->cmd_handle); 3477 QMEM_WR16(qlt, req + 0x08, cmd->cmd_rp->rp_handle); 3478 QMEM_WR32(qlt, req + 0x10, cmd->cmd_rportid); 3479 QMEM_WR32(qlt, req + 0x14, qcmd->fw_xchg_addr); 3480 3481 /* 3482 * Mode-specific fields 3483 */ 3484 QMEM_WR16(qlt, req + 0x1A, flags); 3485 QMEM_WR32(qlt, req + 0x1C, task->task_resid); 3486 QMEM_WR16(qlt, req + 0x20, cmd->cmd_oxid); 3487 QMEM_WR16(qlt, req + 0x22, scsi_status); 3488 3489 /* 3490 * Trigger FW to send SCSI status out 3491 */ 3492 qlt_submit_req_entries(qlt, 1); 3493 mutex_exit(&qlt->req_lock); 3494 return (STMF_SUCCESS); 3495 } 3496 3497 ASSERT(task->task_scsi_status == STATUS_CHECK); 3498 /* 3499 * Decide the SCSI status mode, that should be used 3500 */ 3501 use_mode2 = (task->task_sense_length > 24); 3502 3503 /* 3504 * Prepare required information per the SCSI status mode 3505 */ 3506 flags = (uint16_t)(BIT_15 | 3507 (((uint16_t)qcmd->param.atio_byte3 & 0xf0) << 5)); 3508 if (use_mode2) { 3509 flags = (uint16_t)(flags | BIT_7); 3510 3511 size = task->task_sense_length; 3512 qcmd->dbuf_rsp_iu = qlt_i_dmem_alloc(qlt, 3513 task->task_sense_length, &size, 0); 3514 if (!qcmd->dbuf_rsp_iu) { 3515 return (FCT_ALLOC_FAILURE); 3516 } 3517 3518 /* 3519 * Start to construct FCP_RSP IU 3520 */ 3521 fcp_rsp_iu = qcmd->dbuf_rsp_iu->db_sglist[0].seg_addr; 3522 bzero(fcp_rsp_iu, 24); 3523 3524 /* 3525 * FCP_RSP IU flags, byte10 3526 */ 3527 fcp_rsp_iu[10] = (uint8_t)(fcp_rsp_iu[10] | BIT_1); 3528 if (task->task_status_ctrl == TASK_SCTRL_OVER) { 3529 fcp_rsp_iu[10] = (uint8_t)(fcp_rsp_iu[10] | BIT_2); 3530 } else if (task->task_status_ctrl == TASK_SCTRL_UNDER) { 3531 fcp_rsp_iu[10] = (uint8_t)(fcp_rsp_iu[10] | BIT_3); 3532 } 3533 3534 /* 3535 * SCSI status code, byte11 3536 */ 3537 fcp_rsp_iu[11] = task->task_scsi_status; 3538 3539 /* 3540 * FCP_RESID (Overrun or underrun) 3541 */ 3542 fcp_rsp_iu[12] = (uint8_t)((task->task_resid >> 24) & 0xFF); 3543 fcp_rsp_iu[13] = (uint8_t)((task->task_resid >> 16) & 0xFF); 3544 fcp_rsp_iu[14] = (uint8_t)((task->task_resid >> 8) & 0xFF); 3545 fcp_rsp_iu[15] = (uint8_t)((task->task_resid >> 0) & 0xFF); 3546 3547 /* 3548 * FCP_SNS_LEN 3549 */ 3550 fcp_rsp_iu[18] = (uint8_t)((task->task_sense_length >> 8) & 3551 0xFF); 3552 fcp_rsp_iu[19] = (uint8_t)((task->task_sense_length >> 0) & 3553 0xFF); 3554 3555 /* 3556 * FCP_RSP_LEN 3557 */ 3558 /* 3559 * no FCP_RSP_INFO 3560 */ 3561 /* 3562 * FCP_SNS_INFO 3563 */ 3564 bcopy(task->task_sense_data, fcp_rsp_iu + 24, 3565 task->task_sense_length); 3566 3567 /* 3568 * Ensure dma data consistency 3569 */ 3570 qlt_dmem_dma_sync(qcmd->dbuf_rsp_iu, DDI_DMA_SYNC_FORDEV); 3571 } else { 3572 flags = (uint16_t)(flags | BIT_6); 3573 3574 scsi_status = (uint16_t)task->task_scsi_status; 3575 if (task->task_status_ctrl == TASK_SCTRL_OVER) { 3576 scsi_status = (uint16_t)(scsi_status | BIT_10); 3577 } else if (task->task_status_ctrl == TASK_SCTRL_UNDER) { 3578 scsi_status = (uint16_t)(scsi_status | BIT_11); 3579 } 3580 if (task->task_sense_length) { 3581 scsi_status = (uint16_t)(scsi_status | BIT_9); 3582 } 3583 bcopy(task->task_sense_data, sensbuf, task->task_sense_length); 3584 qcmd->dbuf_rsp_iu = NULL; 3585 } 3586 3587 /* 3588 * Fillout CTIO type 7 IOCB 3589 */ 3590 mutex_enter(&qlt->req_lock); 3591 req = (uint8_t *)qlt_get_req_entries(qlt, 1); 3592 if (req == NULL) { 3593 mutex_exit(&qlt->req_lock); 3594 if (use_mode2) { 3595 qlt_dmem_free(cmd->cmd_port->port_fds, 3596 qcmd->dbuf_rsp_iu); 3597 qcmd->dbuf_rsp_iu = NULL; 3598 } 3599 return (FCT_BUSY); 3600 } 3601 3602 /* 3603 * Common fields 3604 */ 3605 bzero(req, IOCB_SIZE); 3606 req[0x00] = 0x12; 3607 req[0x01] = 0x1; 3608 req[0x02] = BIT_7; /* to indicate if it's a pure status req */ 3609 QMEM_WR32(qlt, req + 0x04, cmd->cmd_handle); 3610 QMEM_WR16(qlt, req + 0x08, cmd->cmd_rp->rp_handle); 3611 QMEM_WR16(qlt, req + 0x0A, 0); /* not timed by FW */ 3612 if (use_mode2) { 3613 QMEM_WR16(qlt, req+0x0C, 1); /* FCP RSP IU data field */ 3614 } 3615 QMEM_WR32(qlt, req + 0x10, cmd->cmd_rportid); 3616 QMEM_WR32(qlt, req + 0x14, qcmd->fw_xchg_addr); 3617 3618 /* 3619 * Mode-specific fields 3620 */ 3621 if (!use_mode2) { 3622 QMEM_WR16(qlt, req + 0x18, task->task_sense_length); 3623 } 3624 QMEM_WR16(qlt, req + 0x1A, flags); 3625 QMEM_WR32(qlt, req + 0x1C, task->task_resid); 3626 QMEM_WR16(qlt, req + 0x20, cmd->cmd_oxid); 3627 if (use_mode2) { 3628 bctl = (qlt_dmem_bctl_t *)qcmd->dbuf_rsp_iu->db_port_private; 3629 QMEM_WR32(qlt, req + 0x2C, 24 + task->task_sense_length); 3630 QMEM_WR64(qlt, req + 0x34, bctl->bctl_dev_addr); 3631 QMEM_WR32(qlt, req + 0x3C, 24 + task->task_sense_length); 3632 } else { 3633 QMEM_WR16(qlt, req + 0x22, scsi_status); 3634 psd = req+0x28; 3635 3636 /* 3637 * Data in sense buf is always big-endian, data in IOCB 3638 * should always be little-endian, so we must do swapping. 3639 */ 3640 size = ((task->task_sense_length + 3) & (~3)); 3641 for (ndx = 0; ndx < size; ndx += 4) { 3642 psd[ndx + 0] = sensbuf[ndx + 3]; 3643 psd[ndx + 1] = sensbuf[ndx + 2]; 3644 psd[ndx + 2] = sensbuf[ndx + 1]; 3645 psd[ndx + 3] = sensbuf[ndx + 0]; 3646 } 3647 } 3648 3649 /* 3650 * Trigger FW to send SCSI status out 3651 */ 3652 qlt_submit_req_entries(qlt, 1); 3653 mutex_exit(&qlt->req_lock); 3654 3655 return (STMF_SUCCESS); 3656 } 3657 3658 fct_status_t 3659 qlt_send_els_response(qlt_state_t *qlt, fct_cmd_t *cmd) 3660 { 3661 qlt_cmd_t *qcmd; 3662 fct_els_t *els = (fct_els_t *)cmd->cmd_specific; 3663 uint8_t *req, *addr; 3664 qlt_dmem_bctl_t *bctl; 3665 uint32_t minsize; 3666 uint8_t elsop, req1f; 3667 3668 addr = els->els_resp_payload; 3669 qcmd = (qlt_cmd_t *)cmd->cmd_fca_private; 3670 3671 minsize = els->els_resp_size; 3672 qcmd->dbuf = qlt_i_dmem_alloc(qlt, els->els_resp_size, &minsize, 0); 3673 if (qcmd->dbuf == NULL) 3674 return (FCT_BUSY); 3675 3676 bctl = (qlt_dmem_bctl_t *)qcmd->dbuf->db_port_private; 3677 3678 bcopy(addr, qcmd->dbuf->db_sglist[0].seg_addr, els->els_resp_size); 3679 qlt_dmem_dma_sync(qcmd->dbuf, DDI_DMA_SYNC_FORDEV); 3680 3681 if (addr[0] == 0x02) { /* ACC */ 3682 req1f = BIT_5; 3683 } else { 3684 req1f = BIT_6; 3685 } 3686 elsop = els->els_req_payload[0]; 3687 if ((elsop == ELS_OP_PRLI) || (elsop == ELS_OP_PRLO) || 3688 (elsop == ELS_OP_TPRLO) || (elsop == ELS_OP_LOGO)) { 3689 req1f = (uint8_t)(req1f | BIT_4); 3690 } 3691 3692 mutex_enter(&qlt->req_lock); 3693 req = (uint8_t *)qlt_get_req_entries(qlt, 1); 3694 if (req == NULL) { 3695 mutex_exit(&qlt->req_lock); 3696 qlt_dmem_free(NULL, qcmd->dbuf); 3697 qcmd->dbuf = NULL; 3698 return (FCT_BUSY); 3699 } 3700 bzero(req, IOCB_SIZE); 3701 req[0] = 0x53; req[1] = 1; req[0xf] = 0x10; 3702 req[0x16] = elsop; req[0x1f] = req1f; 3703 QMEM_WR32(qlt, (&req[4]), cmd->cmd_handle); 3704 QMEM_WR16(qlt, (&req[0xA]), cmd->cmd_rp->rp_handle); 3705 QMEM_WR16(qlt, (&req[0xC]), 1); 3706 QMEM_WR32(qlt, (&req[0x10]), qcmd->fw_xchg_addr); 3707 QMEM_WR32(qlt, (&req[0x18]), cmd->cmd_rportid); 3708 if (qlt->cur_topology == PORT_TOPOLOGY_PT_TO_PT) { 3709 req[0x1b] = (uint8_t)((cmd->cmd_lportid >> 16) & 0xff); 3710 req[0x1c] = (uint8_t)(cmd->cmd_lportid & 0xff); 3711 req[0x1d] = (uint8_t)((cmd->cmd_lportid >> 8) & 0xff); 3712 } 3713 QMEM_WR32(qlt, (&req[0x24]), els->els_resp_size); 3714 QMEM_WR64(qlt, (&req[0x28]), bctl->bctl_dev_addr); 3715 QMEM_WR32(qlt, (&req[0x30]), els->els_resp_size); 3716 qlt_submit_req_entries(qlt, 1); 3717 mutex_exit(&qlt->req_lock); 3718 3719 return (FCT_SUCCESS); 3720 } 3721 3722 fct_status_t 3723 qlt_send_abts_response(qlt_state_t *qlt, fct_cmd_t *cmd, int terminate) 3724 { 3725 qlt_abts_cmd_t *qcmd; 3726 fct_rcvd_abts_t *abts = (fct_rcvd_abts_t *)cmd->cmd_specific; 3727 uint8_t *req; 3728 uint32_t lportid; 3729 uint32_t fctl; 3730 int i; 3731 3732 qcmd = (qlt_abts_cmd_t *)cmd->cmd_fca_private; 3733 3734 mutex_enter(&qlt->req_lock); 3735 req = (uint8_t *)qlt_get_req_entries(qlt, 1); 3736 if (req == NULL) { 3737 mutex_exit(&qlt->req_lock); 3738 return (FCT_BUSY); 3739 } 3740 bcopy(qcmd->buf, req, IOCB_SIZE); 3741 lportid = QMEM_RD32(qlt, req+0x14) & 0xFFFFFF; 3742 fctl = QMEM_RD32(qlt, req+0x1C); 3743 fctl = ((fctl ^ BIT_23) & ~BIT_22) | (BIT_19 | BIT_16); 3744 req[0] = 0x55; req[1] = 1; req[2] = (uint8_t)terminate; 3745 QMEM_WR32(qlt, (&req[4]), cmd->cmd_handle); 3746 if (cmd->cmd_rp) 3747 QMEM_WR16(qlt, (&req[0xA]), cmd->cmd_rp->rp_handle); 3748 else 3749 QMEM_WR16(qlt, (&req[0xA]), cmd->cmd_rp_handle); 3750 if (terminate) { 3751 QMEM_WR16(qlt, (&req[0xC]), 1); 3752 } 3753 QMEM_WR32(qlt, req+0x14, cmd->cmd_rportid); 3754 req[0x17] = abts->abts_resp_rctl; 3755 QMEM_WR32(qlt, req+0x18, lportid); 3756 QMEM_WR32(qlt, req+0x1C, fctl); 3757 req[0x23]++; 3758 for (i = 0; i < 12; i += 4) { 3759 /* Take care of firmware's LE requirement */ 3760 req[0x2C+i] = abts->abts_resp_payload[i+3]; 3761 req[0x2C+i+1] = abts->abts_resp_payload[i+2]; 3762 req[0x2C+i+2] = abts->abts_resp_payload[i+1]; 3763 req[0x2C+i+3] = abts->abts_resp_payload[i]; 3764 } 3765 qlt_submit_req_entries(qlt, 1); 3766 mutex_exit(&qlt->req_lock); 3767 3768 return (FCT_SUCCESS); 3769 } 3770 3771 static void 3772 qlt_handle_inot(qlt_state_t *qlt, uint8_t *inot) 3773 { 3774 int i; 3775 uint32_t d; 3776 caddr_t req; 3777 /* Just put it on the request queue */ 3778 mutex_enter(&qlt->req_lock); 3779 req = qlt_get_req_entries(qlt, 1); 3780 if (req == NULL) { 3781 mutex_exit(&qlt->req_lock); 3782 /* XXX handle this */ 3783 return; 3784 } 3785 for (i = 0; i < 16; i++) { 3786 d = QMEM_RD32(qlt, inot); 3787 inot += 4; 3788 QMEM_WR32(qlt, req, d); 3789 req += 4; 3790 } 3791 req -= 64; 3792 req[0] = 0x0e; 3793 qlt_submit_req_entries(qlt, 1); 3794 mutex_exit(&qlt->req_lock); 3795 } 3796 3797 uint8_t qlt_task_flags[] = { 1, 3, 2, 1, 4, 0, 1, 1 }; 3798 static void 3799 qlt_handle_atio(qlt_state_t *qlt, uint8_t *atio) 3800 { 3801 fct_cmd_t *cmd; 3802 scsi_task_t *task; 3803 qlt_cmd_t *qcmd; 3804 uint32_t rportid, fw_xchg_addr; 3805 uint8_t *p, *q, *req, tm; 3806 uint16_t cdb_size, flags, oxid; 3807 char info[160]; 3808 3809 /* 3810 * If either bidirection xfer is requested of there is extended 3811 * CDB, atio[0x20 + 11] will be greater than or equal to 3. 3812 */ 3813 cdb_size = 16; 3814 if (atio[0x20 + 11] >= 3) { 3815 uint8_t b = atio[0x20 + 11]; 3816 uint16_t b1; 3817 if ((b & 3) == 3) { 3818 EL(qlt, "bidirectional I/O not supported\n"); 3819 cmn_err(CE_WARN, "qlt(%d) CMD with bidirectional I/O " 3820 "received, dropping the cmd as bidirectional " 3821 " transfers are not yet supported", qlt->instance); 3822 /* XXX abort the I/O */ 3823 return; 3824 } 3825 cdb_size = (uint16_t)(cdb_size + (b & 0xfc)); 3826 /* 3827 * Verify that we have enough entries. Without additional CDB 3828 * Everything will fit nicely within the same 64 bytes. So the 3829 * additional cdb size is essentially the # of additional bytes 3830 * we need. 3831 */ 3832 b1 = (uint16_t)b; 3833 if (((((b1 & 0xfc) + 63) >> 6) + 1) > ((uint16_t)atio[1])) { 3834 EL(qlt, "extended cdb received\n"); 3835 cmn_err(CE_WARN, "qlt(%d): cmd received with extended " 3836 " cdb (cdb size = %d bytes), however the firmware " 3837 " did not DMAed the entire FCP_CMD IU, entry count " 3838 " is %d while it should be %d", qlt->instance, 3839 cdb_size, atio[1], ((((b1 & 0xfc) + 63) >> 6) + 1)); 3840 /* XXX abort the I/O */ 3841 return; 3842 } 3843 } 3844 3845 rportid = (((uint32_t)atio[8 + 5]) << 16) | 3846 (((uint32_t)atio[8 + 6]) << 8) | atio[8+7]; 3847 fw_xchg_addr = QMEM_RD32(qlt, atio+4); 3848 oxid = (uint16_t)((((uint16_t)atio[8 + 16]) << 8) | atio[8+17]); 3849 3850 if (fw_xchg_addr == 0xFFFFFFFF) { 3851 EL(qlt, "fw_xchg_addr==0xFFFFFFFF\n"); 3852 cmd = NULL; 3853 } else { 3854 cmd = fct_scsi_task_alloc(qlt->qlt_port, FCT_HANDLE_NONE, 3855 rportid, atio+0x20, cdb_size, STMF_TASK_EXT_NONE); 3856 if (cmd == NULL) { 3857 EL(qlt, "fct_scsi_task_alloc cmd==NULL\n"); 3858 } 3859 } 3860 if (cmd == NULL) { 3861 EL(qlt, "fct_scsi_task_alloc cmd==NULL\n"); 3862 /* Abort this IO */ 3863 flags = (uint16_t)(BIT_14 | ((atio[3] & 0xF0) << 5)); 3864 3865 mutex_enter(&qlt->req_lock); 3866 req = (uint8_t *)qlt_get_req_entries(qlt, 1); 3867 if (req == NULL) { 3868 mutex_exit(&qlt->req_lock); 3869 3870 (void) snprintf(info, 160, 3871 "qlt_handle_atio: qlt-%p, can't " 3872 "allocate space for scsi_task", (void *)qlt); 3873 info[159] = 0; 3874 (void) fct_port_shutdown(qlt->qlt_port, 3875 STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info); 3876 return; 3877 } 3878 bzero(req, IOCB_SIZE); 3879 req[0] = 0x12; req[1] = 0x1; 3880 QMEM_WR32(qlt, req+4, 0); 3881 QMEM_WR16(qlt, req+8, fct_get_rp_handle(qlt->qlt_port, 3882 rportid)); 3883 QMEM_WR16(qlt, req+10, 60); 3884 QMEM_WR32(qlt, req+0x10, rportid); 3885 QMEM_WR32(qlt, req+0x14, fw_xchg_addr); 3886 QMEM_WR16(qlt, req+0x1A, flags); 3887 QMEM_WR16(qlt, req+0x20, oxid); 3888 qlt_submit_req_entries(qlt, 1); 3889 mutex_exit(&qlt->req_lock); 3890 3891 return; 3892 } 3893 3894 task = (scsi_task_t *)cmd->cmd_specific; 3895 qcmd = (qlt_cmd_t *)cmd->cmd_fca_private; 3896 qcmd->fw_xchg_addr = fw_xchg_addr; 3897 qcmd->param.atio_byte3 = atio[3]; 3898 cmd->cmd_oxid = oxid; 3899 cmd->cmd_rxid = (uint16_t)((((uint16_t)atio[8 + 18]) << 8) | 3900 atio[8+19]); 3901 cmd->cmd_rportid = rportid; 3902 cmd->cmd_lportid = (((uint32_t)atio[8 + 1]) << 16) | 3903 (((uint32_t)atio[8 + 2]) << 8) | atio[8 + 3]; 3904 cmd->cmd_rp_handle = FCT_HANDLE_NONE; 3905 /* Dont do a 64 byte read as this is IOMMU */ 3906 q = atio+0x28; 3907 /* XXX Handle fcp_cntl */ 3908 task->task_cmd_seq_no = (uint32_t)(*q++); 3909 task->task_csn_size = 8; 3910 task->task_flags = qlt_task_flags[(*q++) & 7]; 3911 tm = *q++; 3912 if (tm) { 3913 if (tm & BIT_1) 3914 task->task_mgmt_function = TM_ABORT_TASK_SET; 3915 else if (tm & BIT_2) 3916 task->task_mgmt_function = TM_CLEAR_TASK_SET; 3917 else if (tm & BIT_4) 3918 task->task_mgmt_function = TM_LUN_RESET; 3919 else if (tm & BIT_5) 3920 task->task_mgmt_function = TM_TARGET_COLD_RESET; 3921 else if (tm & BIT_6) 3922 task->task_mgmt_function = TM_CLEAR_ACA; 3923 else 3924 task->task_mgmt_function = TM_ABORT_TASK; 3925 } 3926 task->task_max_nbufs = STMF_BUFS_MAX; 3927 task->task_csn_size = 8; 3928 task->task_flags = (uint8_t)(task->task_flags | (((*q++) & 3) << 5)); 3929 p = task->task_cdb; 3930 *p++ = *q++; *p++ = *q++; *p++ = *q++; *p++ = *q++; 3931 *p++ = *q++; *p++ = *q++; *p++ = *q++; *p++ = *q++; 3932 *p++ = *q++; *p++ = *q++; *p++ = *q++; *p++ = *q++; 3933 *p++ = *q++; *p++ = *q++; *p++ = *q++; *p++ = *q++; 3934 if (cdb_size > 16) { 3935 uint16_t xtra = (uint16_t)(cdb_size - 16); 3936 uint16_t i; 3937 uint8_t cb[4]; 3938 3939 while (xtra) { 3940 *p++ = *q++; 3941 xtra--; 3942 if (q == ((uint8_t *)qlt->queue_mem_ptr + 3943 ATIO_QUEUE_OFFSET + (ATIO_QUEUE_ENTRIES * 64))) { 3944 q = (uint8_t *)qlt->queue_mem_ptr + 3945 ATIO_QUEUE_OFFSET; 3946 } 3947 } 3948 for (i = 0; i < 4; i++) { 3949 cb[i] = *q++; 3950 if (q == ((uint8_t *)qlt->queue_mem_ptr + 3951 ATIO_QUEUE_OFFSET + (ATIO_QUEUE_ENTRIES * 64))) { 3952 q = (uint8_t *)qlt->queue_mem_ptr + 3953 ATIO_QUEUE_OFFSET; 3954 } 3955 } 3956 task->task_expected_xfer_length = (((uint32_t)cb[0]) << 24) | 3957 (((uint32_t)cb[1]) << 16) | 3958 (((uint32_t)cb[2]) << 8) | cb[3]; 3959 } else { 3960 task->task_expected_xfer_length = (((uint32_t)q[0]) << 24) | 3961 (((uint32_t)q[1]) << 16) | 3962 (((uint32_t)q[2]) << 8) | q[3]; 3963 } 3964 fct_post_rcvd_cmd(cmd, 0); 3965 } 3966 3967 static void 3968 qlt_handle_dereg_completion(qlt_state_t *qlt, uint8_t *rsp) 3969 { 3970 uint16_t status; 3971 uint32_t portid; 3972 uint32_t subcode1, subcode2; 3973 3974 status = QMEM_RD16(qlt, rsp+8); 3975 portid = QMEM_RD32(qlt, rsp+0x10) & 0xffffff; 3976 subcode1 = QMEM_RD32(qlt, rsp+0x14); 3977 subcode2 = QMEM_RD32(qlt, rsp+0x18); 3978 3979 mutex_enter(&qlt->preq_lock); 3980 if (portid != qlt->rp_id_in_dereg) { 3981 int instance = ddi_get_instance(qlt->dip); 3982 3983 EL(qlt, "implicit logout reveived portid = %xh\n", portid); 3984 cmn_err(CE_WARN, "qlt(%d): implicit logout completion for 0x%x" 3985 " received when driver wasn't waiting for it", 3986 instance, portid); 3987 mutex_exit(&qlt->preq_lock); 3988 return; 3989 } 3990 3991 if (status != 0) { 3992 EL(qlt, "implicit logout completed for %xh with status %xh, " 3993 "subcode1 %xh subcode2 %xh\n", portid, status, subcode1, 3994 subcode2); 3995 if (status == 0x31 && subcode1 == 0x0a) { 3996 qlt->rp_dereg_status = FCT_SUCCESS; 3997 } else { 3998 EL(qlt, "implicit logout portid=%xh, status=%xh, " 3999 "subcode1=%xh, subcode2=%xh\n", portid, status, 4000 subcode1, subcode2); 4001 qlt->rp_dereg_status = 4002 QLT_FIRMWARE_ERROR(status, subcode1, subcode2); 4003 } 4004 } else { 4005 qlt->rp_dereg_status = FCT_SUCCESS; 4006 } 4007 cv_signal(&qlt->rp_dereg_cv); 4008 mutex_exit(&qlt->preq_lock); 4009 } 4010 4011 /* 4012 * Note that when an ELS is aborted, the regular or aborted completion 4013 * (if any) gets posted before the abort IOCB comes back on response queue. 4014 */ 4015 static void 4016 qlt_handle_unsol_els_completion(qlt_state_t *qlt, uint8_t *rsp) 4017 { 4018 char info[160]; 4019 fct_cmd_t *cmd; 4020 qlt_cmd_t *qcmd; 4021 uint32_t hndl; 4022 uint32_t subcode1, subcode2; 4023 uint16_t status; 4024 4025 hndl = QMEM_RD32(qlt, rsp+4); 4026 status = QMEM_RD16(qlt, rsp+8); 4027 subcode1 = QMEM_RD32(qlt, rsp+0x24); 4028 subcode2 = QMEM_RD32(qlt, rsp+0x28); 4029 4030 if (!CMD_HANDLE_VALID(hndl)) { 4031 EL(qlt, "handle = %xh\n", hndl); 4032 /* 4033 * This cannot happen for unsol els completion. This can 4034 * only happen when abort for an unsol els completes. 4035 * This condition indicates a firmware bug. 4036 */ 4037 (void) snprintf(info, 160, "qlt_handle_unsol_els_completion: " 4038 "Invalid handle: hndl-%x, status-%x/%x/%x, rsp-%p", 4039 hndl, status, subcode1, subcode2, (void *)rsp); 4040 info[159] = 0; 4041 (void) fct_port_shutdown(qlt->qlt_port, 4042 STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET | 4043 STMF_RFLAG_COLLECT_DEBUG_DUMP, info); 4044 return; 4045 } 4046 4047 if (status == 5) { 4048 /* 4049 * When an unsolicited els is aborted, the abort is done 4050 * by a ELSPT iocb with abort control. This is the aborted IOCB 4051 * and not the abortee. We will do the cleanup when the 4052 * IOCB which caused the abort, returns. 4053 */ 4054 EL(qlt, "status = %xh\n", status); 4055 stmf_trace(0, "--UNSOL ELS returned with status 5 --"); 4056 return; 4057 } 4058 4059 cmd = fct_handle_to_cmd(qlt->qlt_port, hndl); 4060 if (cmd == NULL) { 4061 EL(qlt, "fct_handle_to_cmd cmd==NULL, hndl=%xh\n", hndl); 4062 /* 4063 * Now why would this happen ??? 4064 */ 4065 (void) snprintf(info, 160, 4066 "qlt_handle_unsol_els_completion: can not " 4067 "get cmd, hndl-%x, status-%x, rsp-%p", hndl, status, 4068 (void *)rsp); 4069 info[159] = 0; 4070 (void) fct_port_shutdown(qlt->qlt_port, 4071 STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info); 4072 4073 return; 4074 } 4075 4076 ASSERT(cmd->cmd_type == FCT_CMD_RCVD_ELS); 4077 qcmd = (qlt_cmd_t *)cmd->cmd_fca_private; 4078 if (qcmd->flags & QLT_CMD_ABORTING) { 4079 /* 4080 * This is the same case as "if (status == 5)" above. The 4081 * only difference is that in this case the firmware actually 4082 * finished sending the response. So the abort attempt will 4083 * come back with status ?. We will handle it there. 4084 */ 4085 stmf_trace(0, "--UNSOL ELS finished while we are trying to " 4086 "abort it"); 4087 return; 4088 } 4089 4090 if (qcmd->dbuf != NULL) { 4091 qlt_dmem_free(NULL, qcmd->dbuf); 4092 qcmd->dbuf = NULL; 4093 } 4094 4095 if (status == 0) { 4096 fct_send_response_done(cmd, FCT_SUCCESS, FCT_IOF_FCA_DONE); 4097 } else { 4098 fct_send_response_done(cmd, 4099 QLT_FIRMWARE_ERROR(status, subcode1, subcode2), 0); 4100 } 4101 } 4102 4103 static void 4104 qlt_handle_unsol_els_abort_completion(qlt_state_t *qlt, uint8_t *rsp) 4105 { 4106 char info[160]; 4107 fct_cmd_t *cmd; 4108 qlt_cmd_t *qcmd; 4109 uint32_t hndl; 4110 uint32_t subcode1, subcode2; 4111 uint16_t status; 4112 4113 hndl = QMEM_RD32(qlt, rsp+4); 4114 status = QMEM_RD16(qlt, rsp+8); 4115 subcode1 = QMEM_RD32(qlt, rsp+0x24); 4116 subcode2 = QMEM_RD32(qlt, rsp+0x28); 4117 4118 if (!CMD_HANDLE_VALID(hndl)) { 4119 EL(qlt, "handle = %xh\n", hndl); 4120 ASSERT(hndl == 0); 4121 /* 4122 * Someone has requested to abort it, but no one is waiting for 4123 * this completion. 4124 */ 4125 if ((status != 0) && (status != 8)) { 4126 EL(qlt, "status = %xh\n", status); 4127 /* 4128 * There could be exchange resource leakage, so 4129 * throw HBA fatal error event now 4130 */ 4131 (void) snprintf(info, 160, 4132 "qlt_handle_unsol_els_abort_completion: " 4133 "Invalid handle: hndl-%x, status-%x/%x/%x, rsp-%p", 4134 hndl, status, subcode1, subcode2, (void *)rsp); 4135 info[159] = 0; 4136 (void) fct_port_shutdown(qlt->qlt_port, 4137 STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET | 4138 STMF_RFLAG_COLLECT_DEBUG_DUMP, info); 4139 return; 4140 } 4141 4142 return; 4143 } 4144 4145 cmd = fct_handle_to_cmd(qlt->qlt_port, hndl); 4146 if (cmd == NULL) { 4147 EL(qlt, "fct_handle_to_cmd cmd==NULL, hndl=%xh\n", hndl); 4148 /* 4149 * Why would this happen ?? 4150 */ 4151 (void) snprintf(info, 160, 4152 "qlt_handle_unsol_els_abort_completion: can not get " 4153 "cmd, hndl-%x, status-%x, rsp-%p", hndl, status, 4154 (void *)rsp); 4155 info[159] = 0; 4156 (void) fct_port_shutdown(qlt->qlt_port, 4157 STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info); 4158 4159 return; 4160 } 4161 4162 ASSERT(cmd->cmd_type == FCT_CMD_RCVD_ELS); 4163 qcmd = (qlt_cmd_t *)cmd->cmd_fca_private; 4164 ASSERT(qcmd->flags & QLT_CMD_ABORTING); 4165 4166 if (qcmd->dbuf != NULL) { 4167 qlt_dmem_free(NULL, qcmd->dbuf); 4168 qcmd->dbuf = NULL; 4169 } 4170 4171 if (status == 0) { 4172 fct_cmd_fca_aborted(cmd, FCT_ABORT_SUCCESS, FCT_IOF_FCA_DONE); 4173 } else if (status == 8) { 4174 fct_cmd_fca_aborted(cmd, FCT_NOT_FOUND, FCT_IOF_FCA_DONE); 4175 } else { 4176 fct_cmd_fca_aborted(cmd, 4177 QLT_FIRMWARE_ERROR(status, subcode1, subcode2), 0); 4178 } 4179 } 4180 4181 static void 4182 qlt_handle_sol_els_completion(qlt_state_t *qlt, uint8_t *rsp) 4183 { 4184 char info[160]; 4185 fct_cmd_t *cmd; 4186 fct_els_t *els; 4187 qlt_cmd_t *qcmd; 4188 uint32_t hndl; 4189 uint32_t subcode1, subcode2; 4190 uint16_t status; 4191 4192 hndl = QMEM_RD32(qlt, rsp+4); 4193 status = QMEM_RD16(qlt, rsp+8); 4194 subcode1 = QMEM_RD32(qlt, rsp+0x24); 4195 subcode2 = QMEM_RD32(qlt, rsp+0x28); 4196 4197 if (!CMD_HANDLE_VALID(hndl)) { 4198 EL(qlt, "handle = %xh\n", hndl); 4199 /* 4200 * This cannot happen for sol els completion. 4201 */ 4202 (void) snprintf(info, 160, "qlt_handle_sol_els_completion: " 4203 "Invalid handle: hndl-%x, status-%x/%x/%x, rsp-%p", 4204 hndl, status, subcode1, subcode2, (void *)rsp); 4205 info[159] = 0; 4206 (void) fct_port_shutdown(qlt->qlt_port, 4207 STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET | 4208 STMF_RFLAG_COLLECT_DEBUG_DUMP, info); 4209 return; 4210 } 4211 4212 cmd = fct_handle_to_cmd(qlt->qlt_port, hndl); 4213 if (cmd == NULL) { 4214 EL(qlt, "fct_handle_to_cmd cmd==NULL, hndl=%xh\n", hndl); 4215 (void) snprintf(info, 160, 4216 "qlt_handle_sol_els_completion: can not " 4217 "get cmd, hndl-%x, status-%x, rsp-%p", hndl, status, 4218 (void *)rsp); 4219 info[159] = 0; 4220 (void) fct_port_shutdown(qlt->qlt_port, 4221 STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info); 4222 4223 return; 4224 } 4225 4226 ASSERT(cmd->cmd_type == FCT_CMD_SOL_ELS); 4227 els = (fct_els_t *)cmd->cmd_specific; 4228 qcmd = (qlt_cmd_t *)cmd->cmd_fca_private; 4229 qcmd->fw_xchg_addr = QMEM_RD32(qlt, (&rsp[0x10])); 4230 4231 if (qcmd->flags & QLT_CMD_ABORTING) { 4232 /* 4233 * We will handle it when the ABORT IO IOCB returns. 4234 */ 4235 return; 4236 } 4237 4238 if (qcmd->dbuf != NULL) { 4239 if (status == 0) { 4240 qlt_dmem_dma_sync(qcmd->dbuf, DDI_DMA_SYNC_FORKERNEL); 4241 bcopy(qcmd->dbuf->db_sglist[0].seg_addr + 4242 qcmd->param.resp_offset, 4243 els->els_resp_payload, els->els_resp_size); 4244 } 4245 qlt_dmem_free(NULL, qcmd->dbuf); 4246 qcmd->dbuf = NULL; 4247 } 4248 4249 if (status == 0) { 4250 fct_send_cmd_done(cmd, FCT_SUCCESS, FCT_IOF_FCA_DONE); 4251 } else { 4252 fct_send_cmd_done(cmd, 4253 QLT_FIRMWARE_ERROR(status, subcode1, subcode2), 0); 4254 } 4255 } 4256 4257 static void 4258 qlt_handle_ct_completion(qlt_state_t *qlt, uint8_t *rsp) 4259 { 4260 fct_cmd_t *cmd; 4261 fct_sol_ct_t *ct; 4262 qlt_cmd_t *qcmd; 4263 uint32_t hndl; 4264 uint16_t status; 4265 char info[160]; 4266 4267 hndl = QMEM_RD32(qlt, rsp+4); 4268 status = QMEM_RD16(qlt, rsp+8); 4269 4270 if (!CMD_HANDLE_VALID(hndl)) { 4271 EL(qlt, "handle = %xh\n", hndl); 4272 /* 4273 * Solicited commands will always have a valid handle. 4274 */ 4275 (void) snprintf(info, 160, "qlt_handle_ct_completion: hndl-" 4276 "%x, status-%x, rsp-%p", hndl, status, (void *)rsp); 4277 info[159] = 0; 4278 (void) fct_port_shutdown(qlt->qlt_port, 4279 STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET | 4280 STMF_RFLAG_COLLECT_DEBUG_DUMP, info); 4281 return; 4282 } 4283 4284 cmd = fct_handle_to_cmd(qlt->qlt_port, hndl); 4285 if (cmd == NULL) { 4286 EL(qlt, "fct_handle_to_cmd cmd==NULL, hndl=%xh\n", hndl); 4287 (void) snprintf(info, 160, 4288 "qlt_handle_ct_completion: cannot find " 4289 "cmd, hndl-%x, status-%x, rsp-%p", hndl, status, 4290 (void *)rsp); 4291 info[159] = 0; 4292 (void) fct_port_shutdown(qlt->qlt_port, 4293 STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info); 4294 4295 return; 4296 } 4297 4298 ct = (fct_sol_ct_t *)cmd->cmd_specific; 4299 qcmd = (qlt_cmd_t *)cmd->cmd_fca_private; 4300 ASSERT(cmd->cmd_type == FCT_CMD_SOL_CT); 4301 4302 if (qcmd->flags & QLT_CMD_ABORTING) { 4303 /* 4304 * We will handle it when ABORT IO IOCB returns; 4305 */ 4306 return; 4307 } 4308 4309 ASSERT(qcmd->dbuf); 4310 if (status == 0) { 4311 qlt_dmem_dma_sync(qcmd->dbuf, DDI_DMA_SYNC_FORKERNEL); 4312 bcopy(qcmd->dbuf->db_sglist[0].seg_addr + 4313 qcmd->param.resp_offset, 4314 ct->ct_resp_payload, ct->ct_resp_size); 4315 } 4316 qlt_dmem_free(NULL, qcmd->dbuf); 4317 qcmd->dbuf = NULL; 4318 4319 if (status == 0) { 4320 fct_send_cmd_done(cmd, FCT_SUCCESS, FCT_IOF_FCA_DONE); 4321 } else { 4322 fct_send_cmd_done(cmd, QLT_FIRMWARE_ERROR(status, 0, 0), 0); 4323 } 4324 } 4325 4326 static void 4327 qlt_handle_ctio_completion(qlt_state_t *qlt, uint8_t *rsp) 4328 { 4329 fct_cmd_t *cmd; 4330 scsi_task_t *task; 4331 qlt_cmd_t *qcmd; 4332 stmf_data_buf_t *dbuf; 4333 fct_status_t fc_st; 4334 uint32_t iof = 0; 4335 uint32_t hndl; 4336 uint16_t status; 4337 uint16_t flags; 4338 uint8_t abort_req; 4339 uint8_t n; 4340 char info[160]; 4341 4342 /* XXX: Check validity of the IOCB by checking 4th byte. */ 4343 hndl = QMEM_RD32(qlt, rsp+4); 4344 status = QMEM_RD16(qlt, rsp+8); 4345 flags = QMEM_RD16(qlt, rsp+0x1a); 4346 n = rsp[2]; 4347 4348 if (!CMD_HANDLE_VALID(hndl)) { 4349 EL(qlt, "handle = %xh\n", hndl); 4350 ASSERT(hndl == 0); 4351 /* 4352 * Someone has requested to abort it, but no one is waiting for 4353 * this completion. 4354 */ 4355 EL(qlt, "hndl-%xh, status-%xh, rsp-%p\n", hndl, status, 4356 (void *)rsp); 4357 if ((status != 1) && (status != 2)) { 4358 EL(qlt, "status = %xh\n", status); 4359 /* 4360 * There could be exchange resource leakage, so 4361 * throw HBA fatal error event now 4362 */ 4363 (void) snprintf(info, 160, 4364 "qlt_handle_ctio_completion: hndl-" 4365 "%x, status-%x, rsp-%p", hndl, status, (void *)rsp); 4366 info[159] = 0; 4367 (void) fct_port_shutdown(qlt->qlt_port, 4368 STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info); 4369 4370 } 4371 4372 return; 4373 } 4374 4375 if (flags & BIT_14) { 4376 abort_req = 1; 4377 EL(qlt, "abort: hndl-%x, status-%x, rsp-%p\n", hndl, status, 4378 (void *)rsp); 4379 } else { 4380 abort_req = 0; 4381 } 4382 4383 cmd = fct_handle_to_cmd(qlt->qlt_port, hndl); 4384 if (cmd == NULL) { 4385 EL(qlt, "fct_handle_to_cmd cmd==NULL, hndl=%xh\n", hndl); 4386 (void) snprintf(info, 160, 4387 "qlt_handle_ctio_completion: cannot find " 4388 "cmd, hndl-%x, status-%x, rsp-%p", hndl, status, 4389 (void *)rsp); 4390 info[159] = 0; 4391 (void) fct_port_shutdown(qlt->qlt_port, 4392 STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info); 4393 4394 return; 4395 } 4396 4397 task = (scsi_task_t *)cmd->cmd_specific; 4398 qcmd = (qlt_cmd_t *)cmd->cmd_fca_private; 4399 if (qcmd->dbuf_rsp_iu) { 4400 ASSERT((flags & (BIT_6 | BIT_7)) == BIT_7); 4401 qlt_dmem_free(NULL, qcmd->dbuf_rsp_iu); 4402 qcmd->dbuf_rsp_iu = NULL; 4403 } 4404 4405 if ((status == 1) || (status == 2)) { 4406 if (abort_req) { 4407 fc_st = FCT_ABORT_SUCCESS; 4408 iof = FCT_IOF_FCA_DONE; 4409 } else { 4410 fc_st = FCT_SUCCESS; 4411 if (flags & BIT_15) { 4412 iof = FCT_IOF_FCA_DONE; 4413 } 4414 } 4415 } else { 4416 EL(qlt, "status = %xh\n", status); 4417 if ((status == 8) && abort_req) { 4418 fc_st = FCT_NOT_FOUND; 4419 iof = FCT_IOF_FCA_DONE; 4420 } else { 4421 fc_st = QLT_FIRMWARE_ERROR(status, 0, 0); 4422 } 4423 } 4424 dbuf = NULL; 4425 if (((n & BIT_7) == 0) && (!abort_req)) { 4426 /* A completion of data xfer */ 4427 if (n == 0) { 4428 dbuf = qcmd->dbuf; 4429 } else { 4430 dbuf = stmf_handle_to_buf(task, n); 4431 } 4432 4433 ASSERT(dbuf != NULL); 4434 if (dbuf->db_flags & DB_DIRECTION_FROM_RPORT) 4435 qlt_dmem_dma_sync(dbuf, DDI_DMA_SYNC_FORCPU); 4436 if (flags & BIT_15) { 4437 dbuf->db_flags = (uint16_t)(dbuf->db_flags | 4438 DB_STATUS_GOOD_SENT); 4439 } 4440 4441 dbuf->db_xfer_status = fc_st; 4442 fct_scsi_data_xfer_done(cmd, dbuf, iof); 4443 return; 4444 } 4445 if (!abort_req) { 4446 /* 4447 * This was just a pure status xfer. 4448 */ 4449 fct_send_response_done(cmd, fc_st, iof); 4450 return; 4451 } 4452 4453 fct_cmd_fca_aborted(cmd, fc_st, iof); 4454 } 4455 4456 static void 4457 qlt_handle_sol_abort_completion(qlt_state_t *qlt, uint8_t *rsp) 4458 { 4459 char info[80]; 4460 fct_cmd_t *cmd; 4461 qlt_cmd_t *qcmd; 4462 uint32_t h; 4463 uint16_t status; 4464 4465 h = QMEM_RD32(qlt, rsp+4); 4466 status = QMEM_RD16(qlt, rsp+8); 4467 4468 if (!CMD_HANDLE_VALID(h)) { 4469 EL(qlt, "handle = %xh\n", h); 4470 /* 4471 * Solicited commands always have a valid handle. 4472 */ 4473 (void) snprintf(info, 80, 4474 "qlt_handle_sol_abort_completion: hndl-" 4475 "%x, status-%x, rsp-%p", h, status, (void *)rsp); 4476 info[79] = 0; 4477 (void) fct_port_shutdown(qlt->qlt_port, 4478 STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET | 4479 STMF_RFLAG_COLLECT_DEBUG_DUMP, info); 4480 return; 4481 } 4482 cmd = fct_handle_to_cmd(qlt->qlt_port, h); 4483 if (cmd == NULL) { 4484 EL(qlt, "fct_handle_to_cmd cmd==NULL, hndl=%xh\n", h); 4485 /* 4486 * What happened to the cmd ?? 4487 */ 4488 (void) snprintf(info, 80, 4489 "qlt_handle_sol_abort_completion: cannot " 4490 "find cmd, hndl-%x, status-%x, rsp-%p", h, status, 4491 (void *)rsp); 4492 info[79] = 0; 4493 (void) fct_port_shutdown(qlt->qlt_port, 4494 STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info); 4495 4496 return; 4497 } 4498 4499 ASSERT((cmd->cmd_type == FCT_CMD_SOL_ELS) || 4500 (cmd->cmd_type == FCT_CMD_SOL_CT)); 4501 qcmd = (qlt_cmd_t *)cmd->cmd_fca_private; 4502 if (qcmd->dbuf != NULL) { 4503 qlt_dmem_free(NULL, qcmd->dbuf); 4504 qcmd->dbuf = NULL; 4505 } 4506 ASSERT(qcmd->flags & QLT_CMD_ABORTING); 4507 if (status == 0) { 4508 fct_cmd_fca_aborted(cmd, FCT_ABORT_SUCCESS, FCT_IOF_FCA_DONE); 4509 } else if (status == 0x31) { 4510 fct_cmd_fca_aborted(cmd, FCT_NOT_FOUND, FCT_IOF_FCA_DONE); 4511 } else { 4512 fct_cmd_fca_aborted(cmd, QLT_FIRMWARE_ERROR(status, 0, 0), 0); 4513 } 4514 } 4515 4516 static void 4517 qlt_handle_rcvd_abts(qlt_state_t *qlt, uint8_t *resp) 4518 { 4519 qlt_abts_cmd_t *qcmd; 4520 fct_cmd_t *cmd; 4521 uint32_t remote_portid; 4522 char info[160]; 4523 4524 remote_portid = ((uint32_t)(QMEM_RD16(qlt, (&resp[0x18])))) | 4525 ((uint32_t)(resp[0x1A])) << 16; 4526 cmd = (fct_cmd_t *)fct_alloc(FCT_STRUCT_CMD_RCVD_ABTS, 4527 sizeof (qlt_abts_cmd_t), 0); 4528 if (cmd == NULL) { 4529 EL(qlt, "fct_alloc cmd==NULL\n"); 4530 (void) snprintf(info, 160, 4531 "qlt_handle_rcvd_abts: qlt-%p, can't " 4532 "allocate space for fct_cmd", (void *)qlt); 4533 info[159] = 0; 4534 (void) fct_port_shutdown(qlt->qlt_port, 4535 STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info); 4536 return; 4537 } 4538 4539 resp[0xC] = resp[0xD] = resp[0xE] = 0; 4540 qcmd = (qlt_abts_cmd_t *)cmd->cmd_fca_private; 4541 bcopy(resp, qcmd->buf, IOCB_SIZE); 4542 cmd->cmd_port = qlt->qlt_port; 4543 cmd->cmd_rp_handle = QMEM_RD16(qlt, resp+0xA); 4544 if (cmd->cmd_rp_handle == 0xFFFF) 4545 cmd->cmd_rp_handle = FCT_HANDLE_NONE; 4546 4547 cmd->cmd_rportid = remote_portid; 4548 cmd->cmd_lportid = ((uint32_t)(QMEM_RD16(qlt, (&resp[0x14])))) | 4549 ((uint32_t)(resp[0x16])) << 16; 4550 cmd->cmd_oxid = QMEM_RD16(qlt, (&resp[0x26])); 4551 cmd->cmd_rxid = QMEM_RD16(qlt, (&resp[0x24])); 4552 fct_post_rcvd_cmd(cmd, 0); 4553 } 4554 4555 static void 4556 qlt_handle_abts_completion(qlt_state_t *qlt, uint8_t *resp) 4557 { 4558 uint16_t status; 4559 char info[80]; 4560 4561 status = QMEM_RD16(qlt, resp+8); 4562 4563 if ((status == 0) || (status == 5)) { 4564 return; 4565 } 4566 EL(qlt, "status = %xh\n", status); 4567 (void) snprintf(info, 80, "ABTS completion failed %x/%x/%x resp_off %x", 4568 status, QMEM_RD32(qlt, resp+0x34), QMEM_RD32(qlt, resp+0x38), 4569 ((uint32_t)(qlt->resp_ndx_to_fw)) << 6); 4570 info[79] = 0; 4571 (void) fct_port_shutdown(qlt->qlt_port, STMF_RFLAG_FATAL_ERROR | 4572 STMF_RFLAG_RESET | STMF_RFLAG_COLLECT_DEBUG_DUMP, info); 4573 } 4574 4575 #ifdef DEBUG 4576 uint32_t qlt_drop_abort_counter = 0; 4577 #endif 4578 4579 fct_status_t 4580 qlt_abort_cmd(struct fct_local_port *port, fct_cmd_t *cmd, uint32_t flags) 4581 { 4582 qlt_state_t *qlt = (qlt_state_t *)port->port_fca_private; 4583 4584 if ((qlt->qlt_state == FCT_STATE_OFFLINE) || 4585 (qlt->qlt_state == FCT_STATE_OFFLINING)) { 4586 return (FCT_NOT_FOUND); 4587 } 4588 4589 #ifdef DEBUG 4590 if (qlt_drop_abort_counter > 0) { 4591 if (atomic_add_32_nv(&qlt_drop_abort_counter, -1) == 1) 4592 return (FCT_SUCCESS); 4593 } 4594 #endif 4595 4596 if (cmd->cmd_type == FCT_CMD_FCP_XCHG) { 4597 return (qlt_abort_unsol_scsi_cmd(qlt, cmd)); 4598 } 4599 4600 if (flags & FCT_IOF_FORCE_FCA_DONE) { 4601 cmd->cmd_handle = 0; 4602 } 4603 4604 if (cmd->cmd_type == FCT_CMD_RCVD_ABTS) { 4605 return (qlt_send_abts_response(qlt, cmd, 1)); 4606 } 4607 4608 if (cmd->cmd_type == FCT_CMD_RCVD_ELS) { 4609 return (qlt_abort_purex(qlt, cmd)); 4610 } 4611 4612 if ((cmd->cmd_type == FCT_CMD_SOL_ELS) || 4613 (cmd->cmd_type == FCT_CMD_SOL_CT)) { 4614 return (qlt_abort_sol_cmd(qlt, cmd)); 4615 } 4616 EL(qlt, "cmd->cmd_type = %xh\n", cmd->cmd_type); 4617 4618 ASSERT(0); 4619 return (FCT_FAILURE); 4620 } 4621 4622 fct_status_t 4623 qlt_abort_sol_cmd(qlt_state_t *qlt, fct_cmd_t *cmd) 4624 { 4625 uint8_t *req; 4626 qlt_cmd_t *qcmd; 4627 4628 qcmd = (qlt_cmd_t *)cmd->cmd_fca_private; 4629 qcmd->flags = (uint16_t)(qcmd->flags | QLT_CMD_ABORTING); 4630 EL(qlt, "fctcmd-%p, cmd_handle-%xh\n", cmd, cmd->cmd_handle); 4631 4632 mutex_enter(&qlt->req_lock); 4633 req = (uint8_t *)qlt_get_req_entries(qlt, 1); 4634 if (req == NULL) { 4635 mutex_exit(&qlt->req_lock); 4636 4637 return (FCT_BUSY); 4638 } 4639 bzero(req, IOCB_SIZE); 4640 req[0] = 0x33; req[1] = 1; 4641 QMEM_WR32(qlt, req+4, cmd->cmd_handle); 4642 if (cmd->cmd_rp) { 4643 QMEM_WR16(qlt, req+8, cmd->cmd_rp->rp_handle); 4644 } else { 4645 QMEM_WR16(qlt, req+8, 0xFFFF); 4646 } 4647 4648 QMEM_WR32(qlt, req+0xc, cmd->cmd_handle); 4649 QMEM_WR32(qlt, req+0x30, cmd->cmd_rportid); 4650 qlt_submit_req_entries(qlt, 1); 4651 mutex_exit(&qlt->req_lock); 4652 4653 return (FCT_SUCCESS); 4654 } 4655 4656 fct_status_t 4657 qlt_abort_purex(qlt_state_t *qlt, fct_cmd_t *cmd) 4658 { 4659 uint8_t *req; 4660 qlt_cmd_t *qcmd; 4661 fct_els_t *els; 4662 uint8_t elsop, req1f; 4663 4664 els = (fct_els_t *)cmd->cmd_specific; 4665 qcmd = (qlt_cmd_t *)cmd->cmd_fca_private; 4666 elsop = els->els_req_payload[0]; 4667 EL(qlt, "fctcmd-%p, cmd_handle-%xh, elsop-%xh\n", cmd, cmd->cmd_handle, 4668 elsop); 4669 req1f = 0x60; /* Terminate xchg */ 4670 if ((elsop == ELS_OP_PRLI) || (elsop == ELS_OP_PRLO) || 4671 (elsop == ELS_OP_TPRLO) || (elsop == ELS_OP_LOGO)) { 4672 req1f = (uint8_t)(req1f | BIT_4); 4673 } 4674 4675 mutex_enter(&qlt->req_lock); 4676 req = (uint8_t *)qlt_get_req_entries(qlt, 1); 4677 if (req == NULL) { 4678 mutex_exit(&qlt->req_lock); 4679 4680 return (FCT_BUSY); 4681 } 4682 4683 qcmd->flags = (uint16_t)(qcmd->flags | QLT_CMD_ABORTING); 4684 bzero(req, IOCB_SIZE); 4685 req[0] = 0x53; req[1] = 1; req[0xf] = 0x10; 4686 req[0x16] = elsop; req[0x1f] = req1f; 4687 QMEM_WR32(qlt, (&req[4]), cmd->cmd_handle); 4688 if (cmd->cmd_rp) { 4689 QMEM_WR16(qlt, (&req[0xA]), cmd->cmd_rp->rp_handle); 4690 EL(qlt, "rp_handle-%x\n", cmd->cmd_rp->rp_handle); 4691 } else { 4692 QMEM_WR16(qlt, (&req[0xA]), cmd->cmd_rp_handle); 4693 EL(qlt, "cmd_rp_handle-%x\n", cmd->cmd_rp_handle); 4694 } 4695 4696 QMEM_WR32(qlt, (&req[0x10]), qcmd->fw_xchg_addr); 4697 QMEM_WR32(qlt, (&req[0x18]), cmd->cmd_rportid); 4698 qlt_submit_req_entries(qlt, 1); 4699 mutex_exit(&qlt->req_lock); 4700 4701 return (FCT_SUCCESS); 4702 } 4703 4704 fct_status_t 4705 qlt_abort_unsol_scsi_cmd(qlt_state_t *qlt, fct_cmd_t *cmd) 4706 { 4707 qlt_cmd_t *qcmd = (qlt_cmd_t *)cmd->cmd_fca_private; 4708 uint8_t *req; 4709 uint16_t flags; 4710 4711 flags = (uint16_t)(BIT_14 | 4712 (((uint16_t)qcmd->param.atio_byte3 & 0xf0) << 5)); 4713 EL(qlt, "fctcmd-%p, cmd_handle-%x\n", cmd, cmd->cmd_handle); 4714 4715 mutex_enter(&qlt->req_lock); 4716 req = (uint8_t *)qlt_get_req_entries(qlt, 1); 4717 if (req == NULL) { 4718 mutex_exit(&qlt->req_lock); 4719 4720 return (FCT_BUSY); 4721 } 4722 4723 qcmd->flags = (uint16_t)(qcmd->flags | QLT_CMD_ABORTING); 4724 bzero(req, IOCB_SIZE); 4725 req[0] = 0x12; req[1] = 0x1; 4726 QMEM_WR32(qlt, req+4, cmd->cmd_handle); 4727 QMEM_WR16(qlt, req+8, cmd->cmd_rp->rp_handle); 4728 QMEM_WR16(qlt, req+10, 60); /* 60 seconds timeout */ 4729 QMEM_WR32(qlt, req+0x10, cmd->cmd_rportid); 4730 QMEM_WR32(qlt, req+0x14, qcmd->fw_xchg_addr); 4731 QMEM_WR16(qlt, req+0x1A, flags); 4732 QMEM_WR16(qlt, req+0x20, cmd->cmd_oxid); 4733 qlt_submit_req_entries(qlt, 1); 4734 mutex_exit(&qlt->req_lock); 4735 4736 return (FCT_SUCCESS); 4737 } 4738 4739 fct_status_t 4740 qlt_send_cmd(fct_cmd_t *cmd) 4741 { 4742 qlt_state_t *qlt; 4743 4744 qlt = (qlt_state_t *)cmd->cmd_port->port_fca_private; 4745 if (cmd->cmd_type == FCT_CMD_SOL_ELS) { 4746 return (qlt_send_els(qlt, cmd)); 4747 } else if (cmd->cmd_type == FCT_CMD_SOL_CT) { 4748 return (qlt_send_ct(qlt, cmd)); 4749 } 4750 EL(qlt, "cmd->cmd_type = %xh\n", cmd->cmd_type); 4751 4752 ASSERT(0); 4753 return (FCT_FAILURE); 4754 } 4755 4756 fct_status_t 4757 qlt_send_els(qlt_state_t *qlt, fct_cmd_t *cmd) 4758 { 4759 uint8_t *req; 4760 fct_els_t *els; 4761 qlt_cmd_t *qcmd; 4762 stmf_data_buf_t *buf; 4763 qlt_dmem_bctl_t *bctl; 4764 uint32_t sz, minsz; 4765 4766 els = (fct_els_t *)cmd->cmd_specific; 4767 qcmd = (qlt_cmd_t *)cmd->cmd_fca_private; 4768 qcmd->flags = QLT_CMD_TYPE_SOLICITED; 4769 qcmd->param.resp_offset = (uint16_t)((els->els_req_size + 7) & ~7); 4770 sz = minsz = qcmd->param.resp_offset + els->els_resp_size; 4771 buf = qlt_i_dmem_alloc(qlt, sz, &minsz, 0); 4772 if (buf == NULL) { 4773 return (FCT_BUSY); 4774 } 4775 bctl = (qlt_dmem_bctl_t *)buf->db_port_private; 4776 4777 qcmd->dbuf = buf; 4778 bcopy(els->els_req_payload, buf->db_sglist[0].seg_addr, 4779 els->els_req_size); 4780 qlt_dmem_dma_sync(buf, DDI_DMA_SYNC_FORDEV); 4781 4782 mutex_enter(&qlt->req_lock); 4783 req = (uint8_t *)qlt_get_req_entries(qlt, 1); 4784 if (req == NULL) { 4785 qlt_dmem_free(NULL, buf); 4786 mutex_exit(&qlt->req_lock); 4787 return (FCT_BUSY); 4788 } 4789 bzero(req, IOCB_SIZE); 4790 req[0] = 0x53; req[1] = 1; 4791 QMEM_WR32(qlt, (&req[4]), cmd->cmd_handle); 4792 QMEM_WR16(qlt, (&req[0xA]), cmd->cmd_rp->rp_handle); 4793 QMEM_WR16(qlt, (&req[0xC]), 1); 4794 QMEM_WR16(qlt, (&req[0xE]), 0x1000); 4795 QMEM_WR16(qlt, (&req[0x14]), 1); 4796 req[0x16] = els->els_req_payload[0]; 4797 if (qlt->cur_topology == PORT_TOPOLOGY_PT_TO_PT) { 4798 req[0x1b] = (uint8_t)((cmd->cmd_lportid >> 16) & 0xff); 4799 req[0x1c] = (uint8_t)(cmd->cmd_lportid & 0xff); 4800 req[0x1d] = (uint8_t)((cmd->cmd_lportid >> 8) & 0xff); 4801 } 4802 QMEM_WR32(qlt, (&req[0x18]), cmd->cmd_rp->rp_id); 4803 QMEM_WR32(qlt, (&req[0x20]), els->els_resp_size); 4804 QMEM_WR32(qlt, (&req[0x24]), els->els_req_size); 4805 QMEM_WR64(qlt, (&req[0x28]), bctl->bctl_dev_addr); 4806 QMEM_WR32(qlt, (&req[0x30]), els->els_req_size); 4807 QMEM_WR64(qlt, (&req[0x34]), (bctl->bctl_dev_addr + 4808 qcmd->param.resp_offset)); 4809 QMEM_WR32(qlt, (&req[0x3C]), els->els_resp_size); 4810 qlt_submit_req_entries(qlt, 1); 4811 mutex_exit(&qlt->req_lock); 4812 4813 return (FCT_SUCCESS); 4814 } 4815 4816 fct_status_t 4817 qlt_send_ct(qlt_state_t *qlt, fct_cmd_t *cmd) 4818 { 4819 uint8_t *req; 4820 fct_sol_ct_t *ct; 4821 qlt_cmd_t *qcmd; 4822 stmf_data_buf_t *buf; 4823 qlt_dmem_bctl_t *bctl; 4824 uint32_t sz, minsz; 4825 4826 ct = (fct_sol_ct_t *)cmd->cmd_specific; 4827 qcmd = (qlt_cmd_t *)cmd->cmd_fca_private; 4828 qcmd->flags = QLT_CMD_TYPE_SOLICITED; 4829 qcmd->param.resp_offset = (uint16_t)((ct->ct_req_size + 7) & ~7); 4830 sz = minsz = qcmd->param.resp_offset + ct->ct_resp_size; 4831 buf = qlt_i_dmem_alloc(qlt, sz, &minsz, 0); 4832 if (buf == NULL) { 4833 return (FCT_BUSY); 4834 } 4835 bctl = (qlt_dmem_bctl_t *)buf->db_port_private; 4836 4837 qcmd->dbuf = buf; 4838 bcopy(ct->ct_req_payload, buf->db_sglist[0].seg_addr, 4839 ct->ct_req_size); 4840 qlt_dmem_dma_sync(buf, DDI_DMA_SYNC_FORDEV); 4841 4842 mutex_enter(&qlt->req_lock); 4843 req = (uint8_t *)qlt_get_req_entries(qlt, 1); 4844 if (req == NULL) { 4845 qlt_dmem_free(NULL, buf); 4846 mutex_exit(&qlt->req_lock); 4847 return (FCT_BUSY); 4848 } 4849 bzero(req, IOCB_SIZE); 4850 req[0] = 0x29; req[1] = 1; 4851 QMEM_WR32(qlt, (&req[4]), cmd->cmd_handle); 4852 QMEM_WR16(qlt, (&req[0xA]), cmd->cmd_rp->rp_handle); 4853 QMEM_WR16(qlt, (&req[0xC]), 1); 4854 QMEM_WR16(qlt, (&req[0x10]), 0x20); /* > (2 * RA_TOV) */ 4855 QMEM_WR16(qlt, (&req[0x14]), 1); 4856 4857 QMEM_WR32(qlt, (&req[0x20]), ct->ct_resp_size); 4858 QMEM_WR32(qlt, (&req[0x24]), ct->ct_req_size); 4859 4860 QMEM_WR64(qlt, (&req[0x28]), bctl->bctl_dev_addr); /* COMMAND DSD */ 4861 QMEM_WR32(qlt, (&req[0x30]), ct->ct_req_size); 4862 QMEM_WR64(qlt, (&req[0x34]), (bctl->bctl_dev_addr + 4863 qcmd->param.resp_offset)); /* RESPONSE DSD */ 4864 QMEM_WR32(qlt, (&req[0x3C]), ct->ct_resp_size); 4865 4866 qlt_submit_req_entries(qlt, 1); 4867 mutex_exit(&qlt->req_lock); 4868 4869 return (FCT_SUCCESS); 4870 } 4871 4872 4873 /* 4874 * All QLT_FIRMWARE_* will mainly be handled in this function 4875 * It can not be called in interrupt context 4876 * 4877 * FWDUMP's purpose is to serve ioctl, so we will use qlt_ioctl_flags 4878 * and qlt_ioctl_lock 4879 */ 4880 static fct_status_t 4881 qlt_firmware_dump(fct_local_port_t *port, stmf_state_change_info_t *ssci) 4882 { 4883 qlt_state_t *qlt = (qlt_state_t *)port->port_fca_private; 4884 int i; 4885 int retries, n; 4886 uint_t size_left; 4887 char c = ' '; 4888 uint32_t addr, endaddr, words_to_read; 4889 caddr_t buf; 4890 fct_status_t ret; 4891 4892 mutex_enter(&qlt->qlt_ioctl_lock); 4893 /* 4894 * To make sure that there's no outstanding dumping task 4895 */ 4896 if (qlt->qlt_ioctl_flags & QLT_FWDUMP_INPROGRESS) { 4897 mutex_exit(&qlt->qlt_ioctl_lock); 4898 EL(qlt, "qlt_ioctl_flags=%xh, inprogress\n", 4899 qlt->qlt_ioctl_flags); 4900 EL(qlt, "outstanding\n"); 4901 return (FCT_FAILURE); 4902 } 4903 4904 /* 4905 * To make sure not to overwrite existing dump 4906 */ 4907 if ((qlt->qlt_ioctl_flags & QLT_FWDUMP_ISVALID) && 4908 !(qlt->qlt_ioctl_flags & QLT_FWDUMP_TRIGGERED_BY_USER) && 4909 !(qlt->qlt_ioctl_flags & QLT_FWDUMP_FETCHED_BY_USER)) { 4910 /* 4911 * If we have alreay one dump, but it's not triggered by user 4912 * and the user hasn't fetched it, we shouldn't dump again. 4913 */ 4914 mutex_exit(&qlt->qlt_ioctl_lock); 4915 EL(qlt, "qlt_ioctl_flags=%xh, already done\n", 4916 qlt->qlt_ioctl_flags); 4917 cmn_err(CE_NOTE, "qlt(%d): Skipping firmware dump as there " 4918 "is one already outstanding.", qlt->instance); 4919 return (FCT_FAILURE); 4920 } 4921 qlt->qlt_ioctl_flags |= QLT_FWDUMP_INPROGRESS; 4922 if (ssci->st_rflags & STMF_RFLAG_USER_REQUEST) { 4923 qlt->qlt_ioctl_flags |= QLT_FWDUMP_TRIGGERED_BY_USER; 4924 } else { 4925 qlt->qlt_ioctl_flags &= ~QLT_FWDUMP_TRIGGERED_BY_USER; 4926 } 4927 mutex_exit(&qlt->qlt_ioctl_lock); 4928 4929 size_left = QLT_FWDUMP_BUFSIZE; 4930 if (!qlt->qlt_fwdump_buf) { 4931 ASSERT(!(qlt->qlt_ioctl_flags & QLT_FWDUMP_ISVALID)); 4932 /* 4933 * It's the only place that we allocate buf for dumping. After 4934 * it's allocated, we will use it until the port is detached. 4935 */ 4936 qlt->qlt_fwdump_buf = kmem_zalloc(size_left, KM_SLEEP); 4937 } 4938 4939 /* 4940 * Start to dump firmware 4941 */ 4942 buf = (caddr_t)qlt->qlt_fwdump_buf; 4943 4944 /* 4945 * Print the ISP firmware revision number and attributes information 4946 * Read the RISC to Host Status register 4947 */ 4948 n = (int)snprintf(buf, size_left, "ISP FW Version %d.%02d.%02d " 4949 "Attributes %04x\n\nR2H Status Register\n%08x", 4950 qlt->fw_major, qlt->fw_minor, 4951 qlt->fw_subminor, qlt->fw_attr, REG_RD32(qlt, REG_RISC_STATUS)); 4952 buf += n; size_left -= n; 4953 4954 /* 4955 * Before pausing the RISC, make sure no mailbox can execute 4956 */ 4957 mutex_enter(&qlt->mbox_lock); 4958 if (qlt->mbox_io_state != MBOX_STATE_UNKNOWN) { 4959 /* 4960 * Wait to grab the mailboxes 4961 */ 4962 for (retries = 0; (qlt->mbox_io_state != MBOX_STATE_READY) && 4963 (qlt->mbox_io_state != MBOX_STATE_UNKNOWN); retries++) { 4964 (void) cv_timedwait(&qlt->mbox_cv, &qlt->mbox_lock, 4965 ddi_get_lbolt() + drv_usectohz(1000000)); 4966 if (retries > 5) { 4967 mutex_exit(&qlt->mbox_lock); 4968 EL(qlt, "can't drain out mailbox commands\n"); 4969 goto dump_fail; 4970 } 4971 } 4972 qlt->mbox_io_state = MBOX_STATE_UNKNOWN; 4973 cv_broadcast(&qlt->mbox_cv); 4974 } 4975 mutex_exit(&qlt->mbox_lock); 4976 4977 /* 4978 * Pause the RISC processor 4979 */ 4980 REG_WR32(qlt, REG_HCCR, HCCR_CMD(SET_RISC_PAUSE)); 4981 4982 /* 4983 * Wait for the RISC processor to pause 4984 */ 4985 for (i = 0; i < 200; i++) { 4986 if (REG_RD32(qlt, REG_RISC_STATUS) & 0x100) { 4987 break; 4988 } 4989 drv_usecwait(1000); 4990 } 4991 if (i == 200) { 4992 EL(qlt, "can't pause\n"); 4993 return (FCT_FAILURE); 4994 } 4995 4996 if ((!qlt->qlt_25xx_chip) && (!qlt->qlt_81xx_chip)) { 4997 goto over_25xx_specific_dump; 4998 } 4999 n = (int)snprintf(buf, size_left, "\n\nHostRisc registers\n"); 5000 buf += n; size_left -= n; 5001 REG_WR32(qlt, 0x54, 0x7000); 5002 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5003 buf += n; size_left -= n; 5004 REG_WR32(qlt, 0x54, 0x7010); 5005 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5006 buf += n; size_left -= n; 5007 REG_WR32(qlt, 0x54, 0x7C00); 5008 5009 n = (int)snprintf(buf, size_left, "\nPCIe registers\n"); 5010 buf += n; size_left -= n; 5011 REG_WR32(qlt, 0xC0, 0x1); 5012 n = qlt_fwdump_dump_regs(qlt, buf, 0xc4, 3, size_left); 5013 buf += n; size_left -= n; 5014 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 1, size_left); 5015 buf += n; size_left -= n; 5016 REG_WR32(qlt, 0xC0, 0x0); 5017 5018 over_25xx_specific_dump:; 5019 n = (int)snprintf(buf, size_left, "\n\nHost Interface Registers\n"); 5020 buf += n; size_left -= n; 5021 /* 5022 * Capture data from 32 regsiters 5023 */ 5024 n = qlt_fwdump_dump_regs(qlt, buf, 0, 32, size_left); 5025 buf += n; size_left -= n; 5026 5027 /* 5028 * Disable interrupts 5029 */ 5030 REG_WR32(qlt, 0xc, 0); 5031 5032 /* 5033 * Shadow registers 5034 */ 5035 n = (int)snprintf(buf, size_left, "\nShadow Registers\n"); 5036 buf += n; size_left -= n; 5037 5038 REG_WR32(qlt, 0x54, 0xF70); 5039 addr = 0xb0000000; 5040 for (i = 0; i < 0xb; i++) { 5041 if ((!qlt->qlt_25xx_chip) && 5042 (!qlt->qlt_81xx_chip) && 5043 (i >= 7)) { 5044 break; 5045 } 5046 if (i && ((i & 7) == 0)) { 5047 n = (int)snprintf(buf, size_left, "\n"); 5048 buf += n; size_left -= n; 5049 } 5050 REG_WR32(qlt, 0xF0, addr); 5051 n = (int)snprintf(buf, size_left, "%08x ", REG_RD32(qlt, 0xFC)); 5052 buf += n; size_left -= n; 5053 addr += 0x100000; 5054 } 5055 5056 if ((qlt->qlt_25xx_chip) || (qlt->qlt_81xx_chip)) { 5057 REG_WR32(qlt, 0x54, 0x10); 5058 n = (int)snprintf(buf, size_left, 5059 "\n\nRISC IO Register\n%08x", REG_RD32(qlt, 0xC0)); 5060 buf += n; size_left -= n; 5061 } 5062 5063 /* 5064 * Mailbox registers 5065 */ 5066 n = (int)snprintf(buf, size_left, "\n\nMailbox Registers\n"); 5067 buf += n; size_left -= n; 5068 for (i = 0; i < 32; i += 2) { 5069 if ((i + 2) & 15) { 5070 c = ' '; 5071 } else { 5072 c = '\n'; 5073 } 5074 n = (int)snprintf(buf, size_left, "%04x %04x%c", 5075 REG_RD16(qlt, 0x80 + (i << 1)), 5076 REG_RD16(qlt, 0x80 + ((i+1) << 1)), c); 5077 buf += n; size_left -= n; 5078 } 5079 5080 /* 5081 * Transfer sequence registers 5082 */ 5083 n = (int)snprintf(buf, size_left, "\nXSEQ GP Registers\n"); 5084 buf += n; size_left -= n; 5085 5086 REG_WR32(qlt, 0x54, 0xBF00); 5087 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5088 buf += n; size_left -= n; 5089 REG_WR32(qlt, 0x54, 0xBF10); 5090 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5091 buf += n; size_left -= n; 5092 REG_WR32(qlt, 0x54, 0xBF20); 5093 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5094 buf += n; size_left -= n; 5095 REG_WR32(qlt, 0x54, 0xBF30); 5096 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5097 buf += n; size_left -= n; 5098 REG_WR32(qlt, 0x54, 0xBF40); 5099 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5100 buf += n; size_left -= n; 5101 REG_WR32(qlt, 0x54, 0xBF50); 5102 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5103 buf += n; size_left -= n; 5104 REG_WR32(qlt, 0x54, 0xBF60); 5105 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5106 buf += n; size_left -= n; 5107 REG_WR32(qlt, 0x54, 0xBF70); 5108 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5109 buf += n; size_left -= n; 5110 n = (int)snprintf(buf, size_left, "\nXSEQ-0 registers\n"); 5111 buf += n; size_left -= n; 5112 if ((qlt->qlt_25xx_chip) || (qlt->qlt_81xx_chip)) { 5113 REG_WR32(qlt, 0x54, 0xBFC0); 5114 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5115 buf += n; size_left -= n; 5116 REG_WR32(qlt, 0x54, 0xBFD0); 5117 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5118 buf += n; size_left -= n; 5119 } 5120 REG_WR32(qlt, 0x54, 0xBFE0); 5121 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5122 buf += n; size_left -= n; 5123 n = (int)snprintf(buf, size_left, "\nXSEQ-1 registers\n"); 5124 buf += n; size_left -= n; 5125 REG_WR32(qlt, 0x54, 0xBFF0); 5126 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5127 buf += n; size_left -= n; 5128 5129 /* 5130 * Receive sequence registers 5131 */ 5132 n = (int)snprintf(buf, size_left, "\nRSEQ GP Registers\n"); 5133 buf += n; size_left -= n; 5134 REG_WR32(qlt, 0x54, 0xFF00); 5135 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5136 buf += n; size_left -= n; 5137 REG_WR32(qlt, 0x54, 0xFF10); 5138 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5139 buf += n; size_left -= n; 5140 REG_WR32(qlt, 0x54, 0xFF20); 5141 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5142 buf += n; size_left -= n; 5143 REG_WR32(qlt, 0x54, 0xFF30); 5144 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5145 buf += n; size_left -= n; 5146 REG_WR32(qlt, 0x54, 0xFF40); 5147 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5148 buf += n; size_left -= n; 5149 REG_WR32(qlt, 0x54, 0xFF50); 5150 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5151 buf += n; size_left -= n; 5152 REG_WR32(qlt, 0x54, 0xFF60); 5153 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5154 buf += n; size_left -= n; 5155 REG_WR32(qlt, 0x54, 0xFF70); 5156 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5157 buf += n; size_left -= n; 5158 n = (int)snprintf(buf, size_left, "\nRSEQ-0 registers\n"); 5159 buf += n; size_left -= n; 5160 if ((qlt->qlt_25xx_chip) || (qlt->qlt_81xx_chip)) { 5161 REG_WR32(qlt, 0x54, 0xFFC0); 5162 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5163 buf += n; size_left -= n; 5164 } 5165 REG_WR32(qlt, 0x54, 0xFFD0); 5166 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5167 buf += n; size_left -= n; 5168 n = (int)snprintf(buf, size_left, "\nRSEQ-1 registers\n"); 5169 buf += n; size_left -= n; 5170 REG_WR32(qlt, 0x54, 0xFFE0); 5171 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5172 buf += n; size_left -= n; 5173 n = (int)snprintf(buf, size_left, "\nRSEQ-2 registers\n"); 5174 buf += n; size_left -= n; 5175 REG_WR32(qlt, 0x54, 0xFFF0); 5176 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5177 buf += n; size_left -= n; 5178 5179 if ((!qlt->qlt_25xx_chip) && (!qlt->qlt_81xx_chip)) 5180 goto over_aseq_regs; 5181 5182 /* 5183 * Auxiliary sequencer registers 5184 */ 5185 n = (int)snprintf(buf, size_left, "\nASEQ GP Registers\n"); 5186 buf += n; size_left -= n; 5187 REG_WR32(qlt, 0x54, 0xB000); 5188 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5189 buf += n; size_left -= n; 5190 REG_WR32(qlt, 0x54, 0xB010); 5191 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5192 buf += n; size_left -= n; 5193 REG_WR32(qlt, 0x54, 0xB020); 5194 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5195 buf += n; size_left -= n; 5196 REG_WR32(qlt, 0x54, 0xB030); 5197 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5198 buf += n; size_left -= n; 5199 REG_WR32(qlt, 0x54, 0xB040); 5200 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5201 buf += n; size_left -= n; 5202 REG_WR32(qlt, 0x54, 0xB050); 5203 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5204 buf += n; size_left -= n; 5205 REG_WR32(qlt, 0x54, 0xB060); 5206 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5207 buf += n; size_left -= n; 5208 REG_WR32(qlt, 0x54, 0xB070); 5209 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5210 buf += n; size_left -= n; 5211 n = (int)snprintf(buf, size_left, "\nASEQ-0 registers\n"); 5212 buf += n; size_left -= n; 5213 REG_WR32(qlt, 0x54, 0xB0C0); 5214 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5215 buf += n; size_left -= n; 5216 REG_WR32(qlt, 0x54, 0xB0D0); 5217 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5218 buf += n; size_left -= n; 5219 n = (int)snprintf(buf, size_left, "\nASEQ-1 registers\n"); 5220 buf += n; size_left -= n; 5221 REG_WR32(qlt, 0x54, 0xB0E0); 5222 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5223 buf += n; size_left -= n; 5224 n = (int)snprintf(buf, size_left, "\nASEQ-2 registers\n"); 5225 buf += n; size_left -= n; 5226 REG_WR32(qlt, 0x54, 0xB0F0); 5227 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5228 buf += n; size_left -= n; 5229 5230 over_aseq_regs:; 5231 5232 /* 5233 * Command DMA registers 5234 */ 5235 n = (int)snprintf(buf, size_left, "\nCommand DMA registers\n"); 5236 buf += n; size_left -= n; 5237 REG_WR32(qlt, 0x54, 0x7100); 5238 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5239 buf += n; size_left -= n; 5240 5241 /* 5242 * Queues 5243 */ 5244 n = (int)snprintf(buf, size_left, 5245 "\nRequest0 Queue DMA Channel registers\n"); 5246 buf += n; size_left -= n; 5247 REG_WR32(qlt, 0x54, 0x7200); 5248 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 8, size_left); 5249 buf += n; size_left -= n; 5250 n = qlt_fwdump_dump_regs(qlt, buf, 0xe4, 7, size_left); 5251 buf += n; size_left -= n; 5252 5253 n = (int)snprintf(buf, size_left, 5254 "\n\nResponse0 Queue DMA Channel registers\n"); 5255 buf += n; size_left -= n; 5256 REG_WR32(qlt, 0x54, 0x7300); 5257 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 8, size_left); 5258 buf += n; size_left -= n; 5259 n = qlt_fwdump_dump_regs(qlt, buf, 0xe4, 7, size_left); 5260 buf += n; size_left -= n; 5261 5262 n = (int)snprintf(buf, size_left, 5263 "\n\nRequest1 Queue DMA Channel registers\n"); 5264 buf += n; size_left -= n; 5265 REG_WR32(qlt, 0x54, 0x7400); 5266 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 8, size_left); 5267 buf += n; size_left -= n; 5268 n = qlt_fwdump_dump_regs(qlt, buf, 0xe4, 7, size_left); 5269 buf += n; size_left -= n; 5270 5271 /* 5272 * Transmit DMA registers 5273 */ 5274 n = (int)snprintf(buf, size_left, "\n\nXMT0 Data DMA registers\n"); 5275 buf += n; size_left -= n; 5276 REG_WR32(qlt, 0x54, 0x7600); 5277 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5278 buf += n; size_left -= n; 5279 REG_WR32(qlt, 0x54, 0x7610); 5280 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5281 buf += n; size_left -= n; 5282 n = (int)snprintf(buf, size_left, "\nXMT1 Data DMA registers\n"); 5283 buf += n; size_left -= n; 5284 REG_WR32(qlt, 0x54, 0x7620); 5285 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5286 buf += n; size_left -= n; 5287 REG_WR32(qlt, 0x54, 0x7630); 5288 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5289 buf += n; size_left -= n; 5290 n = (int)snprintf(buf, size_left, "\nXMT2 Data DMA registers\n"); 5291 buf += n; size_left -= n; 5292 REG_WR32(qlt, 0x54, 0x7640); 5293 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5294 buf += n; size_left -= n; 5295 REG_WR32(qlt, 0x54, 0x7650); 5296 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5297 buf += n; size_left -= n; 5298 n = (int)snprintf(buf, size_left, "\nXMT3 Data DMA registers\n"); 5299 buf += n; size_left -= n; 5300 REG_WR32(qlt, 0x54, 0x7660); 5301 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5302 buf += n; size_left -= n; 5303 REG_WR32(qlt, 0x54, 0x7670); 5304 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5305 buf += n; size_left -= n; 5306 n = (int)snprintf(buf, size_left, "\nXMT4 Data DMA registers\n"); 5307 buf += n; size_left -= n; 5308 REG_WR32(qlt, 0x54, 0x7680); 5309 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5310 buf += n; size_left -= n; 5311 REG_WR32(qlt, 0x54, 0x7690); 5312 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5313 buf += n; size_left -= n; 5314 n = (int)snprintf(buf, size_left, "\nXMT Data DMA Common registers\n"); 5315 buf += n; size_left -= n; 5316 REG_WR32(qlt, 0x54, 0x76A0); 5317 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5318 buf += n; size_left -= n; 5319 5320 /* 5321 * Receive DMA registers 5322 */ 5323 n = (int)snprintf(buf, size_left, 5324 "\nRCV Thread 0 Data DMA registers\n"); 5325 buf += n; size_left -= n; 5326 REG_WR32(qlt, 0x54, 0x7700); 5327 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5328 buf += n; size_left -= n; 5329 REG_WR32(qlt, 0x54, 0x7710); 5330 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5331 buf += n; size_left -= n; 5332 n = (int)snprintf(buf, size_left, 5333 "\nRCV Thread 1 Data DMA registers\n"); 5334 buf += n; size_left -= n; 5335 REG_WR32(qlt, 0x54, 0x7720); 5336 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5337 buf += n; size_left -= n; 5338 REG_WR32(qlt, 0x54, 0x7730); 5339 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5340 buf += n; size_left -= n; 5341 5342 /* 5343 * RISC registers 5344 */ 5345 n = (int)snprintf(buf, size_left, "\nRISC GP registers\n"); 5346 buf += n; size_left -= n; 5347 REG_WR32(qlt, 0x54, 0x0F00); 5348 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5349 buf += n; size_left -= n; 5350 REG_WR32(qlt, 0x54, 0x0F10); 5351 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5352 buf += n; size_left -= n; 5353 REG_WR32(qlt, 0x54, 0x0F20); 5354 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5355 buf += n; size_left -= n; 5356 REG_WR32(qlt, 0x54, 0x0F30); 5357 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5358 buf += n; size_left -= n; 5359 REG_WR32(qlt, 0x54, 0x0F40); 5360 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5361 buf += n; size_left -= n; 5362 REG_WR32(qlt, 0x54, 0x0F50); 5363 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5364 buf += n; size_left -= n; 5365 REG_WR32(qlt, 0x54, 0x0F60); 5366 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5367 buf += n; size_left -= n; 5368 REG_WR32(qlt, 0x54, 0x0F70); 5369 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5370 buf += n; size_left -= n; 5371 5372 /* 5373 * Local memory controller registers 5374 */ 5375 n = (int)snprintf(buf, size_left, "\nLMC registers\n"); 5376 buf += n; size_left -= n; 5377 REG_WR32(qlt, 0x54, 0x3000); 5378 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5379 buf += n; size_left -= n; 5380 REG_WR32(qlt, 0x54, 0x3010); 5381 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5382 buf += n; size_left -= n; 5383 REG_WR32(qlt, 0x54, 0x3020); 5384 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5385 buf += n; size_left -= n; 5386 REG_WR32(qlt, 0x54, 0x3030); 5387 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5388 buf += n; size_left -= n; 5389 REG_WR32(qlt, 0x54, 0x3040); 5390 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5391 buf += n; size_left -= n; 5392 REG_WR32(qlt, 0x54, 0x3050); 5393 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5394 buf += n; size_left -= n; 5395 REG_WR32(qlt, 0x54, 0x3060); 5396 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5397 buf += n; size_left -= n; 5398 5399 if ((qlt->qlt_25xx_chip) || (qlt->qlt_81xx_chip)) { 5400 REG_WR32(qlt, 0x54, 0x3070); 5401 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5402 buf += n; size_left -= n; 5403 } 5404 5405 /* 5406 * Fibre protocol module regsiters 5407 */ 5408 n = (int)snprintf(buf, size_left, "\nFPM hardware registers\n"); 5409 buf += n; size_left -= n; 5410 REG_WR32(qlt, 0x54, 0x4000); 5411 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5412 buf += n; size_left -= n; 5413 REG_WR32(qlt, 0x54, 0x4010); 5414 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5415 buf += n; size_left -= n; 5416 REG_WR32(qlt, 0x54, 0x4020); 5417 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5418 buf += n; size_left -= n; 5419 REG_WR32(qlt, 0x54, 0x4030); 5420 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5421 buf += n; size_left -= n; 5422 REG_WR32(qlt, 0x54, 0x4040); 5423 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5424 buf += n; size_left -= n; 5425 REG_WR32(qlt, 0x54, 0x4050); 5426 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5427 buf += n; size_left -= n; 5428 REG_WR32(qlt, 0x54, 0x4060); 5429 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5430 buf += n; size_left -= n; 5431 REG_WR32(qlt, 0x54, 0x4070); 5432 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5433 buf += n; size_left -= n; 5434 REG_WR32(qlt, 0x54, 0x4080); 5435 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5436 buf += n; size_left -= n; 5437 REG_WR32(qlt, 0x54, 0x4090); 5438 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5439 buf += n; size_left -= n; 5440 REG_WR32(qlt, 0x54, 0x40A0); 5441 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5442 buf += n; size_left -= n; 5443 REG_WR32(qlt, 0x54, 0x40B0); 5444 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5445 buf += n; size_left -= n; 5446 if (qlt->qlt_81xx_chip) { 5447 REG_WR32(qlt, 0x54, 0x40C0); 5448 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5449 buf += n; size_left -= n; 5450 REG_WR32(qlt, 0x54, 0x40D0); 5451 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5452 buf += n; size_left -= n; 5453 } 5454 5455 /* 5456 * Fibre buffer registers 5457 */ 5458 n = (int)snprintf(buf, size_left, "\nFB hardware registers\n"); 5459 buf += n; size_left -= n; 5460 REG_WR32(qlt, 0x54, 0x6000); 5461 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5462 buf += n; size_left -= n; 5463 REG_WR32(qlt, 0x54, 0x6010); 5464 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5465 buf += n; size_left -= n; 5466 REG_WR32(qlt, 0x54, 0x6020); 5467 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5468 buf += n; size_left -= n; 5469 REG_WR32(qlt, 0x54, 0x6030); 5470 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5471 buf += n; size_left -= n; 5472 REG_WR32(qlt, 0x54, 0x6040); 5473 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5474 buf += n; size_left -= n; 5475 REG_WR32(qlt, 0x54, 0x6100); 5476 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5477 buf += n; size_left -= n; 5478 REG_WR32(qlt, 0x54, 0x6130); 5479 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5480 buf += n; size_left -= n; 5481 REG_WR32(qlt, 0x54, 0x6150); 5482 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5483 buf += n; size_left -= n; 5484 REG_WR32(qlt, 0x54, 0x6170); 5485 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5486 buf += n; size_left -= n; 5487 REG_WR32(qlt, 0x54, 0x6190); 5488 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5489 buf += n; size_left -= n; 5490 REG_WR32(qlt, 0x54, 0x61B0); 5491 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5492 buf += n; size_left -= n; 5493 if (qlt->qlt_81xx_chip) { 5494 REG_WR32(qlt, 0x54, 0x61C0); 5495 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5496 buf += n; size_left -= n; 5497 } 5498 if ((qlt->qlt_25xx_chip) || (qlt->qlt_81xx_chip)) { 5499 REG_WR32(qlt, 0x54, 0x6F00); 5500 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left); 5501 buf += n; size_left -= n; 5502 } 5503 5504 qlt->intr_sneak_counter = 10; 5505 mutex_enter(&qlt->intr_lock); 5506 (void) qlt_reset_chip(qlt); 5507 drv_usecwait(20); 5508 qlt->intr_sneak_counter = 0; 5509 mutex_exit(&qlt->intr_lock); 5510 5511 /* 5512 * Memory 5513 */ 5514 n = (int)snprintf(buf, size_left, "\nCode RAM\n"); 5515 buf += n; size_left -= n; 5516 5517 addr = 0x20000; 5518 endaddr = 0x22000; 5519 words_to_read = 0; 5520 while (addr < endaddr) { 5521 words_to_read = MBOX_DMA_MEM_SIZE >> 2; 5522 if ((words_to_read + addr) > endaddr) { 5523 words_to_read = endaddr - addr; 5524 } 5525 if ((ret = qlt_read_risc_ram(qlt, addr, words_to_read)) != 5526 QLT_SUCCESS) { 5527 EL(qlt, "Error reading risc ram - CODE RAM status=" 5528 "%llxh\n", ret); 5529 goto dump_fail; 5530 } 5531 5532 n = qlt_dump_risc_ram(qlt, addr, words_to_read, buf, size_left); 5533 buf += n; size_left -= n; 5534 5535 if (size_left < 100000) { 5536 EL(qlt, "run out of space - CODE RAM size_left=%d\n", 5537 size_left); 5538 goto dump_ok; 5539 } 5540 addr += words_to_read; 5541 } 5542 5543 n = (int)snprintf(buf, size_left, "\nExternal Memory\n"); 5544 buf += n; size_left -= n; 5545 5546 addr = 0x100000; 5547 endaddr = (((uint32_t)(qlt->fw_endaddrhi)) << 16) | qlt->fw_endaddrlo; 5548 endaddr++; 5549 if (endaddr & 7) { 5550 endaddr = (endaddr + 7) & 0xFFFFFFF8; 5551 } 5552 5553 words_to_read = 0; 5554 while (addr < endaddr) { 5555 words_to_read = MBOX_DMA_MEM_SIZE >> 2; 5556 if ((words_to_read + addr) > endaddr) { 5557 words_to_read = endaddr - addr; 5558 } 5559 if ((ret = qlt_read_risc_ram(qlt, addr, words_to_read)) != 5560 QLT_SUCCESS) { 5561 EL(qlt, "Error reading risc ram - EXT RAM status=" 5562 "%llxh\n", ret); 5563 goto dump_fail; 5564 } 5565 n = qlt_dump_risc_ram(qlt, addr, words_to_read, buf, size_left); 5566 buf += n; size_left -= n; 5567 if (size_left < 100000) { 5568 EL(qlt, "run out of space - EXT RAM\n"); 5569 goto dump_ok; 5570 } 5571 addr += words_to_read; 5572 } 5573 5574 /* 5575 * Label the end tag 5576 */ 5577 n = (int)snprintf(buf, size_left, "[<==END] ISP Debug Dump\n"); 5578 buf += n; size_left -= n; 5579 5580 /* 5581 * Queue dumping 5582 */ 5583 n = (int)snprintf(buf, size_left, "\nRequest Queue\n"); 5584 buf += n; size_left -= n; 5585 n = qlt_dump_queue(qlt, qlt->queue_mem_ptr + REQUEST_QUEUE_OFFSET, 5586 REQUEST_QUEUE_ENTRIES, buf, size_left); 5587 buf += n; size_left -= n; 5588 5589 n = (int)snprintf(buf, size_left, "\nPriority Queue\n"); 5590 buf += n; size_left -= n; 5591 n = qlt_dump_queue(qlt, qlt->queue_mem_ptr + PRIORITY_QUEUE_OFFSET, 5592 PRIORITY_QUEUE_ENTRIES, buf, size_left); 5593 buf += n; size_left -= n; 5594 5595 n = (int)snprintf(buf, size_left, "\nResponse Queue\n"); 5596 buf += n; size_left -= n; 5597 n = qlt_dump_queue(qlt, qlt->queue_mem_ptr + RESPONSE_QUEUE_OFFSET, 5598 RESPONSE_QUEUE_ENTRIES, buf, size_left); 5599 buf += n; size_left -= n; 5600 5601 n = (int)snprintf(buf, size_left, "\nATIO queue\n"); 5602 buf += n; size_left -= n; 5603 n = qlt_dump_queue(qlt, qlt->queue_mem_ptr + ATIO_QUEUE_OFFSET, 5604 ATIO_QUEUE_ENTRIES, buf, size_left); 5605 buf += n; size_left -= n; 5606 5607 /* 5608 * Label dump reason 5609 */ 5610 n = (int)snprintf(buf, size_left, "\nFirmware dump reason: %s-%s\n", 5611 qlt->qlt_port_alias, ssci->st_additional_info); 5612 buf += n; size_left -= n; 5613 5614 dump_ok: 5615 EL(qlt, "left-%d\n", size_left); 5616 5617 mutex_enter(&qlt->qlt_ioctl_lock); 5618 qlt->qlt_ioctl_flags &= 5619 ~(QLT_FWDUMP_INPROGRESS | QLT_FWDUMP_FETCHED_BY_USER); 5620 qlt->qlt_ioctl_flags |= QLT_FWDUMP_ISVALID; 5621 mutex_exit(&qlt->qlt_ioctl_lock); 5622 return (FCT_SUCCESS); 5623 5624 dump_fail: 5625 EL(qlt, "dump not done\n"); 5626 mutex_enter(&qlt->qlt_ioctl_lock); 5627 qlt->qlt_ioctl_flags &= QLT_IOCTL_FLAG_MASK; 5628 mutex_exit(&qlt->qlt_ioctl_lock); 5629 return (FCT_FAILURE); 5630 } 5631 5632 static int 5633 qlt_fwdump_dump_regs(qlt_state_t *qlt, caddr_t buf, int startaddr, int count, 5634 uint_t size_left) 5635 { 5636 int i; 5637 int n; 5638 char c = ' '; 5639 5640 for (i = 0, n = 0; i < count; i++) { 5641 if ((i + 1) & 7) { 5642 c = ' '; 5643 } else { 5644 c = '\n'; 5645 } 5646 n = (int)(n + (int)snprintf(&buf[n], (uint_t)(size_left - n), 5647 "%08x%c", REG_RD32(qlt, startaddr + (i << 2)), c)); 5648 } 5649 return (n); 5650 } 5651 5652 static int 5653 qlt_dump_risc_ram(qlt_state_t *qlt, uint32_t addr, uint32_t words, 5654 caddr_t buf, uint_t size_left) 5655 { 5656 int i; 5657 int n; 5658 char c = ' '; 5659 uint32_t *ptr; 5660 5661 ptr = (uint32_t *)((caddr_t)qlt->queue_mem_ptr + MBOX_DMA_MEM_OFFSET); 5662 for (i = 0, n = 0; i < words; i++) { 5663 if ((i & 7) == 0) { 5664 n = (int)(n + (int)snprintf(&buf[n], 5665 (uint_t)(size_left - n), "%08x: ", addr + i)); 5666 } 5667 if ((i + 1) & 7) { 5668 c = ' '; 5669 } else { 5670 c = '\n'; 5671 } 5672 n = (int)(n + (int)snprintf(&buf[n], (uint_t)(size_left - n), 5673 "%08x%c", ptr[i], c)); 5674 } 5675 return (n); 5676 } 5677 5678 static int 5679 qlt_dump_queue(qlt_state_t *qlt, caddr_t qadr, int entries, caddr_t buf, 5680 uint_t size_left) 5681 { 5682 int i; 5683 int n; 5684 char c = ' '; 5685 int words; 5686 uint16_t *ptr; 5687 uint16_t w; 5688 5689 words = entries * 32; 5690 ptr = (uint16_t *)qadr; 5691 for (i = 0, n = 0; i < words; i++) { 5692 if ((i & 7) == 0) { 5693 n = (int)(n + (int)snprintf(&buf[n], 5694 (uint_t)(size_left - n), "%05x: ", i)); 5695 } 5696 if ((i + 1) & 7) { 5697 c = ' '; 5698 } else { 5699 c = '\n'; 5700 } 5701 w = QMEM_RD16(qlt, &ptr[i]); 5702 n = (int)(n + (int)snprintf(&buf[n], (size_left - n), "%04x%c", 5703 w, c)); 5704 } 5705 return (n); 5706 } 5707 5708 /* 5709 * Only called by debug dump. Interrupts are disabled and mailboxes alongwith 5710 * mailbox ram is available. 5711 * Copy data from RISC RAM to system memory 5712 */ 5713 static fct_status_t 5714 qlt_read_risc_ram(qlt_state_t *qlt, uint32_t addr, uint32_t words) 5715 { 5716 uint64_t da; 5717 fct_status_t ret; 5718 5719 REG_WR16(qlt, REG_MBOX(0), MBC_DUMP_RAM_EXTENDED); 5720 da = qlt->queue_mem_cookie.dmac_laddress; 5721 da += MBOX_DMA_MEM_OFFSET; 5722 5723 /* System destination address */ 5724 REG_WR16(qlt, REG_MBOX(3), LSW(LSD(da))); 5725 REG_WR16(qlt, REG_MBOX(2), MSW(LSD(da))); 5726 REG_WR16(qlt, REG_MBOX(7), LSW(MSD(da))); 5727 REG_WR16(qlt, REG_MBOX(6), MSW(MSD(da))); 5728 5729 /* Length */ 5730 REG_WR16(qlt, REG_MBOX(5), LSW(words)); 5731 REG_WR16(qlt, REG_MBOX(4), MSW(words)); 5732 5733 /* RISC source address */ 5734 REG_WR16(qlt, REG_MBOX(1), LSW(addr)); 5735 REG_WR16(qlt, REG_MBOX(8), MSW(addr)); 5736 5737 ret = qlt_raw_mailbox_command(qlt); 5738 REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR)); 5739 if (ret == QLT_SUCCESS) { 5740 (void) ddi_dma_sync(qlt->queue_mem_dma_handle, 5741 MBOX_DMA_MEM_OFFSET, words << 2, DDI_DMA_SYNC_FORCPU); 5742 } else { 5743 EL(qlt, "qlt_raw_mailbox_command=ch status=%llxh\n", ret); 5744 } 5745 return (ret); 5746 } 5747 5748 static void 5749 qlt_verify_fw(qlt_state_t *qlt) 5750 { 5751 caddr_t req; 5752 /* Just put it on the request queue */ 5753 mutex_enter(&qlt->req_lock); 5754 req = qlt_get_req_entries(qlt, 1); 5755 if (req == NULL) { 5756 mutex_exit(&qlt->req_lock); 5757 /* XXX handle this */ 5758 return; 5759 } 5760 5761 bzero(req, IOCB_SIZE); 5762 5763 req[0] = 0x1b; 5764 req[1] = 1; 5765 5766 QMEM_WR32(qlt, (&req[4]), 0xffffffff); 5767 QMEM_WR16(qlt, (&req[0x8]), 1); /* options - don't update */ 5768 QMEM_WR32(qlt, (&req[0x14]), 0x80010300); 5769 5770 qlt_submit_req_entries(qlt, 1); 5771 mutex_exit(&qlt->req_lock); 5772 } 5773 5774 static void 5775 qlt_handle_verify_fw_completion(qlt_state_t *qlt, uint8_t *rsp) 5776 { 5777 uint16_t status; 5778 char info[80]; 5779 5780 status = QMEM_RD16(qlt, rsp+8); 5781 if (status != 0) { 5782 (void) snprintf(info, 80, "qlt_handle_verify_fw_completion: " 5783 "status:%x, rsp:%p", status, (void *)rsp); 5784 if (status == 3) { 5785 uint16_t error_code; 5786 5787 error_code = QMEM_RD16(qlt, rsp+0xA); 5788 (void) snprintf(info, 80, "qlt_handle_verify_fw_" 5789 "completion: error code:%x", error_code); 5790 } 5791 } 5792 } 5793 5794 /* 5795 * qlt_el_trace_desc_ctor - Construct an extended logging trace descriptor. 5796 * 5797 * Input: Pointer to the adapter state structure. 5798 * Returns: Success or Failure. 5799 * Context: Kernel context. 5800 */ 5801 static int 5802 qlt_el_trace_desc_ctor(qlt_state_t *qlt) 5803 { 5804 int rval = DDI_SUCCESS; 5805 5806 qlt->el_trace_desc = (qlt_el_trace_desc_t *) 5807 kmem_zalloc(sizeof (qlt_el_trace_desc_t), KM_SLEEP); 5808 5809 if (qlt->el_trace_desc == NULL) { 5810 cmn_err(CE_WARN, "qlt(%d): can't construct trace descriptor", 5811 qlt->instance); 5812 rval = DDI_FAILURE; 5813 } else { 5814 qlt->el_trace_desc->next = 0; 5815 qlt->el_trace_desc->trace_buffer = 5816 (char *)kmem_zalloc(EL_TRACE_BUF_SIZE, KM_SLEEP); 5817 5818 if (qlt->el_trace_desc->trace_buffer == NULL) { 5819 cmn_err(CE_WARN, "qlt(%d): can't get trace buffer", 5820 qlt->instance); 5821 kmem_free(qlt->el_trace_desc, 5822 sizeof (qlt_el_trace_desc_t)); 5823 qlt->el_trace_desc = NULL; 5824 rval = DDI_FAILURE; 5825 } else { 5826 qlt->el_trace_desc->trace_buffer_size = 5827 EL_TRACE_BUF_SIZE; 5828 mutex_init(&qlt->el_trace_desc->mutex, NULL, 5829 MUTEX_DRIVER, NULL); 5830 } 5831 } 5832 5833 return (rval); 5834 } 5835 5836 /* 5837 * qlt_el_trace_desc_dtor - Destroy an extended logging trace descriptor. 5838 * 5839 * Input: Pointer to the adapter state structure. 5840 * Returns: Success or Failure. 5841 * Context: Kernel context. 5842 */ 5843 static int 5844 qlt_el_trace_desc_dtor(qlt_state_t *qlt) 5845 { 5846 int rval = DDI_SUCCESS; 5847 5848 if (qlt->el_trace_desc == NULL) { 5849 cmn_err(CE_WARN, "qlt(%d): can't destroy el trace descriptor", 5850 qlt->instance); 5851 rval = DDI_FAILURE; 5852 } else { 5853 if (qlt->el_trace_desc->trace_buffer != NULL) { 5854 kmem_free(qlt->el_trace_desc->trace_buffer, 5855 qlt->el_trace_desc->trace_buffer_size); 5856 } 5857 mutex_destroy(&qlt->el_trace_desc->mutex); 5858 kmem_free(qlt->el_trace_desc, sizeof (qlt_el_trace_desc_t)); 5859 qlt->el_trace_desc = NULL; 5860 } 5861 5862 return (rval); 5863 } 5864 5865 /* 5866 * qlt_el_msg 5867 * Extended logging message 5868 * 5869 * Input: 5870 * qlt: adapter state pointer. 5871 * fn: function name. 5872 * ce: level 5873 * ...: Variable argument list. 5874 * 5875 * Context: 5876 * Kernel/Interrupt context. 5877 */ 5878 void 5879 qlt_el_msg(qlt_state_t *qlt, const char *fn, int ce, ...) 5880 { 5881 char *s, *fmt = 0, *fmt1 = 0; 5882 char fmt2[EL_BUFFER_RESERVE]; 5883 int rval, tmp; 5884 int tracing = 0; 5885 va_list vl; 5886 5887 /* Tracing is the default but it can be disabled. */ 5888 if ((rval = qlt_validate_trace_desc(qlt)) == DDI_SUCCESS) { 5889 tracing = 1; 5890 5891 mutex_enter(&qlt->el_trace_desc->mutex); 5892 5893 /* 5894 * Ensure enough space for the string. Wrap to 5895 * start when default message allocation size 5896 * would overrun the end. 5897 */ 5898 if ((qlt->el_trace_desc->next + EL_BUFFER_RESERVE) >= 5899 qlt->el_trace_desc->trace_buffer_size) { 5900 fmt = qlt->el_trace_desc->trace_buffer; 5901 qlt->el_trace_desc->next = 0; 5902 } else { 5903 fmt = qlt->el_trace_desc->trace_buffer + 5904 qlt->el_trace_desc->next; 5905 } 5906 } 5907 5908 /* if no buffer use the stack */ 5909 if (fmt == NULL) { 5910 fmt = fmt2; 5911 } 5912 5913 va_start(vl, ce); 5914 5915 s = va_arg(vl, char *); 5916 5917 rval = (int)snprintf(fmt, (size_t)EL_BUFFER_RESERVE, 5918 "QEL qlt(%d): %s, ", qlt->instance, fn); 5919 fmt1 = fmt + rval; 5920 tmp = (int)vsnprintf(fmt1, 5921 (size_t)(uint32_t)((int)EL_BUFFER_RESERVE - rval), s, vl); 5922 rval += tmp; 5923 5924 /* 5925 * Calculate the offset where the next message will go, 5926 * skipping the NULL. 5927 */ 5928 if (tracing) { 5929 uint16_t next = (uint16_t)(rval += 1); 5930 qlt->el_trace_desc->next += next; 5931 mutex_exit(&qlt->el_trace_desc->mutex); 5932 } 5933 5934 if (enable_extended_logging) { 5935 cmn_err(ce, fmt); 5936 } 5937 5938 va_end(vl); 5939 } 5940 5941 /* 5942 * qlt_dump_el_trace_buffer 5943 * Outputs extended logging trace buffer. 5944 * 5945 * Input: 5946 * qlt: adapter state pointer. 5947 */ 5948 void 5949 qlt_dump_el_trace_buffer(qlt_state_t *qlt) 5950 { 5951 char *dump_start = NULL; 5952 char *dump_current = NULL; 5953 char *trace_start; 5954 char *trace_end; 5955 int wrapped = 0; 5956 int rval; 5957 5958 mutex_enter(&qlt->el_trace_desc->mutex); 5959 5960 rval = qlt_validate_trace_desc(qlt); 5961 if (rval != NULL) { 5962 cmn_err(CE_CONT, "qlt(%d) Dump EL trace - invalid desc\n", 5963 qlt->instance); 5964 } else if ((dump_start = qlt_find_trace_start(qlt)) != NULL) { 5965 dump_current = dump_start; 5966 trace_start = qlt->el_trace_desc->trace_buffer; 5967 trace_end = trace_start + 5968 qlt->el_trace_desc->trace_buffer_size; 5969 5970 cmn_err(CE_CONT, "qlt(%d) Dump EL trace - start %p %p\n", 5971 qlt->instance, 5972 (void *)dump_start, (void *)trace_start); 5973 5974 while (((uintptr_t)dump_current - (uintptr_t)trace_start) <= 5975 (uintptr_t)qlt->el_trace_desc->trace_buffer_size) { 5976 /* Show it... */ 5977 cmn_err(CE_CONT, "%p - %s", (void *)dump_current, 5978 dump_current); 5979 /* Make the next the current */ 5980 dump_current += (strlen(dump_current) + 1); 5981 /* check for wrap */ 5982 if ((dump_current + EL_BUFFER_RESERVE) >= trace_end) { 5983 dump_current = trace_start; 5984 wrapped = 1; 5985 } else if (wrapped) { 5986 /* Don't go past next. */ 5987 if ((trace_start + qlt->el_trace_desc->next) <= 5988 dump_current) { 5989 break; 5990 } 5991 } else if (*dump_current == NULL) { 5992 break; 5993 } 5994 } 5995 } 5996 mutex_exit(&qlt->el_trace_desc->mutex); 5997 } 5998 5999 /* 6000 * qlt_validate_trace_desc 6001 * Ensures the extended logging trace descriptor is good. 6002 * 6003 * Input: 6004 * qlt: adapter state pointer. 6005 * 6006 * Returns: 6007 * ql local function return status code. 6008 */ 6009 static int 6010 qlt_validate_trace_desc(qlt_state_t *qlt) 6011 { 6012 int rval = DDI_SUCCESS; 6013 6014 if (qlt->el_trace_desc == NULL) { 6015 rval = DDI_FAILURE; 6016 } else if (qlt->el_trace_desc->trace_buffer == NULL) { 6017 rval = DDI_FAILURE; 6018 } 6019 return (rval); 6020 } 6021 6022 /* 6023 * qlt_find_trace_start 6024 * Locate the oldest extended logging trace entry. 6025 * 6026 * Input: 6027 * qlt: adapter state pointer. 6028 * 6029 * Returns: 6030 * Pointer to a string. 6031 * 6032 * Context: 6033 * Kernel/Interrupt context. 6034 */ 6035 static char * 6036 qlt_find_trace_start(qlt_state_t *qlt) 6037 { 6038 char *trace_start = 0; 6039 char *trace_next = 0; 6040 6041 trace_next = qlt->el_trace_desc->trace_buffer + 6042 qlt->el_trace_desc->next; 6043 6044 /* 6045 * If the buffer has not wrapped next will point at a null so 6046 * start is the beginning of the buffer. If next points at a char 6047 * then we must traverse the buffer until a null is detected and 6048 * that will be the beginning of the oldest whole object in the buffer 6049 * which is the start. 6050 */ 6051 6052 if ((trace_next + EL_BUFFER_RESERVE) >= 6053 (qlt->el_trace_desc->trace_buffer + 6054 qlt->el_trace_desc->trace_buffer_size)) { 6055 trace_start = qlt->el_trace_desc->trace_buffer; 6056 } else if (*trace_next != NULL) { 6057 trace_start = trace_next + (strlen(trace_next) + 1); 6058 } else { 6059 trace_start = qlt->el_trace_desc->trace_buffer; 6060 } 6061 return (trace_start); 6062 } 6063 6064 6065 static int 6066 qlt_read_int_prop(qlt_state_t *qlt, char *prop, int defval) 6067 { 6068 return (ddi_getprop(DDI_DEV_T_ANY, qlt->dip, 6069 DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, prop, defval)); 6070 } 6071 6072 static int 6073 qlt_read_string_prop(qlt_state_t *qlt, char *prop, char **prop_val) 6074 { 6075 return (ddi_prop_lookup_string(DDI_DEV_T_ANY, qlt->dip, 6076 DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, prop, prop_val)); 6077 } 6078 6079 static int 6080 qlt_read_int_instance_prop(qlt_state_t *qlt, char *prop, int defval) 6081 { 6082 char inst_prop[256]; 6083 int val; 6084 6085 /* 6086 * Get adapter instance specific parameters. If the instance 6087 * specific parameter isn't there, try the global parameter. 6088 */ 6089 6090 (void) sprintf(inst_prop, "hba%d-%s", qlt->instance, prop); 6091 6092 if ((val = qlt_read_int_prop(qlt, inst_prop, defval)) == defval) { 6093 val = qlt_read_int_prop(qlt, prop, defval); 6094 } 6095 6096 return (val); 6097 } 6098 6099 static int 6100 qlt_read_string_instance_prop(qlt_state_t *qlt, char *prop, char **prop_val) 6101 { 6102 char instance_prop[256]; 6103 6104 /* Get adapter instance specific parameter. */ 6105 (void) sprintf(instance_prop, "hba%d-%s", qlt->instance, prop); 6106 return (qlt_read_string_prop(qlt, instance_prop, prop_val)); 6107 } 6108 6109 static int 6110 qlt_convert_string_to_ull(char *prop, int radix, 6111 u_longlong_t *result) 6112 { 6113 return (ddi_strtoull((const char *)prop, 0, radix, result)); 6114 } 6115 6116 static boolean_t 6117 qlt_wwn_overload_prop(qlt_state_t *qlt) 6118 { 6119 char *prop_val = 0; 6120 int rval; 6121 int radix; 6122 u_longlong_t wwnn = 0, wwpn = 0; 6123 boolean_t overloaded = FALSE; 6124 6125 radix = 16; 6126 6127 rval = qlt_read_string_instance_prop(qlt, "adapter-wwnn", &prop_val); 6128 if (rval == DDI_PROP_SUCCESS) { 6129 rval = qlt_convert_string_to_ull(prop_val, radix, &wwnn); 6130 } 6131 if (rval == DDI_PROP_SUCCESS) { 6132 rval = qlt_read_string_instance_prop(qlt, "adapter-wwpn", 6133 &prop_val); 6134 if (rval == DDI_PROP_SUCCESS) { 6135 rval = qlt_convert_string_to_ull(prop_val, radix, 6136 &wwpn); 6137 } 6138 } 6139 if (rval == DDI_PROP_SUCCESS) { 6140 overloaded = TRUE; 6141 /* Overload the current node/port name nvram copy */ 6142 bcopy((char *)&wwnn, qlt->nvram->node_name, 8); 6143 BIG_ENDIAN_64(qlt->nvram->node_name); 6144 bcopy((char *)&wwpn, qlt->nvram->port_name, 8); 6145 BIG_ENDIAN_64(qlt->nvram->port_name); 6146 } 6147 return (overloaded); 6148 } 6149 6150 /* 6151 * prop_text - Return a pointer to a string describing the status 6152 * 6153 * Input: prop_status = the return status from a property function. 6154 * Returns: pointer to a string. 6155 * Context: Kernel context. 6156 */ 6157 char * 6158 prop_text(int prop_status) 6159 { 6160 string_table_t *entry = &prop_status_tbl[0]; 6161 6162 return (value2string(entry, prop_status, 0xFFFF)); 6163 } 6164 6165 /* 6166 * value2string Return a pointer to a string associated with the value 6167 * 6168 * Input: entry = the value to string table 6169 * value = the value 6170 * Returns: pointer to a string. 6171 * Context: Kernel context. 6172 */ 6173 char * 6174 value2string(string_table_t *entry, int value, int delimiter) 6175 { 6176 for (; entry->value != delimiter; entry++) { 6177 if (entry->value == value) { 6178 break; 6179 } 6180 } 6181 return (entry->string); 6182 } 6183 6184 /* 6185 * qlt_chg_endian Change endianess of byte array. 6186 * 6187 * Input: buf = array pointer. 6188 * size = size of array in bytes. 6189 * 6190 * Context: Interrupt or Kernel context. 6191 */ 6192 void 6193 qlt_chg_endian(uint8_t buf[], size_t size) 6194 { 6195 uint8_t byte; 6196 size_t cnt1; 6197 size_t cnt; 6198 6199 cnt1 = size - 1; 6200 for (cnt = 0; cnt < size / 2; cnt++) { 6201 byte = buf[cnt1]; 6202 buf[cnt1] = buf[cnt]; 6203 buf[cnt] = byte; 6204 cnt1--; 6205 } 6206 } 6207 6208 /* 6209 * ql_mps_reset 6210 * Reset MPS for FCoE functions. 6211 * 6212 * Input: 6213 * ha = virtual adapter state pointer. 6214 * 6215 * Context: 6216 * Kernel context. 6217 */ 6218 static void 6219 qlt_mps_reset(qlt_state_t *qlt) 6220 { 6221 uint32_t data, dctl = 1000; 6222 6223 do { 6224 if (dctl-- == 0 || qlt_raw_wrt_risc_ram_word(qlt, 0x7c00, 1) != 6225 QLT_SUCCESS) { 6226 return; 6227 } 6228 if (qlt_raw_rd_risc_ram_word(qlt, 0x7c00, &data) != 6229 QLT_SUCCESS) { 6230 qlt_raw_wrt_risc_ram_word(qlt, 0x7c00, 0); 6231 return; 6232 } 6233 } while (!(data & BIT_0)); 6234 6235 if (qlt_raw_rd_risc_ram_word(qlt, 0x7A15, &data) == QLT_SUCCESS) { 6236 dctl = (uint16_t)PCICFG_RD16(qlt, 0x54); 6237 if ((data & 0xe0) != (dctl & 0xe0)) { 6238 data &= 0xff1f; 6239 data |= dctl & 0xe0; 6240 qlt_raw_wrt_risc_ram_word(qlt, 0x7A15, data); 6241 } 6242 } 6243 qlt_raw_wrt_risc_ram_word(qlt, 0x7c00, 0); 6244 } 6245 6246 /* 6247 * qlt_raw_wrt_risc_ram_word 6248 * Write RISC RAM word. 6249 * 6250 * Input: qlt: adapter state pointer. 6251 * risc_address: risc ram word address. 6252 * data: data. 6253 * 6254 * Returns: qlt local function return status code. 6255 * 6256 * Context: Kernel context. 6257 */ 6258 static fct_status_t 6259 qlt_raw_wrt_risc_ram_word(qlt_state_t *qlt, uint32_t risc_address, 6260 uint32_t data) 6261 { 6262 fct_status_t ret; 6263 6264 REG_WR16(qlt, REG_MBOX(0), MBC_WRITE_RAM_EXTENDED); 6265 REG_WR16(qlt, REG_MBOX(1), LSW(risc_address)); 6266 REG_WR16(qlt, REG_MBOX(2), LSW(data)); 6267 REG_WR16(qlt, REG_MBOX(3), MSW(data)); 6268 REG_WR16(qlt, REG_MBOX(8), MSW(risc_address)); 6269 ret = qlt_raw_mailbox_command(qlt); 6270 REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR)); 6271 if (ret != QLT_SUCCESS) { 6272 EL(qlt, "qlt_raw_mailbox_command=MBC_WRITE_RAM_EXTENDED status" 6273 "=%llxh\n", ret); 6274 } 6275 return (ret); 6276 } 6277 6278 /* 6279 * ql_raw_rd_risc_ram_word 6280 * Read RISC RAM word. 6281 * 6282 * Input: qlt: adapter state pointer. 6283 * risc_address: risc ram word address. 6284 * data: data pointer. 6285 * 6286 * Returns: ql local function return status code. 6287 * 6288 * Context: Kernel context. 6289 */ 6290 static fct_status_t 6291 qlt_raw_rd_risc_ram_word(qlt_state_t *qlt, uint32_t risc_address, 6292 uint32_t *data) 6293 { 6294 fct_status_t ret; 6295 6296 REG_WR16(qlt, REG_MBOX(0), MBC_READ_RAM_EXTENDED); 6297 REG_WR16(qlt, REG_MBOX(1), LSW(risc_address)); 6298 REG_WR16(qlt, REG_MBOX(2), MSW(risc_address)); 6299 ret = qlt_raw_mailbox_command(qlt); 6300 *data = REG_RD16(qlt, REG_MBOX(2)); 6301 *data |= (REG_RD16(qlt, REG_MBOX(3)) << 16); 6302 REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR)); 6303 if (ret != QLT_SUCCESS) { 6304 EL(qlt, "qlt_raw_mailbox_command=MBC_READ_RAM_EXTENDED status" 6305 "=%llxh\n", ret); 6306 } 6307 return (ret); 6308 } 6309 6310 static void 6311 qlt_properties(qlt_state_t *qlt) 6312 { 6313 int32_t cnt = 0; 6314 int32_t defval = 0xffff; 6315 6316 if (qlt_wwn_overload_prop(qlt) == TRUE) { 6317 EL(qlt, "wwnn overloaded.\n"); 6318 } 6319 6320 if ((cnt = qlt_read_int_instance_prop(qlt, "bucketcnt2k", defval)) != 6321 defval) { 6322 qlt->qlt_bucketcnt[0] = cnt; 6323 EL(qlt, "2k bucket o/l=%d\n", cnt); 6324 } 6325 6326 if ((cnt = qlt_read_int_instance_prop(qlt, "bucketcnt8k", defval)) != 6327 defval) { 6328 qlt->qlt_bucketcnt[1] = cnt; 6329 EL(qlt, "8k bucket o/l=%d\n", cnt); 6330 } 6331 6332 if ((cnt = qlt_read_int_instance_prop(qlt, "bucketcnt64k", defval)) != 6333 defval) { 6334 qlt->qlt_bucketcnt[2] = cnt; 6335 EL(qlt, "64k bucket o/l=%d\n", cnt); 6336 } 6337 6338 if ((cnt = qlt_read_int_instance_prop(qlt, "bucketcnt128k", defval)) != 6339 defval) { 6340 qlt->qlt_bucketcnt[3] = cnt; 6341 EL(qlt, "128k bucket o/l=%d\n", cnt); 6342 } 6343 6344 if ((cnt = qlt_read_int_instance_prop(qlt, "bucketcnt256", defval)) != 6345 defval) { 6346 qlt->qlt_bucketcnt[4] = cnt; 6347 EL(qlt, "256k bucket o/l=%d\n", cnt); 6348 } 6349 } 6350