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