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.
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.
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]
23 * Copyright 2009 QLogic Corporation. All rights reserved.
24 * Use is subject to license terms.
28 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
35 #include <sys/sunddi.h>
36 #include <sys/modctl.h>
39 #include <sys/byteorder.h>
40 #include <sys/atomic.h>
41 #include <sys/scsi/scsi.h>
43 #include <sys/stmf_defines.h>
44 #include <sys/fct_defines.h>
46 #include <sys/stmf_ioctl.h>
47 #include <sys/portif.h>
52 #include "qlt_ioctl.h"
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
,
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
,
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
,
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
);
124 static fct_status_t
qlt_read_risc_ram(qlt_state_t
*qlt
, uint32_t addr
,
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
);
137 static int qlt_setup_msi(qlt_state_t
*qlt
);
138 static int qlt_setup_msix(qlt_state_t
*qlt
);
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
);
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
,
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,
156 static fct_status_t
qlt_raw_rd_risc_ram_word(qlt_state_t
*qlt
, uint32_t,
158 static void qlt_mps_reset(qlt_state_t
*qlt
);
159 static void qlt_properties(qlt_state_t
*qlt
);
162 #define SETELSBIT(bmp, els) (bmp)[((els) >> 3) & 0x1F] = \
163 (uint8_t)((bmp)[((els) >> 3) & 0x1F] | ((uint8_t)1) << ((els) & 7))
165 int qlt_enable_msix
= 0;
166 int qlt_enable_msi
= 1;
169 string_table_t prop_status_tbl
[] = DDI_PROP_STATUS();
171 /* Array to quickly calculate next free buf index to use */
173 static int qlt_nfb
[] = { 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 0xff };
176 static struct cb_ops qlt_cb_ops
= {
194 static struct dev_ops qlt_ops
= {
209 #ifndef PORT_SPEED_10G
210 #define PORT_SPEED_10G 16
213 static struct modldrv modldrv
= {
215 QLT_NAME
" "QLT_VERSION
,
219 static struct modlinkage modlinkage
= {
220 MODREV_1
, &modldrv
, NULL
223 void *qlt_state
= NULL
;
224 kmutex_t qlt_global_lock
;
225 static uint32_t qlt_loaded_counter
= 0;
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" };
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 */
249 int enable_extended_logging
= 0;
251 static char qlt_provider_name
[] = "qlt";
252 static struct stmf_port_provider
*qlt_pp
;
259 ret
= ddi_soft_state_init(&qlt_state
, sizeof (qlt_state_t
), 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
) {
268 mutex_destroy(&qlt_global_lock
);
269 ddi_soft_state_fini(&qlt_state
);
272 ret
= mod_install(&modlinkage
);
274 (void) stmf_deregister_port_provider(qlt_pp
);
276 mutex_destroy(&qlt_global_lock
);
277 ddi_soft_state_fini(&qlt_state
);
288 if (qlt_loaded_counter
)
290 ret
= mod_remove(&modlinkage
);
292 (void) stmf_deregister_port_provider(qlt_pp
);
294 mutex_destroy(&qlt_global_lock
);
295 ddi_soft_state_fini(&qlt_state
);
301 _info(struct modinfo
*modinfop
)
303 return (mod_info(&modlinkage
, modinfop
));
308 qlt_attach(dev_info_t
*dip
, ddi_attach_cmd_t cmd
)
312 ddi_device_acc_attr_t dev_acc_attr
;
319 int max_payload_size
;
322 /* No support for suspend resume yet */
323 if (cmd
!= DDI_ATTACH
)
324 return (DDI_FAILURE
);
325 instance
= ddi_get_instance(dip
);
327 if (ddi_soft_state_zalloc(qlt_state
, instance
) != DDI_SUCCESS
) {
328 return (DDI_FAILURE
);
331 if ((qlt
= (qlt_state_t
*)ddi_get_soft_state(qlt_state
, instance
)) ==
336 qlt
->instance
= instance
;
338 qlt
->nvram
= (qlt_nvram_t
*)kmem_zalloc(sizeof (qlt_nvram_t
), KM_SLEEP
);
341 if (qlt_el_trace_desc_ctor(qlt
) != DDI_SUCCESS
) {
342 cmn_err(CE_WARN
, "qlt(%d): can't setup el tracing", instance
);
346 EL(qlt
, "instance=%d, ptr=%p\n", instance
, (void *)qlt
);
348 if (pci_config_setup(dip
, &qlt
->pcicfg_acc_handle
) != DDI_SUCCESS
) {
351 did
= PCICFG_RD16(qlt
, PCI_CONF_DEVID
);
352 if ((did
!= 0x2422) && (did
!= 0x2432) &&
353 (did
!= 0x8432) && (did
!= 0x2532) &&
355 cmn_err(CE_WARN
, "qlt(%d): unknown devid(%x), failing attach",
360 if ((did
& 0xFF00) == 0x8000)
361 qlt
->qlt_81xx_chip
= 1;
362 else if ((did
& 0xFF00) == 0x2500)
363 qlt
->qlt_25xx_chip
= 1;
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
) {
373 uint32_t pci_bits
= REG_RD32(qlt
, REG_CTRL_STATUS
);
374 uint32_t slot
= pci_bits
& PCI_64_BIT_SLOT
;
377 if ((pci_bits
== 3) || (pci_bits
== 7)) {
379 "!qlt(%d): HBA running at PCI%sMHz (%d)",
380 instance
, pci_speeds
[pci_bits
], pci_bits
);
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
);
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
);
398 if (ddi_dma_alloc_handle(dip
, &qlt_queue_dma_attr
, DDI_DMA_SLEEP
,
399 0, &qlt
->queue_mem_dma_handle
) != DDI_SUCCESS
) {
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
) !=
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
) {
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
;
421 /* mutex are inited in this function */
422 if (qlt_setup_interrupts(qlt
) != DDI_SUCCESS
)
425 (void) snprintf(qlt
->qlt_minor_name
, sizeof (qlt
->qlt_minor_name
),
427 (void) snprintf(qlt
->qlt_port_alias
, sizeof (qlt
->qlt_port_alias
),
428 "%s,0", qlt
->qlt_minor_name
);
430 if (ddi_create_minor_node(dip
, qlt
->qlt_minor_name
, S_IFCHR
,
431 instance
, DDI_NT_STMF_PP
, 0) != DDI_SUCCESS
) {
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
);
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
;
444 if (max_read_size
== 512)
446 else if (max_read_size
== 1024)
448 else if (max_read_size
== 2048)
450 else if (max_read_size
== 4096)
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
;
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)
466 else if (max_read_size
== 256)
468 else if (max_read_size
== 512)
470 else if (max_read_size
== 1024)
472 else if (max_read_size
== 2048)
474 else if (max_read_size
== 4096)
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",
481 goto over_max_read_xfer_setting
;
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
);
488 cmn_err(CE_WARN
, "qlt(%d): dont know how to set "
489 "pci-max-read-request for this device (%x)",
492 over_max_read_xfer_setting
:;
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)
501 else if (max_payload_size
== 256)
503 else if (max_payload_size
== 512)
505 else if (max_payload_size
== 1024)
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",
512 goto over_max_payload_setting
;
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
);
519 cmn_err(CE_WARN
, "qlt(%d): dont know how to set "
520 "pcie-max-payload-size for this device (%x)",
524 over_max_payload_setting
:;
526 qlt_enable_intr(qlt
);
528 if (qlt_port_start((caddr_t
)qlt
) != QLT_SUCCESS
)
532 return (DDI_SUCCESS
);
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
);
540 qlt_destroy_mutex(qlt
);
541 qlt_release_intr(qlt
);
543 (void) ddi_dma_unbind_handle(qlt
->queue_mem_dma_handle
);
545 ddi_dma_mem_free(&qlt
->queue_mem_acc_handle
);
547 ddi_dma_free_handle(&qlt
->queue_mem_dma_handle
);
549 ddi_regs_map_free(&qlt
->regs_acc_handle
);
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
);
556 ddi_soft_state_free(qlt_state
, instance
);
557 return (DDI_FAILURE
);
560 #define FCT_I_EVENT_BRING_PORT_OFFLINE 0x83
564 qlt_detach(dev_info_t
*dip
, ddi_detach_cmd_t cmd
)
570 instance
= ddi_get_instance(dip
);
571 if ((qlt
= (qlt_state_t
*)ddi_get_soft_state(qlt_state
, instance
)) ==
573 return (DDI_FAILURE
);
576 if (qlt
->fw_code01
) {
577 return (DDI_FAILURE
);
580 if ((qlt
->qlt_state
!= FCT_STATE_OFFLINE
) ||
581 qlt
->qlt_state_not_acked
) {
582 return (DDI_FAILURE
);
584 if (qlt_port_stop((caddr_t
)qlt
) != FCT_SUCCESS
) {
585 return (DDI_FAILURE
);
588 qlt_disable_intr(qlt
);
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
);
604 return (DDI_SUCCESS
);
608 * qlt_quiesce quiesce a device attached to the system.
611 qlt_quiesce(dev_info_t
*dip
)
617 qlt
= ddi_get_soft_state(qlt_state
, ddi_get_instance(dip
));
620 return (DDI_SUCCESS
);
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
));
634 REG_WR32(qlt
, REG_HCCR
,
635 HCCR_CMD(CLEAR_HOST_TO_RISC_INTR
));
639 /* Reset the chip. */
640 REG_WR32(qlt
, REG_CTRL_STATUS
, CHIP_SOFT_RESET
| DMA_SHUTDOWN_CTRL
|
644 qlt_disable_intr(qlt
);
646 return (DDI_SUCCESS
);
650 qlt_enable_intr(qlt_state_t
*qlt
)
652 if (qlt
->intr_cap
& DDI_INTR_FLAG_BLOCK
) {
653 (void) ddi_intr_block_enable(qlt
->htable
, qlt
->intr_cnt
);
656 for (i
= 0; i
< qlt
->intr_cnt
; i
++)
657 (void) ddi_intr_enable(qlt
->htable
[i
]);
659 qlt
->qlt_intr_enabled
= 1;
663 qlt_disable_intr(qlt_state_t
*qlt
)
665 if (qlt
->intr_cap
& DDI_INTR_FLAG_BLOCK
) {
666 (void) ddi_intr_block_disable(qlt
->htable
, qlt
->intr_cnt
);
669 for (i
= 0; i
< qlt
->intr_cnt
; i
++)
670 (void) ddi_intr_disable(qlt
->htable
[i
]);
672 qlt
->qlt_intr_enabled
= 0;
676 qlt_release_intr(qlt_state_t
*qlt
)
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
]);
684 kmem_free(qlt
->htable
, (uint_t
)qlt
->intr_size
);
695 qlt_init_mutex(qlt_state_t
*qlt
)
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 *));
708 qlt_destroy_mutex(qlt_state_t
*qlt
)
710 mutex_destroy(&qlt
->req_lock
);
711 mutex_destroy(&qlt
->preq_lock
);
712 mutex_destroy(&qlt
->mbox_lock
);
713 mutex_destroy(&qlt
->intr_lock
);
718 qlt_setup_msix(qlt_state_t
*qlt
)
720 int count
, avail
, actual
;
722 int itype
= DDI_INTR_TYPE_MSIX
;
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
,
729 return (DDI_FAILURE
);
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
,
735 return (DDI_FAILURE
);
738 stmf_trace(qlt
->qlt_port_alias
,
739 "qlt_setup_msix: nintrs=%d,avail=%d", count
, avail
);
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
,
753 if (actual
< count
) {
754 EL(qlt
, "requested: %d, received: %d\n", count
, actual
);
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
);
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
);
774 (void) ddi_intr_get_cap(qlt
->htable
[0], &qlt
->intr_cap
);
775 qlt
->intr_flags
|= QLT_INTR_MSIX
;
776 return (DDI_SUCCESS
);
779 qlt_destroy_mutex(qlt
);
781 for (i
= 0; i
< actual
; i
++)
782 (void) ddi_intr_free(qlt
->htable
[i
]);
786 kmem_free(qlt
->htable
, (uint_t
)qlt
->intr_size
);
788 qlt_release_intr(qlt
);
794 qlt_setup_msi(qlt_state_t
*qlt
)
796 int count
, avail
, actual
;
797 int itype
= DDI_INTR_TYPE_MSI
;
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
,
806 return (DDI_FAILURE
);
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
,
812 return (DDI_FAILURE
);
815 EL(qlt
, "nintrs=%d, avail=%d\n", count
, avail
);
817 /* MSI requires only 1 interrupt. */
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
,
831 if (actual
< count
) {
832 EL(qlt
, "requested: %d, received: %d\n", count
, actual
);
834 qlt
->intr_cnt
= actual
;
837 * Get priority for first msi, assume remaining are all the same.
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
);
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
);
857 (void) ddi_intr_get_cap(qlt
->htable
[0], &qlt
->intr_cap
);
858 qlt
->intr_flags
|= QLT_INTR_MSI
;
859 return (DDI_SUCCESS
);
862 qlt_destroy_mutex(qlt
);
864 for (i
= 0; i
< actual
; i
++)
865 (void) ddi_intr_free(qlt
->htable
[i
]);
867 kmem_free(qlt
->htable
, (uint_t
)qlt
->intr_size
);
869 qlt_release_intr(qlt
);
874 qlt_setup_fixed(qlt_state_t
*qlt
)
879 int itype
= DDI_INTR_TYPE_FIXED
;
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
,
886 return (DDI_FAILURE
);
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
,
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
);
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
);
914 qlt
->intr_flags
|= QLT_INTR_FIXED
;
915 return (DDI_SUCCESS
);
918 qlt_destroy_mutex(qlt
);
920 (void) ddi_intr_free(qlt
->htable
[0]);
922 kmem_free(qlt
->htable
, (uint_t
)qlt
->intr_size
);
924 qlt_release_intr(qlt
);
929 qlt_setup_interrupts(qlt_state_t
*qlt
)
934 * x86 has a bug in the ddi_intr_block_enable/disable area (6562198).
937 if (qlt_enable_msi
!= 0) {
939 if (ddi_intr_get_supported_types(qlt
->dip
, &itypes
) != DDI_SUCCESS
) {
940 itypes
= DDI_INTR_TYPE_FIXED
;
943 if (qlt_enable_msix
&& (itypes
& DDI_INTR_TYPE_MSIX
)) {
944 if (qlt_setup_msix(qlt
) == DDI_SUCCESS
)
945 return (DDI_SUCCESS
);
948 if (itypes
& DDI_INTR_TYPE_MSI
) {
949 if (qlt_setup_msi(qlt
) == DDI_SUCCESS
)
950 return (DDI_SUCCESS
);
955 return (qlt_setup_fixed(qlt
));
959 * Filling the hba attributes
962 qlt_populate_hba_fru_details(struct fct_local_port
*port
,
963 struct fct_port_attrs
*port_attrs
)
967 qlt_state_t
*qlt
= (qlt_state_t
*)port
->port_fca_private
;
969 (void) snprintf(port_attrs
->manufacturer
, FCHBA_MANUFACTURER_LEN
,
971 (void) snprintf(port_attrs
->driver_name
, FCHBA_DRIVER_NAME_LEN
,
973 (void) snprintf(port_attrs
->driver_version
, FCHBA_DRIVER_VERSION_LEN
,
975 port_attrs
->serial_number
[0] = '\0';
976 port_attrs
->hardware_version
[0] = '\0';
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
);
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
);
992 (void) snprintf(port_attrs
->option_rom_version
,
993 FCHBA_OPTION_ROM_VERSION_LEN
, "No Fcode found");
995 (void) snprintf(port_attrs
->option_rom_version
,
996 FCHBA_OPTION_ROM_VERSION_LEN
, "N/A");
999 port_attrs
->vendor_specific_id
= qlt
->nvram
->subsystem_vendor_id
[0] |
1000 qlt
->nvram
->subsystem_vendor_id
[1] << 8;
1002 port_attrs
->max_frame_size
= qlt
->nvram
->max_frame_length
[1] << 8 |
1003 qlt
->nvram
->max_frame_length
[0];
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
|
1011 if (qlt
->qlt_81xx_chip
)
1012 port_attrs
->supported_speed
= PORT_SPEED_10G
;
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
);
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
);
1028 qlt_info(uint32_t cmd
, fct_local_port_t
*port
,
1029 void *arg
, uint8_t *buf
, uint32_t *bufsizep
)
1031 qlt_state_t
*qlt
= (qlt_state_t
*)port
->port_fca_private
;
1033 fct_status_t ret
= FCT_SUCCESS
;
1035 fct_port_link_status_t
*link_status
;
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
));
1046 /* send mailbox command to get link status */
1047 mcp
= qlt_alloc_mailbox_command(qlt
, 156);
1049 EL(qlt
, "qlt_alloc_mailbox_command mcp=null\n");
1050 ret
= FCT_ALLOC_FAILURE
;
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
;
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
);
1066 qlt_dmem_dma_sync(mcp
->dbuf
, DDI_DMA_SYNC_FORCPU
);
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)));
1080 qlt_free_mailbox_command(qlt
, mcp
);
1083 EL(qlt
, "Unknown cmd=%xh\n", cmd
);
1091 qlt_port_start(caddr_t arg
)
1093 qlt_state_t
*qlt
= (qlt_state_t
*)arg
;
1094 fct_local_port_t
*port
;
1095 fct_dbuf_store_t
*fds
;
1098 if (qlt_dmem_init(qlt
) != QLT_SUCCESS
) {
1099 return (FCT_FAILURE
);
1101 /* Initialize the ddi_dma_handle free pool */
1102 qlt_dma_handle_pool_init(qlt
);
1104 port
= (fct_local_port_t
*)fct_alloc(FCT_STRUCT_LOCAL_PORT
, 0, 0);
1106 goto qlt_pstart_fail_1
;
1108 fds
= (fct_dbuf_store_t
*)fct_alloc(FCT_STRUCT_DBUF_STORE
, 0, 0);
1110 goto qlt_pstart_fail_2
;
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
;
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
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
;
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
;
1158 return (QLT_SUCCESS
);
1161 (void) fct_deregister_local_port(port
);
1163 qlt_pstart_fail_2_5
:
1167 qlt
->qlt_port
= NULL
;
1169 qlt_dma_handle_pool_fini(qlt
);
1171 return (QLT_FAILURE
);
1175 qlt_port_stop(caddr_t arg
)
1177 qlt_state_t
*qlt
= (qlt_state_t
*)arg
;
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
);
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
);
1189 return (QLT_SUCCESS
);
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
1198 qlt_port_online(qlt_state_t
*qlt
)
1208 instance
= ddi_get_instance(qlt
->dip
);
1210 /* XXX Make sure a sane state */
1212 if ((ret
= qlt_download_fw(qlt
)) != QLT_SUCCESS
) {
1213 cmn_err(CE_NOTE
, "reset chip failed %llx", (long long)ret
);
1217 bzero(qlt
->queue_mem_ptr
, TOTAL_DMA_MEM_SIZE
);
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
);
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");
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
;
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],
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;
1293 * XXX support for tunables. Also should we cache icb ?
1295 if (qlt
->qlt_81xx_chip
) {
1296 /* allocate extra 64 bytes for Extended init control block */
1297 mcp
= qlt_alloc_mailbox_command(qlt
, 0xC0);
1299 mcp
= qlt_alloc_mailbox_command(qlt
, 0x80);
1302 EL(qlt
, "qlt_alloc_mailbox_command mcp=null\n");
1303 return (STMF_ALLOC_FAILURE
);
1305 icb
= (caddr_t
)mcp
->dbuf
->db_sglist
[0].seg_addr
;
1306 if (qlt
->qlt_81xx_chip
) {
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 */
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
;
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));
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
|
1354 if (qlt
->qlt_81xx_chip
) {
1355 qlt_dmem_bctl_t
*bctl
;
1359 qlt_nvram_81xx_t
*qlt81nvr
;
1362 qlt81nvr
= (qlt_nvram_81xx_t
*)qlt
->nvram
;
1363 src
= (caddr_t
)&qlt81nvr
->ext_blk
;
1364 index
= sizeof (qlt_ext_icb_81xx_t
);
1366 /* Use defaults for cases where we find nothing in NVR */
1368 EL(qlt
, "nvram eicb=null\n");
1369 cmn_err(CE_NOTE
, "qlt(%d) NVR eicb is zeroed",
1371 qlt81nvr
->ext_blk
.version
[0] = 1;
1373 * not yet, for !FIP firmware at least
1375 * qlt81nvr->ext_blk.fcf_vlan_match = 0x81;
1377 #ifdef _LITTLE_ENDIAN
1378 qlt81nvr
->ext_blk
.fcf_vlan_id
[0] = 0xEA;
1379 qlt81nvr
->ext_blk
.fcf_vlan_id
[1] = 0x03;
1381 qlt81nvr
->ext_blk
.fcf_vlan_id
[1] = 0xEA;
1382 qlt81nvr
->ext_blk
.fcf_vlan_id
[0] = 0x03;
1390 bctl
= (qlt_dmem_bctl_t
*)mcp
->dbuf
->db_port_private
;
1391 da
= bctl
->bctl_dev_addr
+ 0x80; /* base addr of eicb (phys) */
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
) &
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
|
1406 qlt_dmem_dma_sync(mcp
->dbuf
, DDI_DMA_SYNC_FORDEV
);
1407 mcp
->to_fw
[0] = MBC_INITIALIZE_FIRMWARE
;
1410 * This is the 1st command after adapter initialize which will
1411 * use interrupts and regular mailbox interface.
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
));
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
,
1434 * Report FW versions for 81xx - MPI rev is useful
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
|
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
);
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);
1452 qlt_free_mailbox_command(qlt
, mcp
);
1454 for (i
= 0; i
< 5; i
++) {
1455 qlt
->qlt_bufref
[i
] = 0;
1457 qlt
->qlt_bumpbucket
= 0;
1458 qlt
->qlt_pmintry
= 0;
1459 qlt
->qlt_pmin_ok
= 0;
1461 if (ret
!= QLT_SUCCESS
)
1463 return (FCT_SUCCESS
);
1467 qlt_port_offline(qlt_state_t
*qlt
)
1471 mutex_enter(&qlt
->mbox_lock
);
1473 if (qlt
->mbox_io_state
== MBOX_STATE_UNKNOWN
) {
1474 mutex_exit(&qlt
->mbox_lock
);
1475 goto poff_mbox_done
;
1478 /* Wait to grab the mailboxes */
1479 for (retries
= 0; qlt
->mbox_io_state
!= MBOX_STATE_READY
;
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
;
1489 qlt
->mbox_io_state
= MBOX_STATE_UNKNOWN
;
1490 mutex_exit(&qlt
->mbox_lock
);
1492 qlt
->intr_sneak_counter
= 10;
1493 mutex_enter(&qlt
->intr_lock
);
1494 (void) qlt_reset_chip(qlt
);
1496 qlt
->intr_sneak_counter
= 0;
1497 mutex_exit(&qlt
->intr_lock
);
1499 return (FCT_SUCCESS
);
1503 qlt_get_link_info(fct_local_port_t
*port
, fct_link_info_t
*li
)
1505 qlt_state_t
*qlt
= (qlt_state_t
*)port
->port_fca_private
;
1507 fct_status_t fc_ret
;
1511 et
= ddi_get_lbolt() + drv_usectohz(5000000);
1512 mcp
= qlt_alloc_mailbox_command(qlt
, 0);
1514 mcp
->to_fw
[0] = MBC_GET_ID
;
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
;
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
;
1533 li
->portid
= ((uint32_t)(mcp
->from_fw
[2])) |
1534 (((uint32_t)(mcp
->from_fw
[3])) << 16);
1536 li
->port_speed
= qlt
->link_speed
;
1537 switch (mcp
->from_fw
[6]) {
1539 li
->port_topology
= PORT_TOPOLOGY_PUBLIC_LOOP
;
1540 li
->port_fca_flogi_done
= 1;
1543 li
->port_topology
= PORT_TOPOLOGY_PRIVATE_LOOP
;
1544 li
->port_no_fct_flogi
= 1;
1547 li
->port_topology
= PORT_TOPOLOGY_FABRIC_PT_TO_PT
;
1548 li
->port_fca_flogi_done
= 1;
1550 case 2: /*FALLTHROUGH*/
1552 li
->port_topology
= PORT_TOPOLOGY_PT_TO_PT
;
1553 li
->port_fca_flogi_done
= 1;
1556 li
->port_topology
= PORT_TOPOLOGY_UNKNOWN
;
1557 EL(qlt
, "Unknown topology=%xh\n", mcp
->from_fw
[6]);
1559 qlt
->cur_topology
= li
->port_topology
;
1560 fc_ret
= FCT_SUCCESS
;
1562 qlt_free_mailbox_command(qlt
, mcp
);
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;
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",
1575 stmf_trace(qlt
->qlt_port_alias
, "Attempt to get port "
1576 "database for F_port failed, ret = %llx", fc_ret
);
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);
1585 qlt_free_mailbox_command(qlt
, mcp
);
1591 qlt_open(dev_t
*devp
, int flag
, int otype
, cred_t
*credp
)
1596 if (otype
!= OTYP_CHR
) {
1601 * Since this is for debugging only, only allow root to issue ioctl now
1603 if (drv_priv(credp
)) {
1607 instance
= (int)getminor(*devp
);
1608 qlt
= ddi_get_soft_state(qlt_state
, instance
);
1613 mutex_enter(&qlt
->qlt_ioctl_lock
);
1614 if (qlt
->qlt_ioctl_flags
& QLT_IOCTL_FLAG_EXCL
) {
1616 * It is already open for exclusive access.
1617 * So shut the door on this caller.
1619 mutex_exit(&qlt
->qlt_ioctl_lock
);
1624 if (qlt
->qlt_ioctl_flags
& QLT_IOCTL_FLAG_OPEN
) {
1626 * Exclusive operation not possible
1627 * as it is already opened
1629 mutex_exit(&qlt
->qlt_ioctl_lock
);
1632 qlt
->qlt_ioctl_flags
|= QLT_IOCTL_FLAG_EXCL
;
1634 qlt
->qlt_ioctl_flags
|= QLT_IOCTL_FLAG_OPEN
;
1635 mutex_exit(&qlt
->qlt_ioctl_lock
);
1642 qlt_close(dev_t dev
, int flag
, int otype
, cred_t
*credp
)
1647 if (otype
!= OTYP_CHR
) {
1651 instance
= (int)getminor(dev
);
1652 qlt
= ddi_get_soft_state(qlt_state
, instance
);
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
);
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.
1668 qlt
->qlt_ioctl_flags
&= ~QLT_IOCTL_FLAG_MASK
;
1669 mutex_exit(&qlt
->qlt_ioctl_lock
);
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
1683 qlt_ioctl(dev_t dev
, int cmd
, intptr_t data
, int mode
,
1684 cred_t
*credp
, int *rval
)
1688 #ifdef _LITTLE_ENDIAN
1691 stmf_iocdata_t
*iocd
;
1698 char info
[QLT_INFO_LEN
];
1701 if (drv_priv(credp
) != 0)
1704 qlt
= ddi_get_soft_state(qlt_state
, (int32_t)getminor(dev
));
1705 ret
= stmf_copyin_iocdata(data
, mode
, &iocd
, &ibuf
, &obuf
);
1708 iocd
->stmf_error
= 0;
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
);
1718 mutex_enter(&qlt
->qlt_ioctl_lock
);
1719 if (!(qlt
->qlt_ioctl_flags
& QLT_FWDUMP_ISVALID
)) {
1720 mutex_exit(&qlt
->qlt_ioctl_lock
);
1722 EL(qlt
, "no fwdump\n");
1723 iocd
->stmf_error
= QLTIO_NO_DUMP
;
1726 if (qlt
->qlt_ioctl_flags
& QLT_FWDUMP_INPROGRESS
) {
1727 mutex_exit(&qlt
->qlt_ioctl_lock
);
1729 EL(qlt
, "fwdump inprogress\n");
1730 iocd
->stmf_error
= QLTIO_DUMP_INPROGRESS
;
1733 if (qlt
->qlt_ioctl_flags
& QLT_FWDUMP_FETCHED_BY_USER
) {
1734 mutex_exit(&qlt
->qlt_ioctl_lock
);
1736 EL(qlt
, "fwdump already fetched\n");
1737 iocd
->stmf_error
= QLTIO_ALREADY_FETCHED
;
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
);
1746 case QLT_IOCTL_TRIGGER_FWDUMP
:
1747 if (qlt
->qlt_state
!= FCT_STATE_ONLINE
) {
1749 iocd
->stmf_error
= QLTIO_NOT_ONLINE
;
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="
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
);
1768 iocd
->stmf_error
= QLTIO_INVALID_FW_SIZE
;
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
]);
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
);
1783 iocd
->stmf_error
= QLTIO_INVALID_FW_SIZE
;
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]);
1792 iocd
->stmf_error
= QLTIO_INVALID_FW_TYPE
;
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
;
1802 atomic_inc_32(&qlt_loaded_counter
);
1804 qlt
->fw_length01
= intp
[3];
1805 qlt
->fw_code01
= (uint32_t *)kmem_alloc(iocd
->stmf_ibuf_size
,
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];
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
);
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
));
1830 fwi
= (qlt_fw_info_t
*)obuf
;
1831 if (qlt
->qlt_stay_offline
) {
1832 fwi
->fwi_stay_offline
= 1;
1834 if (qlt
->qlt_state
== FCT_STATE_ONLINE
) {
1835 fwi
->fwi_port_active
= 1;
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];
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];
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];
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
);
1873 if (*((char *)ibuf
)) {
1874 qlt
->qlt_stay_offline
= 1;
1876 qlt
->qlt_stay_offline
= 0;
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
);
1888 mcp
= qlt_alloc_mailbox_command(qlt
, 0);
1890 EL(qlt
, "IOCTL_MBOX mcp == NULL\n");
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
)
1902 if (st
!= QLT_SUCCESS
) {
1903 EL(qlt
, "IOCTL_MBOX status=%xh\n", st
);
1906 case QLT_MBOX_NOT_INITIALIZED
:
1907 iocd
->stmf_error
= QLTIO_MBOX_NOT_INITIALIZED
;
1910 iocd
->stmf_error
= QLTIO_CANT_GET_MBOXES
;
1912 case QLT_MBOX_TIMEOUT
:
1913 iocd
->stmf_error
= QLTIO_MBOX_TIMED_OUT
;
1915 case QLT_MBOX_ABORTED
:
1916 iocd
->stmf_error
= QLTIO_MBOX_ABORTED
;
1922 case QLT_IOCTL_ELOG
:
1923 qlt_dump_el_trace_buffer(qlt
);
1927 EL(qlt
, "Unknown ioctl-%xh\n", cmd
);
1932 ret
= stmf_copyout_iocdata(data
, mode
, iocd
, obuf
);
1933 } else if (iocd
->stmf_error
) {
1934 (void) stmf_copyout_iocdata(data
, mode
, iocd
, obuf
);
1937 kmem_free(obuf
, iocd
->stmf_obuf_size
);
1941 kmem_free(ibuf
, iocd
->stmf_ibuf_size
);
1944 kmem_free(iocd
, sizeof (stmf_iocdata_t
));
1949 qlt_force_lip(qlt_state_t
*qlt
)
1954 mcp
= qlt_alloc_mailbox_command(qlt
, 0);
1955 mcp
->to_fw
[0] = 0x0072;
1956 mcp
->to_fw
[1] = BIT_4
;
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
);
1963 if (mcp
->from_fw
[0] != 0x4000) {
1964 QLT_LOG(qlt
->qlt_port_alias
, "qlt FLIP: fw[0]=%x",
1969 qlt_free_mailbox_command(qlt
, mcp
);
1974 qlt_ctl(struct fct_local_port
*port
, int cmd
, void *arg
)
1976 stmf_change_status_t st
;
1977 stmf_state_change_info_t
*ssci
= (stmf_state_change_info_t
*)arg
;
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
));
1987 qlt
= (qlt_state_t
*)port
->port_fca_private
;
1988 st
.st_completion_status
= FCT_SUCCESS
;
1989 st
.st_additional_info
= NULL
;
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;
2007 qlt
->qlt_state
= FCT_STATE_ONLINE
;
2010 fct_ctl(port
->port_lport
, FCT_CMD_PORT_ONLINE_COMPLETE
, &st
);
2011 qlt
->qlt_change_state_flags
= 0;
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
;
2020 if (st
.st_completion_status
== FCT_SUCCESS
) {
2021 qlt
->qlt_state
= FCT_STATE_OFFLINING
;
2022 qlt
->qlt_state_not_acked
= 1;
2024 if (ssci
->st_rflags
& STMF_RFLAG_COLLECT_DEBUG_DUMP
) {
2025 (void) qlt_firmware_dump(port
, ssci
);
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;
2035 qlt
->qlt_state
= FCT_STATE_OFFLINE
;
2038 fct_ctl(port
->port_lport
, FCT_CMD_PORT_OFFLINE_COMPLETE
, &st
);
2041 case FCT_ACK_PORT_ONLINE_COMPLETE
:
2042 qlt
->qlt_state_not_acked
= 0;
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",
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
);
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");
2068 *((fct_status_t
*)arg
) = qlt_force_lip(qlt
);
2069 EL(qlt
, "forcelip done\n");
2074 EL(qlt
, "unsupport cmd - 0x%02X", cmd
);
2081 qlt_do_flogi(fct_local_port_t
*port
, fct_flogi_xchg_t
*fx
)
2083 qlt_state_t
*qlt
= (qlt_state_t
*)port
->port_fca_private
;
2085 EL(qlt
, "FLOGI requested not supported\n");
2086 cmn_err(CE_WARN
, "qlt: FLOGI requested (not supported)");
2087 return (FCT_FAILURE
);
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**
2098 qlt_get_req_entries(qlt_state_t
*qlt
, uint32_t n
)
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
))
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
) {
2120 stmf_trace(qlt
->qlt_port_alias
,
2127 /* We dont change anything until the entries are sumitted */
2128 return (&qlt
->req_ptr
[qlt
->req_ndx_to_fw
<< 6]);
2132 * updates the req in ptr to fw. Assumes that req lock is held.
2135 qlt_submit_req_entries(qlt_state_t
*qlt
, uint32_t n
)
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
);
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**
2153 qlt_get_preq_entries(qlt_state_t
*qlt
, uint32_t n
)
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));
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
))
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
) {
2183 /* We dont change anything until the entries are sumitted */
2184 return (&qlt
->preq_ptr
[qlt
->preq_ndx_to_fw
<< 6]);
2188 * updates the req in ptr to fw. Assumes that req lock is held.
2191 qlt_submit_preq_entries(qlt_state_t
*qlt
, uint32_t n
)
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
);
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.
2213 qlt_reset_chip(qlt_state_t
*qlt
)
2217 EL(qlt
, "initiated\n");
2219 /* XXX: Switch off LEDs */
2221 /* Disable Interrupts */
2222 REG_WR32(qlt
, REG_INTR_CTRL
, 0);
2223 (void) REG_RD32(qlt
, REG_INTR_CTRL
);
2225 REG_WR32(qlt
, REG_CTRL_STATUS
, DMA_SHUTDOWN_CTRL
| PCI_X_XFER_CTRL
);
2227 /* Wait for DMA to be stopped */
2229 while (REG_RD32(qlt
, REG_CTRL_STATUS
) & DMA_ACTIVE_STATUS
) {
2230 delay(drv_usectohz(10000)); /* mostly 10ms is 1 tick */
2232 /* 3 sec should be more than enough */
2234 return (QLT_DMA_STUCK
);
2237 /* Reset the Chip */
2238 REG_WR32(qlt
, REG_CTRL_STATUS
,
2239 DMA_SHUTDOWN_CTRL
| PCI_X_XFER_CTRL
| CHIP_SOFT_RESET
);
2241 qlt
->qlt_link_up
= 0;
2245 /* Wait for ROM firmware to initialize (0x0000) in mailbox 0 */
2247 while (REG_RD16(qlt
, REG_MBOX(0)) != 0) {
2248 delay(drv_usectohz(10000));
2250 /* 3 sec should be more than enough */
2252 return (QLT_ROM_STUCK
);
2254 /* Disable Interrupts (Probably not needed) */
2255 REG_WR32(qlt
, REG_INTR_CTRL
, 0);
2257 return (QLT_SUCCESS
);
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.
2273 qlt_download_fw(qlt_state_t
*qlt
)
2275 uint32_t start_addr
;
2278 EL(qlt
, "initiated\n");
2280 (void) qlt_reset_chip(qlt
);
2282 if (qlt
->qlt_81xx_chip
) {
2286 /* Load the two segments */
2287 if (qlt
->fw_code01
!= NULL
) {
2288 ret
= qlt_load_risc_ram(qlt
, qlt
->fw_code01
, qlt
->fw_length01
,
2290 if (ret
== QLT_SUCCESS
) {
2291 ret
= qlt_load_risc_ram(qlt
, qlt
->fw_code02
,
2292 qlt
->fw_length02
, qlt
->fw_addr02
);
2294 start_addr
= qlt
->fw_addr01
;
2295 } else if (qlt
->qlt_81xx_chip
) {
2296 ret
= qlt_load_risc_ram(qlt
, fw8100_code01
, fw8100_length01
,
2298 if (ret
== QLT_SUCCESS
) {
2299 ret
= qlt_load_risc_ram(qlt
, fw8100_code02
,
2300 fw8100_length02
, fw8100_addr02
);
2302 start_addr
= fw8100_addr01
;
2303 } else if (qlt
->qlt_25xx_chip
) {
2304 ret
= qlt_load_risc_ram(qlt
, fw2500_code01
, fw2500_length01
,
2306 if (ret
== QLT_SUCCESS
) {
2307 ret
= qlt_load_risc_ram(qlt
, fw2500_code02
,
2308 fw2500_length02
, fw2500_addr02
);
2310 start_addr
= fw2500_addr01
;
2312 ret
= qlt_load_risc_ram(qlt
, fw2400_code01
, fw2400_length01
,
2314 if (ret
== QLT_SUCCESS
) {
2315 ret
= qlt_load_risc_ram(qlt
, fw2400_code02
,
2316 fw2400_length02
, fw2400_addr02
);
2318 start_addr
= fw2400_addr01
;
2320 if (ret
!= QLT_SUCCESS
) {
2321 EL(qlt
, "qlt_load_risc_ram status=%llxh\n", ret
);
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
);
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
);
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
);
2364 return (QLT_SUCCESS
);
2368 * Used only from qlt_download_fw().
2371 qlt_load_risc_ram(qlt_state_t
*qlt
, uint32_t *host_addr
,
2372 uint32_t word_count
, uint32_t risc_addr
)
2374 uint32_t words_sent
= 0;
2375 uint32_t words_being_sent
;
2376 uint32_t *cur_host_addr
;
2377 uint32_t cur_risc_addr
;
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
,
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",
2408 words_sent
+= words_being_sent
;
2410 return (QLT_SUCCESS
);
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()
2424 qlt_raw_mailbox_command(qlt_state_t
*qlt
)
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) {
2433 return (QLT_MAILBOX_STUCK
);
2435 delay(drv_usectohz(10000));
2437 status
= (REG_RD32(qlt
, REG_RISC_STATUS
) & FW_INTR_STATUS_MASK
);
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
);
2447 return (QLT_MBOX_FAILED
| mbox0
);
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
);
2457 qlt_alloc_mailbox_command(qlt_state_t
*qlt
, uint32_t dma_size
)
2461 mcp
= (mbox_cmd_t
*)kmem_zalloc(sizeof (mbox_cmd_t
), KM_SLEEP
);
2463 qlt_dmem_bctl_t
*bctl
;
2466 mcp
->dbuf
= qlt_i_dmem_alloc(qlt
, dma_size
, &dma_size
, 0);
2467 if (mcp
->dbuf
== NULL
) {
2468 kmem_free(mcp
, sizeof (*mcp
));
2471 mcp
->dbuf
->db_data_size
= dma_size
;
2472 ASSERT(mcp
->dbuf
->db_sglist_length
== 1);
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
;
2483 mcp
->to_fw_mask
|= BIT_0
;
2484 mcp
->from_fw_mask
|= BIT_0
;
2489 qlt_free_mailbox_command(qlt_state_t
*qlt
, mbox_cmd_t
*mcp
)
2492 qlt_i_dmem_free(qlt
, mcp
->dbuf
);
2493 kmem_free(mcp
, sizeof (*mcp
));
2497 * This can sleep. Should never be called from interrupt context.
2500 qlt_mailbox_command(qlt_state_t
*qlt
, mbox_cmd_t
*mcp
)
2504 char info
[QLT_INFO_LEN
];
2506 if (curthread
->t_flag
& T_INTR_THREAD
) {
2508 return (QLT_MBOX_FAILED
);
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
);
2518 /* Wait to grab the mailboxes */
2519 for (retries
= 0; qlt
->mbox_io_state
!= MBOX_STATE_READY
;
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
);
2528 /* Make sure we always ask for mailbox 0 */
2529 mcp
->from_fw_mask
|= BIT_0
;
2531 /* Load mailboxes, set state and generate RISC interrupt */
2532 qlt
->mbox_io_state
= MBOX_STATE_CMD_RUNNING
;
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
]);
2538 REG_WR32(qlt
, REG_HCCR
, HCCR_CMD(SET_HOST_TO_RISC_INTR
));
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]);
2548 qlt
->mbox_io_state
= MBOX_STATE_UNKNOWN
;
2549 mutex_exit(&qlt
->mbox_lock
);
2552 * XXX Throw HBA fatal error event
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
);
2558 if (qlt
->mbox_io_state
== MBOX_STATE_CMD_RUNNING
)
2559 goto qlt_mbox_wait_loop
;
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
);
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]);
2577 return (QLT_SUCCESS
);
2581 * **SHOULD ONLY BE CALLED FROM INTERRUPT CONTEXT. DO NOT CALL ELSEWHERE**
2585 qlt_isr(caddr_t arg
, caddr_t arg2
)
2587 qlt_state_t
*qlt
= (qlt_state_t
*)arg
;
2588 uint32_t risc_status
, intr_type
;
2590 int intr_loop_count
;
2591 char info
[QLT_INFO_LEN
];
2593 risc_status
= REG_RD32(qlt
, REG_RISC_STATUS
);
2594 if (!mutex_tryenter(&qlt
->intr_lock
)) {
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.
2604 if (risc_status
& BIT_15
) {
2606 return (DDI_INTR_CLAIMED
);
2607 } else if (qlt
->intr_sneak_counter
) {
2608 qlt
->intr_sneak_counter
--;
2609 return (DDI_INTR_CLAIMED
);
2611 return (DDI_INTR_UNCLAIMED
);
2614 if (((risc_status
& BIT_15
) == 0) ||
2615 (qlt
->qlt_intr_enabled
== 0)) {
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.
2624 mutex_exit(&qlt
->intr_lock
);
2625 return (DDI_INTR_UNCLAIMED
);
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.
2635 intr_loop_count
= 0;
2637 REG_WR32(qlt
, REG_INTR_CTRL
, 0);
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",
2648 (void) fct_port_shutdown(qlt
->qlt_port
,
2649 STMF_RFLAG_FATAL_ERROR
| STMF_RFLAG_RESET
|
2650 STMF_RFLAG_COLLECT_DEBUG_DUMP
, info
);
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));
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
,
2683 EL(qlt
, "Async event %x mb1=%x mb2=%x, mb3=%x, mb5=%x, mb6=%x",
2684 code
, mbox1
, mbox2
, mbox3
, mbox5
, mbox6
);
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);
2691 } else if (code
== 0x8012) {
2692 qlt
->qlt_link_up
= 0;
2693 fct_handle_event(qlt
->qlt_port
, FCT_EVENT_LINK_DOWN
,
2695 } else if (code
== 0x8011) {
2697 case 0: qlt
->link_speed
= PORT_SPEED_1G
;
2699 case 1: qlt
->link_speed
= PORT_SPEED_2G
;
2701 case 3: qlt
->link_speed
= PORT_SPEED_4G
;
2703 case 4: qlt
->link_speed
= PORT_SPEED_8G
;
2705 case 0x13: qlt
->link_speed
= PORT_SPEED_10G
;
2708 qlt
->link_speed
= PORT_SPEED_UNKNOWN
;
2710 qlt
->qlt_link_up
= 1;
2711 fct_handle_event(qlt
->qlt_port
, FCT_EVENT_LINK_UP
,
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
);
2727 /* issue "verify fw" */
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
);
2735 /* check if "ACK" is required (timeout != 0) */
2736 if (mbox1
& 0x0f00) {
2740 * Ack the request (queue work to do it?)
2741 * using a mailbox iocb
2743 mutex_enter(&qlt
->req_lock
);
2744 req
= qlt_get_req_entries(qlt
, 1);
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);
2757 (void) snprintf(info
, sizeof (info
),
2760 mutex_exit(&qlt
->req_lock
);
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
);
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
));
2778 qlt
->mbox_io_state
= MBOX_STATE_CMD_DONE
;
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
);
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
));
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
)) {
2796 REG_WR32(qlt
, REG_INTR_CTRL
, ENABLE_RISC_INTR
);
2798 mutex_exit(&qlt
->intr_lock
);
2799 return (DDI_INTR_CLAIMED
);
2802 /* **************** NVRAM Functions ********************** */
2805 qlt_read_flash_word(qlt_state_t
*qlt
, uint32_t faddr
, uint32_t *bp
)
2809 /* Clear access error flag */
2810 REG_WR32(qlt
, REG_CTRL_STATUS
,
2811 REG_RD32(qlt
, REG_CTRL_STATUS
) | FLASH_ERROR
);
2813 REG_WR32(qlt
, REG_FLASH_ADDR
, faddr
& ~BIT_31
);
2815 /* Wait for READ cycle to complete. */
2816 for (timer
= 3000; timer
; timer
--) {
2817 if (REG_RD32(qlt
, REG_FLASH_ADDR
) & BIT_31
) {
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
);
2830 *bp
= REG_RD32(qlt
, REG_FLASH_DATA
);
2832 return (QLT_SUCCESS
);
2836 qlt_read_nvram(qlt_state_t
*qlt
)
2838 uint32_t index
, addr
, chksum
;
2842 uint64_t empty_node_name
= 0;
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
;
2851 addr
= REG_RD32(qlt
, REG_CTRL_STATUS
) & FUNCTION_NUMBER
?
2852 NVRAM_FUNC1_ADDR
: NVRAM_FUNC0_ADDR
;
2854 mutex_enter(&qlt_global_lock
);
2857 REG_WR32(qlt
, REG_HCCR
, HCCR_CMD(SET_RISC_PAUSE
));
2858 (void) REG_RD32(qlt
, REG_HCCR
); /* PCI Posting. */
2860 /* Get NVRAM data and calculate checksum. */
2861 ptr
= (uint32_t *)qlt
->nvram
;
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
);
2875 /* Release RISC Pause */
2876 REG_WR32(qlt
, REG_HCCR
, HCCR_CMD(CLEAR_RISC_PAUSE
));
2877 (void) REG_RD32(qlt
, REG_HCCR
); /* PCI Posting. */
2879 mutex_exit(&qlt_global_lock
);
2881 /* Sanity check NVRAM Data */
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
);
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
);
2899 return (QLT_SUCCESS
);
2903 qlt_sync_atio_queue(qlt_state_t
*qlt
)
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
);
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
);
2926 qlt_handle_atio_queue_update(qlt_state_t
*qlt
)
2930 if (qlt
->atio_ndx_to_fw
== qlt
->atio_ndx_from_fw
)
2933 total_ent
= qlt_sync_atio_queue(qlt
);
2936 uint8_t *atio
= (uint8_t *)&qlt
->atio_ptr
[
2937 qlt
->atio_ndx_to_fw
<< 6];
2940 ent_cnt
= (uint32_t)(atio
[1]);
2941 if (ent_cnt
> total_ent
) {
2944 switch ((uint8_t)(atio
[0])) {
2945 case 0x0d: /* INOT */
2946 qlt_handle_inot(qlt
, atio
);
2948 case 0x06: /* ATIO */
2949 qlt_handle_atio(qlt
, atio
);
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
);
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
);
2965 qlt_sync_resp_queue(qlt_state_t
*qlt
)
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
);
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
);
2990 qlt_handle_resp_queue_update(qlt_state_t
*qlt
)
2995 if (qlt
->resp_ndx_to_fw
== qlt
->resp_ndx_from_fw
)
2998 total_ent
= qlt_sync_resp_queue(qlt
);
3001 caddr_t resp
= &qlt
->resp_ptr
[qlt
->resp_ndx_to_fw
<< 6];
3004 ent_cnt
= (uint32_t)(resp
[0] == 0x51 ? resp
[1] : 1);
3005 if (ent_cnt
> total_ent
) {
3008 switch ((uint8_t)(resp
[0])) {
3009 case 0x12: /* CTIO completion */
3010 qlt_handle_ctio_completion(qlt
, (uint8_t *)resp
);
3012 case 0x0e: /* NACK */
3015 case 0x1b: /* Verify FW */
3016 qlt_handle_verify_fw_completion(qlt
, (uint8_t *)resp
);
3018 case 0x29: /* CT PassThrough */
3019 qlt_handle_ct_completion(qlt
, (uint8_t *)resp
);
3021 case 0x33: /* Abort IO IOCB completion */
3022 qlt_handle_sol_abort_completion(qlt
, (uint8_t *)resp
);
3024 case 0x51: /* PUREX */
3025 qlt_handle_purex(qlt
, (uint8_t *)resp
);
3028 qlt_handle_dereg_completion(qlt
, (uint8_t *)resp
);
3030 case 0x53: /* ELS passthrough */
3031 c
= (uint8_t)(((uint8_t)resp
[0x1f]) >> 5);
3033 qlt_handle_sol_els_completion(qlt
,
3035 } else if (c
== 3) {
3036 qlt_handle_unsol_els_abort_completion(qlt
,
3039 qlt_handle_unsol_els_completion(qlt
,
3043 case 0x54: /* ABTS received */
3044 qlt_handle_rcvd_abts(qlt
, (uint8_t *)resp
);
3046 case 0x55: /* ABTS completion */
3047 qlt_handle_abts_completion(qlt
, (uint8_t *)resp
);
3050 EL(qlt
, "response entry=%xh\n", resp
[0]);
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
);
3061 qlt_portid_to_handle(qlt_state_t
*qlt
, uint32_t id
, uint16_t cmd_handle
,
3062 uint16_t *ret_handle
)
3072 mcp
= qlt_alloc_mailbox_command(qlt
, 2048 * 8);
3074 return (STMF_ALLOC_FAILURE
);
3076 mcp
->to_fw
[0] = MBC_GET_ID_LIST
;
3077 mcp
->to_fw
[8] = 2048 * 8;
3079 mcp
->to_fw_mask
|= BIT_9
| BIT_8
;
3080 mcp
->from_fw_mask
|= BIT_1
| BIT_2
;
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
);
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));
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",
3105 qlt_free_mailbox_command(qlt
, mcp
);
3106 return (QLT_FAILURE
);
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
);
3120 *ret_handle
= cmd_handle
;
3122 qlt_free_mailbox_command(qlt
, mcp
);
3123 return (FCT_SUCCESS
);
3128 qlt_fill_plogi_req(fct_local_port_t
*port
, fct_remote_port_t
*rp
,
3133 p
= ((fct_els_t
*)login
->cmd_specific
)->els_req_payload
;
3134 p
[0] = ELS_OP_PLOGI
;
3135 *((uint16_t *)(&p
[4])) = 0x2020;
3139 p
[13] = 0xff; p
[15] = 0x1f;
3140 p
[18] = 7; p
[19] = 0xd0;
3142 bcopy(port
->port_pwwn
, p
+ 20, 8);
3143 bcopy(port
->port_nwwn
, p
+ 28, 8);
3150 return (FCT_SUCCESS
);
3155 qlt_fill_plogi_resp(fct_local_port_t
*port
, fct_remote_port_t
*rp
,
3158 return (FCT_SUCCESS
);
3162 qlt_register_remote_port(fct_local_port_t
*port
, fct_remote_port_t
*rp
,
3167 qlt_state_t
*qlt
= (qlt_state_t
*)port
->port_fca_private
;
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;
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
);
3183 if (login
->cmd_type
== FCT_CMD_SOL_ELS
) {
3184 ret
= qlt_fill_plogi_req(port
, rp
, login
);
3186 ret
= qlt_fill_plogi_resp(port
, rp
, login
);
3189 if (ret
!= FCT_SUCCESS
) {
3190 EL(qlt
, "qlt_fill_plogi, status=%llxh\n", ret
);
3194 if (h
== FCT_HANDLE_NONE
)
3195 return (FCT_SUCCESS
);
3197 if (rp
->rp_handle
== FCT_HANDLE_NONE
) {
3199 return (FCT_SUCCESS
);
3202 if (rp
->rp_handle
== h
)
3203 return (FCT_SUCCESS
);
3205 EL(qlt
, "rp_handle=%xh != h=%xh\n", rp
->rp_handle
, h
);
3206 return (FCT_FAILURE
);
3208 /* invoked in single thread */
3210 qlt_deregister_remote_port(fct_local_port_t
*port
, fct_remote_port_t
*rp
)
3214 clock_t dereg_req_timer
;
3217 qlt
= (qlt_state_t
*)port
->port_fca_private
;
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);
3224 mutex_enter(&qlt
->preq_lock
);
3225 req
= (uint8_t *)qlt_get_preq_entries(qlt
, 1);
3227 mutex_exit(&qlt
->preq_lock
);
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);
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
;
3246 qlt
->rp_dereg_status
= 0;
3247 qlt
->rp_id_in_dereg
= 0;
3248 mutex_exit(&qlt
->preq_lock
);
3253 * Pass received ELS up to framework.
3256 qlt_handle_purex(qlt_state_t
*qlt
, uint8_t *resp
)
3261 uint32_t payload_size
;
3262 uint32_t remote_portid
;
3263 uint8_t *pldptr
, *bndrptr
;
3265 uint16_t iocb_flags
;
3266 char info
[QLT_INFO_LEN
];
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;
3274 payload_size
= QMEM_RD16(qlt
, (&resp
[0x0c])) - 24;
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");
3283 cmd
= (fct_cmd_t
*)fct_alloc(FCT_STRUCT_CMD_RCVD_ELS
,
3284 (int)(payload_size
+ GET_STRUCT_SIZE(qlt_cmd_t
)), 0);
3286 EL(qlt
, "fct_alloc cmd==NULL\n");
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
);
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
;
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];
3322 if (pldptr
== bndrptr
)
3323 pldptr
= (uint8_t *)qlt
->resp_ptr
;
3325 if (off
>= IOCB_SIZE
) {
3330 fct_post_rcvd_cmd(cmd
, 0);
3334 qlt_send_cmd_response(fct_cmd_t
*cmd
, uint32_t ioflags
)
3337 char info
[QLT_INFO_LEN
];
3339 qlt
= (qlt_state_t
*)cmd
->cmd_port
->port_fca_private
;
3341 if (cmd
->cmd_type
== FCT_CMD_FCP_XCHG
) {
3342 if (ioflags
& FCT_IOF_FORCE_FCA_DONE
) {
3343 EL(qlt
, "ioflags = %xh\n", ioflags
);
3346 return (qlt_send_status(qlt
, cmd
));
3350 if (cmd
->cmd_type
== FCT_CMD_RCVD_ELS
) {
3351 if (ioflags
& FCT_IOF_FORCE_FCA_DONE
) {
3354 return (qlt_send_els_response(qlt
, cmd
));
3358 if (ioflags
& FCT_IOF_FORCE_FCA_DONE
) {
3359 cmd
->cmd_handle
= 0;
3362 if (cmd
->cmd_type
== FCT_CMD_RCVD_ABTS
) {
3363 return (qlt_send_abts_response(qlt
, cmd
, 0));
3365 EL(qlt
, "cmd->cmd_type=%xh\n", cmd
->cmd_type
);
3367 return (FCT_FAILURE
);
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
,
3375 (void) fct_port_shutdown(qlt
->qlt_port
,
3376 STMF_RFLAG_FATAL_ERROR
| STMF_RFLAG_RESET
, info
);
3377 return (FCT_FAILURE
);
3382 qlt_xfer_scsi_data(fct_cmd_t
*cmd
, stmf_data_buf_t
*dbuf
, uint32_t ioflags
)
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
;
3389 uint16_t cookie_count
;
3391 if (dbuf
->db_handle
== 0)
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
);
3398 flags
= (uint16_t)(flags
| 1);
3401 if (dbuf
->db_flags
& DB_SEND_STATUS_GOOD
)
3402 flags
= (uint16_t)(flags
| BIT_15
);
3404 if (dbuf
->db_flags
& DB_LU_DATA_BUF
) {
3406 * Data bufs from LU are in scatter/gather list format.
3408 cookie_count
= qlt_get_cookie_count(dbuf
);
3409 rcnt
= qlt_get_iocb_count(cookie_count
);
3414 mutex_enter(&qlt
->req_lock
);
3415 req
= (uint8_t *)qlt_get_req_entries(qlt
, rcnt
);
3417 mutex_exit(&qlt
->req_lock
);
3420 bzero(req
, IOCB_SIZE
); /* XXX needed ? */
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
;
3438 ddi_dma_cookie_t cookie
, *ckp
;
3441 * See if the dma cookies are in simple array format.
3443 ckp
= qlt_get_cookie_array(dbuf
);
3446 * Program the first segment into main record.
3449 ASSERT(ckp
->dmac_size
);
3450 QMEM_WR64(qlt
, req
+0x34, ckp
->dmac_laddress
);
3451 QMEM_WR32(qlt
, req
+0x3c, ckp
->dmac_size
);
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
);
3458 cookie_resid
= cookie_count
-1;
3461 * Program remaining segments into continuation records.
3463 while (cookie_resid
) {
3465 if (req
>= (uint8_t *)qlt
->resp_ptr
) {
3466 req
= (uint8_t *)qlt
->req_ptr
;
3470 req
[2] = req
[3] = 0; /* tidy */
3472 for (cont_segs
= CONT_A64_DATA_SEGMENTS
;
3473 cont_segs
&& cookie_resid
; cont_segs
--) {
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 */
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 */
3495 * zero unused remainder of IOCB
3499 resid
= (size_t)((uintptr_t)(req
+IOCB_SIZE
) -
3501 ASSERT(resid
< IOCB_SIZE
);
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
);
3511 qlt_submit_req_entries(qlt
, rcnt
);
3512 mutex_exit(&qlt
->req_lock
);
3514 return (STMF_SUCCESS
);
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.
3523 qlt_send_status(qlt_state_t
*qlt
, fct_cmd_t
*cmd
)
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
;
3529 uint8_t *req
, *fcp_rsp_iu
;
3530 uint8_t *psd
, sensbuf
[24]; /* sense data */
3532 uint16_t scsi_status
;
3537 * Enter fast channel for non check condition
3539 if (task
->task_scsi_status
!= STATUS_CHECK
) {
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
);
3551 qcmd
->dbuf_rsp_iu
= NULL
;
3554 * Fillout CTIO type 7 IOCB
3556 mutex_enter(&qlt
->req_lock
);
3557 req
= (uint8_t *)qlt_get_req_entries(qlt
, 1);
3559 mutex_exit(&qlt
->req_lock
);
3566 bzero(req
, IOCB_SIZE
);
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
);
3576 * Mode-specific fields
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
);
3584 * Trigger FW to send SCSI status out
3586 qlt_submit_req_entries(qlt
, 1);
3587 mutex_exit(&qlt
->req_lock
);
3588 return (STMF_SUCCESS
);
3591 ASSERT(task
->task_scsi_status
== STATUS_CHECK
);
3593 * Decide the SCSI status mode, that should be used
3595 use_mode2
= (task
->task_sense_length
> 24);
3598 * Prepare required information per the SCSI status mode
3600 flags
= (uint16_t)(BIT_15
|
3601 (((uint16_t)qcmd
->param
.atio_byte3
& 0xf0) << 5));
3603 flags
= (uint16_t)(flags
| BIT_7
);
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
);
3613 * Start to construct FCP_RSP IU
3615 fcp_rsp_iu
= qcmd
->dbuf_rsp_iu
->db_sglist
[0].seg_addr
;
3616 bzero(fcp_rsp_iu
, 24);
3619 * FCP_RSP IU flags, byte10
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
);
3629 * SCSI status code, byte11
3631 fcp_rsp_iu
[11] = task
->task_scsi_status
;
3634 * FCP_RESID (Overrun or underrun)
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);
3644 fcp_rsp_iu
[18] = (uint8_t)((task
->task_sense_length
>> 8) &
3646 fcp_rsp_iu
[19] = (uint8_t)((task
->task_sense_length
>> 0) &
3658 bcopy(task
->task_sense_data
, fcp_rsp_iu
+ 24,
3659 task
->task_sense_length
);
3662 * Ensure dma data consistency
3664 qlt_dmem_dma_sync(qcmd
->dbuf_rsp_iu
, DDI_DMA_SYNC_FORDEV
);
3666 flags
= (uint16_t)(flags
| BIT_6
);
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
);
3674 if (task
->task_sense_length
) {
3675 scsi_status
= (uint16_t)(scsi_status
| BIT_9
);
3677 bcopy(task
->task_sense_data
, sensbuf
, task
->task_sense_length
);
3678 qcmd
->dbuf_rsp_iu
= NULL
;
3682 * Fillout CTIO type 7 IOCB
3684 mutex_enter(&qlt
->req_lock
);
3685 req
= (uint8_t *)qlt_get_req_entries(qlt
, 1);
3687 mutex_exit(&qlt
->req_lock
);
3689 qlt_dmem_free(cmd
->cmd_port
->port_fds
,
3691 qcmd
->dbuf_rsp_iu
= NULL
;
3699 bzero(req
, IOCB_SIZE
);
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 */
3707 QMEM_WR16(qlt
, req
+0x0C, 1); /* FCP RSP IU data field */
3709 QMEM_WR32(qlt
, req
+ 0x10, cmd
->cmd_rportid
);
3710 QMEM_WR32(qlt
, req
+ 0x14, qcmd
->fw_xchg_addr
);
3713 * Mode-specific fields
3716 QMEM_WR16(qlt
, req
+ 0x18, task
->task_sense_length
);
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
);
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
);
3727 QMEM_WR16(qlt
, req
+ 0x22, scsi_status
);
3731 * Data in sense buf is always big-endian, data in IOCB
3732 * should always be little-endian, so we must do swapping.
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];
3744 * Trigger FW to send SCSI status out
3746 qlt_submit_req_entries(qlt
, 1);
3747 mutex_exit(&qlt
->req_lock
);
3749 return (STMF_SUCCESS
);
3753 qlt_send_els_response(qlt_state_t
*qlt
, fct_cmd_t
*cmd
)
3756 fct_els_t
*els
= (fct_els_t
*)cmd
->cmd_specific
;
3757 uint8_t *req
, *addr
;
3758 qlt_dmem_bctl_t
*bctl
;
3760 uint8_t elsop
, req1f
;
3762 addr
= els
->els_resp_payload
;
3763 qcmd
= (qlt_cmd_t
*)cmd
->cmd_fca_private
;
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
)
3770 bctl
= (qlt_dmem_bctl_t
*)qcmd
->dbuf
->db_port_private
;
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
);
3775 if (addr
[0] == 0x02) { /* ACC */
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
);
3786 mutex_enter(&qlt
->req_lock
);
3787 req
= (uint8_t *)qlt_get_req_entries(qlt
, 1);
3789 mutex_exit(&qlt
->req_lock
);
3790 qlt_dmem_free(NULL
, qcmd
->dbuf
);
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);
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
);
3813 return (FCT_SUCCESS
);
3817 qlt_send_abts_response(qlt_state_t
*qlt
, fct_cmd_t
*cmd
, int terminate
)
3819 qlt_abts_cmd_t
*qcmd
;
3820 fct_rcvd_abts_t
*abts
= (fct_rcvd_abts_t
*)cmd
->cmd_specific
;
3826 qcmd
= (qlt_abts_cmd_t
*)cmd
->cmd_fca_private
;
3828 mutex_enter(&qlt
->req_lock
);
3829 req
= (uint8_t *)qlt_get_req_entries(qlt
, 1);
3831 mutex_exit(&qlt
->req_lock
);
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
);
3841 QMEM_WR16(qlt
, (&req
[0xA]), cmd
->cmd_rp
->rp_handle
);
3843 QMEM_WR16(qlt
, (&req
[0xA]), cmd
->cmd_rp_handle
);
3845 QMEM_WR16(qlt
, (&req
[0xC]), 1);
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
);
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
];
3859 qlt_submit_req_entries(qlt
, 1);
3860 mutex_exit(&qlt
->req_lock
);
3862 return (FCT_SUCCESS
);
3866 qlt_handle_inot(qlt_state_t
*qlt
, uint8_t *inot
)
3871 /* Just put it on the request queue */
3872 mutex_enter(&qlt
->req_lock
);
3873 req
= qlt_get_req_entries(qlt
, 1);
3875 mutex_exit(&qlt
->req_lock
);
3876 /* XXX handle this */
3879 for (i
= 0; i
< 16; i
++) {
3880 d
= QMEM_RD32(qlt
, inot
);
3882 QMEM_WR32(qlt
, req
, d
);
3887 qlt_submit_req_entries(qlt
, 1);
3888 mutex_exit(&qlt
->req_lock
);
3891 uint8_t qlt_task_flags
[] = { 1, 3, 2, 1, 4, 0, 1, 1 };
3893 qlt_handle_atio(qlt_state_t
*qlt
, uint8_t *atio
)
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
];
3904 * If either bidirection xfer is requested of there is extended
3905 * CDB, atio[0x20 + 11] will be greater than or equal to 3.
3908 if (atio
[0x20 + 11] >= 3) {
3909 uint8_t b
= atio
[0x20 + 11];
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 */
3919 cdb_size
= (uint16_t)(cdb_size
+ (b
& 0xfc));
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
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 */
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]);
3944 if (fw_xchg_addr
== 0xFFFFFFFF) {
3945 EL(qlt
, "fw_xchg_addr==0xFFFFFFFF\n");
3948 cmd
= fct_scsi_task_alloc(qlt
->qlt_port
, FCT_HANDLE_NONE
,
3949 rportid
, atio
+0x20, cdb_size
, STMF_TASK_EXT_NONE
);
3951 EL(qlt
, "fct_scsi_task_alloc cmd==NULL\n");
3955 EL(qlt
, "fct_scsi_task_alloc cmd==NULL\n");
3957 flags
= (uint16_t)(BIT_14
| ((atio
[3] & 0xF0) << 5));
3959 mutex_enter(&qlt
->req_lock
);
3960 req
= (uint8_t *)qlt_get_req_entries(qlt
, 1);
3962 mutex_exit(&qlt
->req_lock
);
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
);
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
,
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
);
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) |
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 */
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];
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
;
4017 task
->task_mgmt_function
= TM_ABORT_TASK
;
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));
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);
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
+
4041 for (i
= 0; i
< 4; i
++) {
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
+
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];
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];
4057 fct_post_rcvd_cmd(cmd
, 0);
4061 qlt_handle_dereg_completion(qlt_state_t
*qlt
, uint8_t *rsp
)
4065 uint32_t subcode1
, subcode2
;
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);
4072 mutex_enter(&qlt
->preq_lock
);
4073 if (portid
!= qlt
->rp_id_in_dereg
) {
4074 int instance
= ddi_get_instance(qlt
->dip
);
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",
4080 mutex_exit(&qlt
->preq_lock
);
4085 EL(qlt
, "implicit logout completed for %xh with status %xh, "
4086 "subcode1 %xh subcode2 %xh\n", portid
, status
, subcode1
,
4088 if (status
== 0x31 && subcode1
== 0x0a) {
4089 qlt
->rp_dereg_status
= FCT_SUCCESS
;
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
);
4098 qlt
->rp_dereg_status
= FCT_SUCCESS
;
4100 cv_signal(&qlt
->rp_dereg_cv
);
4101 mutex_exit(&qlt
->preq_lock
);
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.
4109 qlt_handle_unsol_els_completion(qlt_state_t
*qlt
, uint8_t *rsp
)
4111 char info
[QLT_INFO_LEN
];
4115 uint32_t subcode1
, subcode2
;
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);
4123 if (!CMD_HANDLE_VALID(hndl
)) {
4124 EL(qlt
, "handle = %xh\n", hndl
);
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.
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
);
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.
4147 EL(qlt
, "status = %xh\n", status
);
4148 stmf_trace(0, "--UNSOL ELS returned with status 5 --");
4152 cmd
= fct_handle_to_cmd(qlt
->qlt_port
, hndl
);
4154 EL(qlt
, "fct_handle_to_cmd cmd==NULL, hndl=%xh\n", hndl
);
4156 * Now why would this happen ???
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
,
4162 (void) fct_port_shutdown(qlt
->qlt_port
,
4163 STMF_RFLAG_FATAL_ERROR
| STMF_RFLAG_RESET
, info
);
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
) {
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.
4177 stmf_trace(0, "--UNSOL ELS finished while we are trying to "
4182 if (qcmd
->dbuf
!= NULL
) {
4183 qlt_dmem_free(NULL
, qcmd
->dbuf
);
4188 fct_send_response_done(cmd
, FCT_SUCCESS
, FCT_IOF_FCA_DONE
);
4190 fct_send_response_done(cmd
,
4191 QLT_FIRMWARE_ERROR(status
, subcode1
, subcode2
), 0);
4196 qlt_handle_unsol_els_abort_completion(qlt_state_t
*qlt
, uint8_t *rsp
)
4198 char info
[QLT_INFO_LEN
];
4202 uint32_t subcode1
, subcode2
;
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);
4210 if (!CMD_HANDLE_VALID(hndl
)) {
4211 EL(qlt
, "handle = %xh\n", hndl
);
4214 * Someone has requested to abort it, but no one is waiting for
4217 if ((status
!= 0) && (status
!= 8)) {
4218 EL(qlt
, "status = %xh\n", status
);
4220 * There could be exchange resource leakage, so
4221 * throw HBA fatal error event now
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
);
4236 cmd
= fct_handle_to_cmd(qlt
->qlt_port
, hndl
);
4238 EL(qlt
, "fct_handle_to_cmd cmd==NULL, hndl=%xh\n", hndl
);
4240 * Why would this happen ??
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
,
4246 (void) fct_port_shutdown(qlt
->qlt_port
,
4247 STMF_RFLAG_FATAL_ERROR
| STMF_RFLAG_RESET
, info
);
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
);
4256 if (qcmd
->dbuf
!= NULL
) {
4257 qlt_dmem_free(NULL
, qcmd
->dbuf
);
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
);
4266 fct_cmd_fca_aborted(cmd
,
4267 QLT_FIRMWARE_ERROR(status
, subcode1
, subcode2
), 0);
4272 qlt_handle_sol_els_completion(qlt_state_t
*qlt
, uint8_t *rsp
)
4274 char info
[QLT_INFO_LEN
];
4279 uint32_t subcode1
, subcode2
;
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);
4287 if (!CMD_HANDLE_VALID(hndl
)) {
4288 EL(qlt
, "handle = %xh\n", hndl
);
4290 * This cannot happen for sol els completion.
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
);
4302 cmd
= fct_handle_to_cmd(qlt
->qlt_port
, hndl
);
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
,
4309 (void) fct_port_shutdown(qlt
->qlt_port
,
4310 STMF_RFLAG_FATAL_ERROR
| STMF_RFLAG_RESET
, info
);
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]));
4320 if (qcmd
->flags
& QLT_CMD_ABORTING
) {
4322 * We will handle it when the ABORT IO IOCB returns.
4327 if (qcmd
->dbuf
!= NULL
) {
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
);
4334 qlt_dmem_free(NULL
, qcmd
->dbuf
);
4339 fct_send_cmd_done(cmd
, FCT_SUCCESS
, FCT_IOF_FCA_DONE
);
4341 fct_send_cmd_done(cmd
,
4342 QLT_FIRMWARE_ERROR(status
, subcode1
, subcode2
), 0);
4347 qlt_handle_ct_completion(qlt_state_t
*qlt
, uint8_t *rsp
)
4354 char info
[QLT_INFO_LEN
];
4356 hndl
= QMEM_RD32(qlt
, rsp
+4);
4357 status
= QMEM_RD16(qlt
, rsp
+8);
4359 if (!CMD_HANDLE_VALID(hndl
)) {
4360 EL(qlt
, "handle = %xh\n", hndl
);
4362 * Solicited commands will always have a valid handle.
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
);
4373 cmd
= fct_handle_to_cmd(qlt
->qlt_port
, hndl
);
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
,
4380 (void) fct_port_shutdown(qlt
->qlt_port
,
4381 STMF_RFLAG_FATAL_ERROR
| STMF_RFLAG_RESET
, info
);
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
);
4390 if (qcmd
->flags
& QLT_CMD_ABORTING
) {
4392 * We will handle it when ABORT IO IOCB returns;
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
);
4404 qlt_dmem_free(NULL
, qcmd
->dbuf
);
4408 fct_send_cmd_done(cmd
, FCT_SUCCESS
, FCT_IOF_FCA_DONE
);
4410 fct_send_cmd_done(cmd
, QLT_FIRMWARE_ERROR(status
, 0, 0), 0);
4415 qlt_handle_ctio_completion(qlt_state_t
*qlt
, uint8_t *rsp
)
4420 stmf_data_buf_t
*dbuf
;
4428 char info
[QLT_INFO_LEN
];
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);
4436 if (!CMD_HANDLE_VALID(hndl
)) {
4437 EL(qlt
, "handle = %xh\n", hndl
);
4440 * Someone has requested to abort it, but no one is waiting for
4443 EL(qlt
, "hndl-%xh, status-%xh, rsp-%p\n", hndl
, status
,
4445 if ((status
!= 1) && (status
!= 2)) {
4446 EL(qlt
, "status = %xh\n", status
);
4448 * There could be exchange resource leakage, so
4449 * throw HBA fatal error event now
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
);
4462 if (flags
& BIT_14
) {
4464 EL(qlt
, "abort: hndl-%x, status-%x, rsp-%p\n", hndl
, status
,
4470 cmd
= fct_handle_to_cmd(qlt
->qlt_port
, hndl
);
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
,
4477 (void) fct_port_shutdown(qlt
->qlt_port
,
4478 STMF_RFLAG_FATAL_ERROR
| STMF_RFLAG_RESET
, info
);
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
;
4491 if ((status
== 1) || (status
== 2)) {
4493 fc_st
= FCT_ABORT_SUCCESS
;
4494 iof
= FCT_IOF_FCA_DONE
;
4496 fc_st
= FCT_SUCCESS
;
4497 if (flags
& BIT_15
) {
4498 iof
= FCT_IOF_FCA_DONE
;
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
;
4507 fc_st
= QLT_FIRMWARE_ERROR(status
, 0, 0);
4511 if (((n
& BIT_7
) == 0) && (!abort_req
)) {
4512 /* A completion of data xfer */
4516 dbuf
= stmf_handle_to_buf(task
, n
);
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
);
4527 dbuf
->db_xfer_status
= fc_st
;
4528 fct_scsi_data_xfer_done(cmd
, dbuf
, iof
);
4533 * This was just a pure status xfer.
4535 fct_send_response_done(cmd
, fc_st
, iof
);
4539 fct_cmd_fca_aborted(cmd
, fc_st
, iof
);
4543 qlt_handle_sol_abort_completion(qlt_state_t
*qlt
, uint8_t *rsp
)
4545 char info
[QLT_INFO_LEN
];
4551 h
= QMEM_RD32(qlt
, rsp
+4);
4552 status
= QMEM_RD16(qlt
, rsp
+8);
4554 if (!CMD_HANDLE_VALID(h
)) {
4555 EL(qlt
, "handle = %xh\n", h
);
4557 * Solicited commands always have a valid handle.
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
);
4567 cmd
= fct_handle_to_cmd(qlt
->qlt_port
, h
);
4569 EL(qlt
, "fct_handle_to_cmd cmd==NULL, hndl=%xh\n", h
);
4571 * What happened to the cmd ??
4573 (void) snprintf(info
, sizeof (info
),
4574 "qlt_handle_sol_abort_completion: cannot "
4575 "find cmd, hndl-%x, status-%x, rsp-%p", h
, status
,
4577 (void) fct_port_shutdown(qlt
->qlt_port
,
4578 STMF_RFLAG_FATAL_ERROR
| STMF_RFLAG_RESET
, info
);
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
);
4590 ASSERT(qcmd
->flags
& QLT_CMD_ABORTING
);
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
);
4596 fct_cmd_fca_aborted(cmd
, QLT_FIRMWARE_ERROR(status
, 0, 0), 0);
4601 qlt_handle_rcvd_abts(qlt_state_t
*qlt
, uint8_t *resp
)
4603 qlt_abts_cmd_t
*qcmd
;
4605 uint32_t remote_portid
;
4606 char info
[QLT_INFO_LEN
];
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);
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
);
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
;
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);
4639 qlt_handle_abts_completion(qlt_state_t
*qlt
, uint8_t *resp
)
4642 char info
[QLT_INFO_LEN
];
4644 status
= QMEM_RD16(qlt
, resp
+8);
4646 if ((status
== 0) || (status
== 5)) {
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
);
4659 uint32_t qlt_drop_abort_counter
= 0;
4663 qlt_abort_cmd(struct fct_local_port
*port
, fct_cmd_t
*cmd
, uint32_t flags
)
4665 qlt_state_t
*qlt
= (qlt_state_t
*)port
->port_fca_private
;
4667 if ((qlt
->qlt_state
== FCT_STATE_OFFLINE
) ||
4668 (qlt
->qlt_state
== FCT_STATE_OFFLINING
)) {
4669 return (FCT_NOT_FOUND
);
4673 if (qlt_drop_abort_counter
> 0) {
4674 if (atomic_dec_32_nv(&qlt_drop_abort_counter
) == 1)
4675 return (FCT_SUCCESS
);
4679 if (cmd
->cmd_type
== FCT_CMD_FCP_XCHG
) {
4680 return (qlt_abort_unsol_scsi_cmd(qlt
, cmd
));
4683 if (flags
& FCT_IOF_FORCE_FCA_DONE
) {
4684 cmd
->cmd_handle
= 0;
4687 if (cmd
->cmd_type
== FCT_CMD_RCVD_ABTS
) {
4688 return (qlt_send_abts_response(qlt
, cmd
, 1));
4691 if (cmd
->cmd_type
== FCT_CMD_RCVD_ELS
) {
4692 return (qlt_abort_purex(qlt
, cmd
));
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
));
4699 EL(qlt
, "cmd->cmd_type = %xh\n", cmd
->cmd_type
);
4702 return (FCT_FAILURE
);
4706 qlt_abort_sol_cmd(qlt_state_t
*qlt
, fct_cmd_t
*cmd
)
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
);
4715 mutex_enter(&qlt
->req_lock
);
4716 req
= (uint8_t *)qlt_get_req_entries(qlt
, 1);
4718 mutex_exit(&qlt
->req_lock
);
4722 bzero(req
, IOCB_SIZE
);
4723 req
[0] = 0x33; req
[1] = 1;
4724 QMEM_WR32(qlt
, req
+4, cmd
->cmd_handle
);
4726 QMEM_WR16(qlt
, req
+8, cmd
->cmd_rp
->rp_handle
);
4728 QMEM_WR16(qlt
, req
+8, 0xFFFF);
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
);
4736 return (FCT_SUCCESS
);
4740 qlt_abort_purex(qlt_state_t
*qlt
, fct_cmd_t
*cmd
)
4745 uint8_t elsop
, req1f
;
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
,
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
);
4758 mutex_enter(&qlt
->req_lock
);
4759 req
= (uint8_t *)qlt_get_req_entries(qlt
, 1);
4761 mutex_exit(&qlt
->req_lock
);
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
);
4772 QMEM_WR16(qlt
, (&req
[0xA]), cmd
->cmd_rp
->rp_handle
);
4773 EL(qlt
, "rp_handle-%x\n", cmd
->cmd_rp
->rp_handle
);
4775 QMEM_WR16(qlt
, (&req
[0xA]), cmd
->cmd_rp_handle
);
4776 EL(qlt
, "cmd_rp_handle-%x\n", cmd
->cmd_rp_handle
);
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
);
4784 return (FCT_SUCCESS
);
4788 qlt_abort_unsol_scsi_cmd(qlt_state_t
*qlt
, fct_cmd_t
*cmd
)
4790 qlt_cmd_t
*qcmd
= (qlt_cmd_t
*)cmd
->cmd_fca_private
;
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
);
4798 mutex_enter(&qlt
->req_lock
);
4799 req
= (uint8_t *)qlt_get_req_entries(qlt
, 1);
4801 mutex_exit(&qlt
->req_lock
);
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
);
4819 return (FCT_SUCCESS
);
4823 qlt_send_cmd(fct_cmd_t
*cmd
)
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
));
4833 EL(qlt
, "cmd->cmd_type = %xh\n", cmd
->cmd_type
);
4836 return (FCT_FAILURE
);
4840 qlt_send_els(qlt_state_t
*qlt
, fct_cmd_t
*cmd
)
4845 stmf_data_buf_t
*buf
;
4846 qlt_dmem_bctl_t
*bctl
;
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);
4858 bctl
= (qlt_dmem_bctl_t
*)buf
->db_port_private
;
4861 bcopy(els
->els_req_payload
, buf
->db_sglist
[0].seg_addr
,
4863 qlt_dmem_dma_sync(buf
, DDI_DMA_SYNC_FORDEV
);
4865 mutex_enter(&qlt
->req_lock
);
4866 req
= (uint8_t *)qlt_get_req_entries(qlt
, 1);
4868 qlt_dmem_free(NULL
, buf
);
4869 mutex_exit(&qlt
->req_lock
);
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);
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
);
4896 return (FCT_SUCCESS
);
4900 qlt_send_ct(qlt_state_t
*qlt
, fct_cmd_t
*cmd
)
4905 stmf_data_buf_t
*buf
;
4906 qlt_dmem_bctl_t
*bctl
;
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);
4918 bctl
= (qlt_dmem_bctl_t
*)buf
->db_port_private
;
4921 bcopy(ct
->ct_req_payload
, buf
->db_sglist
[0].seg_addr
,
4923 qlt_dmem_dma_sync(buf
, DDI_DMA_SYNC_FORDEV
);
4925 mutex_enter(&qlt
->req_lock
);
4926 req
= (uint8_t *)qlt_get_req_entries(qlt
, 1);
4928 qlt_dmem_free(NULL
, buf
);
4929 mutex_exit(&qlt
->req_lock
);
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);
4940 QMEM_WR32(qlt
, (&req
[0x20]), ct
->ct_resp_size
);
4941 QMEM_WR32(qlt
, (&req
[0x24]), ct
->ct_req_size
);
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
);
4949 qlt_submit_req_entries(qlt
, 1);
4950 mutex_exit(&qlt
->req_lock
);
4952 return (FCT_SUCCESS
);
4957 * All QLT_FIRMWARE_* will mainly be handled in this function
4958 * It can not be called in interrupt context
4960 * FWDUMP's purpose is to serve ioctl, so we will use qlt_ioctl_flags
4961 * and qlt_ioctl_lock
4964 qlt_firmware_dump(fct_local_port_t
*port
, stmf_state_change_info_t
*ssci
)
4966 qlt_state_t
*qlt
= (qlt_state_t
*)port
->port_fca_private
;
4971 uint32_t addr
, endaddr
, words_to_read
;
4975 mutex_enter(&qlt
->qlt_ioctl_lock
);
4977 * To make sure that there's no outstanding dumping task
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
);
4988 * To make sure not to overwrite existing dump
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
)) {
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.
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
);
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
;
5008 qlt
->qlt_ioctl_flags
&= ~QLT_FWDUMP_TRIGGERED_BY_USER
;
5010 mutex_exit(&qlt
->qlt_ioctl_lock
);
5012 size_left
= QLT_FWDUMP_BUFSIZE
;
5013 if (!qlt
->qlt_fwdump_buf
) {
5014 ASSERT(!(qlt
->qlt_ioctl_flags
& QLT_FWDUMP_ISVALID
));
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.
5019 qlt
->qlt_fwdump_buf
= kmem_zalloc(size_left
, KM_SLEEP
);
5023 * Start to dump firmware
5025 buf
= (caddr_t
)qlt
->qlt_fwdump_buf
;
5028 * Print the ISP firmware revision number and attributes information
5029 * Read the RISC to Host Status register
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
;
5038 * Before pausing the RISC, make sure no mailbox can execute
5040 mutex_enter(&qlt
->mbox_lock
);
5041 if (qlt
->mbox_io_state
!= MBOX_STATE_UNKNOWN
) {
5043 * Wait to grab the mailboxes
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));
5050 mutex_exit(&qlt
->mbox_lock
);
5051 EL(qlt
, "can't drain out mailbox commands\n");
5055 qlt
->mbox_io_state
= MBOX_STATE_UNKNOWN
;
5056 cv_broadcast(&qlt
->mbox_cv
);
5058 mutex_exit(&qlt
->mbox_lock
);
5061 * Pause the RISC processor
5063 REG_WR32(qlt
, REG_HCCR
, HCCR_CMD(SET_RISC_PAUSE
));
5066 * Wait for the RISC processor to pause
5068 for (i
= 0; i
< 200; i
++) {
5069 if (REG_RD32(qlt
, REG_RISC_STATUS
) & 0x100) {
5075 EL(qlt
, "can't pause\n");
5076 return (FCT_FAILURE
);
5079 if ((!qlt
->qlt_25xx_chip
) && (!qlt
->qlt_81xx_chip
)) {
5080 goto over_25xx_specific_dump
;
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);
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);
5101 over_25xx_specific_dump
:;
5102 n
= (int)snprintf(buf
, size_left
, "\n\nHost Interface Registers\n");
5103 buf
+= n
; size_left
-= n
;
5105 * Capture data from 32 regsiters
5107 n
= qlt_fwdump_dump_regs(qlt
, buf
, 0, 32, size_left
);
5108 buf
+= n
; size_left
-= n
;
5111 * Disable interrupts
5113 REG_WR32(qlt
, 0xc, 0);
5118 n
= (int)snprintf(buf
, size_left
, "\nShadow Registers\n");
5119 buf
+= n
; size_left
-= n
;
5121 REG_WR32(qlt
, 0x54, 0xF70);
5123 for (i
= 0; i
< 0xb; i
++) {
5124 if ((!qlt
->qlt_25xx_chip
) &&
5125 (!qlt
->qlt_81xx_chip
) &&
5129 if (i
&& ((i
& 7) == 0)) {
5130 n
= (int)snprintf(buf
, size_left
, "\n");
5131 buf
+= n
; size_left
-= n
;
5133 REG_WR32(qlt
, 0xF0, addr
);
5134 n
= (int)snprintf(buf
, size_left
, "%08x ", REG_RD32(qlt
, 0xFC));
5135 buf
+= n
; size_left
-= n
;
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
;
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) {
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
;
5164 * Transfer sequence registers
5166 n
= (int)snprintf(buf
, size_left
, "\nXSEQ GP Registers\n");
5167 buf
+= n
; size_left
-= n
;
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
;
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
;
5213 * Receive sequence registers
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
;
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
;
5262 if ((!qlt
->qlt_25xx_chip
) && (!qlt
->qlt_81xx_chip
))
5263 goto over_aseq_regs
;
5266 * Auxiliary sequencer registers
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
;
5316 * Command DMA registers
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
;
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
;
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
;
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
;
5355 * Transmit DMA registers
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
;
5404 * Receive DMA registers
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
;
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
;
5456 * Local memory controller registers
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
;
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
;
5489 * Fibre protocol module regsiters
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
;
5539 * Fibre buffer registers
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
;
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
;
5587 qlt
->intr_sneak_counter
= 10;
5588 mutex_enter(&qlt
->intr_lock
);
5589 (void) qlt_reset_chip(qlt
);
5591 qlt
->intr_sneak_counter
= 0;
5592 mutex_exit(&qlt
->intr_lock
);
5597 n
= (int)snprintf(buf
, size_left
, "\nCode RAM\n");
5598 buf
+= n
; size_left
-= n
;
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
;
5608 if ((ret
= qlt_read_risc_ram(qlt
, addr
, words_to_read
)) !=
5610 EL(qlt
, "Error reading risc ram - CODE RAM status="
5615 n
= qlt_dump_risc_ram(qlt
, addr
, words_to_read
, buf
, size_left
);
5616 buf
+= n
; size_left
-= n
;
5618 if (size_left
< 100000) {
5619 EL(qlt
, "run out of space - CODE RAM size_left=%d\n",
5623 addr
+= words_to_read
;
5626 n
= (int)snprintf(buf
, size_left
, "\nExternal Memory\n");
5627 buf
+= n
; size_left
-= n
;
5630 endaddr
= (((uint32_t)(qlt
->fw_endaddrhi
)) << 16) | qlt
->fw_endaddrlo
;
5633 endaddr
= (endaddr
+ 7) & 0xFFFFFFF8;
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
;
5642 if ((ret
= qlt_read_risc_ram(qlt
, addr
, words_to_read
)) !=
5644 EL(qlt
, "Error reading risc ram - EXT RAM status="
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");
5654 addr
+= words_to_read
;
5660 n
= (int)snprintf(buf
, size_left
, "[<==END] ISP Debug Dump\n");
5661 buf
+= n
; size_left
-= n
;
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
;
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
;
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
;
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
;
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
;
5698 EL(qlt
, "left-%d\n", size_left
);
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
);
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
);
5716 qlt_fwdump_dump_regs(qlt_state_t
*qlt
, caddr_t buf
, int startaddr
, int count
,
5723 for (i
= 0, n
= 0; i
< count
; i
++) {
5729 n
= (int)(n
+ (int)snprintf(&buf
[n
], (uint_t
)(size_left
- n
),
5730 "%08x%c", REG_RD32(qlt
, startaddr
+ (i
<< 2)), c
));
5736 qlt_dump_risc_ram(qlt_state_t
*qlt
, uint32_t addr
, uint32_t words
,
5737 caddr_t buf
, uint_t size_left
)
5744 ptr
= (uint32_t *)((caddr_t
)qlt
->queue_mem_ptr
+ MBOX_DMA_MEM_OFFSET
);
5745 for (i
= 0, n
= 0; i
< words
; i
++) {
5747 n
= (int)(n
+ (int)snprintf(&buf
[n
],
5748 (uint_t
)(size_left
- n
), "%08x: ", addr
+ i
));
5755 n
= (int)(n
+ (int)snprintf(&buf
[n
], (uint_t
)(size_left
- n
),
5756 "%08x%c", ptr
[i
], c
));
5762 qlt_dump_queue(qlt_state_t
*qlt
, caddr_t qadr
, int entries
, caddr_t buf
,
5772 words
= entries
* 32;
5773 ptr
= (uint16_t *)qadr
;
5774 for (i
= 0, n
= 0; i
< words
; i
++) {
5776 n
= (int)(n
+ (int)snprintf(&buf
[n
],
5777 (uint_t
)(size_left
- n
), "%05x: ", i
));
5784 w
= QMEM_RD16(qlt
, &ptr
[i
]);
5785 n
= (int)(n
+ (int)snprintf(&buf
[n
], (size_left
- n
), "%04x%c",
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
5797 qlt_read_risc_ram(qlt_state_t
*qlt
, uint32_t addr
, uint32_t words
)
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
;
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
)));
5813 REG_WR16(qlt
, REG_MBOX(5), LSW(words
));
5814 REG_WR16(qlt
, REG_MBOX(4), MSW(words
));
5816 /* RISC source address */
5817 REG_WR16(qlt
, REG_MBOX(1), LSW(addr
));
5818 REG_WR16(qlt
, REG_MBOX(8), MSW(addr
));
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
);
5826 EL(qlt
, "qlt_raw_mailbox_command=ch status=%llxh\n", ret
);
5832 qlt_verify_fw(qlt_state_t
*qlt
)
5835 /* Just put it on the request queue */
5836 mutex_enter(&qlt
->req_lock
);
5837 req
= qlt_get_req_entries(qlt
, 1);
5839 mutex_exit(&qlt
->req_lock
);
5840 /* XXX handle this */
5844 bzero(req
, IOCB_SIZE
);
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);
5853 qlt_submit_req_entries(qlt
, 1);
5854 mutex_exit(&qlt
->req_lock
);
5858 qlt_handle_verify_fw_completion(qlt_state_t
*qlt
, uint8_t *rsp
)
5861 char info
[QLT_INFO_LEN
];
5863 status
= QMEM_RD16(qlt
, rsp
+8);
5865 (void) snprintf(info
, sizeof (info
),
5866 "qlt_handle_verify_fw_completion: "
5867 "status:%x, rsp:%p", status
, (void *)rsp
);
5869 uint16_t error_code
;
5871 error_code
= QMEM_RD16(qlt
, rsp
+0xA);
5872 (void) snprintf(info
, sizeof (info
),
5873 "qlt_handle_verify_fw_completion: error code:%x",
5880 * qlt_el_trace_desc_ctor - Construct an extended logging trace descriptor.
5882 * Input: Pointer to the adapter state structure.
5883 * Returns: Success or Failure.
5884 * Context: Kernel context.
5887 qlt_el_trace_desc_ctor(qlt_state_t
*qlt
)
5889 int rval
= DDI_SUCCESS
;
5891 qlt
->el_trace_desc
= (qlt_el_trace_desc_t
*)
5892 kmem_zalloc(sizeof (qlt_el_trace_desc_t
), KM_SLEEP
);
5894 if (qlt
->el_trace_desc
== NULL
) {
5895 cmn_err(CE_WARN
, "qlt(%d): can't construct trace descriptor",
5899 qlt
->el_trace_desc
->next
= 0;
5900 qlt
->el_trace_desc
->trace_buffer
=
5901 (char *)kmem_zalloc(EL_TRACE_BUF_SIZE
, KM_SLEEP
);
5903 if (qlt
->el_trace_desc
->trace_buffer
== NULL
) {
5904 cmn_err(CE_WARN
, "qlt(%d): can't get trace buffer",
5906 kmem_free(qlt
->el_trace_desc
,
5907 sizeof (qlt_el_trace_desc_t
));
5908 qlt
->el_trace_desc
= NULL
;
5911 qlt
->el_trace_desc
->trace_buffer_size
=
5913 mutex_init(&qlt
->el_trace_desc
->mutex
, NULL
,
5914 MUTEX_DRIVER
, NULL
);
5922 * qlt_el_trace_desc_dtor - Destroy an extended logging trace descriptor.
5924 * Input: Pointer to the adapter state structure.
5925 * Returns: Success or Failure.
5926 * Context: Kernel context.
5929 qlt_el_trace_desc_dtor(qlt_state_t
*qlt
)
5931 int rval
= DDI_SUCCESS
;
5933 if (qlt
->el_trace_desc
== NULL
) {
5934 cmn_err(CE_WARN
, "qlt(%d): can't destroy el trace descriptor",
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
);
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
;
5952 * Extended logging message
5955 * qlt: adapter state pointer.
5956 * fn: function name.
5958 * ...: Variable argument list.
5961 * Kernel/Interrupt context.
5964 qlt_el_msg(qlt_state_t
*qlt
, const char *fn
, int ce
, ...)
5966 char *s
, *fmt
= 0, *fmt1
= 0;
5967 char fmt2
[EL_BUFFER_RESERVE
];
5972 /* Tracing is the default but it can be disabled. */
5973 if ((rval
= qlt_validate_trace_desc(qlt
)) == DDI_SUCCESS
) {
5976 mutex_enter(&qlt
->el_trace_desc
->mutex
);
5979 * Ensure enough space for the string. Wrap to
5980 * start when default message allocation size
5981 * would overrun the end.
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;
5988 fmt
= qlt
->el_trace_desc
->trace_buffer
+
5989 qlt
->el_trace_desc
->next
;
5993 /* if no buffer use the stack */
6000 s
= va_arg(vl
, char *);
6002 rval
= (int)snprintf(fmt
, (size_t)EL_BUFFER_RESERVE
,
6003 "QEL qlt(%d): %s, ", qlt
->instance
, fn
);
6005 tmp
= (int)vsnprintf(fmt1
,
6006 (size_t)(uint32_t)((int)EL_BUFFER_RESERVE
- rval
), s
, vl
);
6010 * Calculate the offset where the next message will go,
6011 * skipping the NULL.
6014 uint16_t next
= (uint16_t)(rval
+= 1);
6015 qlt
->el_trace_desc
->next
+= next
;
6016 mutex_exit(&qlt
->el_trace_desc
->mutex
);
6019 if (enable_extended_logging
) {
6027 * qlt_dump_el_trace_buffer
6028 * Outputs extended logging trace buffer.
6031 * qlt: adapter state pointer.
6034 qlt_dump_el_trace_buffer(qlt_state_t
*qlt
)
6036 char *dump_start
= NULL
;
6037 char *dump_current
= NULL
;
6043 mutex_enter(&qlt
->el_trace_desc
->mutex
);
6045 rval
= qlt_validate_trace_desc(qlt
);
6047 cmn_err(CE_CONT
, "qlt(%d) Dump EL trace - invalid desc\n",
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
;
6055 cmn_err(CE_CONT
, "qlt(%d) Dump EL trace - start %p %p\n",
6057 (void *)dump_start
, (void *)trace_start
);
6059 while (((uintptr_t)dump_current
- (uintptr_t)trace_start
) <=
6060 (uintptr_t)qlt
->el_trace_desc
->trace_buffer_size
) {
6062 cmn_err(CE_CONT
, "%p - %s", (void *)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
;
6070 } else if (wrapped
) {
6071 /* Don't go past next. */
6072 if ((trace_start
+ qlt
->el_trace_desc
->next
) <=
6076 } else if (*dump_current
== NULL
) {
6081 mutex_exit(&qlt
->el_trace_desc
->mutex
);
6085 * qlt_validate_trace_desc
6086 * Ensures the extended logging trace descriptor is good.
6089 * qlt: adapter state pointer.
6092 * ql local function return status code.
6095 qlt_validate_trace_desc(qlt_state_t
*qlt
)
6097 int rval
= DDI_SUCCESS
;
6099 if (qlt
->el_trace_desc
== NULL
) {
6101 } else if (qlt
->el_trace_desc
->trace_buffer
== NULL
) {
6108 * qlt_find_trace_start
6109 * Locate the oldest extended logging trace entry.
6112 * qlt: adapter state pointer.
6115 * Pointer to a string.
6118 * Kernel/Interrupt context.
6121 qlt_find_trace_start(qlt_state_t
*qlt
)
6123 char *trace_start
= 0;
6124 char *trace_next
= 0;
6126 trace_next
= qlt
->el_trace_desc
->trace_buffer
+
6127 qlt
->el_trace_desc
->next
;
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.
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);
6144 trace_start
= qlt
->el_trace_desc
->trace_buffer
;
6146 return (trace_start
);
6151 qlt_read_int_prop(qlt_state_t
*qlt
, char *prop
, int defval
)
6153 return (ddi_getprop(DDI_DEV_T_ANY
, qlt
->dip
,
6154 DDI_PROP_DONTPASS
| DDI_PROP_CANSLEEP
, prop
, defval
));
6158 qlt_read_string_prop(qlt_state_t
*qlt
, char *prop
, char **prop_val
)
6160 return (ddi_prop_lookup_string(DDI_DEV_T_ANY
, qlt
->dip
,
6161 DDI_PROP_DONTPASS
, prop
, prop_val
));
6165 qlt_read_int_instance_prop(qlt_state_t
*qlt
, char *prop
, int defval
)
6167 char inst_prop
[256];
6171 * Get adapter instance specific parameters. If the instance
6172 * specific parameter isn't there, try the global parameter.
6175 (void) sprintf(inst_prop
, "hba%d-%s", qlt
->instance
, prop
);
6177 if ((val
= qlt_read_int_prop(qlt
, inst_prop
, defval
)) == defval
) {
6178 val
= qlt_read_int_prop(qlt
, prop
, defval
);
6185 qlt_read_string_instance_prop(qlt_state_t
*qlt
, char *prop
, char **prop_val
)
6187 char instance_prop
[256];
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
));
6195 qlt_convert_string_to_ull(char *prop
, int radix
,
6196 u_longlong_t
*result
)
6198 return (ddi_strtoull((const char *)prop
, 0, radix
, result
));
6202 qlt_wwn_overload_prop(qlt_state_t
*qlt
)
6207 u_longlong_t wwnn
= 0, wwpn
= 0;
6208 boolean_t overloaded
= FALSE
;
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
);
6216 if (rval
== DDI_PROP_SUCCESS
) {
6217 rval
= qlt_read_string_instance_prop(qlt
, "adapter-wwpn",
6219 if (rval
== DDI_PROP_SUCCESS
) {
6220 rval
= qlt_convert_string_to_ull(prop_val
, radix
,
6224 if (rval
== DDI_PROP_SUCCESS
) {
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
);
6232 return (overloaded
);
6236 * prop_text - Return a pointer to a string describing the status
6238 * Input: prop_status = the return status from a property function.
6239 * Returns: pointer to a string.
6240 * Context: Kernel context.
6243 prop_text(int prop_status
)
6245 string_table_t
*entry
= &prop_status_tbl
[0];
6247 return (value2string(entry
, prop_status
, 0xFFFF));
6251 * value2string Return a pointer to a string associated with the value
6253 * Input: entry = the value to string table
6255 * Returns: pointer to a string.
6256 * Context: Kernel context.
6259 value2string(string_table_t
*entry
, int value
, int delimiter
)
6261 for (; entry
->value
!= delimiter
; entry
++) {
6262 if (entry
->value
== value
) {
6266 return (entry
->string
);
6270 * qlt_chg_endian Change endianess of byte array.
6272 * Input: buf = array pointer.
6273 * size = size of array in bytes.
6275 * Context: Interrupt or Kernel context.
6278 qlt_chg_endian(uint8_t buf
[], size_t size
)
6285 for (cnt
= 0; cnt
< size
/ 2; cnt
++) {
6287 buf
[cnt1
] = buf
[cnt
];
6295 * Reset MPS for FCoE functions.
6298 * ha = virtual adapter state pointer.
6304 qlt_mps_reset(qlt_state_t
*qlt
)
6306 uint32_t data
, dctl
= 1000;
6309 if (dctl
-- == 0 || qlt_raw_wrt_risc_ram_word(qlt
, 0x7c00, 1) !=
6313 if (qlt_raw_rd_risc_ram_word(qlt
, 0x7c00, &data
) !=
6315 (void) qlt_raw_wrt_risc_ram_word(qlt
, 0x7c00, 0);
6318 } while (!(data
& BIT_0
));
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)) {
6324 data
|= dctl
& 0xe0;
6325 (void) qlt_raw_wrt_risc_ram_word(qlt
, 0x7A15, data
);
6328 (void) qlt_raw_wrt_risc_ram_word(qlt
, 0x7c00, 0);
6332 * qlt_raw_wrt_risc_ram_word
6333 * Write RISC RAM word.
6335 * Input: qlt: adapter state pointer.
6336 * risc_address: risc ram word address.
6339 * Returns: qlt local function return status code.
6341 * Context: Kernel context.
6344 qlt_raw_wrt_risc_ram_word(qlt_state_t
*qlt
, uint32_t risc_address
,
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"
6364 * ql_raw_rd_risc_ram_word
6365 * Read RISC RAM word.
6367 * Input: qlt: adapter state pointer.
6368 * risc_address: risc ram word address.
6369 * data: data pointer.
6371 * Returns: ql local function return status code.
6373 * Context: Kernel context.
6376 qlt_raw_rd_risc_ram_word(qlt_state_t
*qlt
, uint32_t risc_address
,
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"
6396 qlt_properties(qlt_state_t
*qlt
)
6399 int32_t defval
= 0xffff;
6401 if (qlt_wwn_overload_prop(qlt
) == TRUE
) {
6402 EL(qlt
, "wwnn overloaded.\n");
6405 if ((cnt
= qlt_read_int_instance_prop(qlt
, "bucketcnt2k", defval
)) !=
6407 qlt
->qlt_bucketcnt
[0] = cnt
;
6408 EL(qlt
, "2k bucket o/l=%d\n", cnt
);
6411 if ((cnt
= qlt_read_int_instance_prop(qlt
, "bucketcnt8k", defval
)) !=
6413 qlt
->qlt_bucketcnt
[1] = cnt
;
6414 EL(qlt
, "8k bucket o/l=%d\n", cnt
);
6417 if ((cnt
= qlt_read_int_instance_prop(qlt
, "bucketcnt64k", defval
)) !=
6419 qlt
->qlt_bucketcnt
[2] = cnt
;
6420 EL(qlt
, "64k bucket o/l=%d\n", cnt
);
6423 if ((cnt
= qlt_read_int_instance_prop(qlt
, "bucketcnt128k", defval
)) !=
6425 qlt
->qlt_bucketcnt
[3] = cnt
;
6426 EL(qlt
, "128k bucket o/l=%d\n", cnt
);
6429 if ((cnt
= qlt_read_int_instance_prop(qlt
, "bucketcnt256", defval
)) !=
6431 qlt
->qlt_bucketcnt
[4] = cnt
;
6432 EL(qlt
, "256k bucket o/l=%d\n", cnt
);