1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2009-2015 QLogic Corporation. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /*
28 * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
29 */
30
31 #include <sys/conf.h>
32 #include <sys/ddi.h>
33 #include <sys/stat.h>
34 #include <sys/pci.h>
35 #include <sys/sunddi.h>
36 #include <sys/modctl.h>
37 #include <sys/file.h>
38 #include <sys/cred.h>
39 #include <sys/byteorder.h>
40 #include <sys/atomic.h>
41 #include <sys/scsi/scsi.h>
42
43 #include <sys/stmf_defines.h>
44 #include <sys/fct_defines.h>
45 #include <sys/stmf.h>
46 #include <sys/portif.h>
47 #include <sys/fct.h>
48
49 #include "qlt.h"
50 #include "qlt_dma.h"
51 #include "qlt_ioctl.h"
52 #include "qlt_open.h"
53 #include <sys/stmf_ioctl.h>
54
55 static int qlt_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
56 static int qlt_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
57 static uint8_t *qlt_vpd_findtag(qlt_state_t *qlt, uint8_t *vpdbuf,
58 int8_t *opcode);
59 static int qlt_vpd_lookup(qlt_state_t *qlt, uint8_t *opcode, uint8_t *bp,
60 int32_t bplen);
61 static void qlt_enable_intr(qlt_state_t *);
62 static void qlt_disable_intr(qlt_state_t *);
63 static fct_status_t qlt_reset_chip(qlt_state_t *qlt);
64 static fct_status_t qlt_download_fw(qlt_state_t *qlt);
65 static fct_status_t qlt_load_risc_ram(qlt_state_t *qlt, uint32_t *host_addr,
66 uint32_t word_count, uint32_t risc_addr);
67 static fct_status_t qlt_raw_mailbox_command(qlt_state_t *qlt);
68 static mbox_cmd_t *qlt_alloc_mailbox_command(qlt_state_t *qlt,
69 uint32_t dma_size);
70 void qlt_free_mailbox_command(qlt_state_t *qlt, mbox_cmd_t *mcp);
71 static fct_status_t qlt_mailbox_command(qlt_state_t *qlt, mbox_cmd_t *mcp);
72 static uint_t qlt_isr(caddr_t arg, caddr_t arg2);
73 static uint_t qlt_msix_resp_handler(caddr_t arg, caddr_t arg2);
74 static uint_t qlt_msix_default_handler(caddr_t arg, caddr_t arg2);
75 static fct_status_t qlt_firmware_dump(fct_local_port_t *port,
76 stmf_state_change_info_t *ssci);
77 static void qlt_handle_inot(qlt_state_t *qlt, uint8_t *inot);
78 static void qlt_handle_purex(qlt_state_t *qlt, uint8_t *resp);
79 static void qlt_handle_atio(qlt_state_t *qlt, uint8_t *atio);
80 static void qlt_handle_ctio_completion(qlt_state_t *qlt, uint8_t *rsp,
81 uint16_t qi);
82 static void qlt_handle_sol_abort_completion(qlt_state_t *qlt, uint8_t *rsp);
83 static void qlt_handle_dereg_completion(qlt_state_t *qlt, uint8_t *rsp);
84 static void qlt_handle_unsol_els_completion(qlt_state_t *qlt, uint8_t *rsp);
85 static void qlt_handle_unsol_els_abort_completion(qlt_state_t *qlt,
86 uint8_t *rsp);
87 static void qlt_handle_sol_els_completion(qlt_state_t *qlt, uint8_t *rsp);
88 static void qlt_handle_rcvd_abts(qlt_state_t *qlt, uint8_t *resp, uint16_t qi);
89 static void qlt_handle_abts_completion(qlt_state_t *qlt, uint8_t *resp,
90 uint16_t qi);
91 static fct_status_t qlt_read_nvram(qlt_state_t *qlt);
92 static fct_status_t qlt_read_vpd(qlt_state_t *qlt);
93 static fct_status_t qlt_read_rom_image(qlt_state_t *qlt);
94 static void qlt_verify_fw(qlt_state_t *qlt);
95 static void qlt_handle_verify_fw_completion(qlt_state_t *qlt, uint8_t *rsp);
96 fct_status_t qlt_port_start(caddr_t arg);
97 fct_status_t qlt_port_stop(caddr_t arg);
98 fct_status_t qlt_port_online(qlt_state_t *qlt);
99 fct_status_t qlt_port_offline(qlt_state_t *qlt);
100 static fct_status_t qlt_get_link_info(fct_local_port_t *port,
101 fct_link_info_t *li);
102 static void qlt_ctl(struct fct_local_port *port, int cmd, void *arg);
103 static fct_status_t qlt_force_lip(qlt_state_t *);
104 static fct_status_t qlt_do_flogi(struct fct_local_port *port,
105 fct_flogi_xchg_t *fx);
106 void qlt_handle_atio_queue_update(qlt_state_t *qlt);
107 void qlt_handle_resp_queue_update(qlt_state_t *qlt, uint16_t qi);
108 fct_status_t qlt_register_remote_port(fct_local_port_t *port,
109 fct_remote_port_t *rp, fct_cmd_t *login);
110 fct_status_t qlt_deregister_remote_port(fct_local_port_t *port,
111 fct_remote_port_t *rp);
112 fct_status_t qlt_send_cmd_response(fct_cmd_t *cmd, uint32_t ioflags);
113 fct_status_t qlt_send_els_response(qlt_state_t *qlt, fct_cmd_t *cmd);
114 fct_status_t qlt_send_abts_response(qlt_state_t *qlt,
115 fct_cmd_t *cmd, int terminate);
116 static void qlt_handle_inot(qlt_state_t *qlt, uint8_t *inot);
117 int qlt_set_uniq_flag(uint16_t *ptr, uint16_t setf, uint16_t abortf);
118 fct_status_t qlt_abort_cmd(struct fct_local_port *port,
119 fct_cmd_t *cmd, uint32_t flags);
120 fct_status_t qlt_abort_sol_cmd(qlt_state_t *qlt, fct_cmd_t *cmd);
121 fct_status_t qlt_abort_purex(qlt_state_t *qlt, fct_cmd_t *cmd);
122 fct_status_t qlt_abort_unsol_scsi_cmd(qlt_state_t *qlt, fct_cmd_t *cmd);
123 fct_status_t qlt_send_cmd(fct_cmd_t *cmd);
124 fct_status_t qlt_send_els(qlt_state_t *qlt, fct_cmd_t *cmd);
125 fct_status_t qlt_send_status(qlt_state_t *qlt, fct_cmd_t *cmd);
126 fct_status_t qlt_xfer_scsi_data(fct_cmd_t *cmd,
127 stmf_data_buf_t *dbuf, uint32_t ioflags);
128 fct_status_t qlt_send_ct(qlt_state_t *qlt, fct_cmd_t *cmd);
129 static void qlt_handle_ct_completion(qlt_state_t *qlt, uint8_t *rsp);
130 static void qlt_release_intr(qlt_state_t *qlt);
131 static int qlt_setup_interrupts(qlt_state_t *qlt);
132 static void qlt_destroy_mutex(qlt_state_t *qlt);
133
134 static fct_status_t qlt_read_risc_ram(qlt_state_t *qlt, uint32_t addr,
135 uint32_t words);
136 static fct_status_t qlt_mbx_mpi_ram(qlt_state_t *qlt, uint32_t addr,
137 uint32_t words, uint16_t direction);
138 static int qlt_dump_queue(qlt_state_t *qlt, caddr_t qadr, int entries,
139 caddr_t buf, uint_t size_left);
140 static int qlt_dump_risc_ram(qlt_state_t *qlt, uint32_t addr, uint32_t words,
141 caddr_t buf, uint_t size_left);
142 static int qlt_fwdump_dump_regs(qlt_state_t *qlt, caddr_t buf, int startaddr,
143 int count, uint_t size_left);
144 static int qlt_ioctl(dev_t dev, int cmd, intptr_t data, int mode,
145 cred_t *credp, int *rval);
146 static int qlt_open(dev_t *devp, int flag, int otype, cred_t *credp);
147 static int qlt_close(dev_t dev, int flag, int otype, cred_t *credp);
148
149 static int qlt_setup_msi(qlt_state_t *qlt);
150 static int qlt_setup_msix(qlt_state_t *qlt);
151
152 static int qlt_el_trace_desc_ctor(qlt_state_t *qlt);
153 static int qlt_el_trace_desc_dtor(qlt_state_t *qlt);
154
155 static int qlt_read_int_prop(qlt_state_t *qlt, char *prop, int defval);
156 static int qlt_read_string_prop(qlt_state_t *qlt, char *prop, char **prop_val);
157 static int qlt_read_string_instance_prop(qlt_state_t *qlt, char *prop,
158 char **prop_val);
159 static int qlt_read_int_instance_prop(qlt_state_t *, char *, int);
160 static int qlt_convert_string_to_ull(char *prop, int radix,
161 u_longlong_t *result);
162 static boolean_t qlt_wwn_overload_prop(qlt_state_t *qlt);
163 static int qlt_quiesce(dev_info_t *dip);
164 static void qlt_disable_intr(qlt_state_t *qlt);
165 static fct_status_t qlt_raw_wrt_risc_ram_word(qlt_state_t *qlt, uint32_t,
166 uint32_t);
167 static fct_status_t qlt_raw_rd_risc_ram_word(qlt_state_t *qlt, uint32_t,
168 uint32_t *);
169 static void qlt_mps_reset(qlt_state_t *qlt);
170 static void qlt_properties(qlt_state_t *qlt);
171
172 static fct_status_t qlt_mq_create(qlt_state_t *qlt, int idx);
173 static fct_status_t qlt_mq_destroy(qlt_state_t *qlt);
174
175 static fct_status_t qlt_27xx_get_dmp_template(qlt_state_t *);
176 static uint32_t qlt_27xx_dmp_parse_template(qlt_state_t *, qlt_dt_hdr_t *,
177 uint8_t *, uint32_t);
178 static int qlt_27xx_dump_ram(qlt_state_t *, uint16_t, uint32_t,
179 uint32_t, uint8_t *);
180
181 #define SETELSBIT(bmp, els) (bmp)[((els) >> 3) & 0x1F] = \
182 (uint8_t)((bmp)[((els) >> 3) & 0x1F] | ((uint8_t)1) << ((els) & 7))
183
184 int qlt_enable_msix = 1;
185 int qlt_enable_msi = 1;
186
187
188 string_table_t prop_status_tbl[] = DDI_PROP_STATUS();
189
190 /* Array to quickly calculate next free buf index to use */
191 #if 0
192 static int qlt_nfb[] = { 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 0xff };
193 #endif
194
195 static struct cb_ops qlt_cb_ops = {
196 qlt_open,
197 qlt_close,
198 nodev,
199 nodev,
200 nodev,
201 nodev,
202 nodev,
203 qlt_ioctl,
204 nodev,
205 nodev,
206 nodev,
207 nochpoll,
208 ddi_prop_op,
209 0,
210 D_MP | D_NEW
211 };
212
213 static struct dev_ops qlt_ops = {
214 DEVO_REV,
215 0,
216 nodev,
217 nulldev,
218 nulldev,
219 qlt_attach,
220 qlt_detach,
221 nodev,
222 &qlt_cb_ops,
223 NULL,
224 ddi_power,
225 qlt_quiesce
226 };
227
228 #ifndef PORT_SPEED_16G
229 #define PORT_SPEED_16G 32
230 #endif
231
232 #ifndef PORT_SPEED_32G
233 #define PORT_SPEED_32G 64
234 #endif
235
236 #ifndef QL_NAME
237 #define QL_NAME "qlt"
238 #endif
239
240 static struct modldrv modldrv = {
241 &mod_driverops,
242 QLT_NAME" "QLT_VERSION,
243 &qlt_ops,
244 };
245
246 static struct modlinkage modlinkage = {
247 MODREV_1, &modldrv, NULL
248 };
249
250 void *qlt_state = NULL;
251 kmutex_t qlt_global_lock;
252 static uint32_t qlt_loaded_counter = 0;
253 uint8_t qlt_reprocess_attempt_cnt = 5;
254 uint32_t qlt_reprocess_delay = 75; /* default 75 microseconds */
255
256 static char *pci_speeds[] = { " 33", "-X Mode 1 66", "-X Mode 1 100",
257 "-X Mode 1 133", "--Invalid--",
258 "-X Mode 2 66", "-X Mode 2 100",
259 "-X Mode 2 133", " 66" };
260
261 /* Always use 64 bit DMA. */
262 static ddi_dma_attr_t qlt_queue_dma_attr = {
263 DMA_ATTR_V0, /* dma_attr_version */
264 0, /* low DMA address range */
265 0xffffffffffffffff, /* high DMA address range */
266 0xffffffff, /* DMA counter register */
267 64, /* DMA address alignment */
268 0xff, /* DMA burstsizes */
269 1, /* min effective DMA size */
270 0xffffffff, /* max DMA xfer size */
271 0xffffffff, /* segment boundary */
272 1, /* s/g list length */
273 1, /* granularity of device */
274 0 /* DMA transfer flags */
275 };
276
277
278 /* Always use 64 bit DMA. */
279 static ddi_dma_attr_t qlt_queue_dma_attr_mq_req1 = {
280 DMA_ATTR_V0, /* dma_attr_version */
281 0, /* low DMA address range */
282 0xffffffffffffffff, /* high DMA address range */
283 0xffffffff, /* DMA counter register */
284 64, /* DMA address alignment */
285 0xff, /* DMA burstsizes */
286 1, /* min effective DMA size */
287 0xffffffff, /* max DMA xfer size */
288 0xffffffff, /* segment boundary */
289 1, /* s/g list length */
290 1, /* granularity of device */
291 0 /* DMA transfer flags */
292 };
293
294 /* Always use 64 bit DMA. */
295 static ddi_dma_attr_t qlt_queue_dma_attr_mq_rsp1 = {
296 DMA_ATTR_V0, /* dma_attr_version */
297 0, /* low DMA address range */
298 0xffffffffffffffff, /* high DMA address range */
299 0xffffffff, /* DMA counter register */
300 64, /* DMA address alignment */
301 0xff, /* DMA burstsizes */
302 1, /* min effective DMA size */
303 0xffffffff, /* max DMA xfer size */
304 0xffffffff, /* segment boundary */
305 1, /* s/g list length */
306 1, /* granularity of device */
307 0 /* DMA transfer flags */
308 };
309
310
311 /* qlogic logging */
312 int enable_extended_logging = 0;
313 static char qlt_provider_name[] = "qlt";
314 static struct stmf_port_provider *qlt_pp;
315
316 int
_init(void)317 _init(void)
318 {
319 int ret;
320
321 ret = ddi_soft_state_init(&qlt_state, sizeof (qlt_state_t), 0);
322 if (ret == 0) {
323 mutex_init(&qlt_global_lock, 0, MUTEX_DRIVER, 0);
324 qlt_pp = (stmf_port_provider_t *)stmf_alloc(
325 STMF_STRUCT_PORT_PROVIDER, 0, 0);
326 qlt_pp->pp_portif_rev = PORTIF_REV_1;
327 qlt_pp->pp_name = qlt_provider_name;
328 if (stmf_register_port_provider(qlt_pp) != STMF_SUCCESS) {
329 stmf_free(qlt_pp);
330 mutex_destroy(&qlt_global_lock);
331 ddi_soft_state_fini(&qlt_state);
332 return (EIO);
333 }
334 ret = mod_install(&modlinkage);
335 if (ret != 0) {
336 (void) stmf_deregister_port_provider(qlt_pp);
337 stmf_free(qlt_pp);
338 mutex_destroy(&qlt_global_lock);
339 ddi_soft_state_fini(&qlt_state);
340 }
341 }
342 return (ret);
343 }
344
345 int
_fini(void)346 _fini(void)
347 {
348 int ret;
349
350 if (qlt_loaded_counter)
351 return (EBUSY);
352 ret = mod_remove(&modlinkage);
353 if (ret == 0) {
354 (void) stmf_deregister_port_provider(qlt_pp);
355 stmf_free(qlt_pp);
356 mutex_destroy(&qlt_global_lock);
357 ddi_soft_state_fini(&qlt_state);
358 }
359 return (ret);
360 }
361
362 int
_info(struct modinfo * modinfop)363 _info(struct modinfo *modinfop)
364 {
365 return (mod_info(&modlinkage, modinfop));
366 }
367
368 static int
qlt_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)369 qlt_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
370 {
371 int instance;
372 qlt_state_t *qlt;
373 ddi_device_acc_attr_t dev_acc_attr;
374 uint16_t did;
375 uint16_t val;
376 uint16_t mr;
377 size_t discard;
378 uint_t ncookies;
379 int max_read_size;
380 int max_payload_size;
381 fct_status_t ret;
382
383 /* No support for suspend resume yet */
384 if (cmd != DDI_ATTACH)
385 return (DDI_FAILURE);
386 instance = ddi_get_instance(dip);
387
388 cmn_err(CE_CONT, "!Qlogic %s(%d) FCA Driver v%s\n",
389 QLT_NAME, instance, QLT_VERSION);
390
391 if (ddi_soft_state_zalloc(qlt_state, instance) != DDI_SUCCESS) {
392 cmn_err(CE_WARN, "qlt(%d): soft state alloc failed", instance);
393 return (DDI_FAILURE);
394 }
395
396 if ((qlt = (qlt_state_t *)ddi_get_soft_state(qlt_state, instance)) ==
397 NULL) {
398 cmn_err(CE_WARN, "qlt(%d): can't get soft state", instance);
399 goto attach_fail_1;
400 }
401
402 qlt->instance = instance;
403
404 qlt->nvram = (qlt_nvram_t *)kmem_zalloc(sizeof (qlt_nvram_t), KM_SLEEP);
405 qlt->vpd = (uint32_t *)kmem_zalloc(QL_24XX_VPD_SIZE, KM_SLEEP);
406 qlt->dip = dip;
407
408 if (qlt_el_trace_desc_ctor(qlt) != DDI_SUCCESS) {
409 cmn_err(CE_WARN, "qlt(%d): can't setup el tracing", instance);
410 goto attach_fail_2;
411 }
412
413 EL(qlt, "instance=%d, ptr=%p\n", instance, (void *)qlt);
414
415 if (pci_config_setup(dip, &qlt->pcicfg_acc_handle) != DDI_SUCCESS) {
416 cmn_err(CE_WARN, "qlt(%d): pci_config_setup failed", instance);
417 goto attach_fail_3;
418 }
419
420 did = PCICFG_RD16(qlt, PCI_CONF_DEVID);
421 if ((did != 0x2422) && (did != 0x2432) &&
422 (did != 0x8432) && (did != 0x2532) &&
423 (did != 0x8001) && (did != 0x2031) &&
424 (did != 0x2071) && (did != 0x2261)) {
425 cmn_err(CE_WARN, "qlt(%d): unknown devid(%x), failing attach",
426 instance, did);
427 goto attach_fail_4;
428 }
429
430 if ((did & 0xFFFF) == 0x2071) {
431 qlt->qlt_27xx_chip = 1;
432 qlt->qlt_fcoe_enabled = 0;
433 } else if ((did & 0xFFFF) == 0x2261) {
434 qlt->qlt_27xx_chip = 1;
435 qlt->qlt_fcoe_enabled = 0;
436 } else if ((did & 0xFFFF) == 0x2031) {
437 qlt->qlt_83xx_chip = 1;
438 qlt->qlt_fcoe_enabled = 0;
439 } else if ((did & 0xFFF0) == 0x8000) {
440 qlt->qlt_81xx_chip = 1;
441 qlt->qlt_fcoe_enabled = 1;
442 } else if ((did & 0xFF00) == 0x2500)
443 qlt->qlt_25xx_chip = 1;
444
445 dev_acc_attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
446 dev_acc_attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
447 dev_acc_attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
448
449 if ((qlt->qlt_83xx_chip) || (qlt->qlt_27xx_chip)) {
450 int stat_1;
451 off_t regsize_1;
452
453 stat_1 = ddi_dev_regsize(dip, 1, ®size_1);
454 if (stat_1 != DDI_SUCCESS) {
455 stmf_trace(qlt->qlt_port_alias,
456 "instance=%d, reg 1 regsize failed,"
457 " stat %x", instance, stat_1);
458 goto attach_fail_4;
459 }
460
461 if (ddi_regs_map_setup(dip, 1, &qlt->regs, 0, regsize_1,
462 &dev_acc_attr, &qlt->regs_acc_handle) != DDI_SUCCESS) {
463 cmn_err(CE_NOTE, "qlt(%d) ddi_regs_map_setup failed\n",
464 instance);
465 goto attach_fail_4;
466 }
467 } else {
468 /*
469 * 24xx and 25xx: rnumber 0 is config space
470 * rnumber 1 is for IO space
471 * rnumber 2 is for MBAR0: ISP, MSIX, PBA
472 */
473 if (ddi_regs_map_setup(dip, 2, &qlt->regs, 0, 0x100,
474 &dev_acc_attr, &qlt->regs_acc_handle) != DDI_SUCCESS) {
475 goto attach_fail_4;
476 }
477 }
478
479 if ((qlt->qlt_83xx_chip) || (qlt->qlt_27xx_chip)) {
480
481 uint32_t w32h;
482 uint32_t w32l;
483 int stat;
484 off_t regsize;
485
486 w32l = PCICFG_RD32(qlt, PCI_CONF_BASE2);
487 w32h = PCICFG_RD32(qlt, PCI_CONF_BASE3);
488
489 if ((w32h > 0) || w32l > 0) {
490 stat = ddi_dev_regsize(dip, 2, ®size);
491 if (stat != DDI_SUCCESS) {
492 stmf_trace(qlt->qlt_port_alias,
493 "instance=%d, MSI-X regsize failed,"
494 " stat %x", instance, stat);
495 }
496 stmf_trace(qlt->qlt_port_alias,
497 "instance=%d, MSI-X MEM Bar size %x",
498 instance, regsize);
499
500 stat = ddi_regs_map_setup(dip, 2, &qlt->msix_base, 0,
501 /* ((MQ_MAX_QUEUES * 2) +1) << 2, */
502 regsize,
503 &dev_acc_attr, &qlt->msix_acc_handle);
504
505 if (stat != DDI_SUCCESS || qlt->msix_base == NULL ||
506 qlt->msix_acc_handle == NULL) {
507
508 cmn_err(CE_WARN,
509 "qlt(%d): can't map MBar for MSI-X",
510 instance);
511 stmf_trace(qlt->qlt_port_alias,
512 "instance=%d, MSI-X MEM Bar map fail",
513 instance);
514
515 if (qlt->msix_acc_handle != NULL) {
516 ddi_regs_map_free(
517 &qlt->msix_acc_handle);
518 }
519 goto attach_fail_5;
520 }
521 } else {
522 cmn_err(CE_WARN, "qlt(%d): can't setup MBar for MSI-X",
523 instance);
524 stmf_trace(qlt->qlt_port_alias,
525 "instance=%d, No MSI-X MEM Bar", instance);
526 goto attach_fail_5;
527 }
528
529 w32l = PCICFG_RD32(qlt, PCI_CONF_BASE4);
530 w32h = PCICFG_RD32(qlt, PCI_CONF_BASE5);
531
532 if ((w32h > 0) || w32l > 0) {
533 stat = ddi_dev_regsize(dip, 3, ®size);
534 if (stat != DDI_SUCCESS) {
535 stmf_trace(qlt->qlt_port_alias,
536 "instance=%d, MQ regsize failed, stat %x",
537 instance, stat);
538 }
539 stmf_trace(qlt->qlt_port_alias,
540 "instance=%d, MQ MEM Bar size %x",
541 instance, regsize);
542
543 /* for 83xx the QP pointers are in the 3rd MBar */
544 stat = ddi_regs_map_setup(dip, 3, &qlt->mq_reg_base, 0,
545 (MQ_MAX_QUEUES * MQBAR_REG_OFFSET),
546 &dev_acc_attr, &qlt->mq_reg_acc_handle);
547
548 if (stat != DDI_SUCCESS || qlt->mq_reg_base == NULL ||
549 qlt->mq_reg_acc_handle == NULL) {
550
551 cmn_err(CE_WARN, "qlt(%d): can't map QP MBar",
552 instance);
553 stmf_trace(qlt->qlt_port_alias,
554 "instance=%d, QP MEM Bar map fail st:%x",
555 instance, stat);
556
557 if (qlt->msix_acc_handle != NULL) {
558 ddi_regs_map_free(
559 &qlt->msix_acc_handle);
560 }
561 if (qlt->mq_reg_acc_handle != NULL) {
562 ddi_regs_map_free(
563 &qlt->mq_reg_acc_handle);
564 }
565 goto attach_fail_5;
566 } else {
567 qlt->qlt_mq_enabled = 1;
568 }
569 } else {
570 cmn_err(CE_WARN, "qlt(%d): can't setup MBar for QPs",
571 instance);
572 stmf_trace(qlt->qlt_port_alias,
573 "instance=%d, No QPs MEM Bar", instance);
574
575 if (qlt->msix_acc_handle != NULL) {
576 ddi_regs_map_free(
577 &qlt->msix_acc_handle);
578 }
579 goto attach_fail_5;
580 }
581 } else if (qlt->qlt_81xx_chip) {
582
583 uint32_t w32;
584 int stat;
585
586 w32 = PCICFG_RD32(qlt, PCI_CONF_BASE3);
587 if (w32 == 0) {
588
589 cmn_err(CE_WARN, "qlt(%d): can't setup MBar2",
590 instance);
591 stmf_trace(qlt->qlt_port_alias,
592 "instance=%d, No MEM Bar2", instance);
593 goto attach_fail_5;
594 }
595
596 stat = ddi_regs_map_setup(dip, 3, &qlt->mq_reg_base, 0,
597 (MQ_MAX_QUEUES * MQBAR_REG_OFFSET),
598 &dev_acc_attr, &qlt->mq_reg_acc_handle);
599
600 if (stat != DDI_SUCCESS || qlt->mq_reg_base == NULL ||
601 qlt->mq_reg_acc_handle == NULL) {
602
603 cmn_err(CE_WARN, "qlt(%d): can't map MBar2",
604 instance);
605 stmf_trace(qlt->qlt_port_alias,
606 "instance=%d, MEM Bar2 map fail", instance);
607
608 if (qlt->mq_reg_acc_handle != NULL) {
609 ddi_regs_map_free(&qlt->mq_reg_acc_handle);
610 }
611 goto attach_fail_5;
612 } else {
613 qlt->qlt_mq_enabled = 1;
614 }
615 } else if (qlt->qlt_25xx_chip) {
616 uint32_t w32h;
617 uint32_t w32l;
618 int stat;
619 off_t regsize;
620
621 /* MBAR2 rnumber 3 */
622 w32l = PCICFG_RD32(qlt, PCI_CONF_BASE3);
623 w32h = PCICFG_RD32(qlt, PCI_CONF_BASE4);
624
625 if ((w32h > 0) || (w32l > 0)) {
626 stat = ddi_dev_regsize(dip, 3, ®size);
627 if (stat != DDI_SUCCESS) {
628 stmf_trace(qlt->qlt_port_alias,
629 "ISP25xx inst=%d, MQ regsize failed, stat %x",
630 instance, stat);
631 EL(qlt, "ISP25xx MQ regsize failed, stat %x\n",
632 stat);
633
634 }
635 stmf_trace(qlt->qlt_port_alias,
636 "ISP25xx instance=%d, MQ MEM Bar size %lx",
637 instance, regsize);
638 EL(qlt, "ISP25xx MQ MEM Bar (MBAR2) size: %x\n",
639 regsize);
640
641 stat = ddi_regs_map_setup(dip, 3, &qlt->mq_reg_base, 0,
642 (MQ_MAX_QUEUES * MQBAR_REG_OFFSET),
643 &dev_acc_attr, &qlt->mq_reg_acc_handle);
644 if (stat != DDI_SUCCESS || qlt->mq_reg_base == NULL ||
645 qlt->mq_reg_acc_handle == NULL) {
646 cmn_err(CE_WARN,
647 "qlt(%d): ISP25xx can't map QP MBar",
648 instance);
649 stmf_trace(qlt->qlt_port_alias,
650 "instance=%d, QP MEM Bar map fail st:%x",
651 instance, stat);
652 if (qlt->mq_reg_acc_handle != NULL) {
653 ddi_regs_map_free(
654 &qlt->mq_reg_acc_handle);
655 }
656 } else {
657 qlt->qlt_mq_enabled = 1;
658 }
659 } else {
660 stmf_trace(qlt->qlt_port_alias,
661 "instance=%d, No QPs MEM Bar", instance);
662 EL(qlt,
663 "ISP25xx can't setup MBar QPs, use baseq\n");
664 }
665 }
666
667 if (qlt->qlt_mq_enabled) {
668 qlt->mq_req = kmem_zalloc(
669 ((sizeof (qlt_mq_req_ptr_blk_t)) * MQ_MAX_QUEUES),
670 KM_SLEEP);
671 qlt->mq_resp = kmem_zalloc(
672 ((sizeof (qlt_mq_rsp_ptr_blk_t)) * MQ_MAX_QUEUES),
673 KM_SLEEP);
674 } else {
675 qlt->mq_req = kmem_zalloc(
676 (sizeof (qlt_mq_req_ptr_blk_t)), KM_SLEEP);
677 qlt->mq_resp = kmem_zalloc(
678 (sizeof (qlt_mq_rsp_ptr_blk_t)), KM_SLEEP);
679 }
680
681 if (did == 0x2422) {
682 uint32_t pci_bits = REG_RD32(qlt, REG_CTRL_STATUS);
683 uint32_t slot = pci_bits & PCI_64_BIT_SLOT;
684 pci_bits >>= 8;
685 pci_bits &= 0xf;
686 if ((pci_bits == 3) || (pci_bits == 7)) {
687 cmn_err(CE_NOTE,
688 "!qlt(%d): HBA running at PCI%sMHz (%d)",
689 instance, pci_speeds[pci_bits], pci_bits);
690 } else {
691 cmn_err(CE_WARN,
692 "qlt(%d): HBA running at PCI%sMHz %s(%d)",
693 instance, (pci_bits <= 8) ? pci_speeds[pci_bits] :
694 "(Invalid)", ((pci_bits == 0) ||
695 (pci_bits == 8)) ? (slot ? "64 bit slot " :
696 "32 bit slot ") : "", pci_bits);
697 }
698 }
699 if ((ret = qlt_read_nvram(qlt)) != QLT_SUCCESS) {
700 cmn_err(CE_WARN, "qlt(%d): read nvram failure %llx", instance,
701 (unsigned long long)ret);
702 goto attach_fail_5;
703 }
704 if ((ret = qlt_read_vpd(qlt)) != QLT_SUCCESS) {
705 cmn_err(CE_WARN, "qlt(%d): read vpd failure %llx", instance,
706 (unsigned long long)ret);
707 goto attach_fail_5;
708 }
709 if ((ret = qlt_read_rom_image(qlt)) != QLT_SUCCESS) {
710 cmn_err(CE_WARN, "qlt(%d): read rom image failure %llx",
711 instance, (unsigned long long)ret);
712 goto attach_fail_5;
713 }
714
715 qlt_properties(qlt);
716
717 if (ddi_dma_alloc_handle(dip, &qlt_queue_dma_attr, DDI_DMA_SLEEP,
718 0, &qlt->queue_mem_dma_handle) != DDI_SUCCESS) {
719 goto attach_fail_5;
720 }
721 if (ddi_dma_mem_alloc(qlt->queue_mem_dma_handle, TOTAL_DMA_MEM_SIZE,
722 &dev_acc_attr, DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, 0,
723 &qlt->queue_mem_ptr, &discard, &qlt->queue_mem_acc_handle) !=
724 DDI_SUCCESS) {
725 goto attach_fail_6;
726 }
727 if (ddi_dma_addr_bind_handle(qlt->queue_mem_dma_handle, NULL,
728 qlt->queue_mem_ptr, TOTAL_DMA_MEM_SIZE,
729 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, 0,
730 &qlt->queue_mem_cookie, &ncookies) != DDI_SUCCESS) {
731 goto attach_fail_7;
732 }
733 if (ncookies != 1)
734 goto attach_fail_8;
735
736 /*
737 * Base queue (0), alwasy available
738 */
739 qlt->mq_req[0].queue_mem_mq_base_addr =
740 qlt->mq_req[0].mq_ptr =
741 qlt->queue_mem_ptr + REQUEST_QUEUE_OFFSET;
742 qlt->mq_resp[0].queue_mem_mq_base_addr =
743 qlt->mq_resp[0].mq_ptr =
744 qlt->queue_mem_ptr + RESPONSE_QUEUE_OFFSET;
745
746 qlt->preq_ptr = qlt->queue_mem_ptr + PRIORITY_QUEUE_OFFSET;
747 qlt->atio_ptr = qlt->queue_mem_ptr + ATIO_QUEUE_OFFSET;
748
749 /* mutex are inited in this function */
750 if (qlt_setup_interrupts(qlt) != DDI_SUCCESS)
751 goto attach_fail_8;
752
753 qlt->qlt_queue_cnt = 1;
754 if ((qlt->qlt_mq_enabled) && (qlt->intr_cnt > 1)) {
755 int i;
756
757 for (i = 1; i < qlt->intr_cnt; i++) {
758 if (qlt_mq_create(qlt, i) != QLT_SUCCESS) {
759 cmn_err(CE_WARN, "qlt(%d) mq create (%d) "
760 "failed\n", qlt->instance, i);
761 break;
762 }
763 qlt->qlt_queue_cnt++;
764 if (qlt->qlt_queue_cnt >= MQ_MAX_QUEUES)
765 break;
766 }
767 }
768 EL(qlt, "Queue count = %d\n", qlt->qlt_queue_cnt);
769
770 (void) snprintf(qlt->qlt_minor_name, sizeof (qlt->qlt_minor_name),
771 "qlt%d", instance);
772 (void) snprintf(qlt->qlt_port_alias, sizeof (qlt->qlt_port_alias),
773 "%s,0", qlt->qlt_minor_name);
774
775 if (ddi_create_minor_node(dip, qlt->qlt_minor_name, S_IFCHR,
776 instance, DDI_NT_STMF_PP, 0) != DDI_SUCCESS) {
777 goto attach_fail_9;
778 }
779
780 cv_init(&qlt->rp_dereg_cv, NULL, CV_DRIVER, NULL);
781 cv_init(&qlt->mbox_cv, NULL, CV_DRIVER, NULL);
782 mutex_init(&qlt->qlt_ioctl_lock, NULL, MUTEX_DRIVER, NULL);
783
784 /* Setup PCI cfg space registers */
785 max_read_size = qlt_read_int_prop(qlt, "pci-max-read-request", 11);
786 if (max_read_size == 11)
787 goto over_max_read_xfer_setting;
788 if (did == 0x2422) {
789 if (max_read_size == 512)
790 val = 0;
791 else if (max_read_size == 1024)
792 val = 1;
793 else if (max_read_size == 2048)
794 val = 2;
795 else if (max_read_size == 4096)
796 val = 3;
797 else {
798 cmn_err(CE_WARN, "qlt(%d) malformed "
799 "pci-max-read-request in qlt.conf. Valid values "
800 "for this HBA are 512/1024/2048/4096", instance);
801 goto over_max_read_xfer_setting;
802 }
803 mr = (uint16_t)PCICFG_RD16(qlt, 0x4E);
804 mr = (uint16_t)(mr & 0xfff3);
805 mr = (uint16_t)(mr | (val << 2));
806 PCICFG_WR16(qlt, 0x4E, mr);
807 } else if ((did == 0x2432) || (did == 0x8432) ||
808 (did == 0x2532) || (did == 0x8001) ||
809 (did == 0x2031) || (did == 0x2071) ||
810 (did == 0x2261)) {
811 if (max_read_size == 128)
812 val = 0;
813 else if (max_read_size == 256)
814 val = 1;
815 else if (max_read_size == 512)
816 val = 2;
817 else if (max_read_size == 1024)
818 val = 3;
819 else if (max_read_size == 2048)
820 val = 4;
821 else if (max_read_size == 4096)
822 val = 5;
823 else {
824 cmn_err(CE_WARN, "qlt(%d) malformed "
825 "pci-max-read-request in qlt.conf. Valid values "
826 "for this HBA are 128/256/512/1024/2048/4096",
827 instance);
828 goto over_max_read_xfer_setting;
829 }
830 mr = (uint16_t)PCICFG_RD16(qlt, 0x54);
831 mr = (uint16_t)(mr & 0x8fff);
832 mr = (uint16_t)(mr | (val << 12));
833 PCICFG_WR16(qlt, 0x54, mr);
834 } else {
835 cmn_err(CE_WARN, "qlt(%d): dont know how to set "
836 "pci-max-read-request for this device (%x)",
837 instance, did);
838 }
839 over_max_read_xfer_setting:;
840
841 max_payload_size = qlt_read_int_prop(qlt, "pcie-max-payload-size", 11);
842 if (max_payload_size == 11)
843 goto over_max_payload_setting;
844 if ((did == 0x2432) || (did == 0x8432) ||
845 (did == 0x2532) || (did == 0x8001) ||
846 (did == 0x2031) || (did == 0x2071) ||
847 (did == 0x2261)) {
848 if (max_payload_size == 128)
849 val = 0;
850 else if (max_payload_size == 256)
851 val = 1;
852 else if (max_payload_size == 512)
853 val = 2;
854 else if (max_payload_size == 1024)
855 val = 3;
856 else {
857 cmn_err(CE_WARN, "qlt(%d) malformed "
858 "pcie-max-payload-size in qlt.conf. Valid values "
859 "for this HBA are 128/256/512/1024",
860 instance);
861 goto over_max_payload_setting;
862 }
863 mr = (uint16_t)PCICFG_RD16(qlt, 0x54);
864 mr = (uint16_t)(mr & 0xff1f);
865 mr = (uint16_t)(mr | (val << 5));
866 PCICFG_WR16(qlt, 0x54, mr);
867 } else {
868 cmn_err(CE_WARN, "qlt(%d): dont know how to set "
869 "pcie-max-payload-size for this device (%x)",
870 instance, did);
871 }
872
873 over_max_payload_setting:;
874
875 qlt_enable_intr(qlt);
876
877 if (qlt_port_start((caddr_t)qlt) != QLT_SUCCESS) {
878 EL(qlt, "qlt_port_start failed, tear down\n");
879 qlt_disable_intr(qlt);
880 goto attach_fail_10;
881 }
882
883 ddi_report_dev(dip);
884 return (DDI_SUCCESS);
885
886 attach_fail_10:;
887 mutex_destroy(&qlt->qlt_ioctl_lock);
888 cv_destroy(&qlt->mbox_cv);
889 cv_destroy(&qlt->rp_dereg_cv);
890 ddi_remove_minor_node(dip, qlt->qlt_minor_name);
891 attach_fail_9:;
892 qlt_destroy_mutex(qlt);
893 qlt_release_intr(qlt);
894 (void) qlt_mq_destroy(qlt);
895
896 attach_fail_8:;
897 (void) ddi_dma_unbind_handle(qlt->queue_mem_dma_handle);
898 attach_fail_7:;
899 ddi_dma_mem_free(&qlt->queue_mem_acc_handle);
900 attach_fail_6:;
901 ddi_dma_free_handle(&qlt->queue_mem_dma_handle);
902 attach_fail_5:;
903 if (qlt->mq_resp) {
904 kmem_free(qlt->mq_resp,
905 (qlt->qlt_mq_enabled ?
906 (sizeof (qlt_mq_rsp_ptr_blk_t) * MQ_MAX_QUEUES) :
907 (sizeof (qlt_mq_rsp_ptr_blk_t))));
908 }
909 qlt->mq_resp = NULL;
910 if (qlt->mq_req) {
911 kmem_free(qlt->mq_req,
912 (qlt->qlt_mq_enabled ?
913 (sizeof (qlt_mq_req_ptr_blk_t) * MQ_MAX_QUEUES) :
914 (sizeof (qlt_mq_req_ptr_blk_t))));
915 }
916 qlt->mq_req = NULL;
917
918 ddi_regs_map_free(&qlt->regs_acc_handle);
919 attach_fail_4:;
920 pci_config_teardown(&qlt->pcicfg_acc_handle);
921 attach_fail_3:;
922 (void) qlt_el_trace_desc_dtor(qlt);
923 attach_fail_2:;
924 kmem_free(qlt->vpd, QL_24XX_VPD_SIZE);
925 kmem_free(qlt->nvram, sizeof (qlt_nvram_t));
926 attach_fail_1:;
927 ddi_soft_state_free(qlt_state, instance);
928 return (DDI_FAILURE);
929 }
930
931 #define FCT_I_EVENT_BRING_PORT_OFFLINE 0x83
932
933 /* ARGSUSED */
934 static int
qlt_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)935 qlt_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
936 {
937 qlt_state_t *qlt;
938
939 int instance;
940
941 instance = ddi_get_instance(dip);
942 if ((qlt = (qlt_state_t *)ddi_get_soft_state(qlt_state, instance)) ==
943 NULL) {
944 return (DDI_FAILURE);
945 }
946
947 if (qlt->fw_code01) {
948 return (DDI_FAILURE);
949 }
950
951 if ((qlt->qlt_state != FCT_STATE_OFFLINE) ||
952 qlt->qlt_state_not_acked) {
953 return (DDI_FAILURE);
954 }
955 if (qlt_port_stop((caddr_t)qlt) != FCT_SUCCESS) {
956 return (DDI_FAILURE);
957 }
958
959 qlt_disable_intr(qlt);
960
961 if (qlt->dmp_template_addr != NULL) {
962 (void) ddi_dma_unbind_handle(qlt->dmp_template_dma_handle);
963 ddi_dma_mem_free(&qlt->dmp_template_acc_handle);
964 ddi_dma_free_handle(&qlt->dmp_template_dma_handle);
965 }
966
967 if (qlt->fw_bin_dump_buf != NULL) {
968 kmem_free(qlt->fw_bin_dump_buf, qlt->fw_bin_dump_size);
969 qlt->fw_bin_dump_buf = NULL;
970 qlt->fw_bin_dump_size = 0;
971 qlt->fw_ascii_dump_size = 0;
972 }
973
974 if (qlt->qlt_fwdump_buf) {
975 kmem_free(qlt->qlt_fwdump_buf, qlt->fw_dump_size);
976 qlt->qlt_fwdump_buf = NULL;
977 }
978
979 ddi_remove_minor_node(dip, qlt->qlt_minor_name);
980 qlt_destroy_mutex(qlt);
981 qlt_release_intr(qlt);
982 if (qlt->qlt_mq_enabled == 1) {
983 (void) qlt_mq_destroy(qlt);
984 }
985
986 (void) ddi_dma_unbind_handle(qlt->queue_mem_dma_handle);
987 ddi_dma_mem_free(&qlt->queue_mem_acc_handle);
988 ddi_dma_free_handle(&qlt->queue_mem_dma_handle);
989 ddi_regs_map_free(&qlt->regs_acc_handle);
990
991 if (qlt->mq_resp) {
992 kmem_free(qlt->mq_resp,
993 (qlt->qlt_mq_enabled ?
994 (sizeof (qlt_mq_rsp_ptr_blk_t) * MQ_MAX_QUEUES) :
995 (sizeof (qlt_mq_rsp_ptr_blk_t))));
996 }
997 qlt->mq_resp = NULL;
998 if (qlt->mq_req) {
999 kmem_free(qlt->mq_req,
1000 (qlt->qlt_mq_enabled ?
1001 (sizeof (qlt_mq_req_ptr_blk_t) * MQ_MAX_QUEUES) :
1002 (sizeof (qlt_mq_req_ptr_blk_t))));
1003 }
1004 qlt->mq_req = NULL;
1005
1006 if (qlt->qlt_mq_enabled == 1) {
1007 if ((qlt->msix_acc_handle != NULL) &&
1008 ((qlt->qlt_83xx_chip == 1) ||
1009 (qlt->qlt_27xx_chip == 1))) {
1010 ddi_regs_map_free(&qlt->msix_acc_handle);
1011 }
1012 ddi_regs_map_free(&qlt->mq_reg_acc_handle);
1013 }
1014 pci_config_teardown(&qlt->pcicfg_acc_handle);
1015 kmem_free(qlt->nvram, sizeof (qlt_nvram_t));
1016 cv_destroy(&qlt->mbox_cv);
1017 cv_destroy(&qlt->rp_dereg_cv);
1018 (void) qlt_el_trace_desc_dtor(qlt);
1019 ddi_soft_state_free(qlt_state, instance);
1020
1021 return (DDI_SUCCESS);
1022 }
1023
1024 /*
1025 * qlt_quiesce quiesce a device attached to the system.
1026 */
1027 static int
qlt_quiesce(dev_info_t * dip)1028 qlt_quiesce(dev_info_t *dip)
1029 {
1030 qlt_state_t *qlt;
1031 uint32_t timer;
1032 uint32_t stat;
1033
1034 qlt = ddi_get_soft_state(qlt_state, ddi_get_instance(dip));
1035 if (qlt == NULL) {
1036 /* Oh well.... */
1037 return (DDI_SUCCESS);
1038 }
1039
1040 REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_HOST_TO_RISC_INTR));
1041 REG_WR16(qlt, REG_MBOX0, MBC_STOP_FIRMWARE);
1042 REG_WR16(qlt, REG_MBOX(1), 0);
1043 REG_WR16(qlt, REG_MBOX(2), 0);
1044 REG_WR16(qlt, REG_MBOX(3), 0);
1045 REG_WR16(qlt, REG_MBOX(4), 0);
1046 REG_WR16(qlt, REG_MBOX(5), 0);
1047 REG_WR16(qlt, REG_MBOX(6), 0);
1048 REG_WR16(qlt, REG_MBOX(7), 0);
1049 REG_WR16(qlt, REG_MBOX(8), 0);
1050 REG_WR32(qlt, REG_HCCR, HCCR_CMD(SET_HOST_TO_RISC_INTR));
1051 for (timer = 0; timer < 30000; timer++) {
1052 stat = REG_RD32(qlt, REG_RISC_STATUS);
1053 if (stat & RISC_HOST_INTR_REQUEST) {
1054 if ((stat & FW_INTR_STATUS_MASK) < 0x12) {
1055 REG_WR32(qlt, REG_HCCR,
1056 HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
1057 break;
1058 }
1059 REG_WR32(qlt, REG_HCCR,
1060 HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
1061 }
1062 drv_usecwait(100);
1063 }
1064
1065
1066 /* need to ensure no one accesses the hw during the reset 100us */
1067 if ((qlt->qlt_83xx_chip) || (qlt->qlt_27xx_chip)) {
1068 REG_WR32(qlt, REG_INTR_CTRL, 0);
1069 mutex_enter(&qlt->mbox_lock);
1070 if (qlt->qlt_mq_enabled == 1) {
1071 int i;
1072 for (i = 1; i < qlt->qlt_queue_cnt; i++) {
1073 mutex_enter(&qlt->mq_req[i].mq_lock);
1074 }
1075 }
1076 mutex_enter(&qlt->mq_req[0].mq_lock);
1077 drv_usecwait(40);
1078 }
1079
1080 /* Reset the chip. */
1081 REG_WR32(qlt, REG_CTRL_STATUS, CHIP_SOFT_RESET | DMA_SHUTDOWN_CTRL |
1082 PCI_X_XFER_CTRL);
1083 drv_usecwait(100);
1084
1085 if ((qlt->qlt_83xx_chip) || (qlt->qlt_27xx_chip)) {
1086 mutex_exit(&qlt->mq_req[0].mq_lock);
1087 if (qlt->qlt_mq_enabled == 1) {
1088 int i;
1089 for (i = 1; i < qlt->qlt_queue_cnt; i++) {
1090 mutex_exit(&qlt->mq_req[i].mq_lock);
1091 }
1092 }
1093 mutex_exit(&qlt->mbox_lock);
1094 }
1095
1096 qlt_disable_intr(qlt);
1097
1098 return (DDI_SUCCESS);
1099 }
1100
1101 static void
qlt_enable_intr(qlt_state_t * qlt)1102 qlt_enable_intr(qlt_state_t *qlt)
1103 {
1104 if (qlt->intr_cap & DDI_INTR_FLAG_BLOCK) {
1105 int stat;
1106
1107 stat = ddi_intr_block_enable(qlt->htable, qlt->intr_cnt);
1108 if (stat != DDI_SUCCESS) {
1109 stmf_trace(qlt->qlt_port_alias,
1110 "qlt_enable_intr: ddi_intr_block_enable failed:%x",
1111 stat);
1112
1113 cmn_err(CE_WARN, "!qlt(%d): qlt_enable_intr: "
1114 "ddi_intr_block_enable failed:%x",
1115 qlt->instance, stat);
1116 }
1117
1118 #ifndef __sparc
1119 else {
1120 /* Please see CR6840537, MSI isn't re-enabled x86 */
1121 off_t offset;
1122 uint8_t val8;
1123 ddi_intr_handle_impl_t *hdlp;
1124
1125 if (qlt->qlt_81xx_chip || qlt->qlt_25xx_chip) {
1126 offset = (off_t)0x8a;
1127 } else {
1128 offset = (off_t)0x66;
1129 }
1130
1131 hdlp = (ddi_intr_handle_impl_t *)qlt->htable[0];
1132 if ((hdlp->ih_state == DDI_IHDL_STATE_ENABLE) &&
1133 (hdlp->ih_type == DDI_INTR_TYPE_MSI)) {
1134
1135 /* get MSI control */
1136 val8 = pci_config_get8(qlt->pcicfg_acc_handle,
1137 offset);
1138
1139 if ((val8 & 1) == 0) {
1140 stmf_trace(qlt->qlt_port_alias,
1141 "qlt(%d): qlt_enable_intr: "
1142 "MSI enable failed (%x)",
1143 qlt->instance, val8);
1144
1145 /* write enable to MSI control */
1146 val8 = (uint8_t)(val8 | 1);
1147 pci_config_put8(qlt->pcicfg_acc_handle,
1148 offset, val8);
1149
1150 /* read back to veriy */
1151 val8 = pci_config_get8
1152 (qlt->pcicfg_acc_handle, offset);
1153
1154 if (val8 & 1) {
1155 stmf_trace(qlt->qlt_port_alias,
1156 "qlt(%d): qlt_enable_intr: "
1157 "MSI enabled kludge!(%x)",
1158 qlt->instance, val8);
1159 }
1160 }
1161 }
1162 }
1163 #endif /* x86 specific hack */
1164 } else {
1165 int i;
1166 int stat = DDI_SUCCESS;
1167
1168 for (i = 0;
1169 ((i < qlt->intr_cnt) && (stat == DDI_SUCCESS)); i++) {
1170 stat = ddi_intr_enable(qlt->htable[i]);
1171 }
1172 if (stat != DDI_SUCCESS) {
1173 stmf_trace(qlt->qlt_port_alias,
1174 "qlt_enable_intr: ddi_intr_enable failed:%x",
1175 stat);
1176
1177 cmn_err(CE_WARN, "!qlt(%d): qlt_enable_intr: "
1178 "ddi_intr_enable failed:%x", qlt->instance, stat);
1179 }
1180 }
1181 }
1182
1183 static void
qlt_disable_intr(qlt_state_t * qlt)1184 qlt_disable_intr(qlt_state_t *qlt)
1185 {
1186 if (qlt->intr_cap & DDI_INTR_FLAG_BLOCK) {
1187 (void) ddi_intr_block_disable(qlt->htable, qlt->intr_cnt);
1188 } else {
1189 int i;
1190 for (i = 0; i < qlt->intr_cnt; i++)
1191 (void) ddi_intr_disable(qlt->htable[i]);
1192 }
1193 qlt->qlt_intr_enabled = 0;
1194 }
1195
1196 static void
qlt_release_intr(qlt_state_t * qlt)1197 qlt_release_intr(qlt_state_t *qlt)
1198 {
1199 if (qlt->htable) {
1200 int i;
1201 for (i = 0; i < qlt->intr_cnt; i++) {
1202 (void) ddi_intr_remove_handler(qlt->htable[i]);
1203 (void) ddi_intr_free(qlt->htable[i]);
1204 }
1205 kmem_free(qlt->htable, (uint_t)qlt->intr_size);
1206 }
1207 qlt->htable = NULL;
1208 qlt->intr_pri = 0;
1209 qlt->intr_cnt = 0;
1210 qlt->intr_size = 0;
1211 qlt->intr_cap = 0;
1212 }
1213
1214 static void
qlt_init_mutex(qlt_state_t * qlt)1215 qlt_init_mutex(qlt_state_t *qlt)
1216 {
1217 if (qlt->qlt_mq_enabled == 1) {
1218 int i;
1219
1220 for (i = 1; i < MQ_MAX_QUEUES; i++) {
1221 mutex_init(&qlt->mq_req[i].mq_lock, 0, MUTEX_DRIVER,
1222 INT2PTR(qlt->intr_pri, void *));
1223 mutex_init(&qlt->mq_resp[i].mq_lock, 0, MUTEX_DRIVER,
1224 INT2PTR(qlt->intr_pri, void *));
1225 }
1226 }
1227 mutex_init(&qlt->mq_req[0].mq_lock, 0, MUTEX_DRIVER,
1228 INT2PTR(qlt->intr_pri, void *));
1229 mutex_init(&qlt->preq_lock, 0, MUTEX_DRIVER,
1230 INT2PTR(qlt->intr_pri, void *));
1231 mutex_init(&qlt->mbox_lock, NULL, MUTEX_DRIVER,
1232 INT2PTR(qlt->intr_pri, void *));
1233 mutex_init(&qlt->intr_lock, NULL, MUTEX_DRIVER,
1234 INT2PTR(qlt->intr_pri, void *));
1235 }
1236
1237 static void
qlt_destroy_mutex(qlt_state_t * qlt)1238 qlt_destroy_mutex(qlt_state_t *qlt)
1239 {
1240 if (qlt->qlt_mq_enabled == 1) {
1241 int i;
1242
1243 for (i = 1; i < MQ_MAX_QUEUES; i++) {
1244 mutex_destroy(&qlt->mq_req[i].mq_lock);
1245 mutex_destroy(&qlt->mq_resp[i].mq_lock);
1246 }
1247 }
1248 mutex_destroy(&qlt->mq_req[0].mq_lock);
1249 mutex_destroy(&qlt->preq_lock);
1250 mutex_destroy(&qlt->mbox_lock);
1251 mutex_destroy(&qlt->intr_lock);
1252 }
1253
1254 static int
qlt_setup_msix(qlt_state_t * qlt)1255 qlt_setup_msix(qlt_state_t *qlt)
1256 {
1257 int count, avail, actual;
1258 int ret;
1259 int itype = DDI_INTR_TYPE_MSIX;
1260 int i;
1261
1262 /* check 24xx revision */
1263 if ((!qlt->qlt_25xx_chip) && (!qlt->qlt_81xx_chip) &&
1264 (!qlt->qlt_83xx_chip) && (!qlt->qlt_27xx_chip)) {
1265 uint8_t rev_id;
1266 rev_id = (uint8_t)
1267 pci_config_get8(qlt->pcicfg_acc_handle, PCI_CONF_REVID);
1268 if (rev_id < 3) {
1269 return (DDI_FAILURE);
1270 }
1271 }
1272
1273 ret = ddi_intr_get_nintrs(qlt->dip, itype, &count);
1274 if (ret != DDI_SUCCESS || count == 0) {
1275 EL(qlt, "ddi_intr_get_nintrs status=%xh, count=%d\n", ret,
1276 count);
1277 return (DDI_FAILURE);
1278 }
1279 ret = ddi_intr_get_navail(qlt->dip, itype, &avail);
1280 if (ret != DDI_SUCCESS || avail == 0) {
1281 EL(qlt, "ddi_intr_get_navail status=%xh, avail=%d\n", ret,
1282 avail);
1283 return (DDI_FAILURE);
1284 }
1285 if (avail < count) {
1286 stmf_trace(qlt->qlt_port_alias,
1287 "qlt_setup_msix: nintrs=%d,avail=%d", count, avail);
1288 }
1289
1290 if ((qlt->qlt_25xx_chip) && (qlt->qlt_mq_enabled == 0)) {
1291 count = 2;
1292 }
1293
1294 qlt->intr_size = (int)(count * (int)sizeof (ddi_intr_handle_t));
1295 qlt->htable = kmem_zalloc((uint_t)qlt->intr_size, KM_SLEEP);
1296 ret = ddi_intr_alloc(qlt->dip, qlt->htable, itype,
1297 DDI_INTR_ALLOC_NORMAL, count, &actual, 0);
1298
1299 EL(qlt, "qlt_setup_msix: count=%d,avail=%d,actual=%d\n", count,
1300 avail, actual);
1301
1302 /* we need at least 2 interrupt vectors */
1303 if (((qlt->qlt_83xx_chip) || (qlt->qlt_27xx_chip)) &&
1304 (ret != DDI_SUCCESS || actual < 2)) {
1305 EL(qlt, "ddi_intr_alloc status=%xh, actual=%d\n", ret,
1306 actual);
1307 ret = DDI_FAILURE;
1308 goto release_intr;
1309 } else if ((qlt->qlt_81xx_chip) && (ret != DDI_SUCCESS || actual < 3)) {
1310 EL(qlt, "ddi_intr_alloc status=%xh, actual=%d\n", ret,
1311 actual);
1312 ret = DDI_FAILURE;
1313 goto release_intr;
1314 } else if (ret != DDI_SUCCESS || actual < 2) {
1315 EL(qlt, "ddi_intr_alloc status=%xh, actual=%d\n", ret,
1316 actual);
1317 ret = DDI_FAILURE;
1318 goto release_intr;
1319 }
1320 if (actual < count) {
1321 EL(qlt, "requested: %d, received: %d\n", count, actual);
1322 }
1323
1324 qlt->intr_cnt = actual;
1325 ret = ddi_intr_get_pri(qlt->htable[0], &qlt->intr_pri);
1326 if (ret != DDI_SUCCESS) {
1327 EL(qlt, "ddi_intr_get_pri status=%xh\n", ret);
1328 ret = DDI_FAILURE;
1329 goto release_intr;
1330 }
1331 qlt_init_mutex(qlt);
1332 for (i = 0; i < qlt->intr_cnt; i++) {
1333 ret = ddi_intr_add_handler(qlt->htable[i],
1334 (i != 0) ? qlt_msix_resp_handler :
1335 qlt_msix_default_handler,
1336 qlt, INT2PTR((uint_t)i, void *));
1337 if (ret != DDI_SUCCESS) {
1338 EL(qlt, "ddi_intr_add_handler status=%xh\n", ret);
1339 goto release_mutex;
1340 }
1341 }
1342
1343 (void) ddi_intr_get_cap(qlt->htable[0], &qlt->intr_cap);
1344 qlt->intr_flags |= QLT_INTR_MSIX;
1345 return (DDI_SUCCESS);
1346
1347 release_mutex:
1348 qlt_destroy_mutex(qlt);
1349 release_intr:
1350 for (i = 0; i < actual; i++)
1351 (void) ddi_intr_free(qlt->htable[i]);
1352
1353 kmem_free(qlt->htable, (uint_t)qlt->intr_size);
1354 qlt->htable = NULL;
1355 qlt_release_intr(qlt);
1356 return (ret);
1357 }
1358
1359 static int
qlt_setup_msi(qlt_state_t * qlt)1360 qlt_setup_msi(qlt_state_t *qlt)
1361 {
1362 int count, avail, actual;
1363 int itype = DDI_INTR_TYPE_MSI;
1364 int ret;
1365 int i;
1366
1367 /* 83xx and 27xx doesn't do MSI - don't even bother? */
1368 if ((qlt->qlt_83xx_chip) || (qlt->qlt_27xx_chip)) {
1369 return (DDI_FAILURE);
1370 }
1371
1372 /* get the # of interrupts */
1373 ret = ddi_intr_get_nintrs(qlt->dip, itype, &count);
1374 if (ret != DDI_SUCCESS || count == 0) {
1375 EL(qlt, "ddi_intr_get_nintrs status=%xh, count=%d\n", ret,
1376 count);
1377 return (DDI_FAILURE);
1378 }
1379 ret = ddi_intr_get_navail(qlt->dip, itype, &avail);
1380 if (ret != DDI_SUCCESS || avail == 0) {
1381 EL(qlt, "ddi_intr_get_navail status=%xh, avail=%d\n", ret,
1382 avail);
1383 return (DDI_FAILURE);
1384 }
1385 if (avail < count) {
1386 EL(qlt, "nintrs=%d, avail=%d\n", count, avail);
1387 }
1388 /* MSI requires only 1 interrupt. */
1389 count = 1;
1390
1391 /* allocate interrupt */
1392 qlt->intr_size = (int)(count * (int)sizeof (ddi_intr_handle_t));
1393 qlt->htable = kmem_zalloc((uint_t)qlt->intr_size, KM_SLEEP);
1394 ret = ddi_intr_alloc(qlt->dip, qlt->htable, itype,
1395 0, count, &actual, DDI_INTR_ALLOC_NORMAL);
1396 if (ret != DDI_SUCCESS || actual == 0) {
1397 EL(qlt, "ddi_intr_alloc status=%xh, actual=%d\n", ret,
1398 actual);
1399 ret = DDI_FAILURE;
1400 goto free_mem;
1401 }
1402 if (actual < count) {
1403 EL(qlt, "requested: %d, received: %d\n", count, actual);
1404 }
1405 qlt->intr_cnt = actual;
1406
1407 /*
1408 * Get priority for first msi, assume remaining are all the same.
1409 */
1410 ret = ddi_intr_get_pri(qlt->htable[0], &qlt->intr_pri);
1411 if (ret != DDI_SUCCESS) {
1412 EL(qlt, "ddi_intr_get_pri status=%xh\n", ret);
1413 ret = DDI_FAILURE;
1414 goto release_intr;
1415 }
1416 qlt_init_mutex(qlt);
1417
1418 /* add handler */
1419 for (i = 0; i < actual; i++) {
1420 ret = ddi_intr_add_handler(qlt->htable[i], qlt_isr,
1421 qlt, INT2PTR((uint_t)i, void *));
1422 if (ret != DDI_SUCCESS) {
1423 EL(qlt, "ddi_intr_add_handler status=%xh\n", ret);
1424 goto release_mutex;
1425 }
1426 }
1427
1428 (void) ddi_intr_get_cap(qlt->htable[0], &qlt->intr_cap);
1429 qlt->intr_flags |= QLT_INTR_MSI;
1430 return (DDI_SUCCESS);
1431
1432 release_mutex:
1433 qlt_destroy_mutex(qlt);
1434 release_intr:
1435 for (i = 0; i < actual; i++)
1436 (void) ddi_intr_free(qlt->htable[i]);
1437 free_mem:
1438 kmem_free(qlt->htable, (uint_t)qlt->intr_size);
1439 qlt->htable = NULL;
1440 qlt_release_intr(qlt);
1441 return (ret);
1442 }
1443
1444 static int
qlt_setup_fixed(qlt_state_t * qlt)1445 qlt_setup_fixed(qlt_state_t *qlt)
1446 {
1447 int count;
1448 int actual;
1449 int ret;
1450 int itype = DDI_INTR_TYPE_FIXED;
1451
1452 ret = ddi_intr_get_nintrs(qlt->dip, itype, &count);
1453 /* Fixed interrupts can only have one interrupt. */
1454 if (ret != DDI_SUCCESS || count != 1) {
1455 EL(qlt, "ddi_intr_get_nintrs status=%xh, count=%d\n", ret,
1456 count);
1457 return (DDI_FAILURE);
1458 }
1459
1460 qlt->intr_size = sizeof (ddi_intr_handle_t);
1461 qlt->htable = kmem_zalloc((uint_t)qlt->intr_size, KM_SLEEP);
1462 ret = ddi_intr_alloc(qlt->dip, qlt->htable, itype,
1463 DDI_INTR_ALLOC_NORMAL, count, &actual, 0);
1464 if (ret != DDI_SUCCESS || actual != 1) {
1465 EL(qlt, "ddi_intr_alloc status=%xh, actual=%d\n", ret,
1466 actual);
1467 ret = DDI_FAILURE;
1468 goto free_mem;
1469 }
1470
1471 qlt->intr_cnt = actual;
1472 ret = ddi_intr_get_pri(qlt->htable[0], &qlt->intr_pri);
1473 if (ret != DDI_SUCCESS) {
1474 EL(qlt, "ddi_intr_get_pri status=%xh\n", ret);
1475 ret = DDI_FAILURE;
1476 goto release_intr;
1477 }
1478 qlt_init_mutex(qlt);
1479 ret = ddi_intr_add_handler(qlt->htable[0], qlt_isr, qlt, 0);
1480 if (ret != DDI_SUCCESS) {
1481 EL(qlt, "ddi_intr_add_handler status=%xh\n", ret);
1482 goto release_mutex;
1483 }
1484
1485 qlt->intr_flags |= QLT_INTR_FIXED;
1486 return (DDI_SUCCESS);
1487
1488 release_mutex:
1489 qlt_destroy_mutex(qlt);
1490 release_intr:
1491 (void) ddi_intr_free(qlt->htable[0]);
1492 free_mem:
1493 kmem_free(qlt->htable, (uint_t)qlt->intr_size);
1494 qlt->htable = NULL;
1495 qlt_release_intr(qlt);
1496 return (ret);
1497 }
1498
1499 static int
qlt_setup_interrupts(qlt_state_t * qlt)1500 qlt_setup_interrupts(qlt_state_t *qlt)
1501 {
1502 int itypes = 0;
1503
1504 /*
1505 * x86 has a bug in the ddi_intr_block_enable/disable area (6562198).
1506 */
1507 #ifndef __sparc
1508 if ((qlt_enable_msi != 0) || (qlt_enable_msix != 0)) {
1509 #endif
1510 if (ddi_intr_get_supported_types(qlt->dip, &itypes) != DDI_SUCCESS) {
1511 itypes = DDI_INTR_TYPE_FIXED;
1512 }
1513 if (qlt_enable_msix && (itypes & DDI_INTR_TYPE_MSIX)) {
1514 if (qlt_setup_msix(qlt) == DDI_SUCCESS)
1515 return (DDI_SUCCESS);
1516 }
1517 if (qlt_enable_msi && (itypes & DDI_INTR_TYPE_MSI)) {
1518 if (qlt_setup_msi(qlt) == DDI_SUCCESS)
1519 return (DDI_SUCCESS);
1520 }
1521 #ifndef __sparc
1522 }
1523 #endif
1524 return (qlt_setup_fixed(qlt));
1525 }
1526
1527 static uint8_t *
qlt_vpd_findtag(qlt_state_t * qlt,uint8_t * vpdbuf,int8_t * opcode)1528 qlt_vpd_findtag(qlt_state_t *qlt, uint8_t *vpdbuf, int8_t *opcode)
1529 {
1530 uint8_t *vpd = vpdbuf;
1531 uint8_t *end = vpdbuf + QL_24XX_VPD_SIZE;
1532 uint32_t found = 0;
1533
1534 if (vpdbuf == NULL || opcode == NULL) {
1535 EL(qlt, "null parameter passed!\n");
1536 return (NULL);
1537 }
1538
1539 while (vpd < end) {
1540 if (vpd[0] == VPD_TAG_END) {
1541 if (opcode[0] == VPD_TAG_END) {
1542 found = 1;
1543 } else {
1544 found = 0;
1545 }
1546 break;
1547 }
1548
1549 if (bcmp(opcode, vpd, strlen(opcode)) == 0) {
1550 found = 1;
1551 break;
1552 }
1553
1554 if (!(strncmp((char *)vpd, (char *)VPD_TAG_PRODID, 1))) {
1555 vpd += (vpd[2] << 8) + vpd[1] + 3;
1556 } else if (*vpd == VPD_TAG_LRT || *vpd == VPD_TAG_LRTC) {
1557 vpd += 3;
1558 } else {
1559 vpd += vpd[2] +3;
1560 }
1561 }
1562 return (found == 1 ? vpd : NULL);
1563 }
1564
1565 /*
1566 * qlt_vpd_lookup
1567 * Return the VPD data for the request VPD tag
1568 *
1569 * Input:
1570 * qlt = adapter state pointer.
1571 * opcode = VPD opcode to find (must be NULL terminated).
1572 * bp = Pointer to returned data buffer.
1573 * bplen = Length of returned data buffer.
1574 *
1575 * Returns:
1576 * Length of data copied into returned data buffer.
1577 * >0 = VPD data field (NULL terminated)
1578 * 0 = no data.
1579 * -1 = Could not find opcode in vpd buffer / error.
1580 *
1581 * Context:
1582 * Kernel context.
1583 *
1584 * NB: The opcode buffer and the bp buffer *could* be the same buffer!
1585 *
1586 */
1587 static int
qlt_vpd_lookup(qlt_state_t * qlt,uint8_t * opcode,uint8_t * bp,int32_t bplen)1588 qlt_vpd_lookup(qlt_state_t *qlt, uint8_t *opcode, uint8_t *bp,
1589 int32_t bplen)
1590 {
1591 uint8_t *vpd = NULL;
1592 uint8_t *vpdbuf = NULL;
1593 int32_t len = -1;
1594
1595 if (opcode == NULL || bp == NULL || bplen < 1) {
1596 EL(qlt, "invalid parameter passed: opcode=%ph, "
1597 "bp=%ph, bplen=%xh\n", opcode, bp, bplen);
1598 return (len);
1599 }
1600
1601 vpdbuf = (uint8_t *)qlt->vpd;
1602 if ((vpd = qlt_vpd_findtag(qlt, vpdbuf, (int8_t *)opcode)) != NULL) {
1603 /*
1604 * Found the tag
1605 */
1606 if (*opcode == VPD_TAG_END || *opcode == VPD_TAG_LRT ||
1607 *opcode == VPD_TAG_LRTC) {
1608 /*
1609 * We found it, but the tag doesn't have a data
1610 * field.
1611 */
1612 len = 0;
1613 } else if (!(strncmp((char *)vpd, (char *)
1614 VPD_TAG_PRODID, 1))) {
1615 len = vpd[2] << 8;
1616 len += vpd[1];
1617 } else {
1618 len = vpd[2];
1619 }
1620
1621 /*
1622 * Make sure that the vpd len does not exceed the
1623 * vpd end
1624 */
1625 if (vpd+len > vpdbuf + QL_24XX_VPD_SIZE) {
1626 EL(qlt, "vpd tag len (%xh) exceeds vpd buffer "
1627 "length\n", len);
1628 len = -1;
1629 }
1630 } else {
1631 EL(qlt, "Cna't find vpd tag \n");
1632 return (-1);
1633 }
1634
1635 if (len >= 0) {
1636 /*
1637 * make sure we don't exceed callers buffer space len
1638 */
1639 if (len > bplen) {
1640 len = bplen - 1;
1641 }
1642 /* copy the data back */
1643 (void) strncpy((int8_t *)bp, (int8_t *)(vpd+3), (int64_t)len);
1644 bp[len] = '\0';
1645 } else {
1646 /* error -- couldn't find tag */
1647 bp[0] = '\0';
1648 if (opcode[1] != '\0') {
1649 EL(qlt, "unable to find tag '%s'\n", opcode);
1650 } else {
1651 EL(qlt, "unable to find tag '%xh'\n", opcode[0]);
1652 }
1653 }
1654 return (len);
1655 }
1656
1657 void
qlt_get_rom_version(qlt_state_t * qlt,caddr_t orv)1658 qlt_get_rom_version(qlt_state_t *qlt, caddr_t orv)
1659 {
1660 int i;
1661 char bios0_str[32];
1662 char fcode_str[32];
1663 char efi_str[32];
1664 char hppa_str[32];
1665 char tmp[80];
1666 uint32_t bios_cnt = 0;
1667 uint32_t fcode_cnt = 0;
1668 boolean_t last_image = FALSE;
1669
1670 /* collect right rom_version from image[] */
1671 i = 0;
1672 do {
1673 if (qlt->rimage[0].header.signature[0] != PCI_HEADER0) {
1674 break;
1675 }
1676
1677 if (qlt->rimage[i].data.codetype == PCI_CODE_X86PC) {
1678 /* BIOS */
1679 if (bios_cnt == 0) {
1680 (void) snprintf(bios0_str,
1681 32,
1682 "%d.%02d",
1683 qlt->rimage[i].data.
1684 revisionlevel[1],
1685 qlt->rimage[i].data.
1686 revisionlevel[0]);
1687 (void) snprintf(tmp, 80,
1688 " BIOS: %s;", bios0_str);
1689 (void) strcat(orv, tmp);
1690 }
1691 bios_cnt++;
1692 } else if (qlt->rimage[i].data.codetype == PCI_CODE_FCODE) {
1693 /* FCode */
1694 if (fcode_cnt == 0) {
1695 (void) snprintf(fcode_str,
1696 32,
1697 "%d.%02d",
1698 qlt->rimage[i].data.revisionlevel[1],
1699 qlt->rimage[i].data.revisionlevel[0]);
1700 (void) snprintf(tmp, 80,
1701 " FCode: %s;", fcode_str);
1702 (void) strcat(orv, tmp);
1703 }
1704 fcode_cnt++;
1705 } else if (qlt->rimage[i].data.codetype == PCI_CODE_EFI) {
1706 /* EFI */
1707 (void) snprintf(efi_str,
1708 32,
1709 "%d.%02d",
1710 qlt->rimage[i].data.revisionlevel[1],
1711 qlt->rimage[i].data.revisionlevel[0]);
1712 (void) snprintf(tmp, 80, " EFI: %s;", efi_str);
1713 (void) strcat(orv, tmp);
1714 } else if (qlt->rimage[i].data.codetype == PCI_CODE_HPPA) {
1715 /* HPPA */
1716 (void) snprintf(hppa_str,
1717 32,
1718 "%d.%02d",
1719 qlt->rimage[i].data.revisionlevel[1],
1720 qlt->rimage[i].data.revisionlevel[0]);
1721 (void) snprintf(orv, 80, " HPPA: %s;", hppa_str);
1722 (void) strcat(orv, tmp);
1723 } else if (qlt->rimage[i].data.codetype == PCI_CODE_FW) {
1724 EL(qlt, "fw infor skip\n");
1725 } else {
1726 /* Unknown */
1727 EL(qlt, "unknown image\n");
1728 break;
1729 }
1730
1731 if (qlt->rimage[i].data.indicator == PCI_IND_LAST_IMAGE) {
1732 last_image = TRUE;
1733 break;
1734 }
1735
1736 i ++;
1737 } while ((last_image != TRUE) && (i < 6));
1738
1739 if (last_image != TRUE) {
1740 /* No boot image detected */
1741 (void) snprintf(orv, FCHBA_OPTION_ROM_VERSION_LEN, "%s",
1742 "No boot image detected");
1743 }
1744 }
1745
1746 /*
1747 * Filling the hba attributes
1748 */
1749 void
qlt_populate_hba_fru_details(struct fct_local_port * port,struct fct_port_attrs * port_attrs)1750 qlt_populate_hba_fru_details(struct fct_local_port *port,
1751 struct fct_port_attrs *port_attrs)
1752 {
1753 int len;
1754 qlt_state_t *qlt = (qlt_state_t *)port->port_fca_private;
1755
1756 (void) snprintf(port_attrs->manufacturer, FCHBA_MANUFACTURER_LEN,
1757 "QLogic Corp.");
1758 (void) snprintf(port_attrs->driver_name, FCHBA_DRIVER_NAME_LEN,
1759 "%s", QLT_NAME);
1760 (void) snprintf(port_attrs->driver_version, FCHBA_DRIVER_VERSION_LEN,
1761 "%s", QLT_VERSION);
1762 /* get serial_number from vpd data */
1763 if (qlt_vpd_lookup(qlt, (uint8_t *)VPD_TAG_SN, (uint8_t *)
1764 port_attrs->serial_number, FCHBA_SERIAL_NUMBER_LEN) == -1) {
1765 port_attrs->serial_number[0] = '\0';
1766 }
1767 port_attrs->hardware_version[0] = '\0';
1768
1769 (void) snprintf(port_attrs->firmware_version,
1770 FCHBA_FIRMWARE_VERSION_LEN, "%d.%d.%d", qlt->fw_major,
1771 qlt->fw_minor, qlt->fw_subminor);
1772
1773 /* Get FCode version */
1774 qlt_get_rom_version(qlt, (caddr_t)&port_attrs->option_rom_version[0]);
1775
1776 port_attrs->vendor_specific_id = qlt->nvram->subsystem_vendor_id[0] |
1777 qlt->nvram->subsystem_vendor_id[1] << 8;
1778
1779 port_attrs->max_frame_size = qlt->nvram->max_frame_length[1] << 8 |
1780 qlt->nvram->max_frame_length[0];
1781
1782 port_attrs->supported_cos = 0x10000000;
1783
1784 if (qlt->qlt_fcoe_enabled) {
1785 port_attrs->supported_speed = PORT_SPEED_10G;
1786 } else if (qlt->qlt_27xx_chip) {
1787 if ((qlt->qlt_27xx_speed & MAX_SPEED_MASK) == MAX_SPEED_32G) {
1788 port_attrs->supported_speed = PORT_SPEED_8G |
1789 PORT_SPEED_16G | PORT_SPEED_32G;
1790 } else {
1791 port_attrs->supported_speed = PORT_SPEED_4G |
1792 PORT_SPEED_8G | PORT_SPEED_16G;
1793 }
1794 } else if ((qlt->qlt_83xx_chip) || (qlt->qlt_27xx_chip)) {
1795 port_attrs->supported_speed = PORT_SPEED_4G |
1796 PORT_SPEED_8G | PORT_SPEED_16G;
1797 } else if (qlt->qlt_25xx_chip) {
1798 port_attrs->supported_speed = PORT_SPEED_2G | PORT_SPEED_4G |
1799 PORT_SPEED_8G;
1800 } else {
1801 port_attrs->supported_speed = PORT_SPEED_1G |
1802 PORT_SPEED_2G | PORT_SPEED_4G;
1803 }
1804
1805 /* limit string length to nvr model_name length */
1806 len = ((qlt->qlt_81xx_chip) || (qlt->qlt_83xx_chip) ||
1807 (qlt->qlt_27xx_chip)) ? 16 : 8;
1808 (void) snprintf(port_attrs->model,
1809 (uint_t)(len < FCHBA_MODEL_LEN ? len : FCHBA_MODEL_LEN),
1810 "%s", qlt->nvram->model_name);
1811
1812 (void) snprintf(port_attrs->model_description,
1813 (uint_t)(len < FCHBA_MODEL_DESCRIPTION_LEN ? len :
1814 FCHBA_MODEL_DESCRIPTION_LEN),
1815 "%s", qlt->nvram->model_name);
1816 }
1817
1818 /* ARGSUSED */
1819 fct_status_t
qlt_info(uint32_t cmd,fct_local_port_t * port,void * arg,uint8_t * buf,uint32_t * bufsizep)1820 qlt_info(uint32_t cmd, fct_local_port_t *port,
1821 void *arg, uint8_t *buf, uint32_t *bufsizep)
1822 {
1823 qlt_state_t *qlt = (qlt_state_t *)port->port_fca_private;
1824 mbox_cmd_t *mcp;
1825 fct_status_t ret = FCT_SUCCESS;
1826 uint8_t *p;
1827 fct_port_link_status_t *link_status;
1828
1829 switch (cmd) {
1830 case FC_TGT_PORT_RLS:
1831 if (qlt->qlt_state != FCT_STATE_ONLINE) {
1832 break;
1833 }
1834 if ((*bufsizep) < sizeof (fct_port_link_status_t)) {
1835 EL(qlt, "FC_TGT_PORT_RLS bufsizep=%xh < "
1836 "fct_port_link_status_t=%xh\n", *bufsizep,
1837 sizeof (fct_port_link_status_t));
1838 ret = FCT_FAILURE;
1839 break;
1840 }
1841 /* send mailbox command to get link status */
1842 mcp = qlt_alloc_mailbox_command(qlt, 156);
1843 if (mcp == NULL) {
1844 EL(qlt, "qlt_alloc_mailbox_command mcp=null\n");
1845 ret = FCT_ALLOC_FAILURE;
1846 break;
1847 }
1848
1849 /* GET LINK STATUS count */
1850 mcp->to_fw[0] = MBC_GET_STATUS_COUNTS;
1851 mcp->to_fw[8] = 156/4;
1852 mcp->to_fw_mask |= BIT_1 | BIT_8;
1853 mcp->from_fw_mask |= BIT_1 | BIT_2;
1854
1855 ret = qlt_mailbox_command(qlt, mcp);
1856 if (ret != QLT_SUCCESS) {
1857 EL(qlt, "qlt_mbox_command=6dh status=%llxh\n", ret);
1858 qlt_free_mailbox_command(qlt, mcp);
1859 break;
1860 }
1861 qlt_dmem_dma_sync(mcp->dbuf, DDI_DMA_SYNC_FORCPU);
1862
1863 p = mcp->dbuf->db_sglist[0].seg_addr;
1864 link_status = (fct_port_link_status_t *)buf;
1865 link_status->LinkFailureCount = LE_32(*((uint32_t *)p));
1866 link_status->LossOfSyncCount = LE_32(*((uint32_t *)(p + 4)));
1867 link_status->LossOfSignalsCount = LE_32(*((uint32_t *)(p + 8)));
1868 link_status->PrimitiveSeqProtocolErrorCount =
1869 LE_32(*((uint32_t *)(p + 12)));
1870 link_status->InvalidTransmissionWordCount =
1871 LE_32(*((uint32_t *)(p + 16)));
1872 link_status->InvalidCRCCount =
1873 LE_32(*((uint32_t *)(p + 20)));
1874
1875 qlt_free_mailbox_command(qlt, mcp);
1876 break;
1877 default:
1878 EL(qlt, "Unknown cmd=%xh\n", cmd);
1879 ret = FCT_FAILURE;
1880 break;
1881 }
1882 return (ret);
1883 }
1884
1885 fct_status_t
qlt_port_start(caddr_t arg)1886 qlt_port_start(caddr_t arg)
1887 {
1888 qlt_state_t *qlt = (qlt_state_t *)arg;
1889 fct_local_port_t *port;
1890 fct_dbuf_store_t *fds;
1891 fct_status_t ret;
1892
1893 if (qlt_dmem_init(qlt) != QLT_SUCCESS) {
1894 return (FCT_FAILURE);
1895 }
1896
1897 /* Initialize the ddi_dma_handle free pool */
1898 qlt_dma_handle_pool_init(qlt);
1899
1900 port = (fct_local_port_t *)fct_alloc(FCT_STRUCT_LOCAL_PORT, 0, 0);
1901 if (port == NULL) {
1902 goto qlt_pstart_fail_1;
1903 }
1904 fds = (fct_dbuf_store_t *)fct_alloc(FCT_STRUCT_DBUF_STORE, 0, 0);
1905 if (fds == NULL) {
1906 goto qlt_pstart_fail_2;
1907 }
1908 qlt->qlt_port = port;
1909 fds->fds_alloc_data_buf = qlt_dmem_alloc;
1910 fds->fds_free_data_buf = qlt_dmem_free;
1911 fds->fds_setup_dbuf = qlt_dma_setup_dbuf;
1912 fds->fds_teardown_dbuf = qlt_dma_teardown_dbuf;
1913 fds->fds_max_sgl_xfer_len = QLT_DMA_SG_LIST_LENGTH * MMU_PAGESIZE;
1914 fds->fds_copy_threshold = (uint32_t)MMU_PAGESIZE;
1915 fds->fds_fca_private = (void *)qlt;
1916 /*
1917 * Since we keep everything in the state struct and dont allocate any
1918 * port private area, just use that pointer to point to the
1919 * state struct.
1920 */
1921 port->port_fca_private = qlt;
1922 port->port_fca_abort_timeout = 5 * 1000; /* 5 seconds */
1923 bcopy(qlt->nvram->node_name, port->port_nwwn, 8);
1924 bcopy(qlt->nvram->port_name, port->port_pwwn, 8);
1925 fct_wwn_to_str(port->port_nwwn_str, port->port_nwwn);
1926 fct_wwn_to_str(port->port_pwwn_str, port->port_pwwn);
1927 port->port_default_alias = qlt->qlt_port_alias;
1928 port->port_pp = qlt_pp;
1929 port->port_fds = fds;
1930 port->port_max_logins = QLT_MAX_LOGINS;
1931 port->port_max_xchges = QLT_MAX_XCHGES;
1932 port->port_fca_fcp_cmd_size = sizeof (qlt_cmd_t);
1933 port->port_fca_rp_private_size = sizeof (qlt_remote_port_t);
1934 port->port_fca_sol_els_private_size = sizeof (qlt_cmd_t);
1935 port->port_fca_sol_ct_private_size = sizeof (qlt_cmd_t);
1936 port->port_get_link_info = qlt_get_link_info;
1937 port->port_register_remote_port = qlt_register_remote_port;
1938 port->port_deregister_remote_port = qlt_deregister_remote_port;
1939 port->port_send_cmd = qlt_send_cmd;
1940 port->port_xfer_scsi_data = qlt_xfer_scsi_data;
1941 port->port_send_cmd_response = qlt_send_cmd_response;
1942 port->port_abort_cmd = qlt_abort_cmd;
1943 port->port_ctl = qlt_ctl;
1944 port->port_flogi_xchg = qlt_do_flogi;
1945 port->port_populate_hba_details = qlt_populate_hba_fru_details;
1946 port->port_info = qlt_info;
1947 port->port_fca_version = FCT_FCA_MODREV_1;
1948
1949 if ((ret = fct_register_local_port(port)) != FCT_SUCCESS) {
1950 EL(qlt, "fct_register_local_port status=%llxh\n", ret);
1951 goto qlt_pstart_fail_2_5;
1952 }
1953
1954 EL(qlt, "Qlogic qlt(%d) "
1955 "WWPN=%02x%02x%02x%02x%02x%02x%02x%02x:"
1956 "WWNN=%02x%02x%02x%02x%02x%02x%02x%02x\n",
1957 qlt->instance,
1958 qlt->nvram->port_name[0],
1959 qlt->nvram->port_name[1],
1960 qlt->nvram->port_name[2],
1961 qlt->nvram->port_name[3],
1962 qlt->nvram->port_name[4],
1963 qlt->nvram->port_name[5],
1964 qlt->nvram->port_name[6],
1965 qlt->nvram->port_name[7],
1966 qlt->nvram->node_name[0],
1967 qlt->nvram->node_name[1],
1968 qlt->nvram->node_name[2],
1969 qlt->nvram->node_name[3],
1970 qlt->nvram->node_name[4],
1971 qlt->nvram->node_name[5],
1972 qlt->nvram->node_name[6],
1973 qlt->nvram->node_name[7]);
1974
1975 return (QLT_SUCCESS);
1976 #if 0
1977 qlt_pstart_fail_3:
1978 (void) fct_deregister_local_port(port);
1979 #endif
1980 qlt_pstart_fail_2_5:
1981 fct_free(fds);
1982 qlt_pstart_fail_2:
1983 fct_free(port);
1984 qlt->qlt_port = NULL;
1985 qlt_pstart_fail_1:
1986 qlt_dma_handle_pool_fini(qlt);
1987 qlt_dmem_fini(qlt);
1988 return (QLT_FAILURE);
1989 }
1990
1991 fct_status_t
qlt_port_stop(caddr_t arg)1992 qlt_port_stop(caddr_t arg)
1993 {
1994 qlt_state_t *qlt = (qlt_state_t *)arg;
1995 fct_status_t ret;
1996
1997 if ((ret = fct_deregister_local_port(qlt->qlt_port)) != FCT_SUCCESS) {
1998 EL(qlt, "fct_register_local_port status=%llxh\n", ret);
1999 return (QLT_FAILURE);
2000 }
2001 fct_free(qlt->qlt_port->port_fds);
2002 fct_free(qlt->qlt_port);
2003 qlt_dma_handle_pool_fini(qlt);
2004 qlt->qlt_port = NULL;
2005 qlt_dmem_fini(qlt);
2006 return (QLT_SUCCESS);
2007 }
2008
2009 /*
2010 * Called by framework to init the HBA.
2011 * Can be called in the middle of I/O. (Why ??)
2012 * Should make sure sane state both before and after the initialization
2013 */
2014 fct_status_t
qlt_port_online(qlt_state_t * qlt)2015 qlt_port_online(qlt_state_t *qlt)
2016 {
2017 uint64_t da;
2018 int instance, i, j;
2019 fct_status_t ret;
2020 uint16_t rcount;
2021 caddr_t icb;
2022 mbox_cmd_t *mcp;
2023 uint8_t *elsbmp;
2024
2025 instance = ddi_get_instance(qlt->dip);
2026
2027 /* XXX Make sure a sane state */
2028
2029 if ((ret = qlt_download_fw(qlt)) != QLT_SUCCESS) {
2030 cmn_err(CE_NOTE, "qlt(%d): reset chip failed %llx",
2031 qlt->instance, (long long)ret);
2032 return (ret);
2033 }
2034
2035 bzero(qlt->queue_mem_ptr, TOTAL_DMA_MEM_SIZE);
2036
2037 /* Get resource count */
2038 REG_WR16(qlt, REG_MBOX(0), MBC_GET_RESOURCE_COUNTS);
2039 ret = qlt_raw_mailbox_command(qlt);
2040 rcount = REG_RD16(qlt, REG_MBOX(3));
2041 REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
2042 if (ret != QLT_SUCCESS) {
2043 EL(qlt, "qlt_raw_mailbox_command=42h status=%llxh\n", ret);
2044 return (ret);
2045 }
2046
2047 /* Enable PUREX */
2048 REG_WR16(qlt, REG_MBOX(0), MBC_SET_ADDITIONAL_FIRMWARE_OPT);
2049 REG_WR16(qlt, REG_MBOX(1), OPT_PUREX_ENABLE);
2050 REG_WR16(qlt, REG_MBOX(2), 0x0);
2051 REG_WR16(qlt, REG_MBOX(3), 0x0);
2052 ret = qlt_raw_mailbox_command(qlt);
2053 REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
2054 if (ret != QLT_SUCCESS) {
2055 EL(qlt, "qlt_raw_mailbox_command=38h status=%llxh\n", ret);
2056 cmn_err(CE_NOTE, "Enable PUREX failed");
2057 return (ret);
2058 }
2059
2060 /* Pass ELS bitmap to fw */
2061 REG_WR16(qlt, REG_MBOX(0), MBC_SET_PARAMETERS);
2062 REG_WR16(qlt, REG_MBOX(1), PARAM_TYPE(PUREX_ELS_CMDS));
2063 elsbmp = (uint8_t *)qlt->queue_mem_ptr + MBOX_DMA_MEM_OFFSET;
2064 bzero(elsbmp, 32);
2065 da = qlt->queue_mem_cookie.dmac_laddress;
2066 da += MBOX_DMA_MEM_OFFSET;
2067 REG_WR16(qlt, REG_MBOX(3), LSW(LSD(da)));
2068 REG_WR16(qlt, REG_MBOX(2), MSW(LSD(da)));
2069 REG_WR16(qlt, REG_MBOX(7), LSW(MSD(da)));
2070 REG_WR16(qlt, REG_MBOX(6), MSW(MSD(da)));
2071 SETELSBIT(elsbmp, ELS_OP_PLOGI);
2072 SETELSBIT(elsbmp, ELS_OP_LOGO);
2073 SETELSBIT(elsbmp, ELS_OP_ABTX);
2074 /* SETELSBIT(elsbmp, ELS_OP_ECHO); till fct handles it */
2075 SETELSBIT(elsbmp, ELS_OP_PRLI);
2076 SETELSBIT(elsbmp, ELS_OP_PRLO);
2077 SETELSBIT(elsbmp, ELS_OP_SCN);
2078 SETELSBIT(elsbmp, ELS_OP_TPRLO);
2079 SETELSBIT(elsbmp, ELS_OP_PDISC);
2080 SETELSBIT(elsbmp, ELS_OP_ADISC);
2081 SETELSBIT(elsbmp, ELS_OP_RSCN);
2082 SETELSBIT(elsbmp, ELS_OP_RNID);
2083 (void) ddi_dma_sync(qlt->queue_mem_dma_handle, MBOX_DMA_MEM_OFFSET, 32,
2084 DDI_DMA_SYNC_FORDEV);
2085 ret = qlt_raw_mailbox_command(qlt);
2086 REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
2087 if (ret != QLT_SUCCESS) {
2088 EL(qlt, "qlt_raw_mailbox_command=59h status=llxh\n", ret);
2089 cmn_err(CE_NOTE, "Set ELS Bitmap failed ret=%llx, "
2090 "elsbmp0=%x elabmp1=%x", (long long)ret, elsbmp[0],
2091 elsbmp[1]);
2092 return (ret);
2093 }
2094
2095 /* Init queue pointers */
2096 if (qlt->qlt_mq_enabled == 1) {
2097 uint16_t qi;
2098
2099 for (qi = 0; qi < MQ_MAX_QUEUES; qi++) {
2100 MQBAR_WR32(qlt,
2101 (qi * MQBAR_REG_OFFSET) + MQBAR_REQ_IN, 0);
2102 MQBAR_WR32(qlt,
2103 (qi * MQBAR_REG_OFFSET) + MQBAR_REQ_OUT, 0);
2104 MQBAR_WR32(qlt,
2105 (qi * MQBAR_REG_OFFSET) + MQBAR_RESP_IN, 0);
2106 MQBAR_WR32(qlt,
2107 (qi * MQBAR_REG_OFFSET) +
2108 MQBAR_RESP_OUT, 0);
2109 }
2110 } else {
2111 REG_WR32(qlt, REG_REQ_IN_PTR, 0);
2112 REG_WR32(qlt, REG_REQ_OUT_PTR, 0);
2113 REG_WR32(qlt, REG_RESP_IN_PTR, 0);
2114 REG_WR32(qlt, REG_RESP_OUT_PTR, 0);
2115 }
2116
2117 if ((qlt->qlt_83xx_chip) || (qlt->qlt_27xx_chip)) {
2118 REG_WR32(qlt, REG_PREQ_IN_PTR, 0);
2119 REG_WR32(qlt, REG_PREQ_OUT_PTR, 0);
2120 REG_WR32(qlt, REG_ATIO_IN_PTR, 0);
2121 REG_WR32(qlt, REG_ATIO_OUT_PTR, 0);
2122 }
2123 qlt->mq_req[0].mq_ndx_to_fw = qlt->mq_req[0].mq_ndx_from_fw = 0;
2124 qlt->mq_req[0].mq_available = REQUEST_QUEUE_ENTRIES - 1;
2125
2126 if (qlt->qlt_mq_enabled == 1) {
2127 for (i = 1; i < qlt->qlt_queue_cnt; i++) {
2128 qlt->mq_req[i].mq_ndx_to_fw = 0;
2129 qlt->mq_req[i].mq_ndx_from_fw = 0;
2130 qlt->mq_req[i].mq_available =
2131 REQUEST_QUEUE_MQ_ENTRIES - 1;
2132 }
2133 }
2134 qlt->mq_resp[0].mq_ndx_to_fw = qlt->mq_resp[0].mq_ndx_from_fw = 0;
2135
2136 if (qlt->qlt_mq_enabled == 1) {
2137 caddr_t resp;
2138
2139 for (i = 1; i < qlt->qlt_queue_cnt; i++) {
2140 qlt->mq_resp[i].mq_ndx_to_fw = 0;
2141 qlt->mq_resp[i].mq_ndx_from_fw = 0;
2142 for (j = 0; j < RESPONSE_QUEUE_MQ_ENTRIES; j++) {
2143 resp = &qlt->mq_resp[i].mq_ptr[j << 6];
2144 QMEM_WR32_RSPQ(qlt, i, resp+0x3c, 0xdeadbeef);
2145 }
2146 }
2147 }
2148
2149 for (i = 0; i < ATIO_QUEUE_ENTRIES; i++) {
2150 caddr_t atio;
2151
2152 atio = &qlt->atio_ptr[i << 6];
2153 QMEM_WR32(qlt, atio+0x3c, 0xdeadbeef);
2154 }
2155
2156 qlt->preq_ndx_to_fw = qlt->preq_ndx_from_fw = 0;
2157 qlt->atio_ndx_to_fw = qlt->atio_ndx_from_fw = 0;
2158
2159 /*
2160 * XXX support for tunables. Also should we cache icb ?
2161 */
2162 if ((qlt->qlt_83xx_chip) || (qlt->qlt_81xx_chip) ||
2163 (qlt->qlt_27xx_chip) || ((qlt->qlt_25xx_chip) &&
2164 (qlt->qlt_mq_enabled))) {
2165 /*
2166 * allocate extra 64 bytes for Extended init control block,
2167 * with separation to allow for a minimal MID section.
2168 */
2169 mcp = qlt_alloc_mailbox_command(qlt, 0xE0);
2170 } else {
2171 mcp = qlt_alloc_mailbox_command(qlt, 0x80);
2172 }
2173 if (mcp == NULL) {
2174 EL(qlt, "qlt_alloc_mailbox_command mcp=null\n");
2175 return (STMF_ALLOC_FAILURE);
2176 }
2177 icb = (caddr_t)mcp->dbuf->db_sglist[0].seg_addr;
2178 if ((qlt->qlt_83xx_chip) || (qlt->qlt_81xx_chip) ||
2179 (qlt->qlt_27xx_chip) || ((qlt->qlt_25xx_chip) &&
2180 (qlt->qlt_mq_enabled))) {
2181 bzero(icb, 0xE0);
2182 } else {
2183 bzero(icb, 0x80);
2184 }
2185 da = qlt->queue_mem_cookie.dmac_laddress;
2186 DMEM_WR16(qlt, icb, 1); /* Version */
2187 DMEM_WR16(qlt, icb+4, 2112); /* Max frame length */
2188 DMEM_WR16(qlt, icb+6, 16); /* Execution throttle */
2189 DMEM_WR16(qlt, icb+8, rcount); /* Xchg count */
2190 DMEM_WR16(qlt, icb+0x0a, 0x00); /* Hard address (not used) */
2191 bcopy(qlt->qlt_port->port_pwwn, icb+0x0c, 8);
2192 bcopy(qlt->qlt_port->port_nwwn, icb+0x14, 8);
2193 DMEM_WR16(qlt, icb+0x20, 3); /* Login retry count */
2194 DMEM_WR16(qlt, icb+0x24, RESPONSE_QUEUE_ENTRIES);
2195 DMEM_WR16(qlt, icb+0x26, REQUEST_QUEUE_ENTRIES);
2196 if ((!qlt->qlt_83xx_chip) && (!qlt->qlt_81xx_chip) &&
2197 (!qlt->qlt_27xx_chip)) {
2198 DMEM_WR16(qlt, icb+0x28, 100); /* ms of NOS/OLS for Link down */
2199 }
2200 if ((!qlt->qlt_83xx_chip) || (!qlt->qlt_27xx_chip)) {
2201 DMEM_WR16(qlt, icb+0x2a, PRIORITY_QUEUE_ENTRIES);
2202 }
2203 DMEM_WR64(qlt, icb+0x2c, (da+REQUEST_QUEUE_OFFSET));
2204 DMEM_WR64(qlt, icb+0x34, (da+RESPONSE_QUEUE_OFFSET));
2205 if ((!qlt->qlt_83xx_chip) || (!qlt->qlt_27xx_chip)) {
2206 DMEM_WR64(qlt, icb+0x3c, (da+PRIORITY_QUEUE_OFFSET));
2207 }
2208 /* XXX: all hba model atio/resp 0 use vector 0 */
2209 DMEM_WR16(qlt, icb+0x4e, ATIO_QUEUE_ENTRIES);
2210 DMEM_WR64(qlt, icb+0x50, (da+ATIO_QUEUE_OFFSET));
2211 DMEM_WR16(qlt, icb+0x58, 2); /* Interrupt delay Timer */
2212 DMEM_WR16(qlt, icb+0x5a, 4); /* Login timeout (secs) */
2213 if ((qlt->qlt_83xx_chip) || (qlt->qlt_81xx_chip) ||
2214 (qlt->qlt_27xx_chip) || ((qlt->qlt_25xx_chip) &&
2215 (qlt->qlt_mq_enabled))) {
2216 qlt_nvram_81xx_t *qlt81nvr = (qlt_nvram_81xx_t *)qlt->nvram;
2217
2218 /* fw options 1 */
2219 if (qlt->qlt_fcoe_enabled) {
2220 DMEM_WR32(qlt, icb+0x5c, BIT_5 | BIT_4);
2221 } else {
2222 DMEM_WR32(qlt, icb+0x5c,
2223 BIT_11 | BIT_5 | BIT_4 | BIT_2 | BIT_1 | BIT_0);
2224 }
2225 /* fw options 2 */
2226 if (qlt->qlt_mq_enabled) {
2227 if ((qlt->qlt_83xx_chip) || (qlt->qlt_27xx_chip)) {
2228 if (qlt->qlt_fcoe_enabled) {
2229 DMEM_WR32(qlt, icb+0x60,
2230 BIT_26 | BIT_23 | BIT_22);
2231 } else {
2232 DMEM_WR32(qlt, icb+0x60,
2233 BIT_26 | BIT_23 | BIT_22 | BIT_5);
2234 }
2235 } else {
2236 DMEM_WR32(qlt,
2237 icb+0x60, BIT_26 | BIT_23 | BIT_22 | BIT_5);
2238 }
2239 }
2240
2241 /* fw options 3 */
2242 if (qlt->qlt_fcoe_enabled) {
2243 DMEM_WR32(qlt, icb+0x64, BIT_4);
2244 } else {
2245 DMEM_WR32(qlt, icb+0x64,
2246 BIT_14 | BIT_8 | BIT_7 | BIT_4);
2247 }
2248
2249 if (qlt->qlt_mq_enabled) {
2250 DMEM_WR16(qlt, icb+0x68, 5); /* QoS priority = 5 */
2251 }
2252
2253 DMEM_WR32(qlt, icb+0x70,
2254 qlt81nvr->enode_mac[0] |
2255 (qlt81nvr->enode_mac[1] << 8) |
2256 (qlt81nvr->enode_mac[2] << 16) |
2257 (qlt81nvr->enode_mac[3] << 24));
2258 DMEM_WR16(qlt, icb+0x74,
2259 qlt81nvr->enode_mac[4] |
2260 (qlt81nvr->enode_mac[5] << 8));
2261 } else {
2262 DMEM_WR32(qlt, icb+0x5c, BIT_11 | BIT_5 | BIT_4 |
2263 BIT_2 | BIT_1 | BIT_0);
2264 DMEM_WR32(qlt, icb+0x60, BIT_5);
2265 DMEM_WR32(qlt, icb+0x64, BIT_14 | BIT_8 | BIT_7 |
2266 BIT_4);
2267
2268 /* null MID setup */
2269 DMEM_WR16(qlt, icb+0x80, 1); /* VP count 1 */
2270 }
2271
2272 if (qlt->qlt_fcoe_enabled) {
2273 qlt_dmem_bctl_t *bctl;
2274 uint32_t index;
2275 caddr_t src;
2276 caddr_t dst;
2277 qlt_nvram_81xx_t *qlt81nvr;
2278
2279 dst = icb+0xA0;
2280 qlt81nvr = (qlt_nvram_81xx_t *)qlt->nvram;
2281 src = (caddr_t)&qlt81nvr->ext_blk;
2282 index = sizeof (qlt_ext_icb_81xx_t);
2283
2284 /* Use defaults for cases where we find nothing in NVR */
2285 if ((qlt->qlt_83xx_chip) || (*src == 0)) {
2286 if (*src == 0) {
2287 EL(qlt, "nvram eicb=null\n");
2288 cmn_err(CE_NOTE, "qlt(%d) NVR eicb is zeroed",
2289 instance);
2290 }
2291 qlt81nvr->ext_blk.version[0] = 1;
2292 /*
2293 * not yet, for !FIP firmware at least
2294 *
2295 * qlt81nvr->ext_blk.fcf_vlan_match = 0x81;
2296 */
2297 #ifdef _LITTLE_ENDIAN
2298 qlt81nvr->ext_blk.fcf_vlan_id[0] = 0xEA;
2299 qlt81nvr->ext_blk.fcf_vlan_id[1] = 0x03;
2300 #else
2301 qlt81nvr->ext_blk.fcf_vlan_id[1] = 0xEA;
2302 qlt81nvr->ext_blk.fcf_vlan_id[0] = 0x03;
2303 #endif
2304 }
2305
2306 while (index--) {
2307 *dst++ = *src++;
2308 }
2309
2310 bctl = (qlt_dmem_bctl_t *)mcp->dbuf->db_port_private;
2311 da = bctl->bctl_dev_addr + 0xA0; /* base addr of eicb (phys) */
2312
2313 mcp->to_fw[11] = LSW(LSD(da));
2314 mcp->to_fw[10] = MSW(LSD(da));
2315 mcp->to_fw[13] = LSW(MSD(da));
2316 mcp->to_fw[12] = MSW(MSD(da));
2317 mcp->to_fw[14] = (uint16_t)(sizeof (qlt_ext_icb_81xx_t) &
2318 0xffff);
2319
2320 /* eicb enable */
2321 mcp->to_fw[1] = (uint16_t)(mcp->to_fw[1] | BIT_0);
2322 mcp->to_fw_mask |= BIT_14 | BIT_13 | BIT_12 | BIT_11 | BIT_10 |
2323 BIT_1;
2324 }
2325
2326 qlt_dmem_dma_sync(mcp->dbuf, DDI_DMA_SYNC_FORDEV);
2327 if (((qlt->qlt_83xx_chip) || (qlt->qlt_81xx_chip) ||
2328 (qlt->qlt_27xx_chip) || ((qlt->qlt_25xx_chip) &&
2329 (qlt->qlt_mq_enabled))) && (qlt->fw_attr & BIT_6)) {
2330 mcp->to_fw[0] = MBC_INITIALIZE_MULTI_ID_FW;
2331 } else {
2332 mcp->to_fw[0] = MBC_INITIALIZE_FIRMWARE;
2333 }
2334
2335 /*
2336 * This is the 1st command after adapter initialize which will
2337 * use interrupts and regular mailbox interface.
2338 */
2339 qlt->qlt_intr_enabled = 1;
2340 qlt->mbox_io_state = MBOX_STATE_READY;
2341 REG_WR32(qlt, REG_INTR_CTRL, ENABLE_RISC_INTR);
2342 /* Issue mailbox to firmware */
2343 ret = qlt_mailbox_command(qlt, mcp);
2344 if (ret != QLT_SUCCESS) {
2345 EL(qlt, "qlt_mbox_command=48h/60h status=%llxh\n", ret);
2346 cmn_err(CE_NOTE, "qlt(%d) init fw failed %llx, intr status %x",
2347 instance, (long long)ret, REG_RD32(qlt, REG_INTR_STATUS));
2348 qlt_free_mailbox_command(qlt, mcp);
2349 return (ret);
2350 }
2351
2352 mcp->to_fw_mask = BIT_0;
2353 mcp->from_fw_mask = BIT_0 | BIT_1;
2354 mcp->to_fw[0] = 0x28;
2355 ret = qlt_mailbox_command(qlt, mcp);
2356 if (ret != QLT_SUCCESS) {
2357 EL(qlt, "qlt_mbox_command=28h status=%llxh\n", ret);
2358 cmn_err(CE_NOTE, "qlt(%d) get_fw_options %llx", instance,
2359 (long long)ret);
2360 qlt_free_mailbox_command(qlt, mcp);
2361 return (ret);
2362 }
2363
2364 if (qlt->qlt_mq_enabled == 1) {
2365
2366 for (i = 1; i < qlt->qlt_queue_cnt; i++) {
2367 da = qlt->mq_resp[i].queue_mem_mq_cookie.dmac_laddress;
2368
2369 mcp->to_fw_mask = BIT_14 | BIT_13 | BIT_12 | BIT_11 |
2370 BIT_10 | BIT_9 | BIT_8 | BIT_7 | BIT_6 | BIT_5 |
2371 BIT_4 | BIT_3 | BIT_2 | BIT_1 | BIT_0;
2372 mcp->from_fw_mask = BIT_0 | BIT_1;
2373
2374 /* msix vector setup */
2375 mcp->to_fw[14] = (uint16_t)(i);
2376
2377 mcp->to_fw[13] = 0;
2378 mcp->to_fw[12] = 0;
2379 mcp->to_fw[11] = 0;
2380 mcp->to_fw[10] = 0;
2381 mcp->to_fw[9] = 0;
2382 mcp->to_fw[8] = 0;
2383 mcp->to_fw[7] = LSW(MSD(da));
2384 mcp->to_fw[6] = MSW(MSD(da));
2385 mcp->to_fw[5] = RESPONSE_QUEUE_MQ_ENTRIES;
2386 mcp->to_fw[4] = (uint16_t)(i);
2387 mcp->to_fw[3] = LSW(LSD(da));
2388 mcp->to_fw[2] = MSW(LSD(da));
2389 mcp->to_fw[1] = BIT_6 | BIT_1;
2390 mcp->to_fw[0] = 0x1F;
2391 ret = qlt_mailbox_command(qlt, mcp);
2392
2393 if (ret != QLT_SUCCESS) {
2394 EL(qlt, "qlt_mbox_command=1fh status=%llxh\n",
2395 ret);
2396 cmn_err(CE_NOTE, "qlt(%d) queue manage %llx",
2397 instance, (long long)ret);
2398 qlt_free_mailbox_command(qlt, mcp);
2399 return (ret);
2400 }
2401
2402 da = qlt->mq_req[i].queue_mem_mq_cookie.dmac_laddress;
2403
2404 mcp->to_fw_mask = BIT_14 | BIT_13 | BIT_12 | BIT_11 |
2405 BIT_10 | BIT_9 | BIT_8 | BIT_7 | BIT_6 | BIT_5 |
2406 BIT_4 | BIT_3 | BIT_2 | BIT_1 | BIT_0;
2407 mcp->from_fw_mask = BIT_0 | BIT_1;
2408
2409 /*
2410 * msix vector does not apply for request queue create
2411 */
2412 mcp->to_fw[14] = 2;
2413 mcp->to_fw[13] = 0;
2414 mcp->to_fw[12] = 4;
2415 mcp->to_fw[11] = 0;
2416 mcp->to_fw[10] = (uint16_t)(i);
2417 mcp->to_fw[9] = 0;
2418 mcp->to_fw[8] = 0;
2419 mcp->to_fw[7] = LSW(MSD(da));
2420 mcp->to_fw[6] = MSW(MSD(da));
2421 mcp->to_fw[5] = REQUEST_QUEUE_MQ_ENTRIES;
2422 mcp->to_fw[4] = (uint16_t)(i);
2423 mcp->to_fw[3] = LSW(LSD(da));
2424 mcp->to_fw[2] = MSW(LSD(da));
2425 mcp->to_fw[1] = BIT_6;
2426 mcp->to_fw[0] = 0x1F;
2427 ret = qlt_mailbox_command(qlt, mcp);
2428
2429 if (ret != QLT_SUCCESS) {
2430 EL(qlt, "qlt_mbox_command=1fh status=%llxh\n",
2431 ret);
2432 cmn_err(CE_NOTE, "qlt(%d) queue manage %llx",
2433 instance, (long long)ret);
2434 qlt_free_mailbox_command(qlt, mcp);
2435 return (ret);
2436 }
2437 }
2438 }
2439
2440 /*
2441 * Report FW versions for 81xx - MPI rev is useful
2442 */
2443 /* if ((qlt->qlt_83xx_chip) || (qlt->qlt_81xx_chip)) { */
2444 if (qlt->qlt_fcoe_enabled) {
2445 mcp->to_fw_mask = BIT_0;
2446 mcp->from_fw_mask = BIT_11 | BIT_10 | BIT_6 | BIT_3 | BIT_2 |
2447 BIT_1 | BIT_0;
2448
2449 mcp->to_fw[0] = MBC_ABOUT_FIRMWARE;
2450 ret = qlt_mailbox_command(qlt, mcp);
2451 if (ret != QLT_SUCCESS) {
2452 EL(qlt, "about fw failed: %llx\n", (long long)ret);
2453 } else {
2454 EL(qlt, "Firmware version %d.%d.%d, MPI: %d.%d.%d\n",
2455 mcp->from_fw[1], mcp->from_fw[2], mcp->from_fw[3],
2456 mcp->from_fw[10] & 0xff, mcp->from_fw[11] >> 8,
2457 mcp->from_fw[11] & 0xff);
2458 EL(qlt, "Firmware Attributes %x[h]\n",
2459 mcp->from_fw[6]);
2460 }
2461 }
2462
2463 qlt_free_mailbox_command(qlt, mcp);
2464
2465 for (i = 0; i < 5; i++) {
2466 qlt->qlt_bufref[i] = 0;
2467 }
2468 qlt->qlt_bumpbucket = 0;
2469 qlt->qlt_pmintry = 0;
2470 qlt->qlt_pmin_ok = 0;
2471
2472 if (ret != QLT_SUCCESS)
2473 return (ret);
2474
2475 return (FCT_SUCCESS);
2476 }
2477
2478 fct_status_t
qlt_port_offline(qlt_state_t * qlt)2479 qlt_port_offline(qlt_state_t *qlt)
2480 {
2481 int retries;
2482 int i;
2483
2484 mutex_enter(&qlt->mbox_lock);
2485
2486 if (qlt->mbox_io_state == MBOX_STATE_UNKNOWN) {
2487 mutex_exit(&qlt->mbox_lock);
2488 goto poff_mbox_done;
2489 }
2490
2491 /* Wait to grab the mailboxes */
2492 for (retries = 0; qlt->mbox_io_state != MBOX_STATE_READY;
2493 retries++) {
2494 cv_wait(&qlt->mbox_cv, &qlt->mbox_lock);
2495 if ((retries > 5) ||
2496 (qlt->mbox_io_state == MBOX_STATE_UNKNOWN)) {
2497 qlt->mbox_io_state = MBOX_STATE_UNKNOWN;
2498 mutex_exit(&qlt->mbox_lock);
2499 goto poff_mbox_done;
2500 }
2501 }
2502 qlt->mbox_io_state = MBOX_STATE_UNKNOWN;
2503 mutex_exit(&qlt->mbox_lock);
2504 poff_mbox_done:;
2505 qlt->intr_sneak_counter = 10;
2506 mutex_enter(&qlt->intr_lock);
2507 if (qlt->qlt_mq_enabled == 1) {
2508 for (i = 1; i < qlt->qlt_queue_cnt; i++) {
2509 mutex_enter(&qlt->mq_resp[i].mq_lock);
2510 }
2511 }
2512 (void) qlt_reset_chip(qlt);
2513 drv_usecwait(20);
2514 qlt->intr_sneak_counter = 0;
2515 if (qlt->qlt_mq_enabled == 1) {
2516 for (i = 1; i < qlt->qlt_queue_cnt; i++) {
2517 mutex_exit(&qlt->mq_resp[i].mq_lock);
2518 }
2519 }
2520 mutex_exit(&qlt->intr_lock);
2521
2522 return (FCT_SUCCESS);
2523 }
2524
2525 static fct_status_t
qlt_get_link_info(fct_local_port_t * port,fct_link_info_t * li)2526 qlt_get_link_info(fct_local_port_t *port, fct_link_info_t *li)
2527 {
2528 qlt_state_t *qlt = (qlt_state_t *)port->port_fca_private;
2529 mbox_cmd_t *mcp;
2530 fct_status_t fc_ret;
2531 fct_status_t ret;
2532 clock_t et;
2533
2534 et = ddi_get_lbolt() + drv_usectohz(5000000);
2535 mcp = qlt_alloc_mailbox_command(qlt, 0);
2536 link_info_retry:
2537 mcp->to_fw[0] = MBC_GET_ID;
2538 mcp->to_fw[9] = 0;
2539 mcp->to_fw_mask |= BIT_0 | BIT_9;
2540 mcp->from_fw_mask |= BIT_0 | BIT_1 | BIT_2 | BIT_3 | BIT_6 | BIT_7;
2541 /* Issue mailbox to firmware */
2542 ret = qlt_mailbox_command(qlt, mcp);
2543 if (ret != QLT_SUCCESS) {
2544 EL(qlt, "qlt_mbox_command=20h status=%llxh\n", ret);
2545 if ((mcp->from_fw[0] == 0x4005) &&
2546 ((mcp->from_fw[1] == 7) || (mcp->from_fw[1] == 0x1b))) {
2547 /* Firmware is not ready */
2548 if (ddi_get_lbolt() < et) {
2549 delay(drv_usectohz(50000));
2550 goto link_info_retry;
2551 }
2552 }
2553 EL(qlt, "GET ID mbox failed, ret=%llx mb0=%x mb1=%x",
2554 ret, mcp->from_fw[0], mcp->from_fw[1]);
2555 stmf_trace(qlt->qlt_port_alias, "GET ID mbox failed, ret=%llx "
2556 "mb0=%x mb1=%x", ret, mcp->from_fw[0], mcp->from_fw[1]);
2557 fc_ret = FCT_FAILURE;
2558 } else {
2559 li->portid = ((uint32_t)(mcp->from_fw[2])) |
2560 (((uint32_t)(mcp->from_fw[3])) << 16);
2561
2562 li->port_speed = qlt->link_speed;
2563 switch (mcp->from_fw[6]) {
2564 case 1:
2565 li->port_topology = PORT_TOPOLOGY_PUBLIC_LOOP;
2566 li->port_fca_flogi_done = 1;
2567 break;
2568 case 0:
2569 li->port_topology = PORT_TOPOLOGY_PRIVATE_LOOP;
2570 li->port_no_fct_flogi = 1;
2571 break;
2572 case 3:
2573 li->port_topology = PORT_TOPOLOGY_FABRIC_PT_TO_PT;
2574 li->port_fca_flogi_done = 1;
2575 break;
2576 case 2: /*FALLTHROUGH*/
2577 case 4:
2578 li->port_topology = PORT_TOPOLOGY_PT_TO_PT;
2579 li->port_fca_flogi_done = 1;
2580 break;
2581 default:
2582 li->port_topology = PORT_TOPOLOGY_UNKNOWN;
2583 EL(qlt, "Unknown topology=%xh\n", mcp->from_fw[6]);
2584 }
2585 qlt->cur_topology = li->port_topology;
2586 fc_ret = FCT_SUCCESS;
2587
2588 EL(qlt, "MBC_GET_ID done, Topology=%x, portid=%xh, "
2589 "port speed=%xh\n", li->port_topology, li->portid,
2590 li->port_speed);
2591 }
2592 qlt_free_mailbox_command(qlt, mcp);
2593
2594 if ((fc_ret == FCT_SUCCESS) && (li->port_fca_flogi_done)) {
2595 mcp = qlt_alloc_mailbox_command(qlt, 64);
2596 mcp->to_fw[0] = MBC_GET_PORT_DATABASE;
2597 mcp->to_fw[1] = 0x7FE;
2598 mcp->to_fw[9] = 0;
2599 mcp->to_fw[10] = 0;
2600 mcp->to_fw_mask |= BIT_0 | BIT_1 | BIT_9 | BIT_10;
2601 fc_ret = qlt_mailbox_command(qlt, mcp);
2602 if (fc_ret != QLT_SUCCESS) {
2603 EL(qlt, "qlt_mbox_command=64h status=%llxh\n",
2604 fc_ret);
2605 stmf_trace(qlt->qlt_port_alias, "Attempt to get port "
2606 "database for F_port failed, ret = %llx", fc_ret);
2607 } else {
2608 uint8_t *p;
2609
2610 qlt_dmem_dma_sync(mcp->dbuf, DDI_DMA_SYNC_FORCPU);
2611 p = mcp->dbuf->db_sglist[0].seg_addr;
2612 bcopy(p + 0x18, li->port_rpwwn, 8);
2613 bcopy(p + 0x20, li->port_rnwwn, 8);
2614 EL(qlt, "qlt_mbox_command=64h, GET_PORT_DATABASE "
2615 "complete\n");
2616 }
2617 qlt_free_mailbox_command(qlt, mcp);
2618 }
2619 return (fc_ret);
2620 }
2621
2622 static int
qlt_open(dev_t * devp,int flag,int otype,cred_t * credp)2623 qlt_open(dev_t *devp, int flag, int otype, cred_t *credp)
2624 {
2625 int instance;
2626 qlt_state_t *qlt;
2627
2628 if (otype != OTYP_CHR) {
2629 return (EINVAL);
2630 }
2631
2632 /*
2633 * Since this is for debugging only, only allow root to issue ioctl now
2634 */
2635 if (drv_priv(credp)) {
2636 return (EPERM);
2637 }
2638
2639 instance = (int)getminor(*devp);
2640 qlt = ddi_get_soft_state(qlt_state, instance);
2641 if (qlt == NULL) {
2642 return (ENXIO);
2643 }
2644
2645 mutex_enter(&qlt->qlt_ioctl_lock);
2646 if (qlt->qlt_ioctl_flags & QLT_IOCTL_FLAG_EXCL) {
2647 /*
2648 * It is already open for exclusive access.
2649 * So shut the door on this caller.
2650 */
2651 mutex_exit(&qlt->qlt_ioctl_lock);
2652 return (EBUSY);
2653 }
2654
2655 if (flag & FEXCL) {
2656 if (qlt->qlt_ioctl_flags & QLT_IOCTL_FLAG_OPEN) {
2657 /*
2658 * Exclusive operation not possible
2659 * as it is already opened
2660 */
2661 mutex_exit(&qlt->qlt_ioctl_lock);
2662 return (EBUSY);
2663 }
2664 qlt->qlt_ioctl_flags |= QLT_IOCTL_FLAG_EXCL;
2665 }
2666 qlt->qlt_ioctl_flags |= QLT_IOCTL_FLAG_OPEN;
2667 mutex_exit(&qlt->qlt_ioctl_lock);
2668
2669 return (0);
2670 }
2671
2672 /* ARGSUSED */
2673 static int
qlt_close(dev_t dev,int flag,int otype,cred_t * credp)2674 qlt_close(dev_t dev, int flag, int otype, cred_t *credp)
2675 {
2676 int instance;
2677 qlt_state_t *qlt;
2678
2679 if (otype != OTYP_CHR) {
2680 return (EINVAL);
2681 }
2682
2683 instance = (int)getminor(dev);
2684 qlt = ddi_get_soft_state(qlt_state, instance);
2685 if (qlt == NULL) {
2686 return (ENXIO);
2687 }
2688
2689 mutex_enter(&qlt->qlt_ioctl_lock);
2690 if ((qlt->qlt_ioctl_flags & QLT_IOCTL_FLAG_OPEN) == 0) {
2691 mutex_exit(&qlt->qlt_ioctl_lock);
2692 return (ENODEV);
2693 }
2694
2695 /*
2696 * It looks there's one hole here, maybe there could several concurrent
2697 * shareed open session, but we never check this case.
2698 * But it will not hurt too much, disregard it now.
2699 */
2700 qlt->qlt_ioctl_flags &= ~QLT_IOCTL_FLAG_MASK;
2701 mutex_exit(&qlt->qlt_ioctl_lock);
2702
2703 return (0);
2704 }
2705
2706 /*
2707 * All of these ioctls are unstable interfaces which are meant to be used
2708 * in a controlled lab env. No formal testing will be (or needs to be) done
2709 * for these ioctls. Specially note that running with an additional
2710 * uploaded firmware is not supported and is provided here for test
2711 * purposes only.
2712 */
2713 /* ARGSUSED */
2714 static int
qlt_ioctl(dev_t dev,int cmd,intptr_t data,int mode,cred_t * credp,int * rval)2715 qlt_ioctl(dev_t dev, int cmd, intptr_t data, int mode,
2716 cred_t *credp, int *rval)
2717 {
2718 qlt_state_t *qlt;
2719 int ret = 0;
2720 #ifdef _LITTLE_ENDIAN
2721 int i;
2722 #endif
2723 stmf_iocdata_t *iocd;
2724 void *ibuf = NULL;
2725 void *obuf = NULL;
2726 uint32_t *intp;
2727 qlt_fw_info_t *fwi;
2728 mbox_cmd_t *mcp;
2729 fct_status_t st;
2730 char info[80];
2731 fct_status_t ret2;
2732
2733 if (drv_priv(credp) != 0)
2734 return (EPERM);
2735
2736 qlt = ddi_get_soft_state(qlt_state, (int32_t)getminor(dev));
2737 ret = stmf_copyin_iocdata(data, mode, &iocd, &ibuf, &obuf);
2738 if (ret)
2739 return (ret);
2740 iocd->stmf_error = 0;
2741
2742 switch (cmd) {
2743 case QLT_IOCTL_FETCH_FWDUMP:
2744 if (iocd->stmf_obuf_size < QLT_FWDUMP_BUFSIZE) {
2745 EL(qlt, "FETCH_FWDUMP obuf_size=%d < %d\n",
2746 iocd->stmf_obuf_size, QLT_FWDUMP_BUFSIZE);
2747 ret = EINVAL;
2748 break;
2749 }
2750 mutex_enter(&qlt->qlt_ioctl_lock);
2751 if (!(qlt->qlt_ioctl_flags & QLT_FWDUMP_ISVALID)) {
2752 mutex_exit(&qlt->qlt_ioctl_lock);
2753 ret = ENODATA;
2754 EL(qlt, "no fwdump\n");
2755 iocd->stmf_error = QLTIO_NO_DUMP;
2756 break;
2757 }
2758 if (qlt->qlt_ioctl_flags & QLT_FWDUMP_INPROGRESS) {
2759 mutex_exit(&qlt->qlt_ioctl_lock);
2760 ret = EBUSY;
2761 EL(qlt, "fwdump inprogress\n");
2762 iocd->stmf_error = QLTIO_DUMP_INPROGRESS;
2763 break;
2764 }
2765 if (qlt->qlt_ioctl_flags & QLT_FWDUMP_FETCHED_BY_USER) {
2766 mutex_exit(&qlt->qlt_ioctl_lock);
2767 ret = EEXIST;
2768 EL(qlt, "fwdump already fetched\n");
2769 iocd->stmf_error = QLTIO_ALREADY_FETCHED;
2770 break;
2771 }
2772 bcopy(qlt->qlt_fwdump_buf, obuf, QLT_FWDUMP_BUFSIZE);
2773 qlt->qlt_ioctl_flags |= QLT_FWDUMP_FETCHED_BY_USER;
2774 mutex_exit(&qlt->qlt_ioctl_lock);
2775
2776 break;
2777
2778 case QLT_IOCTL_TRIGGER_FWDUMP:
2779 if (qlt->qlt_state != FCT_STATE_ONLINE) {
2780 ret = EACCES;
2781 iocd->stmf_error = QLTIO_NOT_ONLINE;
2782 break;
2783 }
2784 (void) snprintf(info, 80, "qlt_ioctl: qlt-%p, "
2785 "user triggered FWDUMP with RFLAG_RESET", (void *)qlt);
2786 info[79] = 0;
2787 if ((ret2 = fct_port_shutdown(qlt->qlt_port,
2788 STMF_RFLAG_USER_REQUEST | STMF_RFLAG_RESET |
2789 STMF_RFLAG_COLLECT_DEBUG_DUMP, info)) != FCT_SUCCESS) {
2790 EL(qlt, "TRIGGER_FWDUMP fct_port_shutdown status="
2791 "%llxh\n", ret2);
2792 ret = EIO;
2793 }
2794 break;
2795 case QLT_IOCTL_UPLOAD_FW:
2796 if ((iocd->stmf_ibuf_size < 1024) ||
2797 (iocd->stmf_ibuf_size & 3)) {
2798 EL(qlt, "UPLOAD_FW ibuf_size=%d < 1024\n",
2799 iocd->stmf_ibuf_size);
2800 ret = EINVAL;
2801 iocd->stmf_error = QLTIO_INVALID_FW_SIZE;
2802 break;
2803 }
2804 intp = (uint32_t *)ibuf;
2805 #ifdef _LITTLE_ENDIAN
2806 for (i = 0; (i << 2) < iocd->stmf_ibuf_size; i++) {
2807 intp[i] = BSWAP_32(intp[i]);
2808 }
2809 #endif
2810 if (((intp[3] << 2) >= iocd->stmf_ibuf_size) ||
2811 (((intp[intp[3] + 3] + intp[3]) << 2) !=
2812 iocd->stmf_ibuf_size)) {
2813 EL(qlt, "UPLOAD_FW fw_size=%d >= %d\n", intp[3] << 2,
2814 iocd->stmf_ibuf_size);
2815 ret = EINVAL;
2816 iocd->stmf_error = QLTIO_INVALID_FW_SIZE;
2817 break;
2818 }
2819 if ((qlt->qlt_81xx_chip && ((intp[8] & 8) == 0)) ||
2820 (qlt->qlt_25xx_chip && ((intp[8] & 4) == 0)) ||
2821 (!qlt->qlt_25xx_chip && !qlt->qlt_81xx_chip &&
2822 !qlt->qlt_83xx_chip && !qlt->qlt_27xx_chip &&
2823 ((intp[8] & 3) == 0))) {
2824 EL(qlt, "UPLOAD_FW fw_type=%d\n", intp[8]);
2825 ret = EACCES;
2826 iocd->stmf_error = QLTIO_INVALID_FW_TYPE;
2827 break;
2828 }
2829
2830 /* Everything looks ok, lets copy this firmware */
2831 if (qlt->fw_code01) {
2832 kmem_free(qlt->fw_code01, (qlt->fw_length01 +
2833 qlt->fw_length02) << 2);
2834 qlt->fw_code01 = NULL;
2835 } else {
2836 atomic_inc_32(&qlt_loaded_counter);
2837 }
2838 qlt->fw_length01 = intp[3];
2839 qlt->fw_code01 = (uint32_t *)kmem_alloc(iocd->stmf_ibuf_size,
2840 KM_SLEEP);
2841 bcopy(intp, qlt->fw_code01, iocd->stmf_ibuf_size);
2842 qlt->fw_addr01 = intp[2];
2843 qlt->fw_code02 = &qlt->fw_code01[intp[3]];
2844 qlt->fw_addr02 = qlt->fw_code02[2];
2845 qlt->fw_length02 = qlt->fw_code02[3];
2846 break;
2847
2848 case QLT_IOCTL_CLEAR_FW:
2849 if (qlt->fw_code01) {
2850 kmem_free(qlt->fw_code01, (qlt->fw_length01 +
2851 qlt->fw_length02) << 2);
2852 qlt->fw_code01 = NULL;
2853 atomic_dec_32(&qlt_loaded_counter);
2854 }
2855 break;
2856
2857 case QLT_IOCTL_GET_FW_INFO:
2858 if (iocd->stmf_obuf_size != sizeof (qlt_fw_info_t)) {
2859 EL(qlt, "GET_FW_INFO obuf_size=%d != %d\n",
2860 iocd->stmf_obuf_size, sizeof (qlt_fw_info_t));
2861 ret = EINVAL;
2862 break;
2863 }
2864 fwi = (qlt_fw_info_t *)obuf;
2865 if (qlt->qlt_stay_offline) {
2866 fwi->fwi_stay_offline = 1;
2867 }
2868 if (qlt->qlt_state == FCT_STATE_ONLINE) {
2869 fwi->fwi_port_active = 1;
2870 }
2871 fwi->fwi_active_major = qlt->fw_major;
2872 fwi->fwi_active_minor = qlt->fw_minor;
2873 fwi->fwi_active_subminor = qlt->fw_subminor;
2874 fwi->fwi_active_attr = qlt->fw_attr;
2875 if (qlt->fw_code01) {
2876 fwi->fwi_fw_uploaded = 1;
2877 fwi->fwi_loaded_major = (uint16_t)qlt->fw_code01[4];
2878 fwi->fwi_loaded_minor = (uint16_t)qlt->fw_code01[5];
2879 fwi->fwi_loaded_subminor = (uint16_t)qlt->fw_code01[6];
2880 fwi->fwi_loaded_attr = (uint16_t)qlt->fw_code01[7];
2881 }
2882 if (qlt->qlt_27xx_chip) {
2883 fwi->fwi_default_major = (uint16_t)fw2700_code01[4];
2884 fwi->fwi_default_minor = (uint16_t)fw2700_code01[5];
2885 fwi->fwi_default_subminor = (uint16_t)fw2700_code01[6];
2886 fwi->fwi_default_attr = (uint16_t)fw2700_code01[7];
2887 } else if (qlt->qlt_83xx_chip) {
2888 fwi->fwi_default_major = (uint16_t)fw8300fc_code01[4];
2889 fwi->fwi_default_minor = (uint16_t)fw8300fc_code01[5];
2890 fwi->fwi_default_subminor =
2891 (uint16_t)fw8300fc_code01[6];
2892 fwi->fwi_default_attr = (uint16_t)fw8300fc_code01[7];
2893 } else if (qlt->qlt_81xx_chip) {
2894 fwi->fwi_default_major = (uint16_t)fw8100_code01[4];
2895 fwi->fwi_default_minor = (uint16_t)fw8100_code01[5];
2896 fwi->fwi_default_subminor = (uint16_t)fw8100_code01[6];
2897 fwi->fwi_default_attr = (uint16_t)fw8100_code01[7];
2898 } else if (qlt->qlt_25xx_chip) {
2899 fwi->fwi_default_major = (uint16_t)fw2500_code01[4];
2900 fwi->fwi_default_minor = (uint16_t)fw2500_code01[5];
2901 fwi->fwi_default_subminor = (uint16_t)fw2500_code01[6];
2902 fwi->fwi_default_attr = (uint16_t)fw2500_code01[7];
2903 } else {
2904 fwi->fwi_default_major = (uint16_t)fw2400_code01[4];
2905 fwi->fwi_default_minor = (uint16_t)fw2400_code01[5];
2906 fwi->fwi_default_subminor = (uint16_t)fw2400_code01[6];
2907 fwi->fwi_default_attr = (uint16_t)fw2400_code01[7];
2908 }
2909 break;
2910
2911 case QLT_IOCTL_STAY_OFFLINE:
2912 if (!iocd->stmf_ibuf_size) {
2913 EL(qlt, "STAY_OFFLINE ibuf_size=%d\n",
2914 iocd->stmf_ibuf_size);
2915 ret = EINVAL;
2916 break;
2917 }
2918 if (*((char *)ibuf)) {
2919 qlt->qlt_stay_offline = 1;
2920 } else {
2921 qlt->qlt_stay_offline = 0;
2922 }
2923 break;
2924
2925 case QLT_IOCTL_MBOX:
2926 if ((iocd->stmf_ibuf_size < sizeof (qlt_ioctl_mbox_t)) ||
2927 (iocd->stmf_obuf_size < sizeof (qlt_ioctl_mbox_t))) {
2928 EL(qlt, "IOCTL_MBOX ibuf_size=%d, obuf_size=%d\n",
2929 iocd->stmf_ibuf_size, iocd->stmf_obuf_size);
2930 ret = EINVAL;
2931 break;
2932 }
2933 mcp = qlt_alloc_mailbox_command(qlt, 0);
2934 if (mcp == NULL) {
2935 EL(qlt, "IOCTL_MBOX mcp == NULL\n");
2936 ret = ENOMEM;
2937 break;
2938 }
2939 bcopy(ibuf, mcp, sizeof (qlt_ioctl_mbox_t));
2940 st = qlt_mailbox_command(qlt, mcp);
2941 bcopy(mcp, obuf, sizeof (qlt_ioctl_mbox_t));
2942 qlt_free_mailbox_command(qlt, mcp);
2943 if (st != QLT_SUCCESS) {
2944 if ((st & (~((uint64_t)(0xFFFF)))) == QLT_MBOX_FAILED)
2945 st = QLT_SUCCESS;
2946 }
2947 if (st != QLT_SUCCESS) {
2948 EL(qlt, "IOCTL_MBOX status=%xh\n", st);
2949 ret = EIO;
2950 switch (st) {
2951 case QLT_MBOX_NOT_INITIALIZED:
2952 iocd->stmf_error = QLTIO_MBOX_NOT_INITIALIZED;
2953 break;
2954 case QLT_MBOX_BUSY:
2955 iocd->stmf_error = QLTIO_CANT_GET_MBOXES;
2956 break;
2957 case QLT_MBOX_TIMEOUT:
2958 iocd->stmf_error = QLTIO_MBOX_TIMED_OUT;
2959 break;
2960 case QLT_MBOX_ABORTED:
2961 iocd->stmf_error = QLTIO_MBOX_ABORTED;
2962 break;
2963 }
2964 }
2965 break;
2966
2967 case QLT_IOCTL_ELOG:
2968 EL(qlt, "Not support yet, ioctl-%xh\n", cmd);
2969 break;
2970
2971 default:
2972 EL(qlt, "Unknown ioctl-%xh\n", cmd);
2973 ret = ENOTTY;
2974 }
2975
2976 if (ret == 0) {
2977 ret = stmf_copyout_iocdata(data, mode, iocd, obuf);
2978 } else if (iocd->stmf_error) {
2979 (void) stmf_copyout_iocdata(data, mode, iocd, obuf);
2980 }
2981 if (obuf) {
2982 kmem_free(obuf, iocd->stmf_obuf_size);
2983 obuf = NULL;
2984 }
2985 if (ibuf) {
2986 kmem_free(ibuf, iocd->stmf_ibuf_size);
2987 ibuf = NULL;
2988 }
2989 kmem_free(iocd, sizeof (stmf_iocdata_t));
2990 return (ret);
2991 }
2992
2993 static fct_status_t
qlt_force_lip(qlt_state_t * qlt)2994 qlt_force_lip(qlt_state_t *qlt)
2995 {
2996 mbox_cmd_t *mcp;
2997 fct_status_t rval;
2998
2999 mcp = qlt_alloc_mailbox_command(qlt, 0);
3000 if (qlt->qlt_fcoe_enabled) {
3001 mcp->to_fw[0] = MBC_PORT_RESET;
3002 } else {
3003 mcp->to_fw[0] = MBC_LIP_FULL_LOGIN;
3004 mcp->to_fw[1] = BIT_4;
3005 mcp->to_fw[3] = 1;
3006 mcp->to_fw_mask |= BIT_1 | BIT_3;
3007 }
3008 rval = qlt_mailbox_command(qlt, mcp);
3009 if (rval != FCT_SUCCESS) {
3010 EL(qlt, "qlt force lip MB failed: rval=%x\n", rval);
3011 } else {
3012 if (mcp->from_fw[0] != QLT_MBX_CMD_SUCCESS) {
3013 QLT_LOG(qlt->qlt_port_alias, "qlt FLIP: fw[0]=%x",
3014 mcp->from_fw[0]);
3015 rval = FCT_FAILURE;
3016 }
3017 }
3018 qlt_free_mailbox_command(qlt, mcp);
3019 return (rval);
3020 }
3021
3022 static void
qlt_ctl(struct fct_local_port * port,int cmd,void * arg)3023 qlt_ctl(struct fct_local_port *port, int cmd, void *arg)
3024 {
3025 stmf_change_status_t st;
3026 stmf_state_change_info_t *ssci = (stmf_state_change_info_t *)arg;
3027 qlt_state_t *qlt;
3028 fct_status_t ret;
3029
3030 ASSERT((cmd == FCT_CMD_PORT_ONLINE) ||
3031 (cmd == FCT_CMD_PORT_OFFLINE) ||
3032 (cmd == FCT_CMD_FORCE_LIP) ||
3033 (cmd == FCT_ACK_PORT_ONLINE_COMPLETE) ||
3034 (cmd == FCT_ACK_PORT_OFFLINE_COMPLETE));
3035
3036 qlt = (qlt_state_t *)port->port_fca_private;
3037 st.st_completion_status = FCT_SUCCESS;
3038 st.st_additional_info = NULL;
3039
3040 EL(qlt, "port (%p) qlt_state (%xh) cmd (%xh) arg (%p)\n",
3041 port, qlt->qlt_state, cmd, arg);
3042
3043 switch (cmd) {
3044 case FCT_CMD_PORT_ONLINE:
3045 if (qlt->qlt_state == FCT_STATE_ONLINE)
3046 st.st_completion_status = STMF_ALREADY;
3047 else if (qlt->qlt_state != FCT_STATE_OFFLINE)
3048 st.st_completion_status = FCT_FAILURE;
3049 if (st.st_completion_status == FCT_SUCCESS) {
3050 qlt->qlt_state = FCT_STATE_ONLINING;
3051 qlt->qlt_state_not_acked = 1;
3052 st.st_completion_status = qlt_port_online(qlt);
3053 if (st.st_completion_status != STMF_SUCCESS) {
3054 EL(qlt, "PORT_ONLINE status=%xh\n",
3055 st.st_completion_status);
3056 qlt->qlt_state = FCT_STATE_OFFLINE;
3057 qlt->qlt_state_not_acked = 0;
3058 } else {
3059 qlt->qlt_state = FCT_STATE_ONLINE;
3060 }
3061 }
3062 fct_ctl(port->port_lport, FCT_CMD_PORT_ONLINE_COMPLETE, &st);
3063 qlt->qlt_change_state_flags = 0;
3064 break;
3065
3066 case FCT_CMD_PORT_OFFLINE:
3067 if (qlt->qlt_state == FCT_STATE_OFFLINE) {
3068 st.st_completion_status = STMF_ALREADY;
3069 } else if (qlt->qlt_state != FCT_STATE_ONLINE) {
3070 st.st_completion_status = FCT_FAILURE;
3071 }
3072 if (st.st_completion_status == FCT_SUCCESS) {
3073 qlt->qlt_state = FCT_STATE_OFFLINING;
3074 qlt->qlt_state_not_acked = 1;
3075
3076 if (ssci->st_rflags & STMF_RFLAG_COLLECT_DEBUG_DUMP) {
3077 (void) qlt_firmware_dump(port, ssci);
3078 }
3079 qlt->qlt_change_state_flags = (uint32_t)ssci->st_rflags;
3080 st.st_completion_status = qlt_port_offline(qlt);
3081 if (st.st_completion_status != STMF_SUCCESS) {
3082 EL(qlt, "PORT_OFFLINE status=%xh\n",
3083 st.st_completion_status);
3084 qlt->qlt_state = FCT_STATE_ONLINE;
3085 qlt->qlt_state_not_acked = 0;
3086 } else {
3087 qlt->qlt_state = FCT_STATE_OFFLINE;
3088 }
3089 }
3090 fct_ctl(port->port_lport, FCT_CMD_PORT_OFFLINE_COMPLETE, &st);
3091 break;
3092
3093 case FCT_ACK_PORT_ONLINE_COMPLETE:
3094 qlt->qlt_state_not_acked = 0;
3095 break;
3096
3097 case FCT_ACK_PORT_OFFLINE_COMPLETE:
3098 qlt->qlt_state_not_acked = 0;
3099 if ((qlt->qlt_change_state_flags & STMF_RFLAG_RESET) &&
3100 (qlt->qlt_stay_offline == 0)) {
3101 if ((ret = fct_port_initialize(port,
3102 qlt->qlt_change_state_flags,
3103 "qlt_ctl FCT_ACK_PORT_OFFLINE_COMPLETE "
3104 "with RLFLAG_RESET")) != FCT_SUCCESS) {
3105 EL(qlt, "fct_port_initialize status=%llxh\n",
3106 ret);
3107 cmn_err(CE_WARN, "qlt_ctl: "
3108 "fct_port_initialize failed, please use "
3109 "stmfstate to start the port-%s manualy",
3110 qlt->qlt_port_alias);
3111 }
3112 }
3113 break;
3114
3115 case FCT_CMD_FORCE_LIP:
3116 if (qlt->qlt_fcoe_enabled) {
3117 EL(qlt, "force lip is an unsupported command "
3118 "for this adapter type\n");
3119 } else {
3120 if (qlt->qlt_state == FCT_STATE_ONLINE) {
3121 *((fct_status_t *)arg) = qlt_force_lip(qlt);
3122 EL(qlt, "forcelip done\n");
3123 }
3124 }
3125 break;
3126
3127 default:
3128 EL(qlt, "unsupport cmd - 0x%02X\n", cmd);
3129 break;
3130 }
3131 }
3132
3133 /* ARGSUSED */
3134 static fct_status_t
qlt_do_flogi(fct_local_port_t * port,fct_flogi_xchg_t * fx)3135 qlt_do_flogi(fct_local_port_t *port, fct_flogi_xchg_t *fx)
3136 {
3137 qlt_state_t *qlt = (qlt_state_t *)port->port_fca_private;
3138
3139 EL(qlt, "FLOGI requested not supported\n");
3140 cmn_err(CE_WARN, "qlt: FLOGI requested (not supported)");
3141 return (FCT_FAILURE);
3142 }
3143
3144 /*
3145 * Return a pointer to n entries in the request queue. Assumes that
3146 * request queue lock is held. Does a very short busy wait if
3147 * less/zero entries are available. Retuns NULL if it still cannot
3148 * fullfill the request.
3149 * **CALL qlt_submit_req_entries() BEFORE DROPPING THE LOCK**
3150 */
3151 caddr_t
qlt_get_req_entries(qlt_state_t * qlt,uint32_t n,uint16_t qi)3152 qlt_get_req_entries(qlt_state_t *qlt, uint32_t n, uint16_t qi)
3153 {
3154 int try = 0;
3155
3156 while (qlt->mq_req[qi].mq_available < n) {
3157 uint32_t val1, val2, val3;
3158
3159 if (qlt->qlt_mq_enabled) {
3160 /* debounce */
3161 val1 = MQBAR_RD32(qlt,
3162 (qi * MQBAR_REG_OFFSET) + MQBAR_REQ_OUT);
3163 val2 = MQBAR_RD32(qlt,
3164 (qi * MQBAR_REG_OFFSET) + MQBAR_REQ_OUT);
3165 val3 = MQBAR_RD32(qlt,
3166 (qi * MQBAR_REG_OFFSET) + MQBAR_REQ_OUT);
3167 } else {
3168 val1 = REG_RD32(qlt, REG_REQ_OUT_PTR);
3169 val2 = REG_RD32(qlt, REG_REQ_OUT_PTR);
3170 val3 = REG_RD32(qlt, REG_REQ_OUT_PTR);
3171 }
3172 if ((val1 != val2) || (val2 != val3))
3173 continue;
3174
3175 qlt->mq_req[qi].mq_ndx_from_fw = val1;
3176 if (qi != 0) {
3177 qlt->mq_req[qi].mq_available =
3178 REQUEST_QUEUE_MQ_ENTRIES - 1 -
3179 ((qlt->mq_req[qi].mq_ndx_to_fw -
3180 qlt->mq_req[qi].mq_ndx_from_fw) &
3181 (REQUEST_QUEUE_MQ_ENTRIES - 1));
3182 } else {
3183 qlt->mq_req[qi].mq_available =
3184 REQUEST_QUEUE_ENTRIES - 1 -
3185 ((qlt->mq_req[qi].mq_ndx_to_fw -
3186 qlt->mq_req[qi].mq_ndx_from_fw) &
3187 (REQUEST_QUEUE_ENTRIES - 1));
3188 }
3189 if (qlt->mq_req[qi].mq_available < n) {
3190 if (try < 2) {
3191 drv_usecwait(100);
3192 try++;
3193 continue;
3194 } else {
3195 stmf_trace(qlt->qlt_port_alias,
3196 "Req Q# %xh is full", qi);
3197 EL(qlt, "Req %xh is full (%d,%d) (%d,%d)\n",
3198 qi, qlt->mq_req[qi].mq_ndx_to_fw,
3199 qlt->mq_req[qi].mq_ndx_from_fw,
3200 n, qlt->mq_req[qi].mq_available);
3201 return (NULL);
3202 }
3203 }
3204 break;
3205 }
3206 /* We dont change anything until the entries are sumitted */
3207 return (&qlt->mq_req[qi].mq_ptr[qlt->mq_req[qi].mq_ndx_to_fw << 6]);
3208 }
3209
3210 /*
3211 * updates the req in ptr to fw. Assumes that req lock is held.
3212 */
3213 void
qlt_submit_req_entries(qlt_state_t * qlt,uint32_t n,uint16_t qi)3214 qlt_submit_req_entries(qlt_state_t *qlt, uint32_t n, uint16_t qi)
3215 {
3216
3217 ASSERT(n >= 1);
3218
3219 qlt->mq_req[qi].mq_ndx_to_fw += n;
3220 if (qi != 0) {
3221 qlt->mq_req[qi].mq_ndx_to_fw &= REQUEST_QUEUE_MQ_ENTRIES - 1;
3222 } else {
3223 qlt->mq_req[qi].mq_ndx_to_fw &= REQUEST_QUEUE_ENTRIES - 1;
3224 }
3225 qlt->mq_req[qi].mq_available -= n;
3226
3227 if (qlt->qlt_mq_enabled) {
3228 MQBAR_WR32(qlt, (qi * MQBAR_REG_OFFSET) + MQBAR_REQ_IN,
3229 qlt->mq_req[qi].mq_ndx_to_fw);
3230 } else {
3231 REG_WR32(qlt, REG_REQ_IN_PTR, qlt->mq_req[0].mq_ndx_to_fw);
3232 }
3233 }
3234
3235 /*
3236 * Return a pointer to n entries in the priority request queue. Assumes that
3237 * priority request queue lock is held. Does a very short busy wait if
3238 * less/zero entries are available. Retuns NULL if it still cannot
3239 * fullfill the request.
3240 * **CALL qlt_submit_preq_entries() BEFORE DROPPING THE LOCK**
3241 */
3242 caddr_t
qlt_get_preq_entries(qlt_state_t * qlt,uint32_t n)3243 qlt_get_preq_entries(qlt_state_t *qlt, uint32_t n)
3244 {
3245 int try = 0;
3246 uint32_t req_available = PRIORITY_QUEUE_ENTRIES - 1 -
3247 ((qlt->preq_ndx_to_fw - qlt->preq_ndx_from_fw) &
3248 (PRIORITY_QUEUE_ENTRIES - 1));
3249
3250 while (req_available < n) {
3251 uint32_t val1, val2, val3;
3252 val1 = REG_RD32(qlt, REG_PREQ_OUT_PTR);
3253 val2 = REG_RD32(qlt, REG_PREQ_OUT_PTR);
3254 val3 = REG_RD32(qlt, REG_PREQ_OUT_PTR);
3255 if ((val1 != val2) || (val2 != val3))
3256 continue;
3257
3258 qlt->preq_ndx_from_fw = val1;
3259 req_available = PRIORITY_QUEUE_ENTRIES - 1 -
3260 ((qlt->preq_ndx_to_fw - qlt->preq_ndx_from_fw) &
3261 (PRIORITY_QUEUE_ENTRIES - 1));
3262 if (req_available < n) {
3263 if (try < 2) {
3264 drv_usecwait(100);
3265 try++;
3266 continue;
3267 } else {
3268 return (NULL);
3269 }
3270 }
3271 break;
3272 }
3273 /* We dont change anything until the entries are sumitted */
3274 return (&qlt->preq_ptr[qlt->preq_ndx_to_fw << 6]);
3275 }
3276
3277 /*
3278 * updates the req in ptr to fw. Assumes that req lock is held.
3279 */
3280 void
qlt_submit_preq_entries(qlt_state_t * qlt,uint32_t n)3281 qlt_submit_preq_entries(qlt_state_t *qlt, uint32_t n)
3282 {
3283 ASSERT(n >= 1);
3284 qlt->preq_ndx_to_fw += n;
3285 qlt->preq_ndx_to_fw &= PRIORITY_QUEUE_ENTRIES - 1;
3286 REG_WR32(qlt, REG_PREQ_IN_PTR, qlt->preq_ndx_to_fw);
3287 }
3288
3289 /*
3290 * - Should not be called from Interrupt.
3291 * - A very hardware specific function. Does not touch driver state.
3292 * - Assumes that interrupts are disabled or not there.
3293 * - Expects that the caller makes sure that all activity has stopped
3294 * and its ok now to go ahead and reset the chip. Also the caller
3295 * takes care of post reset damage control.
3296 * - called by initialize adapter() and dump_fw(for reset only).
3297 * - During attach() nothing much is happening and during initialize_adapter()
3298 * the function (caller) does all the housekeeping so that this function
3299 * can execute in peace.
3300 * - Returns 0 on success.
3301 */
3302 static fct_status_t
qlt_reset_chip(qlt_state_t * qlt)3303 qlt_reset_chip(qlt_state_t *qlt)
3304 {
3305 int cntr;
3306
3307 EL(qlt, "initiated\n");
3308
3309 /* XXX: Switch off LEDs */
3310
3311 qlt->qlt_intr_enabled = 0;
3312 /* Disable Interrupts */
3313 REG_WR32(qlt, REG_INTR_CTRL, 0);
3314 (void) REG_RD32(qlt, REG_INTR_CTRL);
3315 /* Stop DMA */
3316 REG_WR32(qlt, REG_CTRL_STATUS, DMA_SHUTDOWN_CTRL | PCI_X_XFER_CTRL);
3317
3318 /* Wait for DMA to be stopped */
3319 cntr = 0;
3320 while (REG_RD32(qlt, REG_CTRL_STATUS) & DMA_ACTIVE_STATUS) {
3321 delay(drv_usectohz(10000)); /* mostly 10ms is 1 tick */
3322 cntr++;
3323 /* 3 sec should be more than enough */
3324 if (cntr == 300)
3325 return (QLT_DMA_STUCK);
3326 }
3327
3328 /* need to ensure no one accesses the hw during the reset 100us */
3329 if ((qlt->qlt_83xx_chip) || (qlt->qlt_27xx_chip)) {
3330 mutex_enter(&qlt->mbox_lock);
3331 if (qlt->qlt_mq_enabled == 1) {
3332 int i;
3333
3334 for (i = 1; i < qlt->qlt_queue_cnt; i++) {
3335 mutex_enter(&qlt->mq_req[i].mq_lock);
3336 }
3337 }
3338 mutex_enter(&qlt->mq_req[0].mq_lock);
3339 /*
3340 * We need to give time for other threads to finsh their
3341 * interupts (or we need another lock)
3342 */
3343 drv_usecwait(40);
3344 }
3345
3346 /* Reset the Chip */
3347 REG_WR32(qlt, REG_CTRL_STATUS,
3348 DMA_SHUTDOWN_CTRL | PCI_X_XFER_CTRL | CHIP_SOFT_RESET);
3349
3350 qlt->qlt_link_up = 0;
3351
3352 drv_usecwait(100);
3353
3354 if ((qlt->qlt_83xx_chip) || (qlt->qlt_27xx_chip)) {
3355 mutex_exit(&qlt->mq_req[0].mq_lock);
3356 if (qlt->qlt_mq_enabled == 1) {
3357 int i;
3358
3359 for (i = 1; i < qlt->qlt_queue_cnt; i++) {
3360 mutex_exit(&qlt->mq_req[i].mq_lock);
3361 }
3362 }
3363 mutex_exit(&qlt->mbox_lock);
3364 }
3365
3366 /* Wait for ROM firmware to initialize (0x0000) in mailbox 0 */
3367 cntr = 0;
3368 while (REG_RD16(qlt, REG_MBOX(0)) != 0) {
3369 delay(drv_usectohz(10000));
3370 cntr++;
3371 /* 3 sec should be more than enough */
3372 if (cntr == 300)
3373 return (QLT_ROM_STUCK);
3374 }
3375 /* Disable Interrupts (Probably not needed) */
3376 REG_WR32(qlt, REG_INTR_CTRL, 0);
3377
3378 return (QLT_SUCCESS);
3379 }
3380
3381 /*
3382 * - Should not be called from Interrupt.
3383 * - A very hardware specific function. Does not touch driver state.
3384 * - Assumes that interrupts are disabled or not there.
3385 * - Expects that the caller makes sure that all activity has stopped
3386 * and its ok now to go ahead and reset the chip. Also the caller
3387 * takes care of post reset damage control.
3388 * - called by initialize adapter() and dump_fw(for reset only).
3389 * - During attach() nothing much is happening and during initialize_adapter()
3390 * the function (caller) does all the housekeeping so that this function
3391 * can execute in peace.
3392 * - Returns 0 on success.
3393 */
3394 static fct_status_t
qlt_download_fw(qlt_state_t * qlt)3395 qlt_download_fw(qlt_state_t *qlt)
3396 {
3397 uint32_t start_addr;
3398 fct_status_t ret;
3399
3400 EL(qlt, "initiated\n");
3401
3402 (void) qlt_reset_chip(qlt);
3403
3404 if (qlt->qlt_81xx_chip) {
3405 qlt_mps_reset(qlt);
3406 }
3407
3408 /* Load the two segments */
3409 if (qlt->fw_code01 != NULL) {
3410 ret = qlt_load_risc_ram(qlt, qlt->fw_code01, qlt->fw_length01,
3411 qlt->fw_addr01);
3412 if (ret == QLT_SUCCESS) {
3413 ret = qlt_load_risc_ram(qlt, qlt->fw_code02,
3414 qlt->fw_length02, qlt->fw_addr02);
3415 }
3416 start_addr = qlt->fw_addr01;
3417 } else if (qlt->qlt_27xx_chip) {
3418 (void) qlt_27xx_get_dmp_template(qlt);
3419 ret = qlt_load_risc_ram(qlt, fw2700_code01,
3420 fw2700_length01, fw2700_addr01);
3421 if (ret == QLT_SUCCESS) {
3422 ret = qlt_load_risc_ram(qlt, fw2700_code02,
3423 fw2700_length02, fw2700_addr02);
3424 }
3425 start_addr = fw2700_addr01;
3426 } else if (qlt->qlt_83xx_chip) {
3427 ret = qlt_load_risc_ram(qlt, fw8300fc_code01,
3428 fw8300fc_length01, fw8300fc_addr01);
3429 if (ret == QLT_SUCCESS) {
3430 ret = qlt_load_risc_ram(qlt, fw8300fc_code02,
3431 fw8300fc_length02, fw8300fc_addr02);
3432 }
3433 start_addr = fw8300fc_addr01;
3434 } else if (qlt->qlt_81xx_chip) {
3435 ret = qlt_load_risc_ram(qlt, fw8100_code01, fw8100_length01,
3436 fw8100_addr01);
3437 if (ret == QLT_SUCCESS) {
3438 ret = qlt_load_risc_ram(qlt, fw8100_code02,
3439 fw8100_length02, fw8100_addr02);
3440 }
3441 start_addr = fw8100_addr01;
3442 } else if (qlt->qlt_25xx_chip) {
3443 ret = qlt_load_risc_ram(qlt, fw2500_code01, fw2500_length01,
3444 fw2500_addr01);
3445 if (ret == QLT_SUCCESS) {
3446 ret = qlt_load_risc_ram(qlt, fw2500_code02,
3447 fw2500_length02, fw2500_addr02);
3448 }
3449 start_addr = fw2500_addr01;
3450 } else {
3451 ret = qlt_load_risc_ram(qlt, fw2400_code01, fw2400_length01,
3452 fw2400_addr01);
3453 if (ret == QLT_SUCCESS) {
3454 ret = qlt_load_risc_ram(qlt, fw2400_code02,
3455 fw2400_length02, fw2400_addr02);
3456 }
3457 start_addr = fw2400_addr01;
3458 }
3459 if (ret != QLT_SUCCESS) {
3460 EL(qlt, "qlt_load_risc_ram status=%llxh\n", ret);
3461 return (ret);
3462 }
3463
3464 /* Verify Checksum */
3465 REG_WR16(qlt, REG_MBOX(0), MBC_VERIFY_CHECKSUM);
3466 REG_WR16(qlt, REG_MBOX(1), MSW(start_addr));
3467 REG_WR16(qlt, REG_MBOX(2), LSW(start_addr));
3468 ret = qlt_raw_mailbox_command(qlt);
3469 REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
3470 if (ret != QLT_SUCCESS) {
3471 EL(qlt, "qlt_raw_mailbox_command=7h status=%llxh\n", ret);
3472 return (ret);
3473 }
3474
3475 /* Execute firmware */
3476 REG_WR16(qlt, REG_MBOX(0), MBC_EXECUTE_FIRMWARE);
3477 REG_WR16(qlt, REG_MBOX(1), MSW(start_addr));
3478 REG_WR16(qlt, REG_MBOX(2), LSW(start_addr));
3479 REG_WR16(qlt, REG_MBOX(3), 0);
3480 #ifdef EXTRA_CREDIT
3481 /* enable extra credits (reduces available buffers) */
3482 if ((qlt->qlt_25xx_chip) || (qlt->qlt_81xx_chip) ||
3483 (qlt->qlt_83xx_chip) || (qlt->qlt_27xx_chip)) {
3484 REG_WR16(qlt, REG_MBOX(4), 1);
3485 } else {
3486 REG_WR16(qlt, REG_MBOX(4), 0);
3487 }
3488 #else
3489 REG_WR16(qlt, REG_MBOX(4), 0);
3490 #endif
3491 ret = qlt_raw_mailbox_command(qlt);
3492 REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
3493 if (ret != QLT_SUCCESS) {
3494 EL(qlt, "qlt_raw_mailbox_command=2h status=%llxh\n", ret);
3495 return (ret);
3496 } else {
3497 if (qlt->qlt_27xx_chip) {
3498 qlt->qlt_27xx_speed = (uint32_t)
3499 (REG_RD16(qlt, REG_MBOX(3)) << 16 |
3500 REG_RD16(qlt, REG_MBOX(2)));
3501
3502 }
3503 }
3504
3505 /* Get revisions (About Firmware) */
3506 REG_WR16(qlt, REG_MBOX(0), MBC_ABOUT_FIRMWARE);
3507 ret = qlt_raw_mailbox_command(qlt);
3508 qlt->fw_major = REG_RD16(qlt, REG_MBOX(1));
3509 qlt->fw_minor = REG_RD16(qlt, REG_MBOX(2));
3510 qlt->fw_subminor = REG_RD16(qlt, REG_MBOX(3));
3511 qlt->fw_endaddrlo = REG_RD16(qlt, REG_MBOX(4));
3512 qlt->fw_endaddrhi = REG_RD16(qlt, REG_MBOX(5));
3513 qlt->fw_attr = REG_RD16(qlt, REG_MBOX(6));
3514 REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
3515 if (ret != QLT_SUCCESS) {
3516 EL(qlt, "qlt_raw_mailbox_command=8h status=%llxh\n", ret);
3517 return (ret);
3518 }
3519
3520 if (qlt->qlt_27xx_chip) {
3521 qlt->fw_ext_memory_end = SHORT_TO_LONG(
3522 REG_RD16(qlt, REG_MBOX(4)),
3523 REG_RD16(qlt, REG_MBOX(5)));
3524 qlt->fw_shared_ram_start = SHORT_TO_LONG(
3525 REG_RD16(qlt, REG_MBOX(18)),
3526 REG_RD16(qlt, REG_MBOX(19)));
3527 qlt->fw_shared_ram_end = SHORT_TO_LONG(
3528 REG_RD16(qlt, REG_MBOX(20)),
3529 REG_RD16(qlt, REG_MBOX(21)));
3530 qlt->fw_ddr_ram_start = SHORT_TO_LONG(
3531 REG_RD16(qlt, REG_MBOX(22)),
3532 REG_RD16(qlt, REG_MBOX(23)));
3533 qlt->fw_ddr_ram_end = SHORT_TO_LONG(
3534 REG_RD16(qlt, REG_MBOX(24)),
3535 REG_RD16(qlt, REG_MBOX(25)));
3536 }
3537
3538
3539 return (QLT_SUCCESS);
3540 }
3541
3542 /*
3543 * Used only from qlt_download_fw().
3544 */
3545 static fct_status_t
qlt_load_risc_ram(qlt_state_t * qlt,uint32_t * host_addr,uint32_t word_count,uint32_t risc_addr)3546 qlt_load_risc_ram(qlt_state_t *qlt, uint32_t *host_addr,
3547 uint32_t word_count, uint32_t risc_addr)
3548 {
3549 uint32_t words_sent = 0;
3550 uint32_t words_being_sent;
3551 uint32_t *cur_host_addr;
3552 uint32_t cur_risc_addr;
3553 uint64_t da;
3554 fct_status_t ret;
3555
3556 while (words_sent < word_count) {
3557 cur_host_addr = &(host_addr[words_sent]);
3558 cur_risc_addr = risc_addr + (words_sent << 2);
3559 words_being_sent = min(word_count - words_sent,
3560 TOTAL_DMA_MEM_SIZE >> 2);
3561 ddi_rep_put32(qlt->queue_mem_acc_handle, cur_host_addr,
3562 (uint32_t *)qlt->queue_mem_ptr, words_being_sent,
3563 DDI_DEV_AUTOINCR);
3564 (void) ddi_dma_sync(qlt->queue_mem_dma_handle, 0,
3565 words_being_sent << 2, DDI_DMA_SYNC_FORDEV);
3566 da = qlt->queue_mem_cookie.dmac_laddress;
3567 REG_WR16(qlt, REG_MBOX(0), MBC_LOAD_RAM_EXTENDED);
3568 REG_WR16(qlt, REG_MBOX(1), LSW(risc_addr));
3569 REG_WR16(qlt, REG_MBOX(8), MSW(cur_risc_addr));
3570 REG_WR16(qlt, REG_MBOX(3), LSW(LSD(da)));
3571 REG_WR16(qlt, REG_MBOX(2), MSW(LSD(da)));
3572 REG_WR16(qlt, REG_MBOX(7), LSW(MSD(da)));
3573 REG_WR16(qlt, REG_MBOX(6), MSW(MSD(da)));
3574 REG_WR16(qlt, REG_MBOX(5), LSW(words_being_sent));
3575 REG_WR16(qlt, REG_MBOX(4), MSW(words_being_sent));
3576 ret = qlt_raw_mailbox_command(qlt);
3577 REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
3578 if (ret != QLT_SUCCESS) {
3579 EL(qlt, "qlt_raw_mailbox_command=0Bh status=%llxh\n",
3580 ret);
3581 return (ret);
3582 }
3583 words_sent += words_being_sent;
3584 }
3585 EL(qlt, "qlt_raw_mailbox_command=0Bh, LOAD_RAM_EXTENDED complete\n");
3586 return (QLT_SUCCESS);
3587 }
3588
3589 /*
3590 * Not used during normal operation. Only during driver init.
3591 * Assumes that interrupts are disabled and mailboxes are loaded.
3592 * Just triggers the mailbox command an waits for the completion.
3593 * Also expects that There is nothing else going on and we will only
3594 * get back a mailbox completion from firmware.
3595 * ---DOES NOT CLEAR INTERRUPT---
3596 * Used only from the code path originating from
3597 * qlt_reset_chip()
3598 */
3599 static fct_status_t
qlt_raw_mailbox_command(qlt_state_t * qlt)3600 qlt_raw_mailbox_command(qlt_state_t *qlt)
3601 {
3602 int cntr = 0;
3603 uint32_t status;
3604 fct_local_port_t *port = qlt->qlt_port;
3605
3606 REG_WR32(qlt, REG_HCCR, HCCR_CMD(SET_HOST_TO_RISC_INTR));
3607 retry_raw:;
3608 while ((REG_RD32(qlt, REG_INTR_STATUS) & RISC_PCI_INTR_REQUEST) == 0) {
3609 cntr++;
3610 if (cntr == 3000) {
3611 EL(qlt, "polling exhausted, dump fw now..\n");
3612 (void) qlt_firmware_dump(port,
3613 (stmf_state_change_info_t *)NULL);
3614 return (QLT_MAILBOX_STUCK);
3615 }
3616 delay(drv_usectohz(10000));
3617 }
3618 status = (REG_RD32(qlt, REG_RISC_STATUS) & FW_INTR_STATUS_MASK);
3619
3620 if ((status == ROM_MBX_CMD_SUCCESSFUL) ||
3621 (status == ROM_MBX_CMD_NOT_SUCCESSFUL) ||
3622 (status == MBX_CMD_SUCCESSFUL) ||
3623 (status == MBX_CMD_NOT_SUCCESSFUL)) {
3624 uint16_t mbox0 = REG_RD16(qlt, REG_MBOX(0));
3625 if (mbox0 == QLT_MBX_CMD_SUCCESS) {
3626 return (QLT_SUCCESS);
3627 } else {
3628 EL(qlt, "mbx cmd failed, dump fw now..\n");
3629 (void) qlt_firmware_dump(port,
3630 (stmf_state_change_info_t *)NULL);
3631 return (QLT_MBOX_FAILED | mbox0);
3632 }
3633 } else if (status == ASYNC_EVENT) {
3634 uint16_t mbox0, mbox1, mbox2, mbox3;
3635 uint16_t mbox4, mbox5, mbox6, mbox7;
3636
3637 mbox0 = REG_RD16(qlt, REG_MBOX(0));
3638 mbox1 = REG_RD16(qlt, REG_MBOX(1));
3639 mbox2 = REG_RD16(qlt, REG_MBOX(2));
3640 mbox3 = REG_RD16(qlt, REG_MBOX(3));
3641 mbox4 = REG_RD16(qlt, REG_MBOX(4));
3642 mbox5 = REG_RD16(qlt, REG_MBOX(5));
3643 mbox6 = REG_RD16(qlt, REG_MBOX(6));
3644 mbox7 = REG_RD16(qlt, REG_MBOX(7));
3645
3646 cmn_err(CE_NOTE, "!qlt(%d): Async event %x mb1=%x mb2=%x"
3647 "mb3=%x mb4=%x mb5=%x mb6=%x mb7=%x",
3648 qlt->instance, mbox0, mbox1, mbox2, mbox3,
3649 mbox4, mbox5, mbox6, mbox7);
3650 if (mbox0 == 0x8002) {
3651 (void) qlt_firmware_dump(port,
3652 (stmf_state_change_info_t *)NULL);
3653 return (QLT_UNEXPECTED_RESPONSE);
3654 } else {
3655 REG_WR32(qlt,
3656 REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
3657 cntr = 0;
3658 goto retry_raw;
3659 }
3660 }
3661
3662 /* This is unexpected, dump a message */
3663 cmn_err(CE_WARN, "qlt(%d): Unexpect intr status %llx",
3664 ddi_get_instance(qlt->dip), (unsigned long long)status);
3665 return (QLT_UNEXPECTED_RESPONSE);
3666 }
3667
3668 static mbox_cmd_t *
qlt_alloc_mailbox_command(qlt_state_t * qlt,uint32_t dma_size)3669 qlt_alloc_mailbox_command(qlt_state_t *qlt, uint32_t dma_size)
3670 {
3671 mbox_cmd_t *mcp;
3672
3673 mcp = (mbox_cmd_t *)kmem_zalloc(sizeof (mbox_cmd_t), KM_SLEEP);
3674 if (dma_size) {
3675 qlt_dmem_bctl_t *bctl;
3676 uint64_t da;
3677
3678 mcp->dbuf = qlt_i_dmem_alloc(qlt, dma_size, &dma_size, 0);
3679 if (mcp->dbuf == NULL) {
3680 kmem_free(mcp, sizeof (*mcp));
3681 return (NULL);
3682 }
3683 mcp->dbuf->db_data_size = dma_size;
3684 ASSERT(mcp->dbuf->db_sglist_length == 1);
3685
3686 bctl = (qlt_dmem_bctl_t *)mcp->dbuf->db_port_private;
3687 da = bctl->bctl_dev_addr;
3688 /* This is the most common initialization of dma ptrs */
3689 mcp->to_fw[3] = LSW(LSD(da));
3690 mcp->to_fw[2] = MSW(LSD(da));
3691 mcp->to_fw[7] = LSW(MSD(da));
3692 mcp->to_fw[6] = MSW(MSD(da));
3693 mcp->to_fw_mask |= BIT_2 | BIT_3 | BIT_7 | BIT_6;
3694 }
3695 mcp->to_fw_mask |= BIT_0;
3696 mcp->from_fw_mask |= BIT_0;
3697 return (mcp);
3698 }
3699
3700 void
qlt_free_mailbox_command(qlt_state_t * qlt,mbox_cmd_t * mcp)3701 qlt_free_mailbox_command(qlt_state_t *qlt, mbox_cmd_t *mcp)
3702 {
3703 if (mcp->dbuf)
3704 qlt_i_dmem_free(qlt, mcp->dbuf);
3705 kmem_free(mcp, sizeof (*mcp));
3706 }
3707
3708 /*
3709 * This can sleep. Should never be called from interrupt context.
3710 */
3711 static fct_status_t
qlt_mailbox_command(qlt_state_t * qlt,mbox_cmd_t * mcp)3712 qlt_mailbox_command(qlt_state_t *qlt, mbox_cmd_t *mcp)
3713 {
3714 int retries;
3715 int i;
3716 char info[80];
3717
3718 if (curthread->t_flag & T_INTR_THREAD) {
3719 ASSERT(0);
3720 return (QLT_MBOX_FAILED);
3721 }
3722
3723 EL(qlt, "mailbox:[0]=%xh [1]=%xh\n",
3724 mcp->to_fw[0], mcp->to_fw[1]);
3725
3726 mutex_enter(&qlt->mbox_lock);
3727 /* See if mailboxes are still uninitialized */
3728 if (qlt->mbox_io_state == MBOX_STATE_UNKNOWN) {
3729 mutex_exit(&qlt->mbox_lock);
3730 return (QLT_MBOX_NOT_INITIALIZED);
3731 }
3732
3733 /* Wait to grab the mailboxes */
3734 for (retries = 0; qlt->mbox_io_state != MBOX_STATE_READY;
3735 retries++) {
3736 cv_wait(&qlt->mbox_cv, &qlt->mbox_lock);
3737 if ((retries > 5) ||
3738 (qlt->mbox_io_state == MBOX_STATE_UNKNOWN)) {
3739 mutex_exit(&qlt->mbox_lock);
3740 return (QLT_MBOX_BUSY);
3741 }
3742 }
3743 /* Make sure we always ask for mailbox 0 */
3744 mcp->from_fw_mask |= BIT_0;
3745
3746 /* Load mailboxes, set state and generate RISC interrupt */
3747 qlt->mbox_io_state = MBOX_STATE_CMD_RUNNING;
3748 qlt->mcp = mcp;
3749 for (i = 0; i < MAX_MBOXES; i++) {
3750 if (mcp->to_fw_mask & ((uint32_t)1 << i))
3751 REG_WR16(qlt, REG_MBOX(i), mcp->to_fw[i]);
3752 }
3753 REG_WR32(qlt, REG_HCCR, HCCR_CMD(SET_HOST_TO_RISC_INTR));
3754
3755 qlt_mbox_wait_loop:;
3756 /* Wait for mailbox command completion */
3757 if (cv_timedwait(&qlt->mbox_cv, &qlt->mbox_lock, ddi_get_lbolt()
3758 + drv_usectohz(MBOX_TIMEOUT)) < 0) {
3759 (void) snprintf(info, 80, "qlt_mailbox_command: qlt-%p, "
3760 "cmd-0x%02X timed out", (void *)qlt, qlt->mcp->to_fw[0]);
3761 info[79] = 0;
3762 qlt->mcp = NULL;
3763 qlt->mbox_io_state = MBOX_STATE_UNKNOWN;
3764 mutex_exit(&qlt->mbox_lock);
3765
3766 /*
3767 * XXX Throw HBA fatal error event
3768 */
3769 (void) fct_port_shutdown(qlt->qlt_port, STMF_RFLAG_FATAL_ERROR |
3770 STMF_RFLAG_RESET | STMF_RFLAG_COLLECT_DEBUG_DUMP, info);
3771 return (QLT_MBOX_TIMEOUT);
3772 }
3773 if (qlt->mbox_io_state == MBOX_STATE_CMD_RUNNING)
3774 goto qlt_mbox_wait_loop;
3775
3776 qlt->mcp = NULL;
3777
3778 /* Make sure its a completion */
3779 if (qlt->mbox_io_state != MBOX_STATE_CMD_DONE) {
3780 ASSERT(qlt->mbox_io_state == MBOX_STATE_UNKNOWN);
3781 mutex_exit(&qlt->mbox_lock);
3782 return (QLT_MBOX_ABORTED);
3783 }
3784
3785 /* MBox command completed. Clear state, retuen based on mbox 0 */
3786 /* Mailboxes are already loaded by interrupt routine */
3787 qlt->mbox_io_state = MBOX_STATE_READY;
3788 mutex_exit(&qlt->mbox_lock);
3789 if (mcp->from_fw[0] != QLT_MBX_CMD_SUCCESS) {
3790 EL(qlt, "fw[0] = %xh\n", mcp->from_fw[0]);
3791 if ((mcp->from_fw[0] != 0x4005) &&
3792 (mcp->from_fw[1] != 0x7)) {
3793 (void) qlt_firmware_dump(qlt->qlt_port,
3794 (stmf_state_change_info_t *)NULL);
3795 }
3796 return (QLT_MBOX_FAILED | mcp->from_fw[0]);
3797 }
3798
3799 return (QLT_SUCCESS);
3800 }
3801
3802 /*
3803 * **SHOULD ONLY BE CALLED FROM INTERRUPT CONTEXT. DO NOT CALL ELSEWHERE**
3804 */
3805 /* ARGSUSED */
3806 static uint_t
qlt_msix_resp_handler(caddr_t arg,caddr_t arg2)3807 qlt_msix_resp_handler(caddr_t arg, caddr_t arg2)
3808 {
3809 qlt_state_t *qlt = (qlt_state_t *)arg;
3810 uint32_t risc_status;
3811 uint16_t qi = 0;
3812
3813 risc_status = REG_RD32(qlt, REG_RISC_STATUS);
3814 if (qlt->qlt_mq_enabled) {
3815 /* XXX: */
3816 /* qi = (uint16_t)((unsigned long)arg2); */
3817 qi = (uint16_t)(risc_status >> 16);
3818
3819 mutex_enter(&qlt->mq_resp[qi].mq_lock);
3820 if (!qlt->qlt_intr_enabled) {
3821 /*
3822 * No further interrupt since intr disabled.
3823 */
3824 REG_WR32(qlt, REG_HCCR,
3825 HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
3826 mutex_exit(&qlt->mq_resp[qi].mq_lock);
3827 return (DDI_INTR_UNCLAIMED);
3828 }
3829
3830 qlt->mq_resp[qi].mq_ndx_from_fw =
3831 (uint16_t)MQBAR_RD32(qlt,
3832 (qi * MQBAR_REG_OFFSET) + MQBAR_RESP_IN);
3833
3834 qlt_handle_resp_queue_update(qlt, qi);
3835 mutex_exit(&qlt->mq_resp[qi].mq_lock);
3836 } else {
3837 mutex_enter(&qlt->intr_lock);
3838 if (!qlt->qlt_intr_enabled) {
3839 /*
3840 * No further interrupt since intr disabled.
3841 */
3842 REG_WR32(qlt, REG_HCCR,
3843 HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
3844 mutex_exit(&qlt->intr_lock);
3845 return (DDI_INTR_UNCLAIMED);
3846 }
3847
3848 qlt->atio_ndx_from_fw =
3849 (uint16_t)REG_RD32(qlt, REG_ATIO_IN_PTR);
3850 qlt_handle_atio_queue_update(qlt);
3851
3852 qlt->mq_resp[qi].mq_ndx_from_fw = risc_status >> 16;
3853 qlt_handle_resp_queue_update(qlt, qi);
3854 mutex_exit(&qlt->intr_lock);
3855 }
3856
3857 if (risc_status & BIT_15) {
3858 REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
3859 }
3860 return (DDI_INTR_CLAIMED);
3861 }
3862
3863
3864 /*
3865 * **SHOULD ONLY BE CALLED FROM INTERRUPT CONTEXT. DO NOT CALL ELSEWHERE**
3866 */
3867 /* ARGSUSED */
3868 static uint_t
qlt_msix_default_handler(caddr_t arg,caddr_t arg2)3869 qlt_msix_default_handler(caddr_t arg, caddr_t arg2)
3870 {
3871 qlt_state_t *qlt = (qlt_state_t *)arg;
3872 uint32_t risc_status, intr_type;
3873 int i;
3874 char info[80];
3875
3876 risc_status = REG_RD32(qlt, REG_RISC_STATUS);
3877 if (!mutex_tryenter(&qlt->intr_lock)) {
3878 /*
3879 * Normally we will always get this lock. If tryenter is
3880 * failing then it means that driver is trying to do
3881 * some cleanup and is masking the intr but some intr
3882 * has sneaked in between. See if our device has generated
3883 * this intr. If so then wait a bit and return claimed.
3884 * If not then return claimed if this is the 1st instance
3885 * of a interrupt after driver has grabbed the lock.
3886 */
3887 if ((risc_status & BIT_15) == 0) {
3888 return (DDI_INTR_UNCLAIMED);
3889 } else {
3890 /* try again */
3891 drv_usecwait(10);
3892 if (!mutex_tryenter(&qlt->intr_lock)) {
3893 /* really bad! */
3894 return (DDI_INTR_CLAIMED);
3895 }
3896 }
3897 }
3898 if (((risc_status & BIT_15) == 0) ||
3899 (qlt->qlt_intr_enabled == 0)) {
3900 /*
3901 * This might be a pure coincedence that we are operating
3902 * in a interrupt disabled mode and another device
3903 * sharing the interrupt line has generated an interrupt
3904 * while an interrupt from our device might be pending. Just
3905 * ignore it and let the code handling the interrupt
3906 * disabled mode handle it.
3907 */
3908 mutex_exit(&qlt->intr_lock);
3909 return (DDI_INTR_UNCLAIMED);
3910 }
3911
3912 /* REG_WR32(qlt, REG_INTR_CTRL, 0); */
3913
3914 /* check for risc pause - unlikely */
3915 if (risc_status & BIT_8) {
3916 uint32_t hccsr;
3917
3918 hccsr = REG_RD32(qlt, REG_HCCR);
3919 EL(qlt, "Risc Pause status=%xh hccsr=%x\n",
3920 risc_status, hccsr);
3921 cmn_err(CE_WARN, "qlt(%d): Risc Pause %08x hccsr:%x",
3922 qlt->instance, risc_status, hccsr);
3923 (void) snprintf(info, 80, "Risc Pause %08x hccsr:%x",
3924 risc_status, hccsr);
3925 info[79] = 0;
3926 (void) fct_port_shutdown(qlt->qlt_port,
3927 STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET |
3928 STMF_RFLAG_COLLECT_DEBUG_DUMP, info);
3929 }
3930
3931 /* check most likely types first */
3932 intr_type = risc_status & 0xff;
3933 if (intr_type == 0x1D) {
3934 qlt->atio_ndx_from_fw =
3935 (uint16_t)REG_RD32(qlt, REG_ATIO_IN_PTR);
3936 qlt_handle_atio_queue_update(qlt);
3937 qlt->mq_resp[0].mq_ndx_from_fw = risc_status >> 16;
3938 qlt_handle_resp_queue_update(qlt, 0);
3939 REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
3940 } else if (intr_type == 0x1C) {
3941 qlt->atio_ndx_from_fw = (uint16_t)(risc_status >> 16);
3942 qlt_handle_atio_queue_update(qlt);
3943 REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
3944 } else if (intr_type == 0x1E) {
3945 /* 83xx */
3946 qlt->atio_ndx_from_fw =
3947 (uint16_t)MQBAR_RD32(qlt, MQBAR_ATIO_IN);
3948 qlt_handle_atio_queue_update(qlt);
3949 REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
3950 } else if (intr_type == 0x13) {
3951 uint16_t qi;
3952
3953 qlt->atio_ndx_from_fw =
3954 (uint16_t)REG_RD32(qlt, REG_ATIO_IN_PTR);
3955 qlt_handle_atio_queue_update(qlt);
3956
3957 if (qlt->qlt_mq_enabled) {
3958 qi = (uint16_t)(risc_status >> 16);
3959 qlt->mq_resp[qi].mq_ndx_from_fw =
3960 (uint16_t)MQBAR_RD32(qlt,
3961 (qi * MQBAR_REG_OFFSET) + MQBAR_RESP_IN);
3962 /* FIX THIS to be optional */
3963 REG_WR32(qlt, REG_HCCR,
3964 HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
3965 } else {
3966 qi = 0;
3967 REG_WR32(qlt, REG_HCCR,
3968 HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
3969 qlt->mq_resp[qi].mq_ndx_from_fw = risc_status >> 16;
3970 }
3971 qlt_handle_resp_queue_update(qlt, qi);
3972
3973 } else if (intr_type == 0x14) {
3974 uint16_t qi = (uint16_t)(risc_status >> 16);
3975
3976 if ((qlt->qlt_83xx_chip) || (qlt->qlt_27xx_chip)) {
3977 qlt->atio_ndx_from_fw =
3978 (uint16_t)MQBAR_RD32(qlt, MQBAR_ATIO_IN);
3979 } else {
3980 qlt->atio_ndx_from_fw = (uint16_t)
3981 REG_RD32(qlt, REG_ATIO_IN_PTR);
3982 }
3983 qlt_handle_atio_queue_update(qlt);
3984
3985 qlt->mq_resp[qi].mq_ndx_from_fw =
3986 (uint16_t)MQBAR_RD32(qlt,
3987 (qi * MQBAR_REG_OFFSET) + MQBAR_RESP_IN);
3988 qlt_handle_resp_queue_update(qlt, qi);
3989
3990 REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
3991
3992 } else if (intr_type == 0x12) {
3993 uint16_t code, mbox1, mbox2, mbox3, mbox4, mbox5, mbox6;
3994
3995 REG_WR32(qlt, REG_INTR_CTRL, 0);
3996
3997 code = (uint16_t)(risc_status >> 16);
3998 mbox1 = REG_RD16(qlt, REG_MBOX(1));
3999 mbox2 = REG_RD16(qlt, REG_MBOX(2));
4000 mbox3 = REG_RD16(qlt, REG_MBOX(3));
4001 mbox4 = REG_RD16(qlt, REG_MBOX(4));
4002 mbox5 = REG_RD16(qlt, REG_MBOX(5));
4003 mbox6 = REG_RD16(qlt, REG_MBOX(6));
4004
4005 REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
4006 EL(qlt, "Async event: %x mb1=%x mb2=%x,"
4007 " mb3=%x, mb4=%x, mb5=%x, mb6=%x", code, mbox1, mbox2,
4008 mbox3, mbox4, mbox5, mbox6);
4009 stmf_trace(qlt->qlt_port_alias, "Async event: %x mb1=%x mb2=%x,"
4010 " mb3=%x, mb4=%x, mb5=%x, mb6=%x", code, mbox1, mbox2,
4011 mbox3, mbox4, mbox5, mbox6);
4012 cmn_err(CE_NOTE, "!qlt(%d): Async event %x mb1=%x mb2=%x,"
4013 " mb3=%x, mb4=%x, mb5=%x, mb6=%x", qlt->instance, code,
4014 mbox1, mbox2, mbox3, mbox4, mbox5, mbox6);
4015
4016 if ((code == 0x8030) || (code == 0x8010) || (code == 0x8013)) {
4017 if (qlt->qlt_link_up) {
4018 fct_handle_event(qlt->qlt_port,
4019 FCT_EVENT_LINK_RESET, 0, 0);
4020 }
4021 } else if (code == 0x8012) {
4022 qlt->qlt_link_up = 0;
4023 fct_handle_event(qlt->qlt_port, FCT_EVENT_LINK_DOWN,
4024 0, 0);
4025 } else if (code == 0x8014) {
4026 if (mbox1 == 0xffff) { /* global event */
4027 uint8_t reason_code;
4028
4029 reason_code = (uint8_t)(mbox3 >> 8);
4030
4031 switch (reason_code) {
4032 case 0x1d: /* FIP Clear Virtual Link received */
4033 case 0x1a: /* received FLOGO */
4034 case 0x1c: /* FCF configuration changed */
4035 case 0x1e: /* FKA timeout */
4036 if (mbox2 == 7) {
4037 qlt->qlt_link_up = 0;
4038 fct_handle_event(qlt->qlt_port,
4039 FCT_EVENT_LINK_DOWN, 0, 0);
4040 }
4041 break;
4042 case 0x12:
4043 if (mbox2 == 4) {
4044 qlt->qlt_link_up = 1;
4045 fct_handle_event(qlt->qlt_port,
4046 FCT_EVENT_LINK_UP, 0, 0);
4047 stmf_trace(qlt->qlt_port_alias,
4048 "SNS login and SCR done");
4049 }
4050 break;
4051 case 0:
4052 if ((mbox2 == 6) &&
4053 (!qlt->qlt_link_up)) {
4054 qlt->qlt_link_up = 1;
4055 fct_handle_event(qlt->qlt_port,
4056 FCT_EVENT_LINK_UP, 0, 0);
4057 stmf_trace(qlt->qlt_port_alias,
4058 "Link reinitialised");
4059 }
4060 break;
4061 default:
4062 stmf_trace(qlt->qlt_port_alias,
4063 "AEN ignored");
4064 break;
4065 }
4066 }
4067 } else if (code == 0x8011) {
4068 switch (mbox1) {
4069 case 0: qlt->link_speed = PORT_SPEED_1G;
4070 break;
4071 case 1: qlt->link_speed = PORT_SPEED_2G;
4072 break;
4073 case 3: qlt->link_speed = PORT_SPEED_4G;
4074 break;
4075 case 4: qlt->link_speed = PORT_SPEED_8G;
4076 break;
4077 case 5: qlt->link_speed = PORT_SPEED_16G;
4078 break;
4079 case 0x13: qlt->link_speed = PORT_SPEED_10G;
4080 break;
4081 default:
4082 qlt->link_speed = PORT_SPEED_UNKNOWN;
4083 }
4084 qlt->qlt_link_up = 1;
4085 fct_handle_event(qlt->qlt_port, FCT_EVENT_LINK_UP,
4086 0, 0);
4087 } else if ((code == 0x8002) || (code == 0x8003) ||
4088 (code == 0x8004) || (code == 0x8005)) {
4089 (void) snprintf(info, 80,
4090 "Got %04x, mb1=%x mb2=%x mb5=%x mb6=%x",
4091 code, mbox1, mbox2, mbox5, mbox6);
4092 info[79] = 0;
4093 (void) fct_port_shutdown(qlt->qlt_port,
4094 STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET |
4095 STMF_RFLAG_COLLECT_DEBUG_DUMP, info);
4096 } else if (code == 0x800F) {
4097 (void) snprintf(info, 80,
4098 "Got 800F, mb1=%x mb2=%x mb3=%x",
4099 mbox1, mbox2, mbox3);
4100
4101 if (mbox1 != 1) {
4102 /* issue "verify fw" */
4103 qlt_verify_fw(qlt);
4104 }
4105 } else if (code == 0x8101) {
4106 (void) snprintf(info, 80,
4107 "IDC Req Rcvd:%04x, mb1=%x mb2=%x mb3=%x",
4108 code, mbox1, mbox2, mbox3);
4109 info[79] = 0;
4110
4111 /* check if "ACK" is required (timeout != 0) */
4112 if (mbox1 & 0x0f00) {
4113 caddr_t req;
4114
4115 /*
4116 * Ack the request (queue work to do it?)
4117 * using a mailbox iocb
4118 * (Only Queue #0 allowed)
4119 */
4120 mutex_enter(&qlt->mq_req[0].mq_lock);
4121 req = qlt_get_req_entries(qlt, 1, 0);
4122 if (req) {
4123 bzero(req, IOCB_SIZE);
4124 req[0] = 0x39; req[1] = 1;
4125 QMEM_WR16(qlt, req+8, 0x101);
4126 QMEM_WR16(qlt, req+10, mbox1);
4127 QMEM_WR16(qlt, req+12, mbox2);
4128 QMEM_WR16(qlt, req+14, mbox3);
4129 QMEM_WR16(qlt, req+16, mbox4);
4130 QMEM_WR16(qlt, req+18, mbox5);
4131 QMEM_WR16(qlt, req+20, mbox6);
4132 qlt_submit_req_entries(qlt, 1, 0);
4133 } else {
4134 (void) snprintf(info, 80,
4135 "IDC ACK failed");
4136 info[79] = 0;
4137 }
4138 mutex_exit(&qlt->mq_req[0].mq_lock);
4139 }
4140 } else {
4141 stmf_trace(qlt->qlt_port_alias,
4142 "Async event: 0x%x ignored",
4143 code);
4144 }
4145 REG_WR32(qlt, REG_INTR_CTRL, ENABLE_RISC_INTR);
4146 } else if ((intr_type == 0x10) || (intr_type == 0x11)) {
4147 /* Handle mailbox completion */
4148 mutex_enter(&qlt->mbox_lock);
4149 if (qlt->mbox_io_state != MBOX_STATE_CMD_RUNNING) {
4150 cmn_err(CE_WARN, "qlt(%d): mailbox completion received"
4151 " when driver wasn't waiting for it %d",
4152 qlt->instance, qlt->mbox_io_state);
4153 } else {
4154 for (i = 0; i < MAX_MBOXES; i++) {
4155 if (qlt->mcp->from_fw_mask &
4156 (((uint32_t)1) << i)) {
4157 qlt->mcp->from_fw[i] =
4158 REG_RD16(qlt, REG_MBOX(i));
4159 }
4160 }
4161 qlt->mbox_io_state = MBOX_STATE_CMD_DONE;
4162 }
4163 REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
4164 cv_broadcast(&qlt->mbox_cv);
4165 mutex_exit(&qlt->mbox_lock);
4166 } else {
4167 cmn_err(CE_WARN, "qlt(%d): Unknown intr type 0x%x",
4168 qlt->instance, intr_type);
4169 stmf_trace(qlt->qlt_port_alias,
4170 "%s: Unknown intr type 0x%x [%x]",
4171 __func__, intr_type, risc_status);
4172 REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
4173 }
4174
4175 /* REG_WR32(qlt, REG_INTR_CTRL, ENABLE_RISC_INTR); */
4176 mutex_exit(&qlt->intr_lock);
4177
4178 return (DDI_INTR_CLAIMED);
4179 }
4180
4181 /*
4182 * **SHOULD ONLY BE CALLED FROM INTERRUPT CONTEXT. DO NOT CALL ELSEWHERE**
4183 */
4184 /* ARGSUSED */
4185 static uint_t
qlt_isr(caddr_t arg,caddr_t arg2)4186 qlt_isr(caddr_t arg, caddr_t arg2)
4187 {
4188 qlt_state_t *qlt = (qlt_state_t *)arg;
4189 uint32_t risc_status, intr_type;
4190 int i;
4191 int intr_loop_count;
4192 char info[80];
4193
4194 risc_status = REG_RD32(qlt, REG_RISC_STATUS);
4195 if (!mutex_tryenter(&qlt->intr_lock)) {
4196 /*
4197 * Normally we will always get this lock. If tryenter is
4198 * failing then it means that driver is trying to do
4199 * some cleanup and is masking the intr but some intr
4200 * has sneaked in between. See if our device has generated
4201 * this intr. If so then wait a bit and return claimed.
4202 * If not then return claimed if this is the 1st instance
4203 * of a interrupt after driver has grabbed the lock.
4204 */
4205 if (risc_status & BIT_15) {
4206 drv_usecwait(10);
4207 return (DDI_INTR_CLAIMED);
4208 } else if (qlt->intr_sneak_counter) {
4209 qlt->intr_sneak_counter--;
4210 return (DDI_INTR_CLAIMED);
4211 } else {
4212 return (DDI_INTR_UNCLAIMED);
4213 }
4214 }
4215 if (((risc_status & BIT_15) == 0) ||
4216 (qlt->qlt_intr_enabled == 0)) {
4217 /*
4218 * This might be a pure coincedence that we are operating
4219 * in a interrupt disabled mode and another device
4220 * sharing the interrupt line has generated an interrupt
4221 * while an interrupt from our device might be pending. Just
4222 * ignore it and let the code handling the interrupt
4223 * disabled mode handle it.
4224 */
4225 mutex_exit(&qlt->intr_lock);
4226 return (DDI_INTR_UNCLAIMED);
4227 }
4228
4229 /*
4230 * XXX take care for MSI-X case. disable intrs
4231 * Its gonna be complicated because of the max iterations.
4232 * as hba will have posted the intr which did not go on PCI
4233 * but we did not service it either because of max iterations.
4234 * Maybe offload the intr on a different thread.
4235 */
4236 intr_loop_count = 0;
4237
4238 REG_WR32(qlt, REG_INTR_CTRL, 0);
4239
4240 intr_again:;
4241
4242 /* check for risc pause */
4243 if (risc_status & BIT_8) {
4244 EL(qlt, "Risc Pause status=%xh\n", risc_status);
4245 cmn_err(CE_WARN, "qlt(%d): Risc Pause %08x",
4246 qlt->instance, risc_status);
4247 (void) snprintf(info, 80, "Risc Pause %08x", risc_status);
4248 info[79] = 0;
4249 (void) fct_port_shutdown(qlt->qlt_port,
4250 STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET |
4251 STMF_RFLAG_COLLECT_DEBUG_DUMP, info);
4252 }
4253
4254 /* First check for high performance path */
4255 intr_type = risc_status & 0xff;
4256 if (intr_type == 0x1D) {
4257
4258 /* process the atio queue first */
4259 qlt->atio_ndx_from_fw =
4260 (uint16_t)REG_RD32(qlt, REG_ATIO_IN_PTR);
4261 qlt_handle_atio_queue_update(qlt);
4262
4263 /* process the response queue next */
4264 qlt->mq_resp[0].mq_ndx_from_fw =
4265 (uint16_t)REG_RD32(qlt, REG_RESP_IN_PTR);
4266 qlt_handle_resp_queue_update(qlt, 0);
4267 REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
4268
4269 } else if (intr_type == 0x1C) {
4270 REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
4271 qlt->atio_ndx_from_fw = (uint16_t)(risc_status >> 16);
4272 qlt_handle_atio_queue_update(qlt);
4273 } else if (intr_type == 0x1E) {
4274 /* 83xx Atio Queue update */
4275 qlt->atio_ndx_from_fw =
4276 (uint16_t)MQBAR_RD32(qlt, MQBAR_ATIO_IN);
4277 qlt_handle_atio_queue_update(qlt);
4278 REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
4279 } else if (intr_type == 0x13) {
4280 uint16_t qi;
4281
4282 qlt->atio_ndx_from_fw =
4283 (uint16_t)REG_RD32(qlt, REG_ATIO_IN_PTR);
4284 qlt_handle_atio_queue_update(qlt);
4285
4286 if (qlt->qlt_mq_enabled) {
4287 qi = (uint16_t)(risc_status >> 16);
4288 qlt->mq_resp[0].mq_ndx_from_fw =
4289 (uint16_t)MQBAR_RD32(qlt,
4290 (qi * MQBAR_REG_OFFSET) + MQBAR_RESP_IN);
4291 /* FIX THIS to be optional */
4292 REG_WR32(qlt, REG_HCCR,
4293 HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
4294 } else {
4295 qi = 0;
4296 REG_WR32(qlt, REG_HCCR,
4297 HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
4298 qlt->mq_resp[qi].mq_ndx_from_fw = risc_status >> 16;
4299 REG_WR32(qlt, REG_HCCR,
4300 HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
4301 }
4302 qlt_handle_resp_queue_update(qlt, qi);
4303
4304 } else if (intr_type == 0x14) {
4305 /* MQ */
4306 uint16_t qi = 0;
4307
4308 if ((qlt->qlt_83xx_chip) || (qlt->qlt_27xx_chip)) {
4309 qlt->atio_ndx_from_fw =
4310 (uint16_t)MQBAR_RD32(qlt, MQBAR_ATIO_IN);
4311 } else {
4312 qi = (uint16_t)(risc_status >> 16);
4313 qlt->atio_ndx_from_fw = (uint16_t)
4314 REG_RD32(qlt, REG_ATIO_IN_PTR);
4315 }
4316 qlt_handle_atio_queue_update(qlt);
4317
4318 qlt->mq_resp[qi].mq_ndx_from_fw =
4319 (uint16_t)MQBAR_RD32(qlt,
4320 (qi * MQBAR_REG_OFFSET) + MQBAR_RESP_IN);
4321 qlt_handle_resp_queue_update(qlt, qi);
4322 REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
4323
4324 } else if (intr_type == 0x12) {
4325 uint16_t code = (uint16_t)(risc_status >> 16);
4326 uint16_t mbox1 = REG_RD16(qlt, REG_MBOX(1));
4327 uint16_t mbox2 = REG_RD16(qlt, REG_MBOX(2));
4328 uint16_t mbox3 = REG_RD16(qlt, REG_MBOX(3));
4329 uint16_t mbox4 = REG_RD16(qlt, REG_MBOX(4));
4330 uint16_t mbox5 = REG_RD16(qlt, REG_MBOX(5));
4331 uint16_t mbox6 = REG_RD16(qlt, REG_MBOX(6));
4332
4333 REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
4334 EL(qlt, "Async event %x mb1=%x, mb2=%x, mb3=%x, mb4=%x, "
4335 "mb5=%x, mb6=%x\n", code, mbox1, mbox2, mbox3, mbox4,
4336 mbox5, mbox6);
4337 stmf_trace(qlt->qlt_port_alias, "Async event %x mb1=%x mb2=%x,"
4338 " mb3=%x, mb4=%x, mb5=%x, mb6=%x", code, mbox1, mbox2,
4339 mbox3, mbox4, mbox5, mbox6);
4340 cmn_err(CE_NOTE, "!qlt(%d): Async event %x mb1=%x mb2=%x,"
4341 " mb3=%x, mb4=%x, mb5=%x, mb6=%x", qlt->instance, code,
4342 mbox1, mbox2, mbox3, mbox4, mbox5, mbox6);
4343
4344 if ((code == 0x8030) || (code == 0x8010) || (code == 0x8013)) {
4345 if (qlt->qlt_link_up) {
4346 fct_handle_event(qlt->qlt_port,
4347 FCT_EVENT_LINK_RESET, 0, 0);
4348 }
4349 } else if (code == 0x8012) {
4350 qlt->qlt_link_up = 0;
4351 fct_handle_event(qlt->qlt_port, FCT_EVENT_LINK_DOWN,
4352 0, 0);
4353 } else if (code == 0x8014) {
4354 if (mbox1 == 0xffff) { /* global event */
4355 uint8_t reason_code;
4356
4357 reason_code = (uint8_t)(mbox3 >> 8);
4358
4359 switch (reason_code) {
4360 case 0x1d: /* FIP Clear Virtual Link received */
4361 case 0x1a: /* received FLOGO */
4362 case 0x1c: /* FCF configuration changed */
4363 case 0x1e: /* FKA timeout */
4364 if (mbox2 == 7) {
4365 qlt->qlt_link_up = 0;
4366 fct_handle_event(qlt->qlt_port,
4367 FCT_EVENT_LINK_DOWN, 0, 0);
4368 }
4369 break;
4370 case 0x12:
4371 if (mbox2 == 4) {
4372 qlt->qlt_link_up = 1;
4373 fct_handle_event(qlt->qlt_port,
4374 FCT_EVENT_LINK_UP, 0, 0);
4375 stmf_trace(qlt->qlt_port_alias,
4376 "SNS login and SCR done");
4377 }
4378 break;
4379 case 0:
4380 if ((mbox2 == 6) &&
4381 (!qlt->qlt_link_up)) {
4382 qlt->qlt_link_up = 1;
4383 fct_handle_event(qlt->qlt_port,
4384 FCT_EVENT_LINK_UP, 0, 0);
4385 stmf_trace(qlt->qlt_port_alias,
4386 "Link reinitialised");
4387 }
4388 break;
4389 default:
4390 stmf_trace(qlt->qlt_port_alias,
4391 "AEN ignored");
4392 break;
4393 }
4394 }
4395 } else if (code == 0x8011) {
4396 switch (mbox1) {
4397 case 0: qlt->link_speed = PORT_SPEED_1G;
4398 break;
4399 case 1: qlt->link_speed = PORT_SPEED_2G;
4400 break;
4401 case 3: qlt->link_speed = PORT_SPEED_4G;
4402 break;
4403 case 4: qlt->link_speed = PORT_SPEED_8G;
4404 break;
4405 case 5: qlt->link_speed = PORT_SPEED_16G;
4406 break;
4407 case 6: qlt->link_speed = PORT_SPEED_32G;
4408 break;
4409 case 0x13: qlt->link_speed = PORT_SPEED_10G;
4410 break;
4411 default:
4412 qlt->link_speed = PORT_SPEED_UNKNOWN;
4413 }
4414 qlt->qlt_link_up = 1;
4415 fct_handle_event(qlt->qlt_port, FCT_EVENT_LINK_UP,
4416 0, 0);
4417 } else if ((code == 0x8002) || (code == 0x8003) ||
4418 (code == 0x8004) || (code == 0x8005)) {
4419 (void) snprintf(info, 80,
4420 "Got %04x, mb1=%x mb2=%x mb5=%x mb6=%x",
4421 code, mbox1, mbox2, mbox5, mbox6);
4422 info[79] = 0;
4423 (void) fct_port_shutdown(qlt->qlt_port,
4424 STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET |
4425 STMF_RFLAG_COLLECT_DEBUG_DUMP, info);
4426 } else if (code == 0x800F) {
4427 (void) snprintf(info, 80,
4428 "Got 800F, mb1=%x mb2=%x mb3=%x",
4429 mbox1, mbox2, mbox3);
4430
4431 if (mbox1 != 1) {
4432 /* issue "verify fw" */
4433 qlt_verify_fw(qlt);
4434 }
4435 } else if (code == 0x8101) {
4436 (void) snprintf(info, 80,
4437 "IDC Req Rcvd:%04x, mb1=%x mb2=%x mb3=%x",
4438 code, mbox1, mbox2, mbox3);
4439 info[79] = 0;
4440
4441 /* check if "ACK" is required (timeout != 0) */
4442 if (mbox1 & 0x0f00) {
4443 caddr_t req;
4444
4445 /*
4446 * Ack the request (queue work to do it?)
4447 * using a mailbox iocb (only Queue 0 allowed)
4448 */
4449 mutex_enter(&qlt->mq_req[0].mq_lock);
4450 req = qlt_get_req_entries(qlt, 1, 0);
4451 if (req) {
4452 bzero(req, IOCB_SIZE);
4453 req[0] = 0x39; req[1] = 1;
4454 QMEM_WR16(qlt, req+8, 0x101);
4455 QMEM_WR16(qlt, req+10, mbox1);
4456 QMEM_WR16(qlt, req+12, mbox2);
4457 QMEM_WR16(qlt, req+14, mbox3);
4458 QMEM_WR16(qlt, req+16, mbox4);
4459 QMEM_WR16(qlt, req+18, mbox5);
4460 QMEM_WR16(qlt, req+20, mbox6);
4461 qlt_submit_req_entries(qlt, 1, 0);
4462 } else {
4463 (void) snprintf(info, 80,
4464 "IDC ACK failed");
4465 info[79] = 0;
4466 }
4467 mutex_exit(&qlt->mq_req[0].mq_lock);
4468 }
4469 }
4470 } else if ((intr_type == 0x10) || (intr_type == 0x11)) {
4471 /* Handle mailbox completion */
4472 mutex_enter(&qlt->mbox_lock);
4473 if (qlt->mbox_io_state != MBOX_STATE_CMD_RUNNING) {
4474 cmn_err(CE_WARN, "qlt(%d): mailbox completion received"
4475 " when driver wasn't waiting for it %d",
4476 qlt->instance, qlt->mbox_io_state);
4477 } else {
4478 for (i = 0; i < MAX_MBOXES; i++) {
4479 if (qlt->mcp->from_fw_mask &
4480 (((uint32_t)1) << i)) {
4481 qlt->mcp->from_fw[i] =
4482 REG_RD16(qlt, REG_MBOX(i));
4483 }
4484 }
4485 qlt->mbox_io_state = MBOX_STATE_CMD_DONE;
4486 }
4487 REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
4488 cv_broadcast(&qlt->mbox_cv);
4489 mutex_exit(&qlt->mbox_lock);
4490 } else {
4491 cmn_err(CE_WARN, "qlt(%d): Unknown intr type 0x%x",
4492 qlt->instance, intr_type);
4493 stmf_trace(qlt->qlt_port_alias,
4494 "%s: Unknown intr type 0x%x [%x]",
4495 __func__, intr_type, risc_status);
4496 REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
4497 }
4498
4499 (void) REG_RD32(qlt, REG_HCCR); /* PCI Posting */
4500
4501 if ((qlt->intr_flags & QLT_INTR_MSIX) == 0) {
4502 risc_status = REG_RD32(qlt, REG_RISC_STATUS);
4503 if ((risc_status & BIT_15) &&
4504 (++intr_loop_count < QLT_MAX_ITERATIONS_PER_INTR)) {
4505 goto intr_again;
4506 }
4507 REG_WR32(qlt, REG_INTR_CTRL, ENABLE_RISC_INTR);
4508 mutex_exit(&qlt->intr_lock);
4509 } else {
4510 mutex_exit(&qlt->intr_lock);
4511 REG_WR32(qlt, REG_INTR_CTRL, ENABLE_RISC_INTR);
4512 }
4513
4514 return (DDI_INTR_CLAIMED);
4515 }
4516
4517 /* **************** NVRAM Functions ********************** */
4518
4519 fct_status_t
qlt_read_flash_word(qlt_state_t * qlt,uint32_t faddr,uint32_t * bp)4520 qlt_read_flash_word(qlt_state_t *qlt, uint32_t faddr, uint32_t *bp)
4521 {
4522 uint32_t timer;
4523
4524 /* Clear access error flag */
4525 REG_WR32(qlt, REG_CTRL_STATUS,
4526 REG_RD32(qlt, REG_CTRL_STATUS) | FLASH_ERROR);
4527
4528 REG_WR32(qlt, REG_FLASH_ADDR, faddr & ~BIT_31);
4529
4530 /* Wait for READ cycle to complete. */
4531 for (timer = 3000; timer; timer--) {
4532 if (REG_RD32(qlt, REG_FLASH_ADDR) & BIT_31) {
4533 break;
4534 }
4535 drv_usecwait(10);
4536 }
4537 if (timer == 0) {
4538 EL(qlt, "flash timeout\n");
4539 return (QLT_FLASH_TIMEOUT);
4540 } else if (REG_RD32(qlt, REG_CTRL_STATUS) & FLASH_ERROR) {
4541 EL(qlt, "flash access error\n");
4542 return (QLT_FLASH_ACCESS_ERROR);
4543 }
4544
4545 *bp = REG_RD32(qlt, REG_FLASH_DATA);
4546
4547 return (QLT_SUCCESS);
4548 }
4549
4550 fct_status_t
qlt_read_nvram(qlt_state_t * qlt)4551 qlt_read_nvram(qlt_state_t *qlt)
4552 {
4553 uint32_t index, addr, chksum;
4554 uint32_t val, *ptr;
4555 fct_status_t ret;
4556 qlt_nvram_t *nv;
4557 uint64_t empty_node_name = 0;
4558
4559 if (qlt->qlt_27xx_chip) {
4560 int func;
4561
4562 func = ((REG_RD32(qlt, REG_CTRL_STATUS) & 0x0000f000) >> 12);
4563 switch (func) {
4564 case 0: addr = QLT27_NVRAM_FUNC0_ADDR; break;
4565 case 1: addr = QLT27_NVRAM_FUNC1_ADDR; break;
4566 case 2: addr = QLT27_NVRAM_FUNC2_ADDR; break;
4567 case 3: addr = QLT27_NVRAM_FUNC3_ADDR; break;
4568 }
4569 } else if (qlt->qlt_83xx_chip) {
4570 if (qlt->qlt_fcoe_enabled) {
4571 addr = REG_RD32(qlt, REG_CTRL_STATUS) & BIT_12 ?
4572 QLT83FCOE_NVRAM_FUNC1_ADDR :
4573 QLT83FCOE_NVRAM_FUNC0_ADDR;
4574 } else {
4575 addr = REG_RD32(qlt, REG_CTRL_STATUS) & BIT_12 ?
4576 QLT83FC_NVRAM_FUNC1_ADDR :
4577 QLT83FC_NVRAM_FUNC0_ADDR;
4578 }
4579 } else if (qlt->qlt_81xx_chip) {
4580 addr = REG_RD32(qlt, REG_CTRL_STATUS) & BIT_12 ?
4581 QLT81_NVRAM_FUNC1_ADDR : QLT81_NVRAM_FUNC0_ADDR;
4582 } else if (qlt->qlt_25xx_chip) {
4583 addr = REG_RD32(qlt, REG_CTRL_STATUS) & FUNCTION_NUMBER ?
4584 QLT25_NVRAM_FUNC1_ADDR : QLT25_NVRAM_FUNC0_ADDR;
4585 } else {
4586 addr = REG_RD32(qlt, REG_CTRL_STATUS) & FUNCTION_NUMBER ?
4587 NVRAM_FUNC1_ADDR : NVRAM_FUNC0_ADDR;
4588 }
4589 mutex_enter(&qlt_global_lock);
4590
4591 /* Pause RISC. */
4592 REG_WR32(qlt, REG_HCCR, HCCR_CMD(SET_RISC_PAUSE));
4593 (void) REG_RD32(qlt, REG_HCCR); /* PCI Posting. */
4594
4595 /* Get NVRAM data and calculate checksum. */
4596 ptr = (uint32_t *)qlt->nvram;
4597 chksum = 0;
4598 for (index = 0; index < sizeof (qlt_nvram_t) / 4; index++) {
4599 ret = qlt_read_flash_word(qlt, addr++, &val);
4600 if (ret != QLT_SUCCESS) {
4601 EL(qlt, "qlt_read_flash_word, status=%llxh\n", ret);
4602 mutex_exit(&qlt_global_lock);
4603 return (ret);
4604 }
4605 chksum += val;
4606 *ptr = LE_32(val);
4607 ptr++;
4608 }
4609
4610 /* Release RISC Pause */
4611 REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_PAUSE));
4612 (void) REG_RD32(qlt, REG_HCCR); /* PCI Posting. */
4613
4614 mutex_exit(&qlt_global_lock);
4615
4616 /* Sanity check NVRAM Data */
4617 nv = qlt->nvram;
4618 if (chksum || nv->id[0] != 'I' || nv->id[1] != 'S' ||
4619 nv->id[2] != 'P' || nv->id[3] != ' ' ||
4620 (nv->nvram_version[0] | nv->nvram_version[1]) == 0) {
4621 EL(qlt, "chksum=%xh, id=%c%c%c%c, ver=%02d%02d\n", chksum,
4622 nv->id[0], nv->id[1], nv->id[2], nv->id[3],
4623 nv->nvram_version[1], nv->nvram_version[0]);
4624 return (QLT_BAD_NVRAM_DATA);
4625 }
4626
4627 /* If node name is zero, hand craft it from port name */
4628 if (bcmp(nv->node_name, &empty_node_name, 8) == 0) {
4629 bcopy(nv->port_name, nv->node_name, 8);
4630 nv->node_name[0] = (uint8_t)(nv->node_name[0] & ~BIT_0);
4631 nv->port_name[0] = (uint8_t)(nv->node_name[0] | BIT_0);
4632 }
4633
4634 return (QLT_SUCCESS);
4635 }
4636
4637 fct_status_t
qlt_read_vpd(qlt_state_t * qlt)4638 qlt_read_vpd(qlt_state_t *qlt)
4639 {
4640 uint32_t index, addr, chksum;
4641 uint32_t val, *ptr;
4642 fct_status_t ret;
4643
4644 if (qlt->qlt_27xx_chip) {
4645 int func;
4646
4647 func = ((REG_RD32(qlt, REG_CTRL_STATUS) & 0x0000f000) >> 12);
4648 switch (func) {
4649 case 0: addr = QLT27_VPD_FUNC0_ADDR; break;
4650 case 1: addr = QLT27_VPD_FUNC1_ADDR; break;
4651 case 2: addr = QLT27_VPD_FUNC2_ADDR; break;
4652 case 3: addr = QLT27_VPD_FUNC3_ADDR; break;
4653 }
4654 } else if (qlt->qlt_83xx_chip) {
4655 if (qlt->qlt_fcoe_enabled) {
4656 addr = REG_RD32(qlt, REG_CTRL_STATUS) & BIT_12 ?
4657 QLT83FCOE_VPD_FUNC1_ADDR :
4658 QLT83FCOE_VPD_FUNC0_ADDR;
4659 } else {
4660 addr = REG_RD32(qlt, REG_CTRL_STATUS) & BIT_12 ?
4661 QLT83FC_VPD_FUNC1_ADDR :
4662 QLT83FC_VPD_FUNC0_ADDR;
4663 }
4664 } else if (qlt->qlt_81xx_chip) {
4665 addr = REG_RD32(qlt, REG_CTRL_STATUS) & BIT_12 ?
4666 QLT81_VPD_FUNC1_ADDR : QLT81_VPD_FUNC0_ADDR;
4667 } else if (qlt->qlt_25xx_chip) {
4668 addr = REG_RD32(qlt, REG_CTRL_STATUS) & FUNCTION_NUMBER ?
4669 QLT25_VPD_FUNC1_ADDR : QLT25_VPD_FUNC0_ADDR;
4670 } else {
4671 addr = REG_RD32(qlt, REG_CTRL_STATUS) & FUNCTION_NUMBER ?
4672 QLT24_VPD_FUNC1_ADDR : QLT24_VPD_FUNC0_ADDR;
4673 }
4674 mutex_enter(&qlt_global_lock);
4675
4676 /* Pause RISC. */
4677 REG_WR32(qlt, REG_HCCR, HCCR_CMD(SET_RISC_PAUSE));
4678 (void) REG_RD32(qlt, REG_HCCR); /* PCI Posting. */
4679
4680 /* Get VPD data and calculate checksum. */
4681 ptr = (uint32_t *)qlt->vpd;
4682 chksum = 0;
4683 for (index = 0; index < QL_24XX_VPD_SIZE / 4; index++) {
4684 ret = qlt_read_flash_word(qlt, addr++, &val);
4685 if (ret != QLT_SUCCESS) {
4686 EL(qlt, "qlt_read_flash_word, status=%llxh\n", ret);
4687 mutex_exit(&qlt_global_lock);
4688 return (ret);
4689 }
4690 chksum += val;
4691 *ptr = LE_32(val);
4692 ptr++;
4693 }
4694
4695 /* Release RISC Pause */
4696 REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_PAUSE));
4697 (void) REG_RD32(qlt, REG_HCCR); /* PCI Posting. */
4698
4699 mutex_exit(&qlt_global_lock);
4700
4701 return (QLT_SUCCESS);
4702 }
4703
4704 fct_status_t
qlt_read_bfe(qlt_state_t * qlt,uint32_t in_addr,uint32_t * out_addr,uint32_t i)4705 qlt_read_bfe(qlt_state_t *qlt, uint32_t in_addr, uint32_t *out_addr, uint32_t i)
4706 {
4707 uint32_t index;
4708 uint32_t chksum;
4709 fct_status_t ret = QLT_SUCCESS;
4710 uint32_t val;
4711 uint16_t dataoffset;
4712 uint32_t *ptr;
4713 uint32_t addr, addr0;
4714 uint16_t length;
4715
4716 val = chksum = 0;
4717 ptr = (uint32_t *)&qlt->rimage[i].header;
4718
4719 addr = in_addr;
4720 addr0 = addr;
4721
4722 /* read rom header first */
4723 for (index = 0; index < sizeof (qlt_rom_header_t)/4;
4724 index ++) {
4725 ret = qlt_read_flash_word(qlt, addr++, &val);
4726 if (ret != QLT_SUCCESS) {
4727 EL(qlt, "read flash, status=%llxh\n", ret);
4728 return (ret);
4729 }
4730 chksum += val;
4731 *ptr = LE_32(val);
4732 ptr++;
4733 }
4734
4735 /* check the signature */
4736 if (qlt->rimage[i].header.signature[0] != PCI_HEADER0) {
4737 EL(qlt, "hdr[%d] sig[1] [0] (%xh) (%xh) is wrong.\n",
4738 i, qlt->rimage[i].header.signature[1],
4739 qlt->rimage[i].header.signature[0]);
4740 return (QLT_SUCCESS);
4741 }
4742
4743 if ((qlt->rimage[i].header.signature[0] == PCI_HEADER0) &&
4744 (qlt->rimage[i].header.signature[1] == PCI_HEADER1)) {
4745 /* get dataoffset */
4746 dataoffset = (qlt->rimage[i].header.dataoffset[1] |
4747 qlt->rimage[i].header.dataoffset[0]);
4748 EL(qlt, "dataoffset[0] = %xh\n", dataoffset);
4749
4750 ptr = (uint32_t *)&qlt->rimage[i].data;
4751
4752 /* adjust addr */
4753 addr = addr0 + (dataoffset/4);
4754 for (index = 0; index < sizeof (qlt_rom_data_t)/4;
4755 index ++) {
4756 ret = qlt_read_flash_word(qlt, addr++, &val);
4757 if (ret != QLT_SUCCESS) {
4758 EL(qlt, "read flash, status=%llxh\n", ret);
4759 return (ret);
4760 }
4761 chksum += val;
4762 *ptr = LE_32(val);
4763 ptr++;
4764 }
4765
4766 /* check signature */
4767 if ((qlt->rimage[i].data.signature[0] != 0x50) &&
4768 (qlt->rimage[i].data.signature[1] != 0x43) &&
4769 (qlt->rimage[i].data.signature[2] != 0x49) &&
4770 (qlt->rimage[i].data.signature[3] != 0x52)) {
4771 EL(qlt,
4772 "data sig[3] [2] [1] [0] (%xh)(%xh)(%xh)(%xh)\n",
4773 qlt->rimage[i].data.signature[3],
4774 qlt->rimage[i].data.signature[2],
4775 qlt->rimage[i].data.signature[1],
4776 qlt->rimage[i].data.signature[0]);
4777 return (QLT_SUCCESS);
4778 }
4779
4780 EL(qlt, "codetype (%xh) revisionlevel[1][0] (%xh)(%xh)\n",
4781 qlt->rimage[i].data.codetype,
4782 qlt->rimage[i].data.revisionlevel[1],
4783 qlt->rimage[i].data.revisionlevel[0]);
4784
4785 /* check if this is the last image */
4786 if (qlt->rimage[i].data.indicator == PCI_IND_LAST_IMAGE) {
4787 EL(qlt, "last image (%xh)\n",
4788 qlt->rimage[i].data.indicator);
4789 return (QLT_SUCCESS);
4790
4791 }
4792
4793 /* Get the image length and adjust the addr according */
4794 length = (qlt->rimage[i].data.imagelength[1] |
4795 qlt->rimage[i].data.imagelength[0]);
4796
4797 EL(qlt, "image[%d] length[1][0] (%xh) (%xh) in sectors\n",
4798 i, length);
4799
4800 /* the starting addr of the next image */
4801 addr = addr0 + ((length * 512)/4);
4802 *out_addr = addr;
4803 }
4804
4805 return (QLT_SUCCESS);
4806 }
4807
4808 fct_status_t
qlt_read_rom_image(qlt_state_t * qlt)4809 qlt_read_rom_image(qlt_state_t *qlt)
4810 {
4811 uint32_t addr;
4812 uint32_t out_addr = 0;
4813 uint32_t count = 0;
4814 boolean_t last_image = FALSE;
4815 fct_status_t ret;
4816
4817 if (qlt->qlt_27xx_chip) {
4818 addr = FLASH_2700_DATA_ADDR + FLASH_2700_BOOT_CODE_ADDR;
4819 } else if (qlt->qlt_83xx_chip) {
4820 addr = FLASH_8300_DATA_ADDR + FLASH_8300_BOOT_CODE_ADDR;
4821 } else if (qlt->qlt_81xx_chip) {
4822 addr = FLASH_8100_DATA_ADDR + FLASH_8100_BOOT_CODE_ADDR;
4823 } else if (qlt->qlt_25xx_chip) {
4824 addr = FLASH_2500_DATA_ADDR + FLASH_2500_BOOT_CODE_ADDR;
4825 } else {
4826 addr = FLASH_2400_DATA_ADDR + FLASH_2400_BOOT_CODE_ADDR;
4827 }
4828 mutex_enter(&qlt_global_lock);
4829
4830 /* Pause RISC. */
4831 REG_WR32(qlt, REG_HCCR, HCCR_CMD(SET_RISC_PAUSE));
4832 (void) REG_RD32(qlt, REG_HCCR); /* PCI Posting. */
4833
4834 do {
4835 ret = qlt_read_bfe(qlt, addr, &out_addr, count);
4836 if (ret != QLT_SUCCESS) {
4837 EL(qlt, "qlt_read_bfe, status=%llxh\n", ret);
4838 break;
4839 }
4840 if (qlt->rimage[count].data.indicator ==
4841 PCI_IND_LAST_IMAGE) {
4842 last_image = TRUE;
4843 } else {
4844 addr = out_addr;
4845 }
4846 count ++;
4847 } while ((last_image != TRUE) && (count < 6));
4848
4849 /* Release RISC Pause */
4850 REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_PAUSE));
4851 (void) REG_RD32(qlt, REG_HCCR); /* PCI Posting. */
4852
4853 mutex_exit(&qlt_global_lock);
4854
4855 return (QLT_SUCCESS);
4856 }
4857
4858 uint32_t
qlt_sync_atio_queue(qlt_state_t * qlt)4859 qlt_sync_atio_queue(qlt_state_t *qlt)
4860 {
4861 uint32_t total_ent;
4862
4863 if (qlt->atio_ndx_from_fw > qlt->atio_ndx_to_fw) {
4864 total_ent = qlt->atio_ndx_from_fw - qlt->atio_ndx_to_fw;
4865 (void) ddi_dma_sync(qlt->queue_mem_dma_handle, ATIO_QUEUE_OFFSET
4866 + (qlt->atio_ndx_to_fw << 6), total_ent << 6,
4867 DDI_DMA_SYNC_FORCPU);
4868 } else {
4869 total_ent = ATIO_QUEUE_ENTRIES - qlt->atio_ndx_to_fw +
4870 qlt->atio_ndx_from_fw;
4871 (void) ddi_dma_sync(qlt->queue_mem_dma_handle, ATIO_QUEUE_OFFSET
4872 + (qlt->atio_ndx_to_fw << 6), (uint_t)(ATIO_QUEUE_ENTRIES -
4873 qlt->atio_ndx_to_fw) << 6, DDI_DMA_SYNC_FORCPU);
4874 (void) ddi_dma_sync(qlt->queue_mem_dma_handle,
4875 ATIO_QUEUE_OFFSET, (uint_t)(qlt->atio_ndx_from_fw << 6),
4876 DDI_DMA_SYNC_FORCPU);
4877 }
4878 return (total_ent);
4879 }
4880
4881 void
qlt_handle_atio_queue_update(qlt_state_t * qlt)4882 qlt_handle_atio_queue_update(qlt_state_t *qlt)
4883 {
4884 uint32_t total_ent;
4885
4886 if (qlt->atio_ndx_to_fw == qlt->atio_ndx_from_fw)
4887 return;
4888
4889 total_ent = qlt_sync_atio_queue(qlt);
4890
4891 do {
4892 uint8_t *atio = (uint8_t *)&qlt->atio_ptr[
4893 qlt->atio_ndx_to_fw << 6];
4894 uint32_t ent_cnt;
4895
4896 ent_cnt = (uint32_t)(atio[1]);
4897 if (ent_cnt > total_ent) {
4898 break;
4899 }
4900 switch ((uint8_t)(atio[0])) {
4901 case 0x06: /* ATIO, make performance case the 1st test */
4902 qlt_handle_atio(qlt, atio);
4903 break;
4904 case 0x0d: /* INOT */
4905 qlt_handle_inot(qlt, atio);
4906 break;
4907 default:
4908 EL(qlt, "atio_queue_update atio[0]=%xh\n", atio[0]);
4909 cmn_err(CE_WARN, "qlt_handle_atio_queue_update: "
4910 "atio[0] is %x, qlt-%p", atio[0], (void *)qlt);
4911 break;
4912 }
4913 qlt->atio_ndx_to_fw = (uint16_t)(
4914 (qlt->atio_ndx_to_fw + ent_cnt) & (ATIO_QUEUE_ENTRIES - 1));
4915 total_ent -= ent_cnt;
4916 } while (total_ent > 0);
4917
4918 if ((qlt->qlt_83xx_chip) || (qlt->qlt_27xx_chip)) {
4919 MQBAR_WR32(qlt, MQBAR_ATIO_OUT, qlt->atio_ndx_to_fw);
4920 } else {
4921 REG_WR32(qlt, REG_ATIO_OUT_PTR, qlt->atio_ndx_to_fw);
4922 }
4923 }
4924
4925 uint32_t
qlt_sync_resp_queue(qlt_state_t * qlt,uint16_t qi)4926 qlt_sync_resp_queue(qlt_state_t *qlt, uint16_t qi)
4927 {
4928 uint32_t total_ent;
4929
4930 if (qlt->mq_resp[qi].mq_ndx_from_fw > qlt->mq_resp[qi].mq_ndx_to_fw) {
4931 total_ent = qlt->mq_resp[qi].mq_ndx_from_fw -
4932 qlt->mq_resp[qi].mq_ndx_to_fw;
4933 if (qi) {
4934 (void) ddi_dma_sync(
4935 qlt->mq_resp[qi].queue_mem_mq_dma_handle,
4936 (qlt->mq_resp[qi].mq_ndx_to_fw << 6),
4937 total_ent << 6,
4938 DDI_DMA_SYNC_FORCPU);
4939 } else {
4940 (void) ddi_dma_sync(
4941 qlt->queue_mem_dma_handle,
4942 RESPONSE_QUEUE_OFFSET +
4943 (qlt->mq_resp[qi].mq_ndx_to_fw << 6),
4944 total_ent << 6,
4945 DDI_DMA_SYNC_FORCPU);
4946 }
4947 } else {
4948 total_ent =
4949 (qi ? RESPONSE_QUEUE_MQ_ENTRIES : RESPONSE_QUEUE_ENTRIES) -
4950 qlt->mq_resp[qi].mq_ndx_to_fw +
4951 qlt->mq_resp[qi].mq_ndx_from_fw;
4952
4953 if (qi) {
4954
4955 (void) ddi_dma_sync(
4956 qlt->mq_resp[qi].queue_mem_mq_dma_handle,
4957 qlt->mq_resp[qi].mq_ndx_to_fw << 6,
4958 (RESPONSE_QUEUE_MQ_ENTRIES -
4959 qlt->mq_resp[qi].mq_ndx_to_fw) << 6,
4960 DDI_DMA_SYNC_FORCPU);
4961 (void) ddi_dma_sync(
4962 qlt->mq_resp[qi].queue_mem_mq_dma_handle, 0,
4963 qlt->mq_resp[qi].mq_ndx_from_fw << 6,
4964 DDI_DMA_SYNC_FORCPU);
4965 } else {
4966 (void) ddi_dma_sync(qlt->queue_mem_dma_handle,
4967 RESPONSE_QUEUE_OFFSET +
4968 (qlt->mq_resp[qi].mq_ndx_to_fw << 6),
4969 (RESPONSE_QUEUE_ENTRIES -
4970 qlt->mq_resp[qi].mq_ndx_to_fw) << 6,
4971 DDI_DMA_SYNC_FORCPU);
4972 (void) ddi_dma_sync(qlt->queue_mem_dma_handle,
4973 RESPONSE_QUEUE_OFFSET,
4974 qlt->mq_resp[qi].mq_ndx_from_fw << 6,
4975 DDI_DMA_SYNC_FORCPU);
4976 }
4977 }
4978
4979 return (total_ent);
4980 }
4981
4982 void
qlt_handle_resp_queue_update(qlt_state_t * qlt,uint16_t qi)4983 qlt_handle_resp_queue_update(qlt_state_t *qlt, uint16_t qi)
4984 {
4985 uint32_t total_ent;
4986 uint8_t c;
4987
4988 if (qlt->mq_resp[qi].mq_ndx_to_fw == qlt->mq_resp[qi].mq_ndx_from_fw)
4989 return;
4990
4991 total_ent = qlt_sync_resp_queue(qlt, qi);
4992
4993 do {
4994 uint32_t qe = qlt->mq_resp[qi].mq_ndx_to_fw;
4995 caddr_t resp = &qlt->mq_resp[qi].mq_ptr[qe << 6];
4996
4997 uint32_t ent_cnt;
4998
4999 ent_cnt = (uint32_t)(resp[0] == 0x51 ? resp[1] : 1);
5000 if (ent_cnt > total_ent) {
5001 break;
5002 }
5003 switch ((uint8_t)(resp[0])) {
5004 case 0x12: /* CTIO completion */
5005 qlt_handle_ctio_completion(qlt, (uint8_t *)resp, qi);
5006 break;
5007 case 0x0e: /* NACK */
5008 /* Do Nothing */
5009 break;
5010 case 0x1b: /* Verify FW */
5011 qlt_handle_verify_fw_completion(qlt, (uint8_t *)resp);
5012 break;
5013 case 0x29: /* CT PassThrough */
5014 qlt_handle_ct_completion(qlt, (uint8_t *)resp);
5015 break;
5016 case 0x32: /* Report ID */
5017 EL(qlt, "report Id received [type %xh]\n", resp[0]);
5018 break;
5019 case 0x33: /* Abort IO IOCB completion */
5020 qlt_handle_sol_abort_completion(qlt, (uint8_t *)resp);
5021 break;
5022 case 0x51: /* PUREX */
5023 qlt_handle_purex(qlt, (uint8_t *)resp);
5024 break;
5025 case 0x52:
5026 qlt_handle_dereg_completion(qlt, (uint8_t *)resp);
5027 break;
5028 case 0x53: /* ELS passthrough */
5029 c = (uint8_t)(((uint8_t)resp[0x1f]) >> 5);
5030 if (c == 0) {
5031 qlt_handle_sol_els_completion(qlt,
5032 (uint8_t *)resp);
5033 } else if (c == 3) {
5034 qlt_handle_unsol_els_abort_completion(qlt,
5035 (uint8_t *)resp);
5036 } else {
5037 qlt_handle_unsol_els_completion(qlt,
5038 (uint8_t *)resp);
5039 }
5040 break;
5041 case 0x54: /* ABTS received */
5042 qlt_handle_rcvd_abts(qlt, (uint8_t *)resp, qi);
5043 break;
5044 case 0x55: /* ABTS completion */
5045 qlt_handle_abts_completion(qlt, (uint8_t *)resp, qi);
5046 break;
5047 default:
5048 EL(qlt, "response entry=%xh\n", resp[0]);
5049 break;
5050 }
5051 if (qi != 0) {
5052 qlt->mq_resp[qi].mq_ndx_to_fw =
5053 (qlt->mq_resp[qi].mq_ndx_to_fw + ent_cnt) &
5054 (RESPONSE_QUEUE_MQ_ENTRIES - 1);
5055 } else {
5056 qlt->mq_resp[qi].mq_ndx_to_fw =
5057 (qlt->mq_resp[qi].mq_ndx_to_fw + ent_cnt) &
5058 (RESPONSE_QUEUE_ENTRIES - 1);
5059 }
5060 total_ent -= ent_cnt;
5061 } while (total_ent > 0);
5062 if (qlt->qlt_mq_enabled) {
5063 MQBAR_WR32(qlt, (qi * MQBAR_REG_OFFSET) + MQBAR_RESP_OUT,
5064 qlt->mq_resp[qi].mq_ndx_to_fw);
5065 } else {
5066 REG_WR32(qlt, REG_RESP_OUT_PTR, qlt->mq_resp[qi].mq_ndx_to_fw);
5067 }
5068 }
5069
5070 fct_status_t
qlt_portid_to_handle(qlt_state_t * qlt,uint32_t id,uint16_t cmd_handle,uint16_t * ret_handle)5071 qlt_portid_to_handle(qlt_state_t *qlt, uint32_t id, uint16_t cmd_handle,
5072 uint16_t *ret_handle)
5073 {
5074 fct_status_t ret;
5075 mbox_cmd_t *mcp;
5076 uint16_t n;
5077 uint16_t h;
5078 uint32_t ent_id;
5079 uint8_t *p;
5080 int found = 0;
5081
5082 mcp = qlt_alloc_mailbox_command(qlt, 2048 * 8);
5083 if (mcp == NULL) {
5084 return (STMF_ALLOC_FAILURE);
5085 }
5086 mcp->to_fw[0] = MBC_GET_ID_LIST;
5087 mcp->to_fw[8] = 2048 * 8;
5088 mcp->to_fw[9] = 0;
5089 mcp->to_fw_mask |= BIT_9 | BIT_8;
5090 mcp->from_fw_mask |= BIT_1 | BIT_2;
5091
5092 ret = qlt_mailbox_command(qlt, mcp);
5093 if (ret != QLT_SUCCESS) {
5094 EL(qlt, "qlt_mbox_command=7Ch status=%llxh\n", ret);
5095 cmn_err(CE_WARN, "qlt(%d) GET ID list failed, ret = %llx, "
5096 "mb0=%x, mb1=%x, mb2=%x", qlt->instance, (long long)ret,
5097 mcp->from_fw[0], mcp->from_fw[1], mcp->from_fw[2]);
5098 qlt_free_mailbox_command(qlt, mcp);
5099 return (ret);
5100 }
5101
5102 EL(qlt, "mbx cmd=7Ch, GET_ID_LIST id=%x fw[1]=%x\n",
5103 id, mcp->from_fw[1]);
5104
5105 qlt_dmem_dma_sync(mcp->dbuf, DDI_DMA_SYNC_FORCPU);
5106 p = mcp->dbuf->db_sglist[0].seg_addr;
5107 for (n = 0; n < mcp->from_fw[1]; n++) {
5108 ent_id = LE_32(*((uint32_t *)p)) & 0xFFFFFF;
5109 h = (uint16_t)((uint16_t)p[4] | (((uint16_t)p[5]) << 8));
5110 if (ent_id == id) {
5111 found = 1;
5112 *ret_handle = h;
5113 if ((cmd_handle != FCT_HANDLE_NONE) &&
5114 (cmd_handle != h)) {
5115 cmn_err(CE_WARN, "qlt(%d) login for portid %x "
5116 "came in with handle %x, while the portid "
5117 "was already using a different handle %x",
5118 qlt->instance, id, cmd_handle, h);
5119 qlt_free_mailbox_command(qlt, mcp);
5120 return (QLT_FAILURE);
5121 }
5122 break;
5123 }
5124 if ((cmd_handle != FCT_HANDLE_NONE) && (h == cmd_handle)) {
5125 cmn_err(CE_WARN, "qlt(%d) login for portid %x came in "
5126 "with handle %x, while the handle was already in "
5127 "use for portid %x",
5128 qlt->instance, id, cmd_handle, ent_id);
5129 qlt_free_mailbox_command(qlt, mcp);
5130 return (QLT_FAILURE);
5131 }
5132 p += 8;
5133 }
5134 if (!found) {
5135 *ret_handle = cmd_handle;
5136 }
5137 qlt_free_mailbox_command(qlt, mcp);
5138 return (FCT_SUCCESS);
5139 }
5140
5141 /* ARGSUSED */
5142 fct_status_t
qlt_fill_plogi_req(fct_local_port_t * port,fct_remote_port_t * rp,fct_cmd_t * login)5143 qlt_fill_plogi_req(fct_local_port_t *port, fct_remote_port_t *rp,
5144 fct_cmd_t *login)
5145 {
5146 uint8_t *p;
5147
5148 p = ((fct_els_t *)login->cmd_specific)->els_req_payload;
5149 p[0] = ELS_OP_PLOGI;
5150 *((uint16_t *)(&p[4])) = 0x2020;
5151 p[7] = 3;
5152 p[8] = 0x88;
5153 p[10] = 8;
5154 p[13] = 0xff; p[15] = 0x1f;
5155 p[18] = 7; p[19] = 0xd0;
5156
5157 bcopy(port->port_pwwn, p + 20, 8);
5158 bcopy(port->port_nwwn, p + 28, 8);
5159
5160 p[68] = 0x80;
5161 p[74] = 8;
5162 p[77] = 0xff;
5163 p[81] = 1;
5164
5165 return (FCT_SUCCESS);
5166 }
5167
5168 /* ARGSUSED */
5169 fct_status_t
qlt_fill_plogi_resp(fct_local_port_t * port,fct_remote_port_t * rp,fct_cmd_t * login)5170 qlt_fill_plogi_resp(fct_local_port_t *port, fct_remote_port_t *rp,
5171 fct_cmd_t *login)
5172 {
5173 return (FCT_SUCCESS);
5174 }
5175
5176 fct_status_t
qlt_register_remote_port(fct_local_port_t * port,fct_remote_port_t * rp,fct_cmd_t * login)5177 qlt_register_remote_port(fct_local_port_t *port, fct_remote_port_t *rp,
5178 fct_cmd_t *login)
5179 {
5180 uint16_t h;
5181 fct_status_t ret;
5182 qlt_state_t *qlt = (qlt_state_t *)port->port_fca_private;
5183
5184 switch (rp->rp_id) {
5185 case 0xFFFFFC: h = 0x7FC; break;
5186 case 0xFFFFFD: h = 0x7FD; break;
5187 case 0xFFFFFE: h = 0x7FE; break;
5188 case 0xFFFFFF: h = 0x7FF; break;
5189 default:
5190 ret = qlt_portid_to_handle(qlt, rp->rp_id,
5191 login->cmd_rp_handle, &h);
5192 if (ret != FCT_SUCCESS) {
5193 EL(qlt, "qlt_portid_to_handle, status=%llxh\n", ret);
5194 return (ret);
5195 }
5196 }
5197
5198 if (login->cmd_type == FCT_CMD_SOL_ELS) {
5199 ret = qlt_fill_plogi_req(port, rp, login);
5200 } else {
5201 ret = qlt_fill_plogi_resp(port, rp, login);
5202 }
5203
5204 if (ret != FCT_SUCCESS) {
5205 EL(qlt, "qlt_fill_plogi, status=%llxh\n", ret);
5206 return (ret);
5207 }
5208
5209 EL(qlt, "rport id=%xh cmd_type=%xh handle=%xh(%xh)\n",
5210 rp->rp_id, login->cmd_type, h, rp->rp_handle);
5211
5212 if (h == FCT_HANDLE_NONE)
5213 return (FCT_SUCCESS);
5214
5215 if (rp->rp_handle == FCT_HANDLE_NONE) {
5216 rp->rp_handle = h;
5217 return (FCT_SUCCESS);
5218 }
5219
5220 if (rp->rp_handle == h)
5221 return (FCT_SUCCESS);
5222
5223 EL(qlt, "failed, rp_handle=%xh != h=%xh\n", rp->rp_handle, h);
5224 return (FCT_FAILURE);
5225 }
5226
5227 /* invoked in single thread */
5228 fct_status_t
qlt_deregister_remote_port(fct_local_port_t * port,fct_remote_port_t * rp)5229 qlt_deregister_remote_port(fct_local_port_t *port, fct_remote_port_t *rp)
5230 {
5231 uint8_t *req;
5232 qlt_state_t *qlt;
5233 clock_t dereg_req_timer;
5234 fct_status_t ret;
5235
5236 qlt = (qlt_state_t *)port->port_fca_private;
5237
5238 if ((qlt->qlt_state == FCT_STATE_OFFLINE) ||
5239 (qlt->qlt_state == FCT_STATE_OFFLINING))
5240 return (FCT_SUCCESS);
5241 ASSERT(qlt->rp_id_in_dereg == 0);
5242
5243 if ((qlt->qlt_83xx_chip) || (qlt->qlt_27xx_chip)) {
5244 mutex_enter(&qlt->mq_req[0].mq_lock);
5245 req = (uint8_t *)qlt_get_req_entries(qlt, 1, 0);
5246 if (req == NULL) {
5247 EL(qlt, "req = NULL\n");
5248 mutex_exit(&qlt->mq_req[0].mq_lock);
5249 return (FCT_BUSY);
5250 }
5251 } else {
5252 mutex_enter(&qlt->preq_lock);
5253 req = (uint8_t *)qlt_get_preq_entries(qlt, 1);
5254 if (req == NULL) {
5255 EL(qlt, "req = NULL\n");
5256 mutex_exit(&qlt->preq_lock);
5257 return (FCT_BUSY);
5258 }
5259 }
5260 bzero(req, IOCB_SIZE);
5261 req[0] = 0x52; req[1] = 1;
5262 /* QMEM_WR32(qlt, (&req[4]), 0xffffffff); */
5263 QMEM_WR16(qlt, (&req[0xA]), rp->rp_handle);
5264 QMEM_WR16(qlt, (&req[0xC]), 0x98); /* implicit logo */
5265 QMEM_WR32(qlt, (&req[0x10]), rp->rp_id);
5266 qlt->rp_id_in_dereg = rp->rp_id;
5267 if ((qlt->qlt_83xx_chip) || (qlt->qlt_27xx_chip)) {
5268 qlt_submit_req_entries(qlt, 1, 0);
5269 } else {
5270 qlt_submit_preq_entries(qlt, 1);
5271 }
5272
5273 dereg_req_timer = ddi_get_lbolt() + drv_usectohz(DEREG_RP_TIMEOUT);
5274 if (cv_timedwait(&qlt->rp_dereg_cv,
5275 (((qlt->qlt_83xx_chip) || (qlt->qlt_27xx_chip)) ?
5276 &qlt->mq_req[0].mq_lock : &qlt->preq_lock),
5277 dereg_req_timer) > 0) {
5278 ret = qlt->rp_dereg_status;
5279 } else {
5280 ret = FCT_BUSY;
5281 }
5282 qlt->rp_dereg_status = 0;
5283 qlt->rp_id_in_dereg = 0;
5284 if ((qlt->qlt_83xx_chip) || (qlt->qlt_27xx_chip)) {
5285 mutex_exit(&qlt->mq_req[0].mq_lock);
5286 } else {
5287 mutex_exit(&qlt->preq_lock);
5288 }
5289
5290 EL(qlt, "Dereg remote port(%Xh), ret=%llxh\n",
5291 rp->rp_id, ret);
5292
5293 return (ret);
5294 }
5295
5296 /*
5297 * Pass received ELS up to framework.
5298 */
5299 static void
qlt_handle_purex(qlt_state_t * qlt,uint8_t * resp)5300 qlt_handle_purex(qlt_state_t *qlt, uint8_t *resp)
5301 {
5302 fct_cmd_t *cmd;
5303 fct_els_t *els;
5304 qlt_cmd_t *qcmd;
5305 uint32_t payload_size;
5306 uint32_t remote_portid;
5307 uint8_t *pldptr, *bndrptr;
5308 int i, off;
5309 uint16_t iocb_flags;
5310 char info[160];
5311
5312 remote_portid = ((uint32_t)(QMEM_RD16(qlt, (&resp[0x18])))) |
5313 ((uint32_t)(resp[0x1A])) << 16;
5314 iocb_flags = QMEM_RD16(qlt, (&resp[8]));
5315 if (iocb_flags & BIT_15) {
5316 payload_size = (QMEM_RD16(qlt, (&resp[0x0e])) & 0xfff) - 24;
5317 } else {
5318 payload_size = QMEM_RD16(qlt, (&resp[0x0c])) - 24;
5319 }
5320
5321 if (payload_size > ((uint32_t)resp[1] * IOCB_SIZE - 0x2C)) {
5322 EL(qlt, "payload is too large = %xh\n", payload_size);
5323 cmn_err(CE_WARN, "handle_purex: payload is too large");
5324 goto cmd_null;
5325 }
5326
5327 cmd = (fct_cmd_t *)fct_alloc(FCT_STRUCT_CMD_RCVD_ELS,
5328 (int)(payload_size + GET_STRUCT_SIZE(qlt_cmd_t)), 0);
5329 if (cmd == NULL) {
5330 EL(qlt, "fct_alloc cmd==NULL\n");
5331 cmd_null:;
5332 (void) snprintf(info, 160, "qlt_handle_purex: qlt-%p, can't "
5333 "allocate space for fct_cmd", (void *)qlt);
5334 info[159] = 0;
5335 (void) fct_port_shutdown(qlt->qlt_port,
5336 STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info);
5337 return;
5338 }
5339
5340 cmd->cmd_port = qlt->qlt_port;
5341 cmd->cmd_rp_handle = QMEM_RD16(qlt, resp+0xa);
5342 if (cmd->cmd_rp_handle == 0xFFFF) {
5343 cmd->cmd_rp_handle = FCT_HANDLE_NONE;
5344 }
5345
5346 els = (fct_els_t *)cmd->cmd_specific;
5347 qcmd = (qlt_cmd_t *)cmd->cmd_fca_private;
5348 els->els_req_size = (uint16_t)payload_size;
5349 els->els_req_payload = GET_BYTE_OFFSET(qcmd,
5350 GET_STRUCT_SIZE(qlt_cmd_t));
5351 qcmd->fw_xchg_addr = QMEM_RD32(qlt, (&resp[0x10]));
5352 cmd->cmd_rportid = remote_portid;
5353 cmd->cmd_lportid = ((uint32_t)(QMEM_RD16(qlt, (&resp[0x14])))) |
5354 ((uint32_t)(resp[0x16])) << 16;
5355 cmd->cmd_oxid = QMEM_RD16(qlt, (&resp[0x26]));
5356 cmd->cmd_rxid = QMEM_RD16(qlt, (&resp[0x24]));
5357 pldptr = &resp[0x2C];
5358 bndrptr = (uint8_t *)(qlt->mq_resp[0].mq_ptr
5359 + (RESPONSE_QUEUE_ENTRIES << 6));
5360 for (i = 0, off = 0x2c; i < payload_size; i += 4) {
5361 /* Take care of fw's swapping of payload */
5362 els->els_req_payload[i] = pldptr[3];
5363 els->els_req_payload[i+1] = pldptr[2];
5364 els->els_req_payload[i+2] = pldptr[1];
5365 els->els_req_payload[i+3] = pldptr[0];
5366 pldptr += 4;
5367 if (pldptr == bndrptr)
5368 pldptr = (uint8_t *)qlt->mq_resp[0].mq_ptr;
5369 off += 4;
5370 if (off >= IOCB_SIZE) {
5371 off = 4;
5372 pldptr += 4;
5373 }
5374 }
5375
5376 EL(qlt, "remote portid = %xh logi/o(%xh) to us revd rex1=%xh\n",
5377 remote_portid, els->els_req_payload[0], qcmd->fw_xchg_addr);
5378
5379 fct_post_rcvd_cmd(cmd, 0);
5380 }
5381
5382 fct_status_t
qlt_send_cmd_response(fct_cmd_t * cmd,uint32_t ioflags)5383 qlt_send_cmd_response(fct_cmd_t *cmd, uint32_t ioflags)
5384 {
5385 qlt_state_t *qlt;
5386 char info[160];
5387
5388 qlt = (qlt_state_t *)cmd->cmd_port->port_fca_private;
5389
5390 if (cmd->cmd_type == FCT_CMD_FCP_XCHG) {
5391 if (ioflags & FCT_IOF_FORCE_FCA_DONE) {
5392 EL(qlt, "ioflags = %xh\n", ioflags);
5393 goto fatal_panic;
5394 } else {
5395 return (qlt_send_status(qlt, cmd));
5396 }
5397 }
5398
5399 if (cmd->cmd_type == FCT_CMD_RCVD_ELS) {
5400 if (ioflags & FCT_IOF_FORCE_FCA_DONE) {
5401 goto fatal_panic;
5402 } else {
5403 return (qlt_send_els_response(qlt, cmd));
5404 }
5405 }
5406
5407 if (ioflags & FCT_IOF_FORCE_FCA_DONE) {
5408 cmd->cmd_handle = 0;
5409 }
5410
5411 if (cmd->cmd_type == FCT_CMD_RCVD_ABTS) {
5412 return (qlt_send_abts_response(qlt, cmd, 0));
5413 } else {
5414 EL(qlt, "cmd->cmd_type=%xh\n", cmd->cmd_type);
5415 ASSERT(0);
5416 return (FCT_FAILURE);
5417 }
5418
5419 fatal_panic:;
5420 (void) snprintf(info, 160, "qlt_send_cmd_response: can not handle "
5421 "FCT_IOF_FORCE_FCA_DONE for cmd %p, ioflags-%x", (void *)cmd,
5422 ioflags);
5423 info[159] = 0;
5424 (void) fct_port_shutdown(qlt->qlt_port,
5425 STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info);
5426 return (FCT_FAILURE);
5427 }
5428
5429 /* ARGSUSED */
5430 fct_status_t
qlt_xfer_scsi_data(fct_cmd_t * cmd,stmf_data_buf_t * dbuf,uint32_t ioflags)5431 qlt_xfer_scsi_data(fct_cmd_t *cmd, stmf_data_buf_t *dbuf, uint32_t ioflags)
5432 {
5433 qlt_dmem_bctl_t *bctl = (qlt_dmem_bctl_t *)dbuf->db_port_private;
5434 qlt_state_t *qlt = (qlt_state_t *)cmd->cmd_port->port_fca_private;
5435 qlt_cmd_t *qcmd = (qlt_cmd_t *)cmd->cmd_fca_private;
5436 uint8_t *req, rcnt;
5437 uint16_t flags;
5438 uint16_t cookie_count;
5439 uint32_t ent_cnt;
5440 uint16_t qi;
5441
5442 qi = qcmd->qid;
5443
5444 if (dbuf->db_handle == 0)
5445 qcmd->dbuf = dbuf;
5446 flags = (uint16_t)(((uint16_t)qcmd->param.atio_byte3 & 0xf0) << 5);
5447 if (dbuf->db_flags & DB_DIRECTION_TO_RPORT) {
5448 flags = (uint16_t)(flags | 2);
5449 qlt_dmem_dma_sync(dbuf, DDI_DMA_SYNC_FORDEV);
5450 } else {
5451 flags = (uint16_t)(flags | 1);
5452 }
5453
5454 if (dbuf->db_flags & DB_SEND_STATUS_GOOD)
5455 flags = (uint16_t)(flags | BIT_15);
5456
5457 if (dbuf->db_flags & DB_LU_DATA_BUF) {
5458 /*
5459 * Data bufs from LU are in scatter/gather list format.
5460 */
5461 cookie_count = qlt_get_cookie_count(dbuf);
5462 rcnt = qlt_get_iocb_count(cookie_count);
5463 } else {
5464 cookie_count = 1;
5465 rcnt = 1;
5466 }
5467 mutex_enter(&qlt->mq_req[qi].mq_lock);
5468 req = (uint8_t *)qlt_get_req_entries(qlt, 1, qi);
5469 if (req == NULL) {
5470 mutex_exit(&qlt->mq_req[qi].mq_lock);
5471 return (FCT_BUSY);
5472 }
5473 bzero(req, IOCB_SIZE);
5474 req[0] = 0x12;
5475 req[1] = rcnt;
5476 req[2] = dbuf->db_handle;
5477 QMEM_WR32_REQ(qlt, qi, req+4, cmd->cmd_handle);
5478 QMEM_WR16_REQ(qlt, qi, req+8, cmd->cmd_rp->rp_handle);
5479 QMEM_WR16_REQ(qlt, qi, req+10, 60); /* 60 seconds timeout */
5480 QMEM_WR16_REQ(qlt, qi, req+12, cookie_count);
5481 QMEM_WR32_REQ(qlt, qi, req+0x10, cmd->cmd_rportid);
5482 QMEM_WR32_REQ(qlt, qi, req+0x14, qcmd->fw_xchg_addr);
5483 QMEM_WR16_REQ(qlt, qi, req+0x1A, flags);
5484 QMEM_WR16_REQ(qlt, qi, req+0x20, cmd->cmd_oxid);
5485 QMEM_WR32_REQ(qlt, qi, req+0x24, dbuf->db_relative_offset);
5486 QMEM_WR32_REQ(qlt, qi, req+0x2C, dbuf->db_data_size);
5487 if (dbuf->db_flags & DB_LU_DATA_BUF) {
5488 uint8_t *qptr; /* qlt continuation segs */
5489 uint16_t cookie_resid;
5490 uint16_t cont_segs;
5491 ddi_dma_cookie_t cookie, *ckp;
5492
5493 /*
5494 * See if the dma cookies are in simple array format.
5495 */
5496 ckp = qlt_get_cookie_array(dbuf);
5497
5498 /*
5499 * Program the first segment into main record.
5500 */
5501 if (ckp) {
5502 ASSERT(ckp->dmac_size);
5503 QMEM_WR64_REQ(qlt, qi, req+0x34, ckp->dmac_laddress);
5504 QMEM_WR32_REQ(qlt, qi, req+0x3c, ckp->dmac_size);
5505 } else {
5506 qlt_ddi_dma_nextcookie(dbuf, &cookie);
5507 ASSERT(cookie.dmac_size);
5508 QMEM_WR64_REQ(qlt, qi, req+0x34, cookie.dmac_laddress);
5509 QMEM_WR32_REQ(qlt, qi, req+0x3c, cookie.dmac_size);
5510 }
5511 cookie_resid = cookie_count-1;
5512
5513 ent_cnt = (qi == 0) ? REQUEST_QUEUE_ENTRIES :
5514 REQUEST_QUEUE_MQ_ENTRIES;
5515 /*
5516 * Program remaining segments into continuation records.
5517 */
5518 while (cookie_resid) {
5519 req += IOCB_SIZE;
5520 if (req >= (uint8_t *)(qlt->mq_req[qi].mq_ptr +
5521 (ent_cnt * IOCB_SIZE))) {
5522 req = (uint8_t *)(qlt->mq_req[qi].mq_ptr);
5523 }
5524
5525 req[0] = 0x0a;
5526 req[1] = 1;
5527 req[2] = req[3] = 0; /* tidy */
5528 qptr = &req[4];
5529 for (cont_segs = CONT_A64_DATA_SEGMENTS;
5530 cont_segs && cookie_resid; cont_segs--) {
5531
5532 if (ckp) {
5533 ++ckp; /* next cookie */
5534 ASSERT(ckp->dmac_size != 0);
5535 QMEM_WR64_REQ(qlt, qi, qptr,
5536 ckp->dmac_laddress);
5537 qptr += 8; /* skip over laddress */
5538 QMEM_WR32_REQ(qlt, qi, qptr,
5539 ckp->dmac_size);
5540 qptr += 4; /* skip over size */
5541 } else {
5542 qlt_ddi_dma_nextcookie(dbuf, &cookie);
5543 ASSERT(cookie.dmac_size != 0);
5544 QMEM_WR64_REQ(qlt, qi, qptr,
5545 cookie.dmac_laddress);
5546 qptr += 8; /* skip over laddress */
5547 QMEM_WR32_REQ(qlt, qi, qptr,
5548 cookie.dmac_size);
5549 qptr += 4; /* skip over size */
5550 }
5551 cookie_resid--;
5552 }
5553 /*
5554 * zero unused remainder of IOCB
5555 */
5556 if (cont_segs) {
5557 size_t resid;
5558 resid = (size_t)((uintptr_t)(req+IOCB_SIZE) -
5559 (uintptr_t)qptr);
5560 ASSERT(resid < IOCB_SIZE);
5561 bzero(qptr, resid);
5562 }
5563 }
5564 } else {
5565 /* Single, contiguous buffer */
5566 QMEM_WR64_REQ(qlt, qi, req+0x34, bctl->bctl_dev_addr);
5567 QMEM_WR32_REQ(qlt, qi, req+0x34+8, dbuf->db_data_size);
5568 }
5569
5570 qlt_submit_req_entries(qlt, rcnt, qi);
5571 mutex_exit(&qlt->mq_req[qi].mq_lock);
5572
5573 return (STMF_SUCCESS);
5574 }
5575
5576 /*
5577 * We must construct proper FCP_RSP_IU now. Here we only focus on
5578 * the handling of FCP_SNS_INFO. If there's protocol failures (FCP_RSP_INFO),
5579 * we could have caught them before we enter here.
5580 */
5581 fct_status_t
qlt_send_status(qlt_state_t * qlt,fct_cmd_t * cmd)5582 qlt_send_status(qlt_state_t *qlt, fct_cmd_t *cmd)
5583 {
5584 qlt_cmd_t *qcmd = (qlt_cmd_t *)cmd->cmd_fca_private;
5585 scsi_task_t *task = (scsi_task_t *)cmd->cmd_specific;
5586 qlt_dmem_bctl_t *bctl;
5587 uint32_t size;
5588 uint8_t *req, *fcp_rsp_iu;
5589 uint8_t *psd, sensbuf[24]; /* sense data */
5590 uint16_t flags;
5591 uint16_t scsi_status;
5592 int use_mode2;
5593 int ndx;
5594 uint16_t qi;
5595
5596 qi = qcmd->qid;
5597
5598 /*
5599 * Enter fast channel for non check condition
5600 */
5601 if (task->task_scsi_status != STATUS_CHECK) {
5602 /*
5603 * We will use mode1
5604 */
5605 flags = (uint16_t)(BIT_6 | BIT_15 |
5606 (((uint16_t)qcmd->param.atio_byte3 & 0xf0) << 5));
5607 scsi_status = (uint16_t)task->task_scsi_status;
5608 if (task->task_status_ctrl == TASK_SCTRL_OVER) {
5609 scsi_status = (uint16_t)(scsi_status | FCP_RESID_OVER);
5610 } else if (task->task_status_ctrl == TASK_SCTRL_UNDER) {
5611 scsi_status = (uint16_t)(scsi_status | FCP_RESID_UNDER);
5612 }
5613 qcmd->dbuf_rsp_iu = NULL;
5614
5615 /*
5616 * Fillout CTIO type 7 IOCB
5617 */
5618 mutex_enter(&qlt->mq_req[qi].mq_lock);
5619 req = (uint8_t *)qlt_get_req_entries(qlt, 1, qi);
5620 if (req == NULL) {
5621 mutex_exit(&qlt->mq_req[qi].mq_lock);
5622 return (FCT_BUSY);
5623 }
5624
5625 /*
5626 * Common fields
5627 */
5628 bzero(req, IOCB_SIZE);
5629 req[0x00] = 0x12;
5630 req[0x01] = 0x1;
5631 req[0x02] = BIT_7; /* indicate if it's a pure status req */
5632 QMEM_WR32_REQ(qlt, qi, req + 0x04, cmd->cmd_handle);
5633 QMEM_WR16_REQ(qlt, qi, req + 0x08, cmd->cmd_rp->rp_handle);
5634 QMEM_WR32_REQ(qlt, qi, req + 0x10, cmd->cmd_rportid);
5635 QMEM_WR32_REQ(qlt, qi, req + 0x14, qcmd->fw_xchg_addr);
5636
5637 /* handle TMF completion - !!! Important FIX */
5638 if (task->task_mgmt_function) {
5639 scsi_status =
5640 (uint16_t)(scsi_status | FCP_RESP_LEN_VALID);
5641
5642 /* no sense length, 4 bytes of resp info */
5643 QMEM_WR16_REQ(qlt, qi, req + 0x24, 4);
5644 }
5645
5646 /*
5647 * Mode-specific fields
5648 */
5649 QMEM_WR16_REQ(qlt, qi, req + 0x1A, flags);
5650 QMEM_WR32_REQ(qlt, qi, req + 0x1C, task->task_resid);
5651 QMEM_WR16_REQ(qlt, qi, req + 0x20, cmd->cmd_oxid);
5652 QMEM_WR16_REQ(qlt, qi, req + 0x22, scsi_status);
5653
5654 /*
5655 * Trigger FW to send SCSI status out
5656 */
5657 qlt_submit_req_entries(qlt, 1, qi);
5658 mutex_exit(&qlt->mq_req[qi].mq_lock);
5659 return (STMF_SUCCESS);
5660 }
5661
5662 ASSERT(task->task_scsi_status == STATUS_CHECK);
5663 /*
5664 * Decide the SCSI status mode, that should be used
5665 */
5666 use_mode2 = (task->task_sense_length > 24);
5667
5668 /*
5669 * Prepare required information per the SCSI status mode
5670 */
5671 flags = (uint16_t)(BIT_15 |
5672 (((uint16_t)qcmd->param.atio_byte3 & 0xf0) << 5));
5673 if (use_mode2) {
5674 flags = (uint16_t)(flags | BIT_7);
5675
5676 size = task->task_sense_length;
5677 qcmd->dbuf_rsp_iu = qlt_i_dmem_alloc(qlt,
5678 task->task_sense_length, &size, 0);
5679 if (!qcmd->dbuf_rsp_iu) {
5680 return (FCT_ALLOC_FAILURE);
5681 }
5682
5683 /*
5684 * Start to construct FCP_RSP IU
5685 */
5686 fcp_rsp_iu = qcmd->dbuf_rsp_iu->db_sglist[0].seg_addr;
5687 bzero(fcp_rsp_iu, 24);
5688
5689 /*
5690 * FCP_RSP IU flags, byte10
5691 */
5692 fcp_rsp_iu[10] = (uint8_t)(fcp_rsp_iu[10] | BIT_1);
5693 if (task->task_status_ctrl == TASK_SCTRL_OVER) {
5694 fcp_rsp_iu[10] = (uint8_t)(fcp_rsp_iu[10] | BIT_2);
5695 } else if (task->task_status_ctrl == TASK_SCTRL_UNDER) {
5696 fcp_rsp_iu[10] = (uint8_t)(fcp_rsp_iu[10] | BIT_3);
5697 }
5698
5699 /*
5700 * SCSI status code, byte11
5701 */
5702 fcp_rsp_iu[11] = task->task_scsi_status;
5703
5704 /*
5705 * FCP_RESID (Overrun or underrun)
5706 */
5707 fcp_rsp_iu[12] = (uint8_t)((task->task_resid >> 24) & 0xFF);
5708 fcp_rsp_iu[13] = (uint8_t)((task->task_resid >> 16) & 0xFF);
5709 fcp_rsp_iu[14] = (uint8_t)((task->task_resid >> 8) & 0xFF);
5710 fcp_rsp_iu[15] = (uint8_t)((task->task_resid >> 0) & 0xFF);
5711
5712 /*
5713 * FCP_SNS_LEN
5714 */
5715 fcp_rsp_iu[18] = (uint8_t)((task->task_sense_length >> 8) &
5716 0xFF);
5717 fcp_rsp_iu[19] = (uint8_t)((task->task_sense_length >> 0) &
5718 0xFF);
5719
5720 /*
5721 * FCP_RSP_LEN
5722 */
5723 /*
5724 * no FCP_RSP_INFO
5725 */
5726 /*
5727 * FCP_SNS_INFO
5728 */
5729 bcopy(task->task_sense_data, fcp_rsp_iu + 24,
5730 task->task_sense_length);
5731
5732 /*
5733 * Ensure dma data consistency
5734 */
5735 qlt_dmem_dma_sync(qcmd->dbuf_rsp_iu, DDI_DMA_SYNC_FORDEV);
5736 } else {
5737 flags = (uint16_t)(flags | BIT_6);
5738
5739 scsi_status = (uint16_t)task->task_scsi_status;
5740 if (task->task_status_ctrl == TASK_SCTRL_OVER) {
5741 scsi_status = (uint16_t)(scsi_status | BIT_10);
5742 } else if (task->task_status_ctrl == TASK_SCTRL_UNDER) {
5743 scsi_status = (uint16_t)(scsi_status | BIT_11);
5744 }
5745 if (task->task_sense_length) {
5746 scsi_status = (uint16_t)(scsi_status | BIT_9);
5747 }
5748 bcopy(task->task_sense_data, sensbuf, task->task_sense_length);
5749 qcmd->dbuf_rsp_iu = NULL;
5750 }
5751
5752 /*
5753 * Fillout CTIO type 7 IOCB
5754 */
5755 mutex_enter(&qlt->mq_req[qi].mq_lock);
5756 req = (uint8_t *)qlt_get_req_entries(qlt, 1, qi);
5757 if (req == NULL) {
5758 mutex_exit(&qlt->mq_req[qi].mq_lock);
5759 if (use_mode2) {
5760 qlt_dmem_free(cmd->cmd_port->port_fds,
5761 qcmd->dbuf_rsp_iu);
5762 qcmd->dbuf_rsp_iu = NULL;
5763 }
5764 return (FCT_BUSY);
5765 }
5766
5767 /*
5768 * Common fields
5769 */
5770 bzero(req, IOCB_SIZE);
5771 req[0x00] = 0x12;
5772 req[0x01] = 0x1;
5773 req[0x02] = BIT_7; /* to indicate if it's a pure status req */
5774 QMEM_WR32_REQ(qlt, qi, req + 0x04, cmd->cmd_handle);
5775 QMEM_WR16_REQ(qlt, qi, req + 0x08, cmd->cmd_rp->rp_handle);
5776 QMEM_WR16_REQ(qlt, qi, req + 0x0A, 0); /* not timed by FW */
5777 if (use_mode2) {
5778 /* FCP RSP IU data field */
5779 QMEM_WR16_REQ(qlt, qi, req+0x0C, 1);
5780 }
5781 QMEM_WR32_REQ(qlt, qi, req + 0x10, cmd->cmd_rportid);
5782 QMEM_WR32_REQ(qlt, qi, req + 0x14, qcmd->fw_xchg_addr);
5783
5784 /*
5785 * Mode-specific fields
5786 */
5787 if (!use_mode2) {
5788 QMEM_WR16_REQ(qlt, qi, req + 0x18, task->task_sense_length);
5789 }
5790 QMEM_WR16_REQ(qlt, qi, req + 0x1A, flags);
5791 QMEM_WR32_REQ(qlt, qi, req + 0x1C, task->task_resid);
5792 QMEM_WR16_REQ(qlt, qi, req + 0x20, cmd->cmd_oxid);
5793 if (use_mode2) {
5794 bctl = (qlt_dmem_bctl_t *)qcmd->dbuf_rsp_iu->db_port_private;
5795 QMEM_WR32_REQ(qlt, qi, req + 0x2C,
5796 24 + task->task_sense_length);
5797 QMEM_WR64_REQ(qlt, qi, req + 0x34, bctl->bctl_dev_addr);
5798 QMEM_WR32_REQ(qlt, qi, req + 0x3C,
5799 24 + task->task_sense_length);
5800 } else {
5801 QMEM_WR16_REQ(qlt, qi, req + 0x22, scsi_status);
5802 psd = req+0x28;
5803
5804 /*
5805 * Data in sense buf is always big-endian, data in IOCB
5806 * should always be little-endian, so we must do swapping.
5807 */
5808 size = ((task->task_sense_length + 3) & (~3));
5809 for (ndx = 0; ndx < size; ndx += 4) {
5810 psd[ndx + 0] = sensbuf[ndx + 3];
5811 psd[ndx + 1] = sensbuf[ndx + 2];
5812 psd[ndx + 2] = sensbuf[ndx + 1];
5813 psd[ndx + 3] = sensbuf[ndx + 0];
5814 }
5815 }
5816
5817 /*
5818 * Trigger FW to send SCSI status out
5819 */
5820 qlt_submit_req_entries(qlt, 1, qi);
5821 mutex_exit(&qlt->mq_req[qi].mq_lock);
5822
5823 return (STMF_SUCCESS);
5824 }
5825
5826 fct_status_t
qlt_send_els_response(qlt_state_t * qlt,fct_cmd_t * cmd)5827 qlt_send_els_response(qlt_state_t *qlt, fct_cmd_t *cmd)
5828 {
5829 qlt_cmd_t *qcmd;
5830 fct_els_t *els = (fct_els_t *)cmd->cmd_specific;
5831 uint8_t *req, *addr;
5832 qlt_dmem_bctl_t *bctl;
5833 uint32_t minsize;
5834 uint8_t elsop, req1f;
5835 uint16_t qi = 0;
5836
5837 addr = els->els_resp_payload;
5838 qcmd = (qlt_cmd_t *)cmd->cmd_fca_private;
5839
5840 minsize = els->els_resp_size;
5841 qcmd->dbuf = qlt_i_dmem_alloc(qlt, els->els_resp_size, &minsize, 0);
5842 if (qcmd->dbuf == NULL)
5843 return (FCT_BUSY);
5844
5845 bctl = (qlt_dmem_bctl_t *)qcmd->dbuf->db_port_private;
5846
5847 bcopy(addr, qcmd->dbuf->db_sglist[0].seg_addr, els->els_resp_size);
5848 qlt_dmem_dma_sync(qcmd->dbuf, DDI_DMA_SYNC_FORDEV);
5849
5850 if (addr[0] == 0x02) { /* ACC */
5851 req1f = BIT_5;
5852 } else {
5853 req1f = BIT_6;
5854 }
5855 elsop = els->els_req_payload[0];
5856 if ((elsop == ELS_OP_PRLI) || (elsop == ELS_OP_PRLO) ||
5857 (elsop == ELS_OP_TPRLO) || (elsop == ELS_OP_LOGO)) {
5858 req1f = (uint8_t)(req1f | BIT_4);
5859 }
5860
5861 mutex_enter(&qlt->mq_req[qi].mq_lock);
5862 req = (uint8_t *)qlt_get_req_entries(qlt, 1, qi);
5863 if (req == NULL) {
5864 EL(qlt, "req = NULL, %xh %xh %p %xh\n", cmd->cmd_oxid,
5865 cmd->cmd_rportid, cmd, qcmd->fw_xchg_addr);
5866 mutex_exit(&qlt->mq_req[qi].mq_lock);
5867 qlt_dmem_free(NULL, qcmd->dbuf);
5868 qcmd->dbuf = NULL;
5869 return (FCT_BUSY);
5870 }
5871 bzero(req, IOCB_SIZE);
5872 req[0] = 0x53; req[1] = 1; req[0xf] = 0x10;
5873 req[0x16] = elsop; req[0x1f] = req1f;
5874 QMEM_WR32(qlt, (&req[4]), cmd->cmd_handle);
5875 QMEM_WR16(qlt, (&req[0xA]), cmd->cmd_rp->rp_handle);
5876 QMEM_WR16(qlt, (&req[0xC]), 1);
5877 QMEM_WR32(qlt, (&req[0x10]), qcmd->fw_xchg_addr);
5878 QMEM_WR32(qlt, (&req[0x18]), cmd->cmd_rportid);
5879 if (qlt->cur_topology == PORT_TOPOLOGY_PT_TO_PT) {
5880 req[0x1b] = (uint8_t)((cmd->cmd_lportid >> 16) & 0xff);
5881 req[0x1c] = (uint8_t)(cmd->cmd_lportid & 0xff);
5882 req[0x1d] = (uint8_t)((cmd->cmd_lportid >> 8) & 0xff);
5883 }
5884 QMEM_WR32(qlt, (&req[0x24]), els->els_resp_size);
5885 QMEM_WR64(qlt, (&req[0x28]), bctl->bctl_dev_addr);
5886 QMEM_WR32(qlt, (&req[0x30]), els->els_resp_size);
5887
5888 EL(qlt, "elsop=%xh req1f=%xh IOCB_TYPE_ELSPASS: rex1=%xh\n",
5889 elsop, req1f, qcmd->fw_xchg_addr);
5890
5891 qlt_submit_req_entries(qlt, 1, qi);
5892 mutex_exit(&qlt->mq_req[qi].mq_lock);
5893
5894 return (FCT_SUCCESS);
5895 }
5896
5897 fct_status_t
qlt_send_abts_response(qlt_state_t * qlt,fct_cmd_t * cmd,int terminate)5898 qlt_send_abts_response(qlt_state_t *qlt, fct_cmd_t *cmd, int terminate)
5899 {
5900 qlt_abts_cmd_t *qcmd;
5901 fct_rcvd_abts_t *abts = (fct_rcvd_abts_t *)cmd->cmd_specific;
5902 uint8_t *req;
5903 uint32_t lportid;
5904 uint32_t fctl;
5905 int i;
5906 uint16_t qi;
5907 uint32_t rex1, rex2;
5908 uint8_t temp[64];
5909
5910 qi = 0;
5911
5912 qcmd = (qlt_abts_cmd_t *)cmd->cmd_fca_private;
5913
5914 mutex_enter(&qlt->mq_req[qi].mq_lock);
5915 req = (uint8_t *)qlt_get_req_entries(qlt, 1, qi);
5916 if (req == NULL) {
5917 bcopy(qcmd->buf, &temp, IOCB_SIZE);
5918 for (i = 0; i < 12; i += 4) {
5919 /* Take care of firmware's LE requirement */
5920 temp[0x2C+i] = abts->abts_resp_payload[i+3];
5921 temp[0x2C+i+1] = abts->abts_resp_payload[i+2];
5922 temp[0x2C+i+2] = abts->abts_resp_payload[i+1];
5923 temp[0x2C+i+3] = abts->abts_resp_payload[i];
5924 }
5925 rex1 = QMEM_RD32(qlt, &temp[0x10]);
5926 rex2 = QMEM_RD32(qlt, &temp[0x3C]);
5927
5928 EL(qlt, "req = NULL, %xh %xh %p %xh %xh\n", cmd->cmd_oxid,
5929 cmd->cmd_rportid, cmd, rex1, rex2);
5930
5931 mutex_exit(&qlt->mq_req[qi].mq_lock);
5932 return (FCT_BUSY);
5933 }
5934 bcopy(qcmd->buf, req, IOCB_SIZE);
5935 lportid = QMEM_RD32(qlt, req+0x14) & 0xFFFFFF;
5936 fctl = QMEM_RD32(qlt, req+0x1C);
5937 fctl = ((fctl ^ BIT_23) & ~BIT_22) | (BIT_19 | BIT_16);
5938 req[0] = 0x55; req[1] = 1; req[2] = (uint8_t)terminate;
5939 QMEM_WR32(qlt, (&req[4]), cmd->cmd_handle);
5940 if (cmd->cmd_rp)
5941 QMEM_WR16(qlt, (&req[0xA]), cmd->cmd_rp->rp_handle);
5942 else
5943 QMEM_WR16(qlt, (&req[0xA]), cmd->cmd_rp_handle);
5944 if (terminate) {
5945 QMEM_WR16(qlt, (&req[0xC]), 1);
5946 }
5947 QMEM_WR32(qlt, req+0x14, cmd->cmd_rportid);
5948 req[0x17] = abts->abts_resp_rctl;
5949 QMEM_WR32(qlt, req+0x18, lportid);
5950 QMEM_WR32(qlt, req+0x1C, fctl);
5951 req[0x23]++;
5952 for (i = 0; i < 12; i += 4) {
5953 /* Take care of firmware's LE requirement */
5954 req[0x2C+i] = abts->abts_resp_payload[i+3];
5955 req[0x2C+i+1] = abts->abts_resp_payload[i+2];
5956 req[0x2C+i+2] = abts->abts_resp_payload[i+1];
5957 req[0x2C+i+3] = abts->abts_resp_payload[i];
5958 }
5959
5960 rex1 = QMEM_RD32(qlt, &req[0x10]);
5961 rex2 = QMEM_RD32(qlt, &req[0x3C]);
5962
5963 EL(qlt, "%xh %xh %d %p %xh %xh\n",
5964 QMEM_RD16(qlt, req+0x26), QMEM_RD16(qlt, req+0x24),
5965 terminate, cmd, rex1, rex2);
5966
5967 qlt_submit_req_entries(qlt, 1, qi);
5968 mutex_exit(&qlt->mq_req[qi].mq_lock);
5969
5970 return (FCT_SUCCESS);
5971 }
5972
5973 static void
qlt_handle_inot(qlt_state_t * qlt,uint8_t * inot)5974 qlt_handle_inot(qlt_state_t *qlt, uint8_t *inot)
5975 {
5976 int i;
5977 uint32_t d;
5978 caddr_t req;
5979 uint16_t qi;
5980 uint8_t *entry = inot;
5981
5982 qi = 0;
5983
5984 /* Just put it on the request queue */
5985 mutex_enter(&qlt->mq_req[qi].mq_lock);
5986 req = qlt_get_req_entries(qlt, 1, qi);
5987 if (req == NULL) {
5988 mutex_exit(&qlt->mq_req[qi].mq_lock);
5989 stmf_trace(qlt->qlt_port_alias,
5990 "qlt_handle_inot: can't get a ReqQ entry");
5991 EL(qlt, "req = NULL\n");
5992 return;
5993 }
5994 for (i = 0; i < 16; i++) {
5995 d = QMEM_RD32(qlt, inot);
5996 inot += 4;
5997 QMEM_WR32(qlt, req, d);
5998 req += 4;
5999 }
6000 req -= 64;
6001 req[0] = 0x0e;
6002
6003 QMEM_WR32(qlt, entry+0x3c, 0xdeadbeef);
6004 EL(qlt, "Issue inot ack\n");
6005
6006 qlt_submit_req_entries(qlt, 1, qi);
6007 mutex_exit(&qlt->mq_req[qi].mq_lock);
6008 }
6009
6010 static uint16_t
qlt_get_queue_id(qlt_state_t * qlt,int id)6011 qlt_get_queue_id(qlt_state_t *qlt, int id)
6012 {
6013 uint16_t qid;
6014
6015 if ((!qlt->qlt_mq_enabled) || (qlt->qlt_queue_cnt == 1)) {
6016 return (0);
6017 }
6018
6019 mutex_enter(&qlt->qlock);
6020 if ((id == 0) && (qlt->last_qi == 0)) {
6021 qlt->last_qi++;
6022 }
6023 qid = qlt->last_qi;
6024 qlt->last_qi++;
6025
6026 if (qlt->last_qi >= qlt->qlt_queue_cnt) {
6027 qlt->last_qi -= qlt->qlt_queue_cnt;
6028 }
6029 mutex_exit(&qlt->qlock);
6030
6031 return (qid);
6032 }
6033
6034 static fct_status_t
qlt_verify_atio_entry(qlt_state_t * qlt,uint8_t * atio)6035 qlt_verify_atio_entry(qlt_state_t *qlt, uint8_t *atio)
6036 {
6037 uint32_t sig;
6038 int i;
6039 char info[160];
6040
6041
6042 sig = QMEM_RD32(qlt, atio+0x3c);
6043 for (i = 0; ((sig == 0xdeadbeef) &&
6044 (i < qlt_reprocess_attempt_cnt)); i++) {
6045 (void) ddi_dma_sync(
6046 qlt->queue_mem_dma_handle,
6047 ATIO_QUEUE_OFFSET + (qlt->atio_ndx_to_fw << 6),
6048 IOCB_SIZE, DDI_DMA_SYNC_FORCPU);
6049
6050 qlt->qlt_atio_reproc_cnt++;
6051 drv_usecwait(qlt_reprocess_delay);
6052 sig = QMEM_RD32(qlt, atio+0x3c);
6053 }
6054
6055 if (i) {
6056 if (i >= qlt_reprocess_attempt_cnt) {
6057 EL(qlt, "atio entry reprocess failed, %x\n",
6058 qlt->qlt_atio_reproc_cnt);
6059 cmn_err(CE_WARN, "qlt%d: atio entry reprocess"
6060 " failed %x\n",
6061 qlt->instance, qlt->qlt_atio_reproc_cnt);
6062 (void) snprintf(info, 160,
6063 "qlt_handle_ctio_completion: atio entry reprocess"
6064 " failed, %x rsp-%p",
6065 qlt->qlt_atio_reproc_cnt, (void *)atio);
6066 info[159] = 0;
6067 (void) fct_port_shutdown(qlt->qlt_port,
6068 STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET |
6069 STMF_RFLAG_COLLECT_DEBUG_DUMP, info);
6070 return (QLT_FAILURE);
6071 } else {
6072 EL(qlt, "atio entry reprocess succeeded, %x %x\n",
6073 i, qlt->qlt_atio_reproc_cnt);
6074 }
6075 }
6076
6077 return (QLT_SUCCESS);
6078 }
6079
6080 uint8_t qlt_task_flags[] = { 1, 3, 2, 1, 4, 0, 1, 1 };
6081 static void
qlt_handle_atio(qlt_state_t * qlt,uint8_t * atio)6082 qlt_handle_atio(qlt_state_t *qlt, uint8_t *atio)
6083 {
6084 fct_cmd_t *cmd;
6085 scsi_task_t *task;
6086 qlt_cmd_t *qcmd;
6087 uint32_t rportid, fw_xchg_addr;
6088 uint8_t *p, *q, *req, tm;
6089 uint16_t cdb_size, flags, oxid;
6090 char info[160];
6091 uint16_t qi;
6092
6093 if (qlt_verify_atio_entry(qlt, atio) != QLT_SUCCESS)
6094 return;
6095
6096 /*
6097 * If either bidirection xfer is requested of there is extended
6098 * CDB, atio[0x20 + 11] will be greater than or equal to 3.
6099 */
6100 cdb_size = 16;
6101 if (atio[0x20 + 11] >= 3) {
6102 uint8_t b = atio[0x20 + 11];
6103 uint16_t b1;
6104 if ((b & 3) == 3) {
6105 EL(qlt, "bidirectional I/O not supported\n");
6106 cmn_err(CE_WARN, "qlt(%d) CMD with bidirectional I/O "
6107 "received, dropping the cmd as bidirectional "
6108 " transfers are not yet supported", qlt->instance);
6109 /* XXX abort the I/O */
6110 return;
6111 }
6112 cdb_size = (uint16_t)(cdb_size + (b & 0xfc));
6113 /*
6114 * Verify that we have enough entries. Without additional CDB
6115 * Everything will fit nicely within the same 64 bytes. So the
6116 * additional cdb size is essentially the # of additional bytes
6117 * we need.
6118 */
6119 b1 = (uint16_t)b;
6120 if (((((b1 & 0xfc) + 63) >> 6) + 1) > ((uint16_t)atio[1])) {
6121 EL(qlt, "extended cdb received\n");
6122 cmn_err(CE_WARN, "qlt(%d): cmd received with extended "
6123 " cdb (cdb size = %d bytes), however the firmware "
6124 " did not DMAed the entire FCP_CMD IU, entry count "
6125 " is %d while it should be %d", qlt->instance,
6126 cdb_size, atio[1], ((((b1 & 0xfc) + 63) >> 6) + 1));
6127 /* XXX abort the I/O */
6128 return;
6129 }
6130 }
6131
6132 rportid = (((uint32_t)atio[8 + 5]) << 16) |
6133 (((uint32_t)atio[8 + 6]) << 8) | atio[8+7];
6134 fw_xchg_addr = QMEM_RD32(qlt, atio+4);
6135 oxid = (uint16_t)((((uint16_t)atio[8 + 16]) << 8) | atio[8+17]);
6136
6137 if (fw_xchg_addr == 0xFFFFFFFF) {
6138 EL(qlt, "fw_xchg_addr==0xFFFFFFFF\n");
6139 cmd = NULL;
6140 } else {
6141 cmd = fct_scsi_task_alloc(qlt->qlt_port, FCT_HANDLE_NONE,
6142 rportid, atio+0x20, cdb_size, STMF_TASK_EXT_NONE);
6143 if (cmd == NULL) {
6144 EL(qlt, "fct_scsi_task_alloc cmd==NULL\n");
6145 }
6146 }
6147 if (cmd == NULL) {
6148 qi = 0; /* just use request queue 0 */
6149
6150 EL(qlt, "fct_scsi_task_alloc cmd==NULL\n");
6151 /* Abort this IO */
6152 flags = (uint16_t)(BIT_14 | ((atio[3] & 0xF0) << 5));
6153
6154 mutex_enter(&qlt->mq_req[qi].mq_lock);
6155 req = (uint8_t *)qlt_get_req_entries(qlt, 1, qi);
6156 if (req == NULL) {
6157 mutex_exit(&qlt->mq_req[0].mq_lock);
6158
6159 (void) snprintf(info, 160,
6160 "qlt_handle_atio: qlt-%p, can't "
6161 "allocate space for scsi_task", (void *)qlt);
6162 info[159] = 0;
6163 (void) fct_port_shutdown(qlt->qlt_port,
6164 STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info);
6165 return;
6166 }
6167 bzero(req, IOCB_SIZE);
6168 req[0] = 0x12; req[1] = 0x1;
6169 QMEM_WR32(qlt, req+4, 0);
6170 QMEM_WR16(qlt, req+8, fct_get_rp_handle(qlt->qlt_port,
6171 rportid));
6172 QMEM_WR16(qlt, req+10, 60);
6173 QMEM_WR32(qlt, req+0x10, rportid);
6174 QMEM_WR32(qlt, req+0x14, fw_xchg_addr);
6175 QMEM_WR16(qlt, req+0x1A, flags);
6176 QMEM_WR16(qlt, req+0x20, oxid);
6177 qlt_submit_req_entries(qlt, 1, qi);
6178 mutex_exit(&qlt->mq_req[qi].mq_lock);
6179
6180 return;
6181 }
6182 if (cmd == NULL) {
6183 uint32_t res;
6184 uint16_t scsi_status = 0;
6185 uint16_t rphdl = 0;
6186
6187 qi = 0; /* always use request queue 0 */
6188
6189 rphdl = fct_get_rp_handle(qlt->qlt_port, rportid);
6190 if ((rphdl != 0xFFFF) &&
6191 (rphdl >= qlt->qlt_port->port_max_logins)) {
6192 rphdl = 0xFFFF;
6193 }
6194
6195 mutex_enter(&qlt->mq_req[qi].mq_lock);
6196 req = (uint8_t *)qlt_get_req_entries(qlt, 1, qi);
6197 if (req == NULL) {
6198 EL(qlt, "cannot get reqq\n");
6199 mutex_exit(&qlt->mq_req[qi].mq_lock);
6200 (void) snprintf(info, 160,
6201 "qlt_handle_atio: qlt-%p, can't "
6202 "allocate space for termi-excg", (void *)qlt);
6203 info[159] = 0;
6204 (void) fct_port_shutdown(qlt->qlt_port,
6205 STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info);
6206 return;
6207 }
6208
6209 if (rphdl != 0xFFFF) {
6210 /* Driver send scsi qfull status now */
6211 flags = (uint16_t)(BIT_15 |
6212 ((uint16_t)(atio[0x3] & 0xF0) << 5));
6213 /* always use SCSI status mode 1 */
6214 flags = (uint16_t)(flags | BIT_6);
6215
6216 scsi_status |= (uint16_t)(0x28);
6217
6218 /* Build SCSI Status Mode 1, FCP_RSP IU 24-48 byte */
6219 bzero(req, IOCB_SIZE);
6220 req[0] = 0x12;
6221 req[1] = 0x1;
6222
6223 /* allocate a special IOCB handle? or donot care */
6224 QMEM_WR32(qlt, req+4, 0);
6225 QMEM_WR16(qlt, req+8, rphdl);
6226 QMEM_WR16(qlt, req+10, 60);
6227 QMEM_WR32(qlt, req+0x10, rportid);
6228 QMEM_WR32(qlt, req+0x14, fw_xchg_addr);
6229
6230 /* sense_length set to 0 */
6231 QMEM_WR16(qlt, req+0x18, 0);
6232
6233 QMEM_WR16(qlt, req+0x1A, flags);
6234
6235 /* Residual transfer length */
6236 res = QMEM_RD32(qlt, atio+0x3C);
6237 BIG_ENDIAN_32(&res);
6238 if (res != 0) {
6239 scsi_status |= FCP_RESID_UNDER;
6240 }
6241 QMEM_WR32_REQ(qlt, qi, req + 0x1C, res);
6242
6243 QMEM_WR16(qlt, req+0x20, oxid);
6244 QMEM_WR16_REQ(qlt, qi, req + 0x22, scsi_status);
6245
6246 EL(qlt, "Send qfull (%Xh) (%Xh)(%Xh)(%Xh) from port "
6247 "(%Xh:%Xh)\n", scsi_status, fw_xchg_addr, flags,
6248 oxid, rportid, rphdl);
6249 } else {
6250 /* Terminate exchange because no remote port context */
6251 flags = (uint16_t)(BIT_14 | ((atio[3] & 0xF0) << 5));
6252
6253 bzero(req, IOCB_SIZE);
6254 req[0] = 0x12;
6255 req[1] = 0x1;
6256
6257 QMEM_WR32(qlt, req+4, 0);
6258 QMEM_WR16(qlt, req+8, rphdl);
6259 QMEM_WR16(qlt, req+10, 60);
6260 QMEM_WR32(qlt, req+0x10, rportid);
6261 QMEM_WR32(qlt, req+0x14, fw_xchg_addr);
6262 QMEM_WR16(qlt, req+0x1A, flags);
6263 QMEM_WR16(qlt, req+0x20, oxid);
6264
6265 EL(qlt, "Termi excg (%Xh)(%Xh)(%Xh) from port (%Xh)\n",
6266 fw_xchg_addr, flags, oxid, rportid);
6267
6268 EL(qlt, "Termi rp_handle (%Xh)\n", rphdl);
6269 }
6270
6271 qlt_submit_req_entries(qlt, 1, qi);
6272 mutex_exit(&qlt->mq_req[qi].mq_lock);
6273 return;
6274 }
6275
6276 qi = qlt_get_queue_id(qlt, 0);
6277 task = (scsi_task_t *)cmd->cmd_specific;
6278 qcmd = (qlt_cmd_t *)cmd->cmd_fca_private;
6279 qcmd->fw_xchg_addr = fw_xchg_addr;
6280 qcmd->param.atio_byte3 = atio[3];
6281 qcmd->qid = qi;
6282 cmd->cmd_oxid = oxid;
6283 cmd->cmd_rxid = (uint16_t)((((uint16_t)atio[8 + 18]) << 8) |
6284 atio[8+19]);
6285 cmd->cmd_rportid = rportid;
6286 cmd->cmd_lportid = (((uint32_t)atio[8 + 1]) << 16) |
6287 (((uint32_t)atio[8 + 2]) << 8) | atio[8 + 3];
6288 cmd->cmd_rp_handle = FCT_HANDLE_NONE;
6289 /* Dont do a 64 byte read as this is IOMMU */
6290 q = atio+0x28;
6291 /* XXX Handle fcp_cntl */
6292 task->task_cmd_seq_no = (uint32_t)(*q++);
6293 task->task_csn_size = 8;
6294 task->task_flags = qlt_task_flags[(*q++) & 7];
6295 tm = *q++;
6296 if (tm) {
6297 if (tm & BIT_1)
6298 task->task_mgmt_function = TM_ABORT_TASK_SET;
6299 else if (tm & BIT_2)
6300 task->task_mgmt_function = TM_CLEAR_TASK_SET;
6301 else if (tm & BIT_4)
6302 task->task_mgmt_function = TM_LUN_RESET;
6303 else if (tm & BIT_5)
6304 task->task_mgmt_function = TM_TARGET_COLD_RESET;
6305 else if (tm & BIT_6)
6306 task->task_mgmt_function = TM_CLEAR_ACA;
6307 else
6308 task->task_mgmt_function = TM_ABORT_TASK;
6309 }
6310 task->task_max_nbufs = STMF_BUFS_MAX;
6311 task->task_csn_size = 8;
6312 task->task_flags = (uint8_t)(task->task_flags | (((*q++) & 3) << 5));
6313 p = task->task_cdb;
6314 *p++ = *q++; *p++ = *q++; *p++ = *q++; *p++ = *q++;
6315 *p++ = *q++; *p++ = *q++; *p++ = *q++; *p++ = *q++;
6316 *p++ = *q++; *p++ = *q++; *p++ = *q++; *p++ = *q++;
6317 *p++ = *q++; *p++ = *q++; *p++ = *q++; *p++ = *q++;
6318 if (cdb_size > 16) {
6319 uint16_t xtra = (uint16_t)(cdb_size - 16);
6320 uint16_t i;
6321 uint8_t cb[4];
6322
6323 while (xtra) {
6324 *p++ = *q++;
6325 xtra--;
6326 if (q == ((uint8_t *)qlt->queue_mem_ptr +
6327 ATIO_QUEUE_OFFSET + (ATIO_QUEUE_ENTRIES * 64))) {
6328 q = (uint8_t *)qlt->queue_mem_ptr +
6329 ATIO_QUEUE_OFFSET;
6330 }
6331 }
6332 for (i = 0; i < 4; i++) {
6333 cb[i] = *q++;
6334 if (q == ((uint8_t *)qlt->queue_mem_ptr +
6335 ATIO_QUEUE_OFFSET + (ATIO_QUEUE_ENTRIES * 64))) {
6336 q = (uint8_t *)qlt->queue_mem_ptr +
6337 ATIO_QUEUE_OFFSET;
6338 }
6339 }
6340 task->task_expected_xfer_length = (((uint32_t)cb[0]) << 24) |
6341 (((uint32_t)cb[1]) << 16) |
6342 (((uint32_t)cb[2]) << 8) | cb[3];
6343 } else {
6344 task->task_expected_xfer_length = (((uint32_t)q[0]) << 24) |
6345 (((uint32_t)q[1]) << 16) |
6346 (((uint32_t)q[2]) << 8) | q[3];
6347 }
6348
6349 QMEM_WR32(qlt, atio+0x3c, 0xdeadbeef);
6350 fct_post_rcvd_cmd(cmd, 0);
6351 }
6352
6353 static void
qlt_handle_dereg_completion(qlt_state_t * qlt,uint8_t * rsp)6354 qlt_handle_dereg_completion(qlt_state_t *qlt, uint8_t *rsp)
6355 {
6356 uint16_t status;
6357 uint32_t portid;
6358 uint32_t subcode1, subcode2;
6359
6360 status = QMEM_RD16(qlt, rsp+8);
6361 portid = QMEM_RD32(qlt, rsp+0x10) & 0xffffff;
6362 subcode1 = QMEM_RD32(qlt, rsp+0x14);
6363 subcode2 = QMEM_RD32(qlt, rsp+0x18);
6364
6365 if ((qlt->qlt_83xx_chip) || (qlt->qlt_27xx_chip)) {
6366 mutex_enter(&qlt->mq_req[0].mq_lock);
6367 } else {
6368 mutex_enter(&qlt->preq_lock);
6369 }
6370 if (portid != qlt->rp_id_in_dereg) {
6371 int instance = ddi_get_instance(qlt->dip);
6372
6373 EL(qlt, "implicit logout reveived portid = %xh\n", portid);
6374 cmn_err(CE_WARN, "qlt(%d): implicit logout completion for 0x%x"
6375 " received when driver wasn't waiting for it",
6376 instance, portid);
6377 if ((qlt->qlt_83xx_chip) || (qlt->qlt_27xx_chip)) {
6378 mutex_exit(&qlt->mq_req[0].mq_lock);
6379 } else {
6380 mutex_exit(&qlt->preq_lock);
6381 }
6382 return;
6383 }
6384
6385 if (status != 0) {
6386 EL(qlt, "implicit logout completed for %xh with status %xh, "
6387 "subcode1 %xh subcode2 %xh\n", portid, status, subcode1,
6388 subcode2);
6389 if (status == 0x31 && subcode1 == 0x0a) {
6390 qlt->rp_dereg_status = FCT_SUCCESS;
6391 } else {
6392 EL(qlt, "implicit logout portid=%xh, status=%xh, "
6393 "subcode1=%xh, subcode2=%xh\n", portid, status,
6394 subcode1, subcode2);
6395 qlt->rp_dereg_status =
6396 QLT_FIRMWARE_ERROR(status, subcode1, subcode2);
6397 }
6398 } else {
6399 qlt->rp_dereg_status = FCT_SUCCESS;
6400 }
6401 cv_signal(&qlt->rp_dereg_cv);
6402 if ((qlt->qlt_83xx_chip) || (qlt->qlt_27xx_chip)) {
6403 mutex_exit(&qlt->mq_req[0].mq_lock);
6404 } else {
6405 mutex_exit(&qlt->preq_lock);
6406 }
6407 }
6408
6409 /*
6410 * Note that when an ELS is aborted, the regular or aborted completion
6411 * (if any) gets posted before the abort IOCB comes back on response queue.
6412 */
6413 static void
qlt_handle_unsol_els_completion(qlt_state_t * qlt,uint8_t * rsp)6414 qlt_handle_unsol_els_completion(qlt_state_t *qlt, uint8_t *rsp)
6415 {
6416 char info[160];
6417 fct_cmd_t *cmd;
6418 qlt_cmd_t *qcmd;
6419 uint32_t hndl;
6420 uint32_t subcode1, subcode2;
6421 uint16_t status;
6422 uint8_t elsop;
6423
6424 hndl = QMEM_RD32(qlt, rsp+4);
6425 status = QMEM_RD16(qlt, rsp+8);
6426 subcode1 = QMEM_RD32(qlt, rsp+0x24);
6427 subcode2 = QMEM_RD32(qlt, rsp+0x28);
6428 elsop = rsp[0x16];
6429
6430 if (!CMD_HANDLE_VALID(hndl)) {
6431 EL(qlt, "handle = %xh\n", hndl);
6432 /*
6433 * This cannot happen for unsol els completion. This can
6434 * only happen when abort for an unsol els completes.
6435 * This condition indicates a firmware bug.
6436 */
6437 (void) snprintf(info, 160, "qlt_handle_unsol_els_completion: "
6438 "Invalid handle: hndl-%x, status-%x/%x/%x, rsp-%p",
6439 hndl, status, subcode1, subcode2, (void *)rsp);
6440 info[159] = 0;
6441 (void) fct_port_shutdown(qlt->qlt_port,
6442 STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET |
6443 STMF_RFLAG_COLLECT_DEBUG_DUMP, info);
6444 return;
6445 }
6446
6447 if (status == 5) {
6448 /*
6449 * When an unsolicited els is aborted, the abort is done
6450 * by a ELSPT iocb with abort control. This is the aborted IOCB
6451 * and not the abortee. We will do the cleanup when the
6452 * IOCB which caused the abort, returns.
6453 */
6454 EL(qlt, "status = %xh\n", status);
6455 stmf_trace(0, "--UNSOL ELS returned with status 5 --");
6456 return;
6457 }
6458
6459 cmd = fct_handle_to_cmd(qlt->qlt_port, hndl);
6460 if (cmd == NULL) {
6461 EL(qlt, "fct_handle_to_cmd cmd==NULL, hndl=%xh\n", hndl);
6462 /*
6463 * Now why would this happen ???
6464 */
6465 (void) snprintf(info, 160,
6466 "qlt_handle_unsol_els_completion: can not "
6467 "get cmd, hndl-%x, status-%x, rsp-%p", hndl, status,
6468 (void *)rsp);
6469 info[159] = 0;
6470 (void) fct_port_shutdown(qlt->qlt_port,
6471 STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info);
6472
6473 return;
6474 }
6475
6476 ASSERT(cmd->cmd_type == FCT_CMD_RCVD_ELS);
6477 qcmd = (qlt_cmd_t *)cmd->cmd_fca_private;
6478 if (qcmd->flags & QLT_CMD_ABORTING) {
6479 /*
6480 * This is the same case as "if (status == 5)" above. The
6481 * only difference is that in this case the firmware actually
6482 * finished sending the response. So the abort attempt will
6483 * come back with status ?. We will handle it there.
6484 */
6485 stmf_trace(0, "--UNSOL ELS finished while we are trying to "
6486 "abort it");
6487 return;
6488 }
6489
6490 if (qcmd->dbuf != NULL) {
6491 qlt_dmem_free(NULL, qcmd->dbuf);
6492 qcmd->dbuf = NULL;
6493 }
6494
6495 if (status == 0) {
6496 fct_send_response_done(cmd, FCT_SUCCESS, FCT_IOF_FCA_DONE);
6497
6498 if ((elsop == ELS_OP_LOGO) &&
6499 (qlt->cur_topology == PORT_TOPOLOGY_PT_TO_PT)) {
6500 EL(qlt, "reset link since this is LOGO and N2N\n");
6501 (void) snprintf(info, 80,
6502 "qlt_handle_unsol_els_completion: qlt-%p, "
6503 "trigger RFLAG_RESET to recover",
6504 (void *)qlt);
6505
6506 info[79] = 0;
6507 (void) fct_port_shutdown(qlt->qlt_port,
6508 STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET,
6509 info);
6510 }
6511 } else {
6512 EL(qlt, "status (0xh) sucode1=%xh subconde2=%xh\n",
6513 status, subcode1, subcode2);
6514 fct_send_response_done(cmd,
6515 QLT_FIRMWARE_ERROR(status, subcode1, subcode2), 0);
6516 }
6517 }
6518
6519 static void
qlt_handle_unsol_els_abort_completion(qlt_state_t * qlt,uint8_t * rsp)6520 qlt_handle_unsol_els_abort_completion(qlt_state_t *qlt, uint8_t *rsp)
6521 {
6522 char info[160];
6523 fct_cmd_t *cmd;
6524 qlt_cmd_t *qcmd;
6525 uint32_t hndl;
6526 uint32_t subcode1, subcode2;
6527 uint16_t status;
6528
6529 hndl = QMEM_RD32(qlt, rsp+4);
6530 status = QMEM_RD16(qlt, rsp+8);
6531 subcode1 = QMEM_RD32(qlt, rsp+0x24);
6532 subcode2 = QMEM_RD32(qlt, rsp+0x28);
6533
6534 if (!CMD_HANDLE_VALID(hndl)) {
6535 EL(qlt, "handle = %xh\n", hndl);
6536 ASSERT(hndl == 0);
6537 /*
6538 * Someone has requested to abort it, but no one is waiting for
6539 * this completion.
6540 */
6541 if ((status != 0) && (status != 8)) {
6542 EL(qlt, "status = %xh\n", status);
6543 /*
6544 * There could be exchange resource leakage, so
6545 * throw HBA fatal error event now
6546 */
6547 (void) snprintf(info, 160,
6548 "qlt_handle_unsol_els_abort_completion: "
6549 "Invalid handle: hndl-%x, status-%x/%x/%x, rsp-%p",
6550 hndl, status, subcode1, subcode2, (void *)rsp);
6551 info[159] = 0;
6552 (void) fct_port_shutdown(qlt->qlt_port,
6553 STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET |
6554 STMF_RFLAG_COLLECT_DEBUG_DUMP, info);
6555 return;
6556 }
6557
6558 return;
6559 }
6560
6561 cmd = fct_handle_to_cmd(qlt->qlt_port, hndl);
6562 if (cmd == NULL) {
6563 EL(qlt, "fct_handle_to_cmd cmd==NULL, hndl=%xh\n", hndl);
6564 /*
6565 * Why would this happen ??
6566 */
6567 (void) snprintf(info, 160,
6568 "qlt_handle_unsol_els_abort_completion: can not get "
6569 "cmd, hndl-%x, status-%x, rsp-%p", hndl, status,
6570 (void *)rsp);
6571 info[159] = 0;
6572 (void) fct_port_shutdown(qlt->qlt_port,
6573 STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info);
6574
6575 return;
6576 }
6577
6578 ASSERT(cmd->cmd_type == FCT_CMD_RCVD_ELS);
6579 qcmd = (qlt_cmd_t *)cmd->cmd_fca_private;
6580 ASSERT(qcmd->flags & QLT_CMD_ABORTING);
6581
6582 if (qcmd->dbuf != NULL) {
6583 qlt_dmem_free(NULL, qcmd->dbuf);
6584 qcmd->dbuf = NULL;
6585 }
6586
6587 if (status == 0) {
6588 fct_cmd_fca_aborted(cmd, FCT_ABORT_SUCCESS, FCT_IOF_FCA_DONE);
6589 } else if (status == 8) {
6590 fct_cmd_fca_aborted(cmd, FCT_NOT_FOUND, FCT_IOF_FCA_DONE);
6591 } else {
6592 fct_cmd_fca_aborted(cmd,
6593 QLT_FIRMWARE_ERROR(status, subcode1, subcode2), 0);
6594 }
6595 }
6596
6597 static void
qlt_handle_sol_els_completion(qlt_state_t * qlt,uint8_t * rsp)6598 qlt_handle_sol_els_completion(qlt_state_t *qlt, uint8_t *rsp)
6599 {
6600 char info[160];
6601 fct_cmd_t *cmd;
6602 fct_els_t *els;
6603 qlt_cmd_t *qcmd;
6604 uint32_t hndl;
6605 uint32_t subcode1, subcode2;
6606 uint16_t status;
6607
6608 hndl = QMEM_RD32(qlt, rsp+4);
6609 status = QMEM_RD16(qlt, rsp+8);
6610 subcode1 = QMEM_RD32(qlt, rsp+0x24);
6611 subcode2 = QMEM_RD32(qlt, rsp+0x28);
6612
6613 if (!CMD_HANDLE_VALID(hndl)) {
6614 EL(qlt, "handle = %xh\n", hndl);
6615 /*
6616 * This cannot happen for sol els completion.
6617 */
6618 (void) snprintf(info, 160, "qlt_handle_sol_els_completion: "
6619 "Invalid handle: hndl-%x, status-%x/%x/%x, rsp-%p",
6620 hndl, status, subcode1, subcode2, (void *)rsp);
6621 info[159] = 0;
6622 (void) fct_port_shutdown(qlt->qlt_port,
6623 STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET |
6624 STMF_RFLAG_COLLECT_DEBUG_DUMP, info);
6625 return;
6626 }
6627
6628 cmd = fct_handle_to_cmd(qlt->qlt_port, hndl);
6629 if (cmd == NULL) {
6630 EL(qlt, "fct_handle_to_cmd cmd==NULL, hndl=%xh\n", hndl);
6631 (void) snprintf(info, 160,
6632 "qlt_handle_sol_els_completion: can not "
6633 "get cmd, hndl-%x, status-%x, rsp-%p", hndl, status,
6634 (void *)rsp);
6635 info[159] = 0;
6636 (void) fct_port_shutdown(qlt->qlt_port,
6637 STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info);
6638
6639 return;
6640 }
6641
6642 ASSERT(cmd->cmd_type == FCT_CMD_SOL_ELS);
6643 els = (fct_els_t *)cmd->cmd_specific;
6644 qcmd = (qlt_cmd_t *)cmd->cmd_fca_private;
6645 qcmd->fw_xchg_addr = QMEM_RD32(qlt, (&rsp[0x10]));
6646
6647 if (qcmd->flags & QLT_CMD_ABORTING) {
6648 /*
6649 * We will handle it when the ABORT IO IOCB returns.
6650 */
6651 return;
6652 }
6653
6654 if (qcmd->dbuf != NULL) {
6655 if (status == 0) {
6656 qlt_dmem_dma_sync(qcmd->dbuf, DDI_DMA_SYNC_FORKERNEL);
6657 bcopy(qcmd->dbuf->db_sglist[0].seg_addr +
6658 qcmd->param.resp_offset,
6659 els->els_resp_payload, els->els_resp_size);
6660 }
6661 qlt_dmem_free(NULL, qcmd->dbuf);
6662 qcmd->dbuf = NULL;
6663 }
6664
6665 if (status == 0) {
6666 fct_send_cmd_done(cmd, FCT_SUCCESS, FCT_IOF_FCA_DONE);
6667 } else {
6668 fct_send_cmd_done(cmd,
6669 QLT_FIRMWARE_ERROR(status, subcode1, subcode2), 0);
6670 }
6671 }
6672
6673 static void
qlt_handle_ct_completion(qlt_state_t * qlt,uint8_t * rsp)6674 qlt_handle_ct_completion(qlt_state_t *qlt, uint8_t *rsp)
6675 {
6676 fct_cmd_t *cmd;
6677 fct_sol_ct_t *ct;
6678 qlt_cmd_t *qcmd;
6679 uint32_t hndl;
6680 uint16_t status;
6681 char info[160];
6682
6683 hndl = QMEM_RD32(qlt, rsp+4);
6684 status = QMEM_RD16(qlt, rsp+8);
6685
6686 if (!CMD_HANDLE_VALID(hndl)) {
6687 EL(qlt, "handle = %xh\n", hndl);
6688 /*
6689 * Solicited commands will always have a valid handle.
6690 */
6691 (void) snprintf(info, 160, "qlt_handle_ct_completion: hndl-"
6692 "%x, status-%x, rsp-%p", hndl, status, (void *)rsp);
6693 info[159] = 0;
6694 (void) fct_port_shutdown(qlt->qlt_port,
6695 STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET |
6696 STMF_RFLAG_COLLECT_DEBUG_DUMP, info);
6697 return;
6698 }
6699
6700 cmd = fct_handle_to_cmd(qlt->qlt_port, hndl);
6701 EL(qlt, "cmd=%ph hndl=%xh status=%xh\n", cmd, hndl, status);
6702 if (cmd == NULL) {
6703 EL(qlt, "fct_handle_to_cmd cmd==NULL, hndl=%xh\n", hndl);
6704 (void) snprintf(info, 160,
6705 "qlt_handle_ct_completion: cannot find "
6706 "cmd, hndl-%x, status-%x, rsp-%p", hndl, status,
6707 (void *)rsp);
6708 info[159] = 0;
6709 (void) fct_port_shutdown(qlt->qlt_port,
6710 STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info);
6711
6712 return;
6713 }
6714
6715 ct = (fct_sol_ct_t *)cmd->cmd_specific;
6716 qcmd = (qlt_cmd_t *)cmd->cmd_fca_private;
6717 ASSERT(cmd->cmd_type == FCT_CMD_SOL_CT);
6718
6719 if (qcmd->flags & QLT_CMD_ABORTING) {
6720 /*
6721 * We will handle it when ABORT IO IOCB returns;
6722 */
6723 return;
6724 }
6725
6726 ASSERT(qcmd->dbuf);
6727 if ((status == 0) || (status == 0x15)) {
6728 qlt_dmem_dma_sync(qcmd->dbuf, DDI_DMA_SYNC_FORKERNEL);
6729 bcopy(qcmd->dbuf->db_sglist[0].seg_addr +
6730 qcmd->param.resp_offset,
6731 ct->ct_resp_payload, ct->ct_resp_size);
6732 }
6733 qlt_dmem_free(NULL, qcmd->dbuf);
6734 qcmd->dbuf = NULL;
6735
6736 if ((status == 0) || (status == 0x15)) {
6737 fct_send_cmd_done(cmd, FCT_SUCCESS, FCT_IOF_FCA_DONE);
6738 } else {
6739 fct_send_cmd_done(cmd, QLT_FIRMWARE_ERROR(status, 0, 0), 0);
6740 }
6741 }
6742
6743 static fct_status_t
qlt_verify_resp_entry(qlt_state_t * qlt,uint8_t * rsp,uint16_t qi)6744 qlt_verify_resp_entry(qlt_state_t *qlt, uint8_t *rsp, uint16_t qi)
6745 {
6746 uint32_t sig;
6747 int i;
6748 char info[160];
6749
6750 sig = QMEM_RD32_RSPQ(qlt, qi, rsp+0x3c);
6751 for (i = 0; ((sig == 0xdeadbeef) &&
6752 (i < qlt_reprocess_attempt_cnt)); i++) {
6753 (void) ddi_dma_sync(
6754 qlt->mq_resp[qi].queue_mem_mq_dma_handle,
6755 (qlt->mq_resp[qi].mq_ndx_to_fw << 6),
6756 IOCB_SIZE, DDI_DMA_SYNC_FORCPU);
6757
6758 qlt->qlt_resp_reproc_cnt++;
6759 drv_usecwait(qlt_reprocess_delay);
6760 sig = QMEM_RD32_RSPQ(qlt, qi, rsp+0x3c);
6761 }
6762
6763 if (i) {
6764 if (i >= qlt_reprocess_attempt_cnt) {
6765 EL(qlt, "resp entry reprocess failed, %x\n",
6766 qlt->qlt_resp_reproc_cnt);
6767 cmn_err(CE_WARN, "qlt%d: resp entry reprocess"
6768 " failed %x\n",
6769 qlt->instance, qlt->qlt_resp_reproc_cnt);
6770 (void) snprintf(info, 160,
6771 "qlt_handle_ctio_completion: resp entry reprocess"
6772 " failed, %x rsp-%p",
6773 qlt->qlt_resp_reproc_cnt, (void *)rsp);
6774 info[159] = 0;
6775 (void) fct_port_shutdown(qlt->qlt_port,
6776 STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET,
6777 info);
6778 return (QLT_FAILURE);
6779 } else {
6780 EL(qlt, "resp entry reprocess succeeded, %x %x\n",
6781 i, qlt->qlt_resp_reproc_cnt);
6782 }
6783 }
6784
6785 return (QLT_SUCCESS);
6786 }
6787
6788 static void
qlt_handle_ctio_completion(qlt_state_t * qlt,uint8_t * rsp,uint16_t qi)6789 qlt_handle_ctio_completion(qlt_state_t *qlt, uint8_t *rsp, uint16_t qi)
6790 {
6791 fct_cmd_t *cmd;
6792 scsi_task_t *task;
6793 qlt_cmd_t *qcmd;
6794 stmf_data_buf_t *dbuf;
6795 fct_status_t fc_st;
6796 uint32_t iof = 0;
6797 uint32_t hndl;
6798 uint32_t rex1;
6799 uint16_t oxid;
6800 uint16_t status;
6801 uint16_t flags;
6802 uint8_t abort_req;
6803 uint8_t n;
6804 char info[160];
6805
6806 if (qlt_verify_resp_entry(qlt, rsp, qi) != QLT_SUCCESS)
6807 return;
6808
6809 /* write a deadbeef in the last 4 bytes of the IOCB */
6810 QMEM_WR32_RSPQ(qlt, qi, rsp+0x3c, 0xdeadbeef);
6811
6812 /* XXX: Check validity of the IOCB by checking 4th byte. */
6813 hndl = QMEM_RD32_RSPQ(qlt, qi, rsp+4);
6814 status = QMEM_RD16_RSPQ(qlt, qi, rsp+8);
6815 flags = QMEM_RD16_RSPQ(qlt, qi, rsp+0x1a);
6816 oxid = QMEM_RD16_RSPQ(qlt, qi, rsp+0x20);
6817 rex1 = QMEM_RD32_RSPQ(qlt, qi, rsp+0x14);
6818 n = rsp[2];
6819
6820 if (!CMD_HANDLE_VALID(hndl)) {
6821 EL(qlt, "handle = %xh\n", hndl);
6822 ASSERT(hndl == 0);
6823 /*
6824 * Someone has requested to abort it, but no one is waiting for
6825 * this completion.
6826 */
6827 EL(qlt, "hndl-%xh, status-%xh, rsp-%p\n", hndl, status,
6828 (void *)rsp);
6829 if ((status != 1) && (status != 2)) {
6830 EL(qlt, "status = %xh\n", status);
6831 if (status == 0x29) {
6832 uint8_t *req;
6833
6834 /*
6835 * The qlt port received an ATIO request from
6836 * remote port before it issued a plogi.
6837 * The qlt fw returned the CTIO completion
6838 * status 0x29 to inform driver to do cleanup
6839 * (terminate the IO exchange). The subsequent
6840 * ABTS from the initiator can be handled
6841 * cleanly.
6842 */
6843 qi = 0;
6844 mutex_enter(&qlt->mq_req[qi].mq_lock);
6845 req = (uint8_t *)
6846 qlt_get_req_entries(qlt, 1, qi);
6847
6848 if (req == NULL) {
6849 EL(qlt, "No reqq entry available to "
6850 "termi exchg\n");
6851 mutex_exit(&qlt->mq_req[qi].mq_lock);
6852
6853 (void) snprintf(info, 160,
6854 "qlt_handle_ctio_completion: no "
6855 "reqq entry available, status-%x,"
6856 "rsp-%p", status, (void *)rsp);
6857
6858 info[159] = 0;
6859
6860 (void) fct_port_shutdown(qlt->qlt_port,
6861 STMF_RFLAG_FATAL_ERROR |
6862 STMF_RFLAG_RESET,
6863 info);
6864
6865 return;
6866 }
6867
6868 flags &= 0x1E00;
6869 flags |= BIT_14;
6870
6871 bzero(req, IOCB_SIZE);
6872 req[0] = 0x12;
6873 req[1] = 0x1;
6874
6875 QMEM_WR32(qlt, req+4, 0);
6876 QMEM_WR16(qlt, req+8, 0xFFFF);
6877 QMEM_WR16(qlt, req+10, 60);
6878 QMEM_WR32(qlt, req+0x14, rex1);
6879 QMEM_WR16(qlt, req+0x1A, flags);
6880 QMEM_WR16(qlt, req+0x20, oxid);
6881
6882 EL(qlt, "Termi exchg (%Xh)(%Xh)(%Xh) "
6883 "rphdl=0xFFFF\n", rex1, flags, oxid);
6884
6885 qlt_submit_req_entries(qlt, 1, qi);
6886 mutex_exit(&qlt->mq_req[qi].mq_lock);
6887 } else {
6888 /*
6889 * There could be exchange resource leakage,
6890 * so throw HBA fatal error event now
6891 */
6892 (void) snprintf(info, 160,
6893 "qlt_handle_ctio_completion: hndl-%x, "
6894 "status-%x, rsp-%p", hndl, status,
6895 (void *)rsp);
6896
6897 info[159] = 0;
6898
6899 (void) fct_port_shutdown(qlt->qlt_port,
6900 STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET,
6901 info);
6902 }
6903 }
6904
6905 return;
6906 }
6907
6908 if (flags & BIT_14) {
6909 abort_req = 1;
6910 EL(qlt, "abort: hndl-%x, status-%x, rsp-%p\n", hndl, status,
6911 (void *)rsp);
6912 } else {
6913 abort_req = 0;
6914 }
6915
6916 cmd = fct_handle_to_cmd(qlt->qlt_port, hndl);
6917 if (cmd == NULL) {
6918 EL(qlt, "fct_handle_to_cmd cmd==NULL, hndl=%xh\n", hndl);
6919 (void) snprintf(info, 160,
6920 "qlt_handle_ctio_completion: cannot find "
6921 "cmd, hndl-%x, status-%x, rsp-%p", hndl, status,
6922 (void *)rsp);
6923 info[159] = 0;
6924 (void) fct_port_shutdown(qlt->qlt_port,
6925 /* STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info); */
6926 STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET |
6927 STMF_RFLAG_COLLECT_DEBUG_DUMP, info);
6928
6929 return;
6930 }
6931
6932 task = (scsi_task_t *)cmd->cmd_specific;
6933 qcmd = (qlt_cmd_t *)cmd->cmd_fca_private;
6934 if (qcmd->dbuf_rsp_iu) {
6935 ASSERT((flags & (BIT_6 | BIT_7)) == BIT_7);
6936 qlt_dmem_free(NULL, qcmd->dbuf_rsp_iu);
6937 qcmd->dbuf_rsp_iu = NULL;
6938 }
6939
6940 if ((status == 1) || (status == 2)) {
6941 if (abort_req) {
6942 fc_st = FCT_ABORT_SUCCESS;
6943 iof = FCT_IOF_FCA_DONE;
6944 } else {
6945 fc_st = FCT_SUCCESS;
6946 if (flags & BIT_15) {
6947 iof = FCT_IOF_FCA_DONE;
6948 }
6949 }
6950 } else {
6951 EL(qlt, "status = %xh\n", status);
6952 if ((status == 8) && abort_req) {
6953 fc_st = FCT_NOT_FOUND;
6954 iof = FCT_IOF_FCA_DONE;
6955 } else {
6956 fc_st = QLT_FIRMWARE_ERROR(status, 0, 0);
6957 }
6958 }
6959 dbuf = NULL;
6960 if (((n & BIT_7) == 0) && (!abort_req)) {
6961 /* A completion of data xfer */
6962 if (n == 0) {
6963 dbuf = qcmd->dbuf;
6964 } else {
6965 dbuf = stmf_handle_to_buf(task, n);
6966 }
6967
6968 ASSERT(dbuf != NULL);
6969 if (dbuf->db_flags & DB_DIRECTION_FROM_RPORT)
6970 qlt_dmem_dma_sync(dbuf, DDI_DMA_SYNC_FORCPU);
6971 if (flags & BIT_15) {
6972 dbuf->db_flags = (uint16_t)(dbuf->db_flags |
6973 DB_STATUS_GOOD_SENT);
6974 }
6975
6976 dbuf->db_xfer_status = fc_st;
6977 fct_scsi_data_xfer_done(cmd, dbuf, iof);
6978 return;
6979 }
6980 if (!abort_req) {
6981 /*
6982 * This was just a pure status xfer.
6983 */
6984 fct_send_response_done(cmd, fc_st, iof);
6985 return;
6986 }
6987
6988 fct_cmd_fca_aborted(cmd, fc_st, iof);
6989
6990 EL(qlt, "(%d) (%p)(%xh,%xh),%x %x %x\n",
6991 qi, cmd, cmd->cmd_oxid, cmd->cmd_rxid,
6992 cmd->cmd_handle, qcmd->fw_xchg_addr,
6993 fc_st);
6994 }
6995
6996 static void
qlt_handle_sol_abort_completion(qlt_state_t * qlt,uint8_t * rsp)6997 qlt_handle_sol_abort_completion(qlt_state_t *qlt, uint8_t *rsp)
6998 {
6999 char info[80];
7000 fct_cmd_t *cmd;
7001 qlt_cmd_t *qcmd;
7002 uint32_t h;
7003 uint16_t status;
7004
7005 h = QMEM_RD32(qlt, rsp+4);
7006 status = QMEM_RD16(qlt, rsp+8);
7007
7008 if (!CMD_HANDLE_VALID(h)) {
7009 EL(qlt, "handle = %xh\n", h);
7010 /*
7011 * Solicited commands always have a valid handle.
7012 */
7013 (void) snprintf(info, 80,
7014 "qlt_handle_sol_abort_completion: hndl-"
7015 "%x, status-%x, rsp-%p", h, status, (void *)rsp);
7016 info[79] = 0;
7017 (void) fct_port_shutdown(qlt->qlt_port,
7018 STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET |
7019 STMF_RFLAG_COLLECT_DEBUG_DUMP, info);
7020 return;
7021 }
7022 cmd = fct_handle_to_cmd(qlt->qlt_port, h);
7023 if (cmd == NULL) {
7024 EL(qlt, "fct_handle_to_cmd cmd==NULL, hndl=%xh\n", h);
7025 /*
7026 * What happened to the cmd ??
7027 */
7028 (void) snprintf(info, 80,
7029 "qlt_handle_sol_abort_completion: cannot "
7030 "find cmd, hndl-%x, status-%x, rsp-%p", h, status,
7031 (void *)rsp);
7032 info[79] = 0;
7033 (void) fct_port_shutdown(qlt->qlt_port,
7034 STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info);
7035
7036 return;
7037 }
7038
7039 ASSERT((cmd->cmd_type == FCT_CMD_SOL_ELS) ||
7040 (cmd->cmd_type == FCT_CMD_SOL_CT));
7041 qcmd = (qlt_cmd_t *)cmd->cmd_fca_private;
7042 if (qcmd->dbuf != NULL) {
7043 qlt_dmem_free(NULL, qcmd->dbuf);
7044 qcmd->dbuf = NULL;
7045 }
7046 ASSERT(qcmd->flags & QLT_CMD_ABORTING);
7047 EL(qlt, "status=%xh\n", status);
7048 if (status == 0) {
7049 fct_cmd_fca_aborted(cmd, FCT_ABORT_SUCCESS, FCT_IOF_FCA_DONE);
7050 } else if (status == 0x31) {
7051 fct_cmd_fca_aborted(cmd, FCT_NOT_FOUND, FCT_IOF_FCA_DONE);
7052 } else {
7053 fct_cmd_fca_aborted(cmd, QLT_FIRMWARE_ERROR(status, 0, 0), 0);
7054 }
7055 }
7056
7057 static void
qlt_handle_rcvd_abts(qlt_state_t * qlt,uint8_t * resp,uint16_t qi)7058 qlt_handle_rcvd_abts(qlt_state_t *qlt, uint8_t *resp, uint16_t qi)
7059 {
7060 qlt_abts_cmd_t *qcmd;
7061 fct_cmd_t *cmd;
7062 uint32_t remote_portid;
7063 uint32_t rex1;
7064 uint32_t rex2;
7065 char info[160];
7066
7067 remote_portid = ((uint32_t)(QMEM_RD16(qlt, (&resp[0x18])))) |
7068 ((uint32_t)(resp[0x1A])) << 16;
7069 cmd = (fct_cmd_t *)fct_alloc(FCT_STRUCT_CMD_RCVD_ABTS,
7070 sizeof (qlt_abts_cmd_t), 0);
7071 if (cmd == NULL) {
7072 EL(qlt, "fct_alloc cmd==NULL\n");
7073 (void) snprintf(info, 160,
7074 "qlt_handle_rcvd_abts: qlt-%p, can't "
7075 "allocate space for fct_cmd", (void *)qlt);
7076 info[159] = 0;
7077 (void) fct_port_shutdown(qlt->qlt_port,
7078 STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info);
7079 return;
7080 }
7081
7082 resp[0xC] = resp[0xD] = resp[0xE] = 0;
7083 qcmd = (qlt_abts_cmd_t *)cmd->cmd_fca_private;
7084 qcmd->qid = qi;
7085 bcopy(resp, qcmd->buf, IOCB_SIZE);
7086 cmd->cmd_port = qlt->qlt_port;
7087 cmd->cmd_rp_handle = QMEM_RD16(qlt, resp+0xA);
7088 if (cmd->cmd_rp_handle == 0xFFFF)
7089 cmd->cmd_rp_handle = FCT_HANDLE_NONE;
7090
7091 cmd->cmd_rportid = remote_portid;
7092 cmd->cmd_lportid = ((uint32_t)(QMEM_RD16(qlt, (&resp[0x14])))) |
7093 ((uint32_t)(resp[0x16])) << 16;
7094 cmd->cmd_oxid = QMEM_RD16(qlt, (&resp[0x26]));
7095 cmd->cmd_rxid = QMEM_RD16(qlt, (&resp[0x24]));
7096
7097 rex1 = QMEM_RD32(qlt, resp+0x10);
7098 rex2 = QMEM_RD32(qlt, resp+0x3C);
7099
7100 EL(qlt, "(%d)(%xh %xh) (%xh)(%p) (%xh %xh) (%x)\n",
7101 qi, cmd->cmd_oxid, cmd->cmd_rxid, remote_portid,
7102 cmd, rex1, rex2, cmd->cmd_handle);
7103
7104 fct_post_rcvd_cmd(cmd, 0);
7105 }
7106
7107 static void
qlt_handle_abts_completion(qlt_state_t * qlt,uint8_t * resp,uint16_t qi)7108 qlt_handle_abts_completion(qlt_state_t *qlt, uint8_t *resp, uint16_t qi)
7109 {
7110 uint16_t status;
7111 char info[80];
7112
7113 status = QMEM_RD16(qlt, resp+8);
7114
7115 if ((status == 0) || (status == 5)) {
7116 EL(qlt, "qi(%d) status =%xh,(%xh %xh)\n",
7117 qi, status, QMEM_RD16(qlt, resp+0x26),
7118 QMEM_RD16(qlt, resp+0x24));
7119 return;
7120 }
7121
7122 EL(qlt, "ABTS status=%x/%x/%x resp_off %x",
7123 status, QMEM_RD32(qlt, resp+0x34),
7124 QMEM_RD32(qlt, resp+0x38),
7125 ((uint32_t)(qlt->mq_resp[0].mq_ndx_to_fw)) << 6);
7126
7127 (void) snprintf(info, 80, "ABTS completion failed %x/%x/%x resp_off %x",
7128 status, QMEM_RD32(qlt, resp+0x34), QMEM_RD32(qlt, resp+0x38),
7129 ((uint32_t)(qlt->mq_resp[0].mq_ndx_to_fw)) << 6);
7130 info[79] = 0;
7131 (void) fct_port_shutdown(qlt->qlt_port, STMF_RFLAG_FATAL_ERROR |
7132 STMF_RFLAG_RESET | STMF_RFLAG_COLLECT_DEBUG_DUMP, info);
7133 }
7134
7135 #ifdef DEBUG
7136 uint32_t qlt_drop_abort_counter = 0;
7137 #endif
7138
7139 fct_status_t
qlt_abort_cmd(struct fct_local_port * port,fct_cmd_t * cmd,uint32_t flags)7140 qlt_abort_cmd(struct fct_local_port *port, fct_cmd_t *cmd, uint32_t flags)
7141 {
7142 qlt_state_t *qlt = (qlt_state_t *)port->port_fca_private;
7143
7144 if ((qlt->qlt_state == FCT_STATE_OFFLINE) ||
7145 (qlt->qlt_state == FCT_STATE_OFFLINING)) {
7146 return (FCT_NOT_FOUND);
7147 }
7148
7149 #ifdef DEBUG
7150 if (qlt_drop_abort_counter > 0) {
7151 if (atomic_dec_32_nv(&qlt_drop_abort_counter) == 1)
7152 return (FCT_SUCCESS);
7153 }
7154 #endif
7155
7156 EL(qlt, "cmd_type = %x\n", cmd->cmd_type);
7157 if (cmd->cmd_type == FCT_CMD_FCP_XCHG) {
7158 return (qlt_abort_unsol_scsi_cmd(qlt, cmd));
7159 }
7160
7161 if (flags & FCT_IOF_FORCE_FCA_DONE) {
7162 cmd->cmd_handle = 0;
7163 }
7164
7165 if (cmd->cmd_type == FCT_CMD_RCVD_ABTS) {
7166 /* this is retried ABTS, terminate it now */
7167 return (qlt_send_abts_response(qlt, cmd, 1));
7168 }
7169
7170 if (cmd->cmd_type == FCT_CMD_RCVD_ELS) {
7171 return (qlt_abort_purex(qlt, cmd));
7172 }
7173
7174 if ((cmd->cmd_type == FCT_CMD_SOL_ELS) ||
7175 (cmd->cmd_type == FCT_CMD_SOL_CT)) {
7176 return (qlt_abort_sol_cmd(qlt, cmd));
7177 }
7178 EL(qlt, "cmd->cmd_type = %x\n", cmd->cmd_type);
7179
7180 ASSERT(0);
7181 return (FCT_FAILURE);
7182 }
7183
7184 fct_status_t
qlt_abort_sol_cmd(qlt_state_t * qlt,fct_cmd_t * cmd)7185 qlt_abort_sol_cmd(qlt_state_t *qlt, fct_cmd_t *cmd)
7186 {
7187 uint8_t *req;
7188 qlt_cmd_t *qcmd;
7189 uint16_t qi;
7190
7191 qcmd = (qlt_cmd_t *)cmd->cmd_fca_private;
7192 qcmd->flags = (uint16_t)(qcmd->flags | QLT_CMD_ABORTING);
7193 qi = qcmd->qid;
7194
7195 EL(qlt, "fctcmd-%p, cmd_handle-%xh rportid=%xh\n",
7196 cmd, cmd->cmd_handle, cmd->cmd_rportid);
7197
7198 mutex_enter(&qlt->mq_req[qi].mq_lock);
7199 req = (uint8_t *)qlt_get_req_entries(qlt, 1, qi);
7200 if (req == NULL) {
7201 EL(qlt, "req == NULL\n");
7202 mutex_exit(&qlt->mq_req[qi].mq_lock);
7203
7204 return (FCT_BUSY);
7205 }
7206 bzero(req, IOCB_SIZE);
7207 req[0] = 0x33; req[1] = 1;
7208 QMEM_WR32(qlt, req+4, cmd->cmd_handle);
7209 if (cmd->cmd_rp) {
7210 QMEM_WR16(qlt, req+8, cmd->cmd_rp->rp_handle);
7211 } else {
7212 QMEM_WR16(qlt, req+8, 0xFFFF);
7213 }
7214
7215 QMEM_WR32(qlt, req+0xc, cmd->cmd_handle);
7216 QMEM_WR32(qlt, req+0x30, cmd->cmd_rportid);
7217 qlt_submit_req_entries(qlt, 1, qi);
7218 mutex_exit(&qlt->mq_req[qi].mq_lock);
7219
7220 return (FCT_SUCCESS);
7221 }
7222
7223 fct_status_t
qlt_abort_purex(qlt_state_t * qlt,fct_cmd_t * cmd)7224 qlt_abort_purex(qlt_state_t *qlt, fct_cmd_t *cmd)
7225 {
7226 uint8_t *req;
7227 qlt_cmd_t *qcmd;
7228 fct_els_t *els;
7229 uint8_t elsop, req1f;
7230 uint16_t qi;
7231
7232 els = (fct_els_t *)cmd->cmd_specific;
7233 qcmd = (qlt_cmd_t *)cmd->cmd_fca_private;
7234 qi = qcmd->qid;
7235 elsop = els->els_req_payload[0];
7236 EL(qlt, "fctcmd-%p, cmd_handle-%xh, elsop-%xh\n", cmd,
7237 cmd->cmd_handle, elsop);
7238 req1f = 0x60; /* Terminate xchg */
7239 if ((elsop == ELS_OP_PRLI) || (elsop == ELS_OP_PRLO) ||
7240 (elsop == ELS_OP_TPRLO) || (elsop == ELS_OP_LOGO)) {
7241 req1f = (uint8_t)(req1f | BIT_4);
7242 }
7243
7244 mutex_enter(&qlt->mq_req[qi].mq_lock);
7245 req = (uint8_t *)qlt_get_req_entries(qlt, 1, qi);
7246 if (req == NULL) {
7247 EL(qlt, "req == NULL\n");
7248 mutex_exit(&qlt->mq_req[qi].mq_lock);
7249 return (FCT_BUSY);
7250 }
7251
7252 qcmd->flags = (uint16_t)(qcmd->flags | QLT_CMD_ABORTING);
7253 bzero(req, IOCB_SIZE);
7254 req[0] = 0x53; req[1] = 1; req[0xf] = 0x10;
7255 req[0x16] = elsop; req[0x1f] = req1f;
7256 QMEM_WR32(qlt, (&req[4]), cmd->cmd_handle);
7257 if (cmd->cmd_rp) {
7258 QMEM_WR16(qlt, (&req[0xA]), cmd->cmd_rp->rp_handle);
7259 EL(qlt, "rp_handle-%x\n", cmd->cmd_rp->rp_handle);
7260 } else {
7261 QMEM_WR16(qlt, (&req[0xA]), cmd->cmd_rp_handle);
7262 EL(qlt, "cmd_rp_handle-%x\n", cmd->cmd_rp_handle);
7263 }
7264
7265 QMEM_WR32(qlt, (&req[0x10]), qcmd->fw_xchg_addr);
7266 QMEM_WR32(qlt, (&req[0x18]), cmd->cmd_rportid);
7267 qlt_submit_req_entries(qlt, 1, qi);
7268 mutex_exit(&qlt->mq_req[qi].mq_lock);
7269
7270 return (FCT_SUCCESS);
7271 }
7272
7273 fct_status_t
qlt_abort_unsol_scsi_cmd(qlt_state_t * qlt,fct_cmd_t * cmd)7274 qlt_abort_unsol_scsi_cmd(qlt_state_t *qlt, fct_cmd_t *cmd)
7275 {
7276 qlt_cmd_t *qcmd = (qlt_cmd_t *)cmd->cmd_fca_private;
7277 uint8_t *req;
7278 uint16_t flags;
7279 uint16_t qi;
7280
7281 qi = qcmd->qid;
7282
7283 flags = (uint16_t)(BIT_14 |
7284 (((uint16_t)qcmd->param.atio_byte3 & 0xf0) << 5));
7285
7286 EL(qlt, "(%d) (%x) (%p) (%x)\n", qi, cmd->cmd_oxid,
7287 cmd, qcmd->fw_xchg_addr);
7288
7289 mutex_enter(&qlt->mq_req[qi].mq_lock);
7290 req = (uint8_t *)qlt_get_req_entries(qlt, 1, qi);
7291 if (req == NULL) {
7292 EL(qlt, "req == NULL\n");
7293 mutex_exit(&qlt->mq_req[qi].mq_lock);
7294 return (FCT_BUSY);
7295 }
7296
7297 qcmd->flags = (uint16_t)(qcmd->flags | QLT_CMD_ABORTING);
7298 bzero(req, IOCB_SIZE);
7299 req[0] = 0x12; req[1] = 0x1;
7300 QMEM_WR32_REQ(qlt, qi, req+4, cmd->cmd_handle);
7301 QMEM_WR16_REQ(qlt, qi, req+8, cmd->cmd_rp->rp_handle);
7302 QMEM_WR16_REQ(qlt, qi, req+10, 60); /* 60 seconds timeout */
7303 QMEM_WR32_REQ(qlt, qi, req+0x10, cmd->cmd_rportid);
7304 QMEM_WR32_REQ(qlt, qi, req+0x14, qcmd->fw_xchg_addr);
7305 QMEM_WR16_REQ(qlt, qi, req+0x1A, flags);
7306 QMEM_WR16_REQ(qlt, qi, req+0x20, cmd->cmd_oxid);
7307 qlt_submit_req_entries(qlt, 1, qi);
7308 mutex_exit(&qlt->mq_req[qi].mq_lock);
7309
7310 return (FCT_SUCCESS);
7311 }
7312
7313 fct_status_t
qlt_send_cmd(fct_cmd_t * cmd)7314 qlt_send_cmd(fct_cmd_t *cmd)
7315 {
7316 qlt_state_t *qlt;
7317
7318 qlt = (qlt_state_t *)cmd->cmd_port->port_fca_private;
7319 EL(qlt, "cmd->cmd_type = %xh\n", cmd->cmd_type);
7320 if (cmd->cmd_type == FCT_CMD_SOL_ELS) {
7321 return (qlt_send_els(qlt, cmd));
7322 } else if (cmd->cmd_type == FCT_CMD_SOL_CT) {
7323 return (qlt_send_ct(qlt, cmd));
7324 }
7325 EL(qlt, "Unknown cmd->cmd_type = %xh\n", cmd->cmd_type);
7326
7327 ASSERT(0);
7328 return (FCT_FAILURE);
7329 }
7330
7331 fct_status_t
qlt_send_els(qlt_state_t * qlt,fct_cmd_t * cmd)7332 qlt_send_els(qlt_state_t *qlt, fct_cmd_t *cmd)
7333 {
7334 uint8_t *req;
7335 fct_els_t *els;
7336 qlt_cmd_t *qcmd;
7337 stmf_data_buf_t *buf;
7338 qlt_dmem_bctl_t *bctl;
7339 uint32_t sz, minsz;
7340 uint16_t qi;
7341
7342 qi = 0;
7343
7344 els = (fct_els_t *)cmd->cmd_specific;
7345 qcmd = (qlt_cmd_t *)cmd->cmd_fca_private;
7346 qcmd->flags = QLT_CMD_TYPE_SOLICITED;
7347 qcmd->param.resp_offset = (uint16_t)((els->els_req_size + 7) & ~7);
7348 sz = minsz = qcmd->param.resp_offset + els->els_resp_size;
7349 buf = qlt_i_dmem_alloc(qlt, sz, &minsz, 0);
7350 if (buf == NULL) {
7351 return (FCT_BUSY);
7352 }
7353 bctl = (qlt_dmem_bctl_t *)buf->db_port_private;
7354
7355 qcmd->dbuf = buf;
7356 bcopy(els->els_req_payload, buf->db_sglist[0].seg_addr,
7357 els->els_req_size);
7358 qlt_dmem_dma_sync(buf, DDI_DMA_SYNC_FORDEV);
7359
7360 mutex_enter(&qlt->mq_req[qi].mq_lock);
7361 req = (uint8_t *)qlt_get_req_entries(qlt, 1, qi);
7362 if (req == NULL) {
7363 EL(qlt, "req = NULL, %xh %xh %p %xh\n", cmd->cmd_oxid,
7364 cmd->cmd_rportid, cmd, qcmd->fw_xchg_addr);
7365 qlt_dmem_free(NULL, buf);
7366 mutex_exit(&qlt->mq_req[qi].mq_lock);
7367 return (FCT_BUSY);
7368 }
7369 bzero(req, IOCB_SIZE);
7370 req[0] = 0x53; req[1] = 1;
7371 QMEM_WR32(qlt, (&req[4]), cmd->cmd_handle);
7372 QMEM_WR16(qlt, (&req[0xA]), cmd->cmd_rp->rp_handle);
7373 QMEM_WR16(qlt, (&req[0xC]), 1);
7374 QMEM_WR16(qlt, (&req[0xE]), 0x1000);
7375 QMEM_WR16(qlt, (&req[0x14]), 1);
7376 req[0x16] = els->els_req_payload[0];
7377 if (qlt->cur_topology == PORT_TOPOLOGY_PT_TO_PT) {
7378 req[0x1b] = (uint8_t)((cmd->cmd_lportid >> 16) & 0xff);
7379 req[0x1c] = (uint8_t)(cmd->cmd_lportid & 0xff);
7380 req[0x1d] = (uint8_t)((cmd->cmd_lportid >> 8) & 0xff);
7381 }
7382 QMEM_WR32(qlt, (&req[0x18]), cmd->cmd_rp->rp_id);
7383 QMEM_WR32(qlt, (&req[0x20]), els->els_resp_size);
7384 QMEM_WR32(qlt, (&req[0x24]), els->els_req_size);
7385 QMEM_WR64(qlt, (&req[0x28]), bctl->bctl_dev_addr);
7386 QMEM_WR32(qlt, (&req[0x30]), els->els_req_size);
7387 QMEM_WR64(qlt, (&req[0x34]), (bctl->bctl_dev_addr +
7388 qcmd->param.resp_offset));
7389 QMEM_WR32(qlt, (&req[0x3C]), els->els_resp_size);
7390
7391 EL(qlt, "ELS opcode %xh to %xh\n",
7392 req[0x16], cmd->cmd_rp->rp_id);
7393
7394 qlt_submit_req_entries(qlt, 1, qi);
7395 mutex_exit(&qlt->mq_req[qi].mq_lock);
7396
7397 return (FCT_SUCCESS);
7398 }
7399
7400 fct_status_t
qlt_send_ct(qlt_state_t * qlt,fct_cmd_t * cmd)7401 qlt_send_ct(qlt_state_t *qlt, fct_cmd_t *cmd)
7402 {
7403 uint8_t *req;
7404 fct_sol_ct_t *ct;
7405 qlt_cmd_t *qcmd;
7406 stmf_data_buf_t *buf;
7407 qlt_dmem_bctl_t *bctl;
7408 uint32_t sz, minsz;
7409 uint16_t qi;
7410
7411 qi = 0;
7412
7413 ct = (fct_sol_ct_t *)cmd->cmd_specific;
7414 qcmd = (qlt_cmd_t *)cmd->cmd_fca_private;
7415 qcmd->flags = QLT_CMD_TYPE_SOLICITED;
7416 qcmd->param.resp_offset = (uint16_t)((ct->ct_req_size + 7) & ~7);
7417 sz = minsz = qcmd->param.resp_offset + ct->ct_resp_size;
7418 buf = qlt_i_dmem_alloc(qlt, sz, &minsz, 0);
7419 if (buf == NULL) {
7420 return (FCT_BUSY);
7421 }
7422 bctl = (qlt_dmem_bctl_t *)buf->db_port_private;
7423
7424 qcmd->dbuf = buf;
7425 bcopy(ct->ct_req_payload, buf->db_sglist[0].seg_addr,
7426 ct->ct_req_size);
7427 qlt_dmem_dma_sync(buf, DDI_DMA_SYNC_FORDEV);
7428
7429 mutex_enter(&qlt->mq_req[qi].mq_lock);
7430 req = (uint8_t *)qlt_get_req_entries(qlt, 1, qi);
7431 if (req == NULL) {
7432 EL(qlt, "req = NULL, %xh %xh %p %xh\n", cmd->cmd_oxid,
7433 cmd->cmd_rportid, cmd, qcmd->fw_xchg_addr);
7434 qlt_dmem_free(NULL, buf);
7435 mutex_exit(&qlt->mq_req[qi].mq_lock);
7436 return (FCT_BUSY);
7437 }
7438 bzero(req, IOCB_SIZE);
7439 req[0] = 0x29; req[1] = 1;
7440 QMEM_WR32(qlt, (&req[4]), cmd->cmd_handle);
7441 QMEM_WR16(qlt, (&req[0xA]), cmd->cmd_rp->rp_handle);
7442 QMEM_WR16(qlt, (&req[0xC]), 1);
7443 QMEM_WR16(qlt, (&req[0x10]), 0x20); /* > (2 * RA_TOV) */
7444 QMEM_WR16(qlt, (&req[0x14]), 1);
7445
7446 QMEM_WR32(qlt, (&req[0x20]), ct->ct_resp_size);
7447 QMEM_WR32(qlt, (&req[0x24]), ct->ct_req_size);
7448
7449 QMEM_WR64(qlt, (&req[0x28]), bctl->bctl_dev_addr); /* COMMAND DSD */
7450 QMEM_WR32(qlt, (&req[0x30]), ct->ct_req_size);
7451 QMEM_WR64(qlt, (&req[0x34]), (bctl->bctl_dev_addr +
7452 qcmd->param.resp_offset)); /* RESPONSE DSD */
7453 QMEM_WR32(qlt, (&req[0x3C]), ct->ct_resp_size);
7454
7455 EL(qlt, "%p cmd_hdl=%xh %xh %xh\n",
7456 cmd, cmd->cmd_handle, ct->ct_req_size, ct->ct_resp_size);
7457
7458 qlt_submit_req_entries(qlt, 1, qi);
7459 mutex_exit(&qlt->mq_req[qi].mq_lock);
7460
7461 return (FCT_SUCCESS);
7462 }
7463
7464 /*ARGSUSED*/
7465 caddr_t
qlt_str_ptr(qlt_state_t * qlt,caddr_t bp,uint32_t * len)7466 qlt_str_ptr(qlt_state_t *qlt, caddr_t bp, uint32_t *len)
7467 {
7468 caddr_t sp;
7469 uint32_t i = 0;
7470
7471 sp = bp;
7472 while (*sp++ != 0) i++;
7473 if (i > *len || !(*len -= i)) {
7474 EL(qlt, "full buffer\n");
7475 return (NULL);
7476 }
7477 return (bp += i);
7478 }
7479
7480 static fct_status_t
qlt_27xx_fw_dump(fct_local_port_t * port,stmf_state_change_info_t * ssci)7481 qlt_27xx_fw_dump(fct_local_port_t *port, stmf_state_change_info_t *ssci)
7482 {
7483 qlt_state_t *qlt = (qlt_state_t *)port->port_fca_private;
7484 qlt_dmp_template_t *template_buff;
7485 uint32_t tsize, dsize, len;
7486 uint32_t cnt, *dp, *bp;
7487 uint8_t *fw;
7488 caddr_t sp;
7489
7490 EL(qlt, "enter...\n");
7491
7492 mutex_enter(&qlt->qlt_ioctl_lock);
7493 /*
7494 * To make sure that there's no outstanding dumping task
7495 */
7496 if (qlt->qlt_ioctl_flags & QLT_FWDUMP_INPROGRESS) {
7497 mutex_exit(&qlt->qlt_ioctl_lock);
7498 EL(qlt, "qlt_ioctl_flags=%xh, inprogress\n",
7499 qlt->qlt_ioctl_flags);
7500 return (FCT_FAILURE);
7501 }
7502
7503 /*
7504 * To make sure not to overwrite existing dump
7505 */
7506 if ((qlt->qlt_ioctl_flags & QLT_FWDUMP_ISVALID) &&
7507 !(qlt->qlt_ioctl_flags & QLT_FWDUMP_TRIGGERED_BY_USER) &&
7508 !(qlt->qlt_ioctl_flags & QLT_FWDUMP_FETCHED_BY_USER)) {
7509 /*
7510 * If we have already one dump, but it's not triggered by user
7511 * and the user hasn't fetched it, we shouldn't dump again.
7512 * But if qlt force a fw dump, then we need to overwrite the
7513 * previous one anyway.
7514 */
7515 mutex_exit(&qlt->qlt_ioctl_lock);
7516 EL(qlt, "qlt_ioctl_flags=%xh, already done\n",
7517 qlt->qlt_ioctl_flags);
7518 cmn_err(CE_NOTE, "qlt(%d): Skipping firmware dump as there "
7519 "is one already outstanding.", qlt->instance);
7520 return (FCT_FAILURE);
7521 }
7522
7523 if (qlt->dmp_template_addr == NULL) {
7524 mutex_exit(&qlt->qlt_ioctl_lock);
7525 EL(qlt, "dmp_template_addr is NULL, can't "
7526 "perform firmware dump\n");
7527 cmn_err(CE_WARN, "!qlt(%d) dmp_template_addr is NULL, can't "
7528 "perform firmware dump", qlt->instance);
7529 return (FCT_FAILURE);
7530 }
7531
7532 qlt->qlt_ioctl_flags |= QLT_FWDUMP_INPROGRESS;
7533 if (ssci != NULL && (ssci->st_rflags & STMF_RFLAG_USER_REQUEST)) {
7534 qlt->qlt_ioctl_flags |= QLT_FWDUMP_TRIGGERED_BY_USER;
7535 } else {
7536 qlt->qlt_ioctl_flags &= ~QLT_FWDUMP_TRIGGERED_BY_USER;
7537 }
7538 mutex_exit(&qlt->qlt_ioctl_lock);
7539
7540 template_buff = (qlt_dmp_template_t *)qlt->dmp_template_addr;
7541 tsize = template_buff->hdr.size_of_template;
7542
7543 if (qlt->fw_bin_dump_size == 0) {
7544 qlt->fw_bin_dump_buf = kmem_zalloc(tsize, KM_NOSLEEP);
7545 if (qlt->fw_bin_dump_buf == NULL) {
7546 cmn_err(CE_WARN, "!qlt(%d) cannot alloc bin dump buf",
7547 qlt->instance);
7548 return (FCT_FAILURE);
7549 }
7550 cnt = (uint32_t)(tsize / sizeof (uint32_t));
7551 dp = (uint32_t *)qlt->fw_bin_dump_buf;
7552 bp = (uint32_t *)&template_buff->hdr;
7553 while (cnt--) {
7554 *dp++ = ddi_get32(qlt->dmp_template_acc_handle, bp++);
7555 }
7556 qlt->fw_bin_dump_size = qlt_27xx_dmp_parse_template(qlt,
7557 (qlt_dt_hdr_t *)qlt->fw_bin_dump_buf, NULL, 0);
7558 kmem_free(qlt->fw_bin_dump_buf, tsize);
7559 qlt->fw_bin_dump_buf = NULL;
7560
7561 if (qlt->fw_bin_dump_size == 0) {
7562 return (FCT_FAILURE);
7563 }
7564
7565 /*
7566 * Determine ascii dump file size
7567 * 2 ascii bytes per binary byte + a space and
7568 * a newline every 16 binary bytes
7569 */
7570 qlt->fw_ascii_dump_size = qlt->fw_bin_dump_size << 1;
7571 qlt->fw_ascii_dump_size += qlt->fw_bin_dump_size;
7572 qlt->fw_ascii_dump_size += qlt->fw_bin_dump_size / 16 + 1;
7573
7574 EL(qlt, "fw_bin_dump_size=%xh, "
7575 "fw_acsii_dump_size=%xh\n", qlt->fw_bin_dump_size,
7576 qlt->fw_ascii_dump_size);
7577 }
7578
7579 if (qlt->fw_bin_dump_buf != NULL) {
7580 /* overwrite the previous fw dump by qlt forced fw dump */
7581 bzero((void *) qlt->fw_bin_dump_buf, qlt->fw_bin_dump_size);
7582 } else {
7583 qlt->fw_bin_dump_buf = kmem_zalloc(qlt->fw_bin_dump_size,
7584 KM_NOSLEEP);
7585 if (qlt->fw_bin_dump_buf == NULL) {
7586 qlt->fw_bin_dump_size = 0;
7587 EL(qlt, "done, failed alloc bin dump buf\n");
7588 return (FCT_FAILURE);
7589 }
7590 }
7591
7592 if ((qlt->fw_dump_size != 0) &&
7593 (qlt->fw_dump_size != qlt->fw_ascii_dump_size)) {
7594 if (qlt->qlt_fwdump_buf != NULL) {
7595 /* Release previously allocated buffer */
7596 kmem_free(qlt->qlt_fwdump_buf, qlt->fw_dump_size);
7597 qlt->qlt_fwdump_buf = NULL;
7598 }
7599 }
7600
7601 if (qlt->qlt_fwdump_buf == NULL) {
7602 qlt->qlt_fwdump_buf = kmem_zalloc(qlt->fw_ascii_dump_size,
7603 KM_NOSLEEP);
7604 if (qlt->qlt_fwdump_buf == NULL) {
7605 EL(qlt, "done, failed alloc ascii fw dump buf\n");
7606 return (FCT_FAILURE);
7607 }
7608 qlt->fw_dump_size = qlt->fw_ascii_dump_size;
7609 }
7610
7611 /* Disable ISP interrupts. */
7612 REG_WR32(qlt, 0xc, 0);
7613
7614 cnt = (uint32_t)(tsize / sizeof (uint32_t));
7615 dp = (uint32_t *)qlt->fw_bin_dump_buf;
7616 bp = (uint32_t *)&template_buff->hdr;
7617 while (cnt--) {
7618 *dp++ = ddi_get32(qlt->dmp_template_acc_handle, bp++);
7619 }
7620
7621 (void) qlt_27xx_dmp_parse_template(qlt,
7622 (qlt_dt_hdr_t *)qlt->fw_bin_dump_buf,
7623 (uint8_t *)dp, qlt->fw_bin_dump_size);
7624
7625 #ifdef _BIG_ENDIAN
7626 cnt = (uint32_t)(tsize / sizeof (uint32_t));
7627 dp = (uint32_t *)qlt->fw_bin_dump_buf;
7628 while (cnt--) {
7629 qlt_chg_endian((uint8_t *)dp, 4);
7630 dp++;
7631 }
7632 #endif
7633
7634 /*
7635 * Build ascii dump
7636 */
7637 len = qlt->fw_ascii_dump_size;
7638 dsize = qlt->fw_bin_dump_size;
7639 fw = (uint8_t *)qlt->fw_bin_dump_buf;
7640 sp = qlt->qlt_fwdump_buf;
7641
7642 EL(qlt, "fw_dump_buffer=%ph, fw=%ph, fw_ascii_dump_size=%xh, "
7643 "dsize=%xh\n", (void *)qlt->qlt_fwdump_buf, (void *)fw,
7644 len, dsize);
7645
7646 /*
7647 * 2 ascii bytes per binary byte + a space and
7648 * a newline every 16 binary bytes
7649 */
7650 cnt = 0;
7651 while (cnt < dsize) {
7652 (void) snprintf(sp, len, "%02x ", *fw++);
7653 if ((sp = qlt_str_ptr(qlt, sp, &len)) == NULL) {
7654 break;
7655 }
7656 if (++cnt % 16 == 0) {
7657 (void) snprintf(sp, len, "\n");
7658 if ((sp = qlt_str_ptr(qlt, sp, &len)) == NULL) {
7659 break;
7660 }
7661 }
7662 }
7663 if (cnt % 16 != 0) {
7664 (void) snprintf(sp, len, "\n");
7665 sp = qlt_str_ptr(qlt, sp, &len);
7666 }
7667
7668 mutex_enter(&qlt->qlt_ioctl_lock);
7669 qlt->qlt_ioctl_flags &=
7670 ~(QLT_FWDUMP_INPROGRESS | QLT_FWDUMP_FETCHED_BY_USER);
7671 qlt->qlt_ioctl_flags |= QLT_FWDUMP_ISVALID;
7672 mutex_exit(&qlt->qlt_ioctl_lock);
7673
7674 EL(qlt, "done...\n");
7675 return (FCT_SUCCESS);
7676 }
7677
7678 /*
7679 * All QLT_FIRMWARE_* will mainly be handled in this function
7680 * It can not be called in interrupt context
7681 *
7682 * FWDUMP's purpose is to serve ioctl, so we will use qlt_ioctl_flags
7683 * and qlt_ioctl_lock
7684 */
7685 static fct_status_t
qlt_firmware_dump(fct_local_port_t * port,stmf_state_change_info_t * ssci)7686 qlt_firmware_dump(fct_local_port_t *port, stmf_state_change_info_t *ssci)
7687 {
7688 qlt_state_t *qlt = (qlt_state_t *)port->port_fca_private;
7689 int i;
7690 int retries, n;
7691 uint_t size_left;
7692 char c = ' ';
7693 uint32_t addr, endaddr, words_to_read;
7694 caddr_t buf;
7695 fct_status_t ret;
7696
7697 if (qlt->qlt_27xx_chip) {
7698 return (qlt_27xx_fw_dump(port, ssci));
7699 }
7700 mutex_enter(&qlt->qlt_ioctl_lock);
7701 /*
7702 * To make sure that there's no outstanding dumping task
7703 */
7704 if (qlt->qlt_ioctl_flags & QLT_FWDUMP_INPROGRESS) {
7705 mutex_exit(&qlt->qlt_ioctl_lock);
7706 EL(qlt, "qlt_ioctl_flags=%xh, inprogress\n",
7707 qlt->qlt_ioctl_flags);
7708 return (FCT_FAILURE);
7709 }
7710
7711 /*
7712 * To make sure not to overwrite existing dump
7713 */
7714 if ((qlt->qlt_ioctl_flags & QLT_FWDUMP_ISVALID) &&
7715 !(qlt->qlt_ioctl_flags & QLT_FWDUMP_TRIGGERED_BY_USER) &&
7716 !(qlt->qlt_ioctl_flags & QLT_FWDUMP_FETCHED_BY_USER)) {
7717 /*
7718 * If we have already one dump, but it's not triggered by user
7719 * and the user hasn't fetched it, we shouldn't dump again.
7720 */
7721 mutex_exit(&qlt->qlt_ioctl_lock);
7722 EL(qlt, "qlt_ioctl_flags=%xh, already done\n",
7723 qlt->qlt_ioctl_flags);
7724 cmn_err(CE_NOTE, "qlt(%d): Skipping firmware dump as there "
7725 "is one already outstanding.", qlt->instance);
7726 return (FCT_FAILURE);
7727 }
7728 qlt->qlt_ioctl_flags |= QLT_FWDUMP_INPROGRESS;
7729 if ((ssci != NULL) && (ssci->st_rflags & STMF_RFLAG_USER_REQUEST)) {
7730 qlt->qlt_ioctl_flags |= QLT_FWDUMP_TRIGGERED_BY_USER;
7731 } else {
7732 qlt->qlt_ioctl_flags &= ~QLT_FWDUMP_TRIGGERED_BY_USER;
7733 }
7734 mutex_exit(&qlt->qlt_ioctl_lock);
7735
7736 size_left = QLT_FWDUMP_BUFSIZE;
7737 if (qlt->qlt_mq_enabled && qlt->qlt_queue_cnt >= 8) {
7738 size_left += 512 * 1024;
7739 }
7740 qlt->fw_dump_size = size_left;
7741 if (!qlt->qlt_fwdump_buf) {
7742 ASSERT(!(qlt->qlt_ioctl_flags & QLT_FWDUMP_ISVALID));
7743 /*
7744 * It's the only place that we allocate buf for dumping. After
7745 * it's allocated, we will use it until the port is detached.
7746 */
7747 qlt->qlt_fwdump_buf = kmem_zalloc(size_left, KM_NOSLEEP);
7748 if (qlt->qlt_fwdump_buf == NULL) {
7749 EL(qlt, "cannot alloc fwdump buffer\n");
7750 cmn_err(CE_WARN, "!qlt(%d): cannot alloc fwdump buf",
7751 qlt->instance);
7752 return (FCT_FAILURE);
7753 }
7754 }
7755
7756 EL(qlt, "starting firmware dump...\n");
7757 cmn_err(CE_WARN, "!qlt(%d) starting firmware dump...",
7758 qlt->instance);
7759
7760 /*
7761 * Start to dump firmware
7762 */
7763 buf = (caddr_t)qlt->qlt_fwdump_buf;
7764
7765 /*
7766 * Print the ISP firmware revision number and attributes information
7767 * Read the RISC to Host Status register
7768 */
7769 n = (int)snprintf(buf, size_left, "ISP FW Version %d.%02d.%02d "
7770 "Attributes %04x\n\nR2H Status register\n%08x",
7771 qlt->fw_major, qlt->fw_minor,
7772 qlt->fw_subminor, qlt->fw_attr, REG_RD32(qlt, REG_RISC_STATUS));
7773 buf += n; size_left -= n;
7774
7775 /*
7776 * Before pausing the RISC, make sure no mailbox can execute
7777 */
7778 mutex_enter(&qlt->mbox_lock);
7779 if ((qlt->mbox_io_state != MBOX_STATE_UNKNOWN) &&
7780 (qlt->qlt_intr_enabled)) {
7781 /*
7782 * Wait to grab the mailboxes
7783 */
7784 for (retries = 0; (qlt->mbox_io_state != MBOX_STATE_READY) &&
7785 (qlt->mbox_io_state != MBOX_STATE_UNKNOWN); retries++) {
7786 (void) cv_timedwait(&qlt->mbox_cv, &qlt->mbox_lock,
7787 ddi_get_lbolt() + drv_usectohz(1000000));
7788 if (retries > 5) {
7789 mutex_exit(&qlt->mbox_lock);
7790 EL(qlt, "can't drain out mailbox commands\n");
7791 goto dump_fail;
7792 }
7793 }
7794 qlt->mbox_io_state = MBOX_STATE_UNKNOWN;
7795 cv_broadcast(&qlt->mbox_cv);
7796 }
7797 mutex_exit(&qlt->mbox_lock);
7798
7799 /*
7800 * Pause the RISC processor
7801 */
7802 REG_WR32(qlt, REG_HCCR, HCCR_CMD(SET_RISC_PAUSE));
7803
7804 /*
7805 * Wait for the RISC processor to pause
7806 */
7807 for (i = 0; i < 200; i++) {
7808 if (REG_RD32(qlt, REG_RISC_STATUS) & 0x100) {
7809 break;
7810 }
7811 drv_usecwait(1000);
7812 }
7813 if (i == 200) {
7814 EL(qlt, "can't pause\n");
7815 return (FCT_FAILURE);
7816 }
7817
7818 if (qlt->qlt_83xx_chip) {
7819 /* Disable ECC checks in FB registers */
7820 REG_WR32(qlt, 0x54, 0x6000);
7821 REG_WR32(qlt, 0xC0, 0); /* 6000h */
7822 REG_WR32(qlt, 0xCC, 0); /* 6003h */
7823 REG_WR32(qlt, 0x54, 0x6010);
7824 REG_WR32(qlt, 0xD4, 0); /* 6015h */
7825
7826 /* disable ECC detection in PCR whilst dumping */
7827 REG_WR32(qlt, 0x54, 0xF70);
7828 REG_WR32(qlt, 0xF0, 0x60000000);
7829 }
7830
7831 if ((!qlt->qlt_25xx_chip) && (!qlt->qlt_81xx_chip) &&
7832 (!qlt->qlt_83xx_chip) && (!qlt->qlt_27xx_chip)) {
7833 goto over_25xx_specific_dump;
7834 }
7835 n = (int)snprintf(buf, size_left, "\n\nHostRisc registers\n");
7836 buf += n; size_left -= n;
7837 REG_WR32(qlt, 0x54, 0x7000);
7838 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
7839 buf += n; size_left -= n;
7840 REG_WR32(qlt, 0x54, 0x7010);
7841 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
7842 buf += n; size_left -= n;
7843 if (qlt->qlt_83xx_chip) {
7844 REG_WR32(qlt, 0x54, 0x7040);
7845 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
7846 buf += n; size_left -= n;
7847 }
7848 REG_WR32(qlt, 0x54, 0x7C00);
7849
7850 n = (int)snprintf(buf, size_left, "\nPCIe registers\n");
7851 buf += n; size_left -= n;
7852 REG_WR32(qlt, 0xC0, 0x1);
7853 n = qlt_fwdump_dump_regs(qlt, buf, 0xc4, 3, size_left);
7854 buf += n; size_left -= n;
7855 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 1, size_left);
7856 buf += n; size_left -= n;
7857 REG_WR32(qlt, 0xC0, 0x0);
7858
7859 /* don't need to do this for 83xx */
7860 if ((!qlt->qlt_83xx_chip) && (qlt->qlt_mq_enabled)) {
7861 uint16_t qi;
7862
7863 for (qi = 0; qi < qlt->qlt_queue_cnt; qi++) {
7864
7865 n = (int)snprintf(buf, size_left,
7866 "\n\nQueue Pointers #%x\n", qi);
7867 buf += n; size_left -= n;
7868
7869 n = (int)snprintf(buf, size_left, "%08x ",
7870 MQBAR_RD32(qlt,
7871 (qi * MQBAR_REG_OFFSET) + MQBAR_REQ_IN));
7872 buf += n; size_left -= n;
7873 n = (int)snprintf(buf, size_left, "%08x ",
7874 MQBAR_RD32(qlt,
7875 (qi * MQBAR_REG_OFFSET) + MQBAR_REQ_OUT));
7876 buf += n; size_left -= n;
7877 n = (int)snprintf(buf, size_left, "%08x ",
7878 MQBAR_RD32(qlt,
7879 (qi * MQBAR_REG_OFFSET) + MQBAR_RESP_IN));
7880 buf += n; size_left -= n;
7881 n = (int)snprintf(buf, size_left, "%08x",
7882 MQBAR_RD32(qlt,
7883 (qi * MQBAR_REG_OFFSET) + MQBAR_RESP_OUT));
7884 buf += n; size_left -= n;
7885 }
7886 }
7887
7888 over_25xx_specific_dump:;
7889 n = (int)snprintf(buf, size_left, "\n\nHost Interface registers\n");
7890 buf += n; size_left -= n;
7891 /*
7892 * Capture data from 32 registers
7893 */
7894 n = qlt_fwdump_dump_regs(qlt, buf, 0, 32, size_left);
7895 buf += n; size_left -= n;
7896
7897 /*
7898 * Disable interrupts
7899 */
7900 REG_WR32(qlt, 0xc, 0);
7901 EL(qlt, "Disable interrupt\n");
7902
7903 /*
7904 * Shadow registers
7905 */
7906 n = (int)snprintf(buf, size_left, "\nShadow registers\n");
7907 buf += n; size_left -= n;
7908
7909 REG_WR32(qlt, 0x54, 0xF70);
7910 addr = 0xb0000000;
7911 for (i = 0; i < 0xb; i++) {
7912 if ((!qlt->qlt_25xx_chip) &&
7913 (!qlt->qlt_81xx_chip) &&
7914 (!qlt->qlt_83xx_chip) &&
7915 (i >= 7)) {
7916 break;
7917 }
7918 if (i && ((i & 7) == 0)) {
7919 n = (int)snprintf(buf, size_left, "\n");
7920 buf += n; size_left -= n;
7921 }
7922 REG_WR32(qlt, 0xF0, addr);
7923 n = (int)snprintf(buf, size_left, "%08x ", REG_RD32(qlt, 0xFC));
7924 buf += n; size_left -= n;
7925 addr += 0x100000;
7926 }
7927
7928 if ((qlt->qlt_25xx_chip) || (qlt->qlt_81xx_chip) ||
7929 (qlt->qlt_83xx_chip)) {
7930 REG_WR32(qlt, 0x54, 0x10);
7931 n = (int)snprintf(buf, size_left,
7932 "\n\nRISC IO register\n%08x", REG_RD32(qlt, 0xC0));
7933 buf += n; size_left -= n;
7934 }
7935
7936 /*
7937 * Mailbox registers
7938 */
7939 n = (int)snprintf(buf, size_left, "\n\nMailbox registers\n");
7940 buf += n; size_left -= n;
7941 for (i = 0; i < 32; i += 2) {
7942 if ((i + 2) & 15) {
7943 c = ' ';
7944 } else {
7945 c = '\n';
7946 }
7947 n = (int)snprintf(buf, size_left, "%04x %04x%c",
7948 REG_RD16(qlt, 0x80 + (i << 1)),
7949 REG_RD16(qlt, 0x80 + ((i+1) << 1)), c);
7950 buf += n; size_left -= n;
7951 }
7952
7953 /*
7954 * Transfer sequence registers
7955 */
7956 n = (int)snprintf(buf, size_left, "\nXSEQ GP registers\n");
7957 buf += n; size_left -= n;
7958
7959 if (qlt->qlt_83xx_chip) {
7960 REG_WR32(qlt, 0x54, 0xBE00);
7961 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
7962 buf += n; size_left -= n;
7963 REG_WR32(qlt, 0x54, 0xBE10);
7964 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
7965 buf += n; size_left -= n;
7966 REG_WR32(qlt, 0x54, 0xBE20);
7967 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
7968 buf += n; size_left -= n;
7969 REG_WR32(qlt, 0x54, 0xBE30);
7970 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
7971 buf += n; size_left -= n;
7972 REG_WR32(qlt, 0x54, 0xBE40);
7973 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
7974 buf += n; size_left -= n;
7975 REG_WR32(qlt, 0x54, 0xBE50);
7976 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
7977 buf += n; size_left -= n;
7978 REG_WR32(qlt, 0x54, 0xBE60);
7979 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
7980 buf += n; size_left -= n;
7981 REG_WR32(qlt, 0x54, 0xBE70);
7982 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
7983 buf += n; size_left -= n;
7984 }
7985 REG_WR32(qlt, 0x54, 0xBF00);
7986 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
7987 buf += n; size_left -= n;
7988 REG_WR32(qlt, 0x54, 0xBF10);
7989 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
7990 buf += n; size_left -= n;
7991 REG_WR32(qlt, 0x54, 0xBF20);
7992 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
7993 buf += n; size_left -= n;
7994 REG_WR32(qlt, 0x54, 0xBF30);
7995 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
7996 buf += n; size_left -= n;
7997 REG_WR32(qlt, 0x54, 0xBF40);
7998 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
7999 buf += n; size_left -= n;
8000 REG_WR32(qlt, 0x54, 0xBF50);
8001 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8002 buf += n; size_left -= n;
8003 REG_WR32(qlt, 0x54, 0xBF60);
8004 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8005 buf += n; size_left -= n;
8006 REG_WR32(qlt, 0x54, 0xBF70);
8007 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8008 buf += n; size_left -= n;
8009 n = (int)snprintf(buf, size_left, "\nXSEQ-0 registers\n");
8010 buf += n; size_left -= n;
8011 if ((qlt->qlt_25xx_chip) || (qlt->qlt_81xx_chip) ||
8012 (qlt->qlt_83xx_chip)) {
8013 REG_WR32(qlt, 0x54, 0xBFC0);
8014 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8015 buf += n; size_left -= n;
8016 REG_WR32(qlt, 0x54, 0xBFD0);
8017 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8018 buf += n; size_left -= n;
8019 }
8020 REG_WR32(qlt, 0x54, 0xBFE0);
8021 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8022 buf += n; size_left -= n;
8023 n = (int)snprintf(buf, size_left, "\nXSEQ-1 registers\n");
8024 buf += n; size_left -= n;
8025 REG_WR32(qlt, 0x54, 0xBFF0);
8026 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8027 buf += n; size_left -= n;
8028
8029 if (qlt->qlt_83xx_chip) {
8030 n = (int)snprintf(buf, size_left, "\nXSEQ-2 registers\n");
8031 buf += n; size_left -= n;
8032 REG_WR32(qlt, 0x54, 0xBEF0);
8033 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8034 buf += n; size_left -= n;
8035 }
8036
8037 /*
8038 * Receive sequence registers
8039 */
8040 n = (int)snprintf(buf, size_left, "\nRSEQ GP registers\n");
8041 buf += n; size_left -= n;
8042 if (qlt->qlt_83xx_chip) {
8043 REG_WR32(qlt, 0x54, 0xFE00);
8044 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8045 buf += n; size_left -= n;
8046 REG_WR32(qlt, 0x54, 0xFE10);
8047 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8048 buf += n; size_left -= n;
8049 REG_WR32(qlt, 0x54, 0xFE20);
8050 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8051 buf += n; size_left -= n;
8052 REG_WR32(qlt, 0x54, 0xFE30);
8053 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8054 buf += n; size_left -= n;
8055 REG_WR32(qlt, 0x54, 0xFE40);
8056 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8057 buf += n; size_left -= n;
8058 REG_WR32(qlt, 0x54, 0xFE50);
8059 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8060 buf += n; size_left -= n;
8061 REG_WR32(qlt, 0x54, 0xFE60);
8062 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8063 buf += n; size_left -= n;
8064 REG_WR32(qlt, 0x54, 0xFE70);
8065 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8066 buf += n; size_left -= n;
8067 }
8068 REG_WR32(qlt, 0x54, 0xFF00);
8069 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8070 buf += n; size_left -= n;
8071 REG_WR32(qlt, 0x54, 0xFF10);
8072 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8073 buf += n; size_left -= n;
8074 REG_WR32(qlt, 0x54, 0xFF20);
8075 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8076 buf += n; size_left -= n;
8077 REG_WR32(qlt, 0x54, 0xFF30);
8078 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8079 buf += n; size_left -= n;
8080 REG_WR32(qlt, 0x54, 0xFF40);
8081 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8082 buf += n; size_left -= n;
8083 REG_WR32(qlt, 0x54, 0xFF50);
8084 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8085 buf += n; size_left -= n;
8086 REG_WR32(qlt, 0x54, 0xFF60);
8087 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8088 buf += n; size_left -= n;
8089 REG_WR32(qlt, 0x54, 0xFF70);
8090 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8091 buf += n; size_left -= n;
8092 n = (int)snprintf(buf, size_left, "\nRSEQ-0 registers\n");
8093 buf += n; size_left -= n;
8094 if ((qlt->qlt_25xx_chip) || (qlt->qlt_81xx_chip) ||
8095 (qlt->qlt_83xx_chip)) {
8096 REG_WR32(qlt, 0x54, 0xFFC0);
8097 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8098 buf += n; size_left -= n;
8099 }
8100 REG_WR32(qlt, 0x54, 0xFFD0);
8101 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8102 buf += n; size_left -= n;
8103 n = (int)snprintf(buf, size_left, "\nRSEQ-1 registers\n");
8104 buf += n; size_left -= n;
8105 REG_WR32(qlt, 0x54, 0xFFE0);
8106 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8107 buf += n; size_left -= n;
8108 n = (int)snprintf(buf, size_left, "\nRSEQ-2 registers\n");
8109 buf += n; size_left -= n;
8110 REG_WR32(qlt, 0x54, 0xFFF0);
8111 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8112 buf += n; size_left -= n;
8113 if (qlt->qlt_83xx_chip) {
8114 n = (int)snprintf(buf, size_left, "\nRSEQ-3 registers\n");
8115 buf += n; size_left -= n;
8116 REG_WR32(qlt, 0x54, 0xFEF0);
8117 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8118 buf += n; size_left -= n;
8119 }
8120
8121 if ((!qlt->qlt_25xx_chip) && (!qlt->qlt_81xx_chip) &&
8122 (!qlt->qlt_83xx_chip))
8123 goto over_aseq_regs;
8124
8125 /*
8126 * Auxiliary sequencer registers
8127 */
8128 n = (int)snprintf(buf, size_left, "\nASEQ GP registers\n");
8129 buf += n; size_left -= n;
8130 REG_WR32(qlt, 0x54, 0xB000);
8131 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8132 buf += n; size_left -= n;
8133 REG_WR32(qlt, 0x54, 0xB010);
8134 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8135 buf += n; size_left -= n;
8136 REG_WR32(qlt, 0x54, 0xB020);
8137 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8138 buf += n; size_left -= n;
8139 REG_WR32(qlt, 0x54, 0xB030);
8140 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8141 buf += n; size_left -= n;
8142 REG_WR32(qlt, 0x54, 0xB040);
8143 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8144 buf += n; size_left -= n;
8145 REG_WR32(qlt, 0x54, 0xB050);
8146 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8147 buf += n; size_left -= n;
8148 REG_WR32(qlt, 0x54, 0xB060);
8149 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8150 buf += n; size_left -= n;
8151 REG_WR32(qlt, 0x54, 0xB070);
8152 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8153 buf += n; size_left -= n;
8154 if (qlt->qlt_83xx_chip) {
8155 REG_WR32(qlt, 0x54, 0xB100);
8156 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8157 buf += n; size_left -= n;
8158 REG_WR32(qlt, 0x54, 0xB110);
8159 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8160 buf += n; size_left -= n;
8161 REG_WR32(qlt, 0x54, 0xB120);
8162 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8163 buf += n; size_left -= n;
8164 REG_WR32(qlt, 0x54, 0xB130);
8165 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8166 buf += n; size_left -= n;
8167 REG_WR32(qlt, 0x54, 0xB140);
8168 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8169 buf += n; size_left -= n;
8170 REG_WR32(qlt, 0x54, 0xB150);
8171 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8172 buf += n; size_left -= n;
8173 REG_WR32(qlt, 0x54, 0xB160);
8174 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8175 buf += n; size_left -= n;
8176 REG_WR32(qlt, 0x54, 0xB170);
8177 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8178 buf += n; size_left -= n;
8179 }
8180 n = (int)snprintf(buf, size_left, "\nASEQ-0 registers\n");
8181 buf += n; size_left -= n;
8182 REG_WR32(qlt, 0x54, 0xB0C0);
8183 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8184 buf += n; size_left -= n;
8185 REG_WR32(qlt, 0x54, 0xB0D0);
8186 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8187 buf += n; size_left -= n;
8188 n = (int)snprintf(buf, size_left, "\nASEQ-1 registers\n");
8189 buf += n; size_left -= n;
8190 REG_WR32(qlt, 0x54, 0xB0E0);
8191 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8192 buf += n; size_left -= n;
8193 n = (int)snprintf(buf, size_left, "\nASEQ-2 registers\n");
8194 buf += n; size_left -= n;
8195 REG_WR32(qlt, 0x54, 0xB0F0);
8196 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8197 buf += n; size_left -= n;
8198 if (qlt->qlt_83xx_chip) {
8199 n = (int)snprintf(buf, size_left, "\nASEQ-3 registers\n");
8200 buf += n; size_left -= n;
8201 REG_WR32(qlt, 0x54, 0xB1F0);
8202 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8203 buf += n; size_left -= n;
8204 }
8205
8206 over_aseq_regs:;
8207
8208 /*
8209 * Command DMA registers
8210 */
8211 n = (int)snprintf(buf, size_left, "\nCommand DMA registers\n");
8212 buf += n; size_left -= n;
8213 REG_WR32(qlt, 0x54, 0x7100);
8214 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8215 buf += n; size_left -= n;
8216 if (qlt->qlt_83xx_chip) {
8217 REG_WR32(qlt, 0x54, 0x7120);
8218 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8219 buf += n; size_left -= n;
8220 REG_WR32(qlt, 0x54, 0x7130);
8221 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8222 buf += n; size_left -= n;
8223 REG_WR32(qlt, 0x54, 0x71F0);
8224 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8225 buf += n; size_left -= n;
8226 }
8227
8228 /*
8229 * Queues
8230 */
8231 n = (int)snprintf(buf, size_left,
8232 "\nRequest0 Queue DMA Channel registers\n");
8233 buf += n; size_left -= n;
8234 REG_WR32(qlt, 0x54, 0x7200);
8235 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 8, size_left);
8236 buf += n; size_left -= n;
8237 n = qlt_fwdump_dump_regs(qlt, buf, 0xe4, 7, size_left);
8238 buf += n; size_left -= n;
8239
8240 n = (int)snprintf(buf, size_left,
8241 "\n\nResponse0 Queue DMA Channel registers\n");
8242 buf += n; size_left -= n;
8243 REG_WR32(qlt, 0x54, 0x7300);
8244 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 8, size_left);
8245 buf += n; size_left -= n;
8246 n = qlt_fwdump_dump_regs(qlt, buf, 0xe4, 7, size_left);
8247 buf += n; size_left -= n;
8248
8249 n = (int)snprintf(buf, size_left,
8250 "\n\nRequest1 Queue DMA Channel registers\n");
8251 buf += n; size_left -= n;
8252 REG_WR32(qlt, 0x54, 0x7400);
8253 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 8, size_left);
8254 buf += n; size_left -= n;
8255 n = qlt_fwdump_dump_regs(qlt, buf, 0xe4, 7, size_left);
8256 buf += n; size_left -= n;
8257
8258 /*
8259 * Transmit DMA registers
8260 */
8261 n = (int)snprintf(buf, size_left, "\n\nXMT0 Data DMA registers\n");
8262 buf += n; size_left -= n;
8263 REG_WR32(qlt, 0x54, 0x7600);
8264 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8265 buf += n; size_left -= n;
8266 REG_WR32(qlt, 0x54, 0x7610);
8267 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8268 buf += n; size_left -= n;
8269 n = (int)snprintf(buf, size_left, "\nXMT1 Data DMA registers\n");
8270 buf += n; size_left -= n;
8271 REG_WR32(qlt, 0x54, 0x7620);
8272 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8273 buf += n; size_left -= n;
8274 REG_WR32(qlt, 0x54, 0x7630);
8275 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8276 buf += n; size_left -= n;
8277 n = (int)snprintf(buf, size_left, "\nXMT2 Data DMA registers\n");
8278 buf += n; size_left -= n;
8279 REG_WR32(qlt, 0x54, 0x7640);
8280 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8281 buf += n; size_left -= n;
8282 REG_WR32(qlt, 0x54, 0x7650);
8283 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8284 buf += n; size_left -= n;
8285 n = (int)snprintf(buf, size_left, "\nXMT3 Data DMA registers\n");
8286 buf += n; size_left -= n;
8287 REG_WR32(qlt, 0x54, 0x7660);
8288 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8289 buf += n; size_left -= n;
8290 REG_WR32(qlt, 0x54, 0x7670);
8291 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8292 buf += n; size_left -= n;
8293 n = (int)snprintf(buf, size_left, "\nXMT4 Data DMA registers\n");
8294 buf += n; size_left -= n;
8295 REG_WR32(qlt, 0x54, 0x7680);
8296 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8297 buf += n; size_left -= n;
8298 REG_WR32(qlt, 0x54, 0x7690);
8299 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8300 buf += n; size_left -= n;
8301 n = (int)snprintf(buf, size_left, "\nXMT Data DMA Common registers\n");
8302 buf += n; size_left -= n;
8303 REG_WR32(qlt, 0x54, 0x76A0);
8304 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8305 buf += n; size_left -= n;
8306
8307 /*
8308 * Receive DMA registers
8309 */
8310 n = (int)snprintf(buf, size_left,
8311 "\nRCV Thread 0 Data DMA registers\n");
8312 buf += n; size_left -= n;
8313 REG_WR32(qlt, 0x54, 0x7700);
8314 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8315 buf += n; size_left -= n;
8316 REG_WR32(qlt, 0x54, 0x7710);
8317 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8318 buf += n; size_left -= n;
8319 n = (int)snprintf(buf, size_left,
8320 "\nRCV Thread 1 Data DMA registers\n");
8321 buf += n; size_left -= n;
8322 REG_WR32(qlt, 0x54, 0x7720);
8323 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8324 buf += n; size_left -= n;
8325 REG_WR32(qlt, 0x54, 0x7730);
8326 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8327 buf += n; size_left -= n;
8328
8329 /*
8330 * RISC registers
8331 */
8332 n = (int)snprintf(buf, size_left, "\nRISC GP registers\n");
8333 buf += n; size_left -= n;
8334 REG_WR32(qlt, 0x54, 0x0F00);
8335 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8336 buf += n; size_left -= n;
8337 REG_WR32(qlt, 0x54, 0x0F10);
8338 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8339 buf += n; size_left -= n;
8340 REG_WR32(qlt, 0x54, 0x0F20);
8341 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8342 buf += n; size_left -= n;
8343 REG_WR32(qlt, 0x54, 0x0F30);
8344 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8345 buf += n; size_left -= n;
8346 REG_WR32(qlt, 0x54, 0x0F40);
8347 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8348 buf += n; size_left -= n;
8349 REG_WR32(qlt, 0x54, 0x0F50);
8350 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8351 buf += n; size_left -= n;
8352 REG_WR32(qlt, 0x54, 0x0F60);
8353 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8354 buf += n; size_left -= n;
8355 REG_WR32(qlt, 0x54, 0x0F70);
8356 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8357 buf += n; size_left -= n;
8358
8359 /*
8360 * Local memory controller registers
8361 */
8362 n = (int)snprintf(buf, size_left, "\nLMC registers\n");
8363 buf += n; size_left -= n;
8364 REG_WR32(qlt, 0x54, 0x3000);
8365 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8366 buf += n; size_left -= n;
8367 REG_WR32(qlt, 0x54, 0x3010);
8368 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8369 buf += n; size_left -= n;
8370 REG_WR32(qlt, 0x54, 0x3020);
8371 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8372 buf += n; size_left -= n;
8373 REG_WR32(qlt, 0x54, 0x3030);
8374 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8375 buf += n; size_left -= n;
8376 REG_WR32(qlt, 0x54, 0x3040);
8377 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8378 buf += n; size_left -= n;
8379 REG_WR32(qlt, 0x54, 0x3050);
8380 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8381 buf += n; size_left -= n;
8382 REG_WR32(qlt, 0x54, 0x3060);
8383 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8384 buf += n; size_left -= n;
8385
8386 if ((qlt->qlt_25xx_chip) || (qlt->qlt_81xx_chip) ||
8387 (qlt->qlt_83xx_chip)) {
8388 REG_WR32(qlt, 0x54, 0x3070);
8389 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8390 buf += n; size_left -= n;
8391 }
8392
8393 /*
8394 * Fibre protocol module registers
8395 */
8396 n = (int)snprintf(buf, size_left, "\nFPM hardware registers\n");
8397 buf += n; size_left -= n;
8398 REG_WR32(qlt, 0x54, 0x4000);
8399 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8400 buf += n; size_left -= n;
8401 REG_WR32(qlt, 0x54, 0x4010);
8402 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8403 buf += n; size_left -= n;
8404 REG_WR32(qlt, 0x54, 0x4020);
8405 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8406 buf += n; size_left -= n;
8407 REG_WR32(qlt, 0x54, 0x4030);
8408 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8409 buf += n; size_left -= n;
8410 REG_WR32(qlt, 0x54, 0x4040);
8411 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8412 buf += n; size_left -= n;
8413 REG_WR32(qlt, 0x54, 0x4050);
8414 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8415 buf += n; size_left -= n;
8416 REG_WR32(qlt, 0x54, 0x4060);
8417 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8418 buf += n; size_left -= n;
8419 REG_WR32(qlt, 0x54, 0x4070);
8420 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8421 buf += n; size_left -= n;
8422 REG_WR32(qlt, 0x54, 0x4080);
8423 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8424 buf += n; size_left -= n;
8425 REG_WR32(qlt, 0x54, 0x4090);
8426 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8427 buf += n; size_left -= n;
8428 REG_WR32(qlt, 0x54, 0x40A0);
8429 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8430 buf += n; size_left -= n;
8431 REG_WR32(qlt, 0x54, 0x40B0);
8432 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8433 buf += n; size_left -= n;
8434 if ((qlt->qlt_83xx_chip) || (qlt->qlt_81xx_chip)) {
8435 REG_WR32(qlt, 0x54, 0x40C0);
8436 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8437 buf += n; size_left -= n;
8438 REG_WR32(qlt, 0x54, 0x40D0);
8439 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8440 buf += n; size_left -= n;
8441 }
8442 if (qlt->qlt_83xx_chip) {
8443 REG_WR32(qlt, 0x54, 0x40E0);
8444 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8445 buf += n; size_left -= n;
8446 REG_WR32(qlt, 0x54, 0x40F0);
8447 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8448 buf += n; size_left -= n;
8449
8450 n = (int)snprintf(buf, size_left, "\nRQ0 Array registers\n");
8451 buf += n; size_left -= n;
8452 REG_WR32(qlt, 0x54, 0x5C00);
8453 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8454 buf += n; size_left -= n;
8455 REG_WR32(qlt, 0x54, 0x5C10);
8456 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8457 buf += n; size_left -= n;
8458 REG_WR32(qlt, 0x54, 0x5C20);
8459 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8460 buf += n; size_left -= n;
8461 REG_WR32(qlt, 0x54, 0x5C30);
8462 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8463 buf += n; size_left -= n;
8464 REG_WR32(qlt, 0x54, 0x5C40);
8465 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8466 buf += n; size_left -= n;
8467 REG_WR32(qlt, 0x54, 0x5C50);
8468 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8469 buf += n; size_left -= n;
8470 REG_WR32(qlt, 0x54, 0x5C60);
8471 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8472 buf += n; size_left -= n;
8473 REG_WR32(qlt, 0x54, 0x5C70);
8474 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8475 buf += n; size_left -= n;
8476 REG_WR32(qlt, 0x54, 0x5C80);
8477 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8478 buf += n; size_left -= n;
8479 REG_WR32(qlt, 0x54, 0x5C90);
8480 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8481 buf += n; size_left -= n;
8482 REG_WR32(qlt, 0x54, 0x5CA0);
8483 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8484 buf += n; size_left -= n;
8485 REG_WR32(qlt, 0x54, 0x5CB0);
8486 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8487 buf += n; size_left -= n;
8488 REG_WR32(qlt, 0x54, 0x5CC0);
8489 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8490 buf += n; size_left -= n;
8491 REG_WR32(qlt, 0x54, 0x5CD0);
8492 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8493 buf += n; size_left -= n;
8494 REG_WR32(qlt, 0x54, 0x5CE0);
8495 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8496 buf += n; size_left -= n;
8497 REG_WR32(qlt, 0x54, 0x5CF0);
8498 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8499 buf += n; size_left -= n;
8500
8501 n = (int)snprintf(buf, size_left, "\nRQ1 Array registers\n");
8502 buf += n; size_left -= n;
8503 REG_WR32(qlt, 0x54, 0x5D00);
8504 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8505 buf += n; size_left -= n;
8506 REG_WR32(qlt, 0x54, 0x5D10);
8507 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8508 buf += n; size_left -= n;
8509 REG_WR32(qlt, 0x54, 0x5D20);
8510 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8511 buf += n; size_left -= n;
8512 REG_WR32(qlt, 0x54, 0x5D30);
8513 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8514 buf += n; size_left -= n;
8515 REG_WR32(qlt, 0x54, 0x5D40);
8516 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8517 buf += n; size_left -= n;
8518 REG_WR32(qlt, 0x54, 0x5D50);
8519 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8520 buf += n; size_left -= n;
8521 REG_WR32(qlt, 0x54, 0x5D60);
8522 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8523 buf += n; size_left -= n;
8524 REG_WR32(qlt, 0x54, 0x5D70);
8525 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8526 buf += n; size_left -= n;
8527 REG_WR32(qlt, 0x54, 0x5D80);
8528 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8529 buf += n; size_left -= n;
8530 REG_WR32(qlt, 0x54, 0x5D90);
8531 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8532 buf += n; size_left -= n;
8533 REG_WR32(qlt, 0x54, 0x5DA0);
8534 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8535 buf += n; size_left -= n;
8536 REG_WR32(qlt, 0x54, 0x5DB0);
8537 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8538 buf += n; size_left -= n;
8539 REG_WR32(qlt, 0x54, 0x5DC0);
8540 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8541 buf += n; size_left -= n;
8542 REG_WR32(qlt, 0x54, 0x5DD0);
8543 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8544 buf += n; size_left -= n;
8545 REG_WR32(qlt, 0x54, 0x5DE0);
8546 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8547 buf += n; size_left -= n;
8548 REG_WR32(qlt, 0x54, 0x5DF0);
8549 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8550 buf += n; size_left -= n;
8551
8552 n = (int)snprintf(buf, size_left, "\nRP0 Array registers\n");
8553 buf += n; size_left -= n;
8554 REG_WR32(qlt, 0x54, 0x5E00);
8555 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8556 buf += n; size_left -= n;
8557 REG_WR32(qlt, 0x54, 0x5E10);
8558 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8559 buf += n; size_left -= n;
8560 REG_WR32(qlt, 0x54, 0x5E20);
8561 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8562 buf += n; size_left -= n;
8563 REG_WR32(qlt, 0x54, 0x5E30);
8564 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8565 buf += n; size_left -= n;
8566 REG_WR32(qlt, 0x54, 0x5E40);
8567 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8568 buf += n; size_left -= n;
8569 REG_WR32(qlt, 0x54, 0x5E50);
8570 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8571 buf += n; size_left -= n;
8572 REG_WR32(qlt, 0x54, 0x5E60);
8573 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8574 buf += n; size_left -= n;
8575 REG_WR32(qlt, 0x54, 0x5E70);
8576 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8577 buf += n; size_left -= n;
8578 REG_WR32(qlt, 0x54, 0x5E80);
8579 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8580 buf += n; size_left -= n;
8581 REG_WR32(qlt, 0x54, 0x5E90);
8582 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8583 buf += n; size_left -= n;
8584 REG_WR32(qlt, 0x54, 0x5EA0);
8585 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8586 buf += n; size_left -= n;
8587 REG_WR32(qlt, 0x54, 0x5EB0);
8588 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8589 buf += n; size_left -= n;
8590 REG_WR32(qlt, 0x54, 0x5EC0);
8591 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8592 buf += n; size_left -= n;
8593 REG_WR32(qlt, 0x54, 0x5ED0);
8594 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8595 buf += n; size_left -= n;
8596 REG_WR32(qlt, 0x54, 0x5EE0);
8597 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8598 buf += n; size_left -= n;
8599 REG_WR32(qlt, 0x54, 0x5EF0);
8600 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8601 buf += n; size_left -= n;
8602
8603 n = (int)snprintf(buf, size_left, "\nRP1 Array registers\n");
8604 buf += n; size_left -= n;
8605 REG_WR32(qlt, 0x54, 0x5F00);
8606 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8607 buf += n; size_left -= n;
8608 REG_WR32(qlt, 0x54, 0x5F10);
8609 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8610 buf += n; size_left -= n;
8611 REG_WR32(qlt, 0x54, 0x5F20);
8612 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8613 buf += n; size_left -= n;
8614 REG_WR32(qlt, 0x54, 0x5F30);
8615 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8616 buf += n; size_left -= n;
8617 REG_WR32(qlt, 0x54, 0x5F40);
8618 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8619 buf += n; size_left -= n;
8620 REG_WR32(qlt, 0x54, 0x5F50);
8621 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8622 buf += n; size_left -= n;
8623 REG_WR32(qlt, 0x54, 0x5F60);
8624 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8625 buf += n; size_left -= n;
8626 REG_WR32(qlt, 0x54, 0x5F70);
8627 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8628 buf += n; size_left -= n;
8629 REG_WR32(qlt, 0x54, 0x5F80);
8630 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8631 buf += n; size_left -= n;
8632 REG_WR32(qlt, 0x54, 0x5F90);
8633 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8634 buf += n; size_left -= n;
8635 REG_WR32(qlt, 0x54, 0x5FA0);
8636 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8637 buf += n; size_left -= n;
8638 REG_WR32(qlt, 0x54, 0x5FB0);
8639 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8640 buf += n; size_left -= n;
8641 REG_WR32(qlt, 0x54, 0x5FC0);
8642 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8643 buf += n; size_left -= n;
8644 REG_WR32(qlt, 0x54, 0x5FD0);
8645 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8646 buf += n; size_left -= n;
8647 REG_WR32(qlt, 0x54, 0x5FE0);
8648 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8649 buf += n; size_left -= n;
8650 REG_WR32(qlt, 0x54, 0x5FF0);
8651 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8652 buf += n; size_left -= n;
8653
8654 n = (int)snprintf(buf,
8655 size_left, "\nQueue Control Registers\n");
8656 buf += n; size_left -= n;
8657 REG_WR32(qlt, 0x54, 0x7800);
8658 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8659 buf += n; size_left -= n;
8660 }
8661
8662 /*
8663 * Fibre buffer registers
8664 */
8665 n = (int)snprintf(buf, size_left, "\nFB hardware registers\n");
8666 buf += n; size_left -= n;
8667 REG_WR32(qlt, 0x54, 0x6000);
8668 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8669 buf += n; size_left -= n;
8670 REG_WR32(qlt, 0x54, 0x6010);
8671 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8672 buf += n; size_left -= n;
8673 REG_WR32(qlt, 0x54, 0x6020);
8674 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8675 buf += n; size_left -= n;
8676 REG_WR32(qlt, 0x54, 0x6030);
8677 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8678 buf += n; size_left -= n;
8679 REG_WR32(qlt, 0x54, 0x6040);
8680 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8681 buf += n; size_left -= n;
8682 if (qlt->qlt_83xx_chip) {
8683 REG_WR32(qlt, 0x54, 0x6060);
8684 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8685 buf += n; size_left -= n;
8686 REG_WR32(qlt, 0x54, 0x6070);
8687 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8688 buf += n; size_left -= n;
8689 }
8690 REG_WR32(qlt, 0x54, 0x6100);
8691 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8692 buf += n; size_left -= n;
8693 REG_WR32(qlt, 0x54, 0x6130);
8694 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8695 buf += n; size_left -= n;
8696 REG_WR32(qlt, 0x54, 0x6150);
8697 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8698 buf += n; size_left -= n;
8699 REG_WR32(qlt, 0x54, 0x6170);
8700 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8701 buf += n; size_left -= n;
8702 REG_WR32(qlt, 0x54, 0x6190);
8703 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8704 buf += n; size_left -= n;
8705 REG_WR32(qlt, 0x54, 0x61B0);
8706 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8707 buf += n; size_left -= n;
8708 if ((qlt->qlt_83xx_chip) || (qlt->qlt_81xx_chip)) {
8709 REG_WR32(qlt, 0x54, 0x61C0);
8710 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8711 buf += n; size_left -= n;
8712 }
8713 if (qlt->qlt_83xx_chip) {
8714 REG_WR32(qlt, 0x54, 0x6530);
8715 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8716 buf += n; size_left -= n;
8717 REG_WR32(qlt, 0x54, 0x6540);
8718 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8719 buf += n; size_left -= n;
8720 REG_WR32(qlt, 0x54, 0x6550);
8721 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8722 buf += n; size_left -= n;
8723 REG_WR32(qlt, 0x54, 0x6560);
8724 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8725 buf += n; size_left -= n;
8726 REG_WR32(qlt, 0x54, 0x6570);
8727 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8728 buf += n; size_left -= n;
8729 REG_WR32(qlt, 0x54, 0x6580);
8730 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8731 buf += n; size_left -= n;
8732 REG_WR32(qlt, 0x54, 0x6590);
8733 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8734 buf += n; size_left -= n;
8735 REG_WR32(qlt, 0x54, 0x65A0);
8736 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8737 buf += n; size_left -= n;
8738 REG_WR32(qlt, 0x54, 0x65B0);
8739 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8740 buf += n; size_left -= n;
8741 REG_WR32(qlt, 0x54, 0x65C0);
8742 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8743 buf += n; size_left -= n;
8744 REG_WR32(qlt, 0x54, 0x65D0);
8745 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8746 buf += n; size_left -= n;
8747 REG_WR32(qlt, 0x54, 0x65E0);
8748 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8749 buf += n; size_left -= n;
8750 }
8751 if ((qlt->qlt_25xx_chip) || (qlt->qlt_81xx_chip) ||
8752 (qlt->qlt_83xx_chip)) {
8753 REG_WR32(qlt, 0x54, 0x6F00);
8754 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8755 buf += n; size_left -= n;
8756 }
8757
8758 if (qlt->qlt_83xx_chip) {
8759 n = (int)snprintf(buf, size_left, "\nAT0 Array registers\n");
8760 buf += n; size_left -= n;
8761 REG_WR32(qlt, 0x54, 0x7080);
8762 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8763 buf += n; size_left -= n;
8764 REG_WR32(qlt, 0x54, 0x7090);
8765 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8766 buf += n; size_left -= n;
8767 REG_WR32(qlt, 0x54, 0x70A0);
8768 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8769 buf += n; size_left -= n;
8770 REG_WR32(qlt, 0x54, 0x70B0);
8771 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8772 buf += n; size_left -= n;
8773 REG_WR32(qlt, 0x54, 0x70C0);
8774 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8775 buf += n; size_left -= n;
8776 REG_WR32(qlt, 0x54, 0x70D0);
8777 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8778 buf += n; size_left -= n;
8779 REG_WR32(qlt, 0x54, 0x70E0);
8780 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8781 buf += n; size_left -= n;
8782 REG_WR32(qlt, 0x54, 0x70F0);
8783 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
8784 buf += n; size_left -= n;
8785 }
8786
8787 EL(qlt, "reset chip\n");
8788 qlt->intr_sneak_counter = 10;
8789 mutex_enter(&qlt->intr_lock);
8790 if (qlt->qlt_mq_enabled) {
8791 for (i = 1; i < qlt->qlt_queue_cnt; i++) {
8792 mutex_enter(&qlt->mq_resp[i].mq_lock);
8793 }
8794 }
8795 (void) qlt_reset_chip(qlt);
8796 drv_usecwait(20);
8797 qlt->intr_sneak_counter = 0;
8798 if (qlt->qlt_mq_enabled) {
8799 for (i = 1; i < qlt->qlt_queue_cnt; i++) {
8800 mutex_exit(&qlt->mq_resp[i].mq_lock);
8801 }
8802 }
8803 mutex_exit(&qlt->intr_lock);
8804 EL(qlt, "reset chip, done\n");
8805
8806 /*
8807 * Memory
8808 */
8809 n = (int)snprintf(buf, size_left, "\nCode RAM\n");
8810 buf += n; size_left -= n;
8811
8812 addr = 0x20000;
8813 endaddr = (qlt->qlt_83xx_chip) ? 0x22400 : 0x22000;
8814 words_to_read = 0;
8815 while (addr < endaddr) {
8816 words_to_read = MBOX_DMA_MEM_SIZE >> 2;
8817 if ((words_to_read + addr) > endaddr) {
8818 words_to_read = endaddr - addr;
8819 }
8820 if ((ret = qlt_read_risc_ram(qlt, addr, words_to_read)) !=
8821 QLT_SUCCESS) {
8822 EL(qlt, "Error reading risc ram - CODE RAM status="
8823 "%llxh\n", ret);
8824 goto dump_fail;
8825 }
8826
8827 n = qlt_dump_risc_ram(qlt, addr, words_to_read, buf, size_left);
8828 buf += n; size_left -= n;
8829
8830 if (size_left < 100000) {
8831 EL(qlt, "run out of space - CODE RAM size_left=%d\n",
8832 size_left);
8833 goto dump_ok;
8834 }
8835 addr += words_to_read;
8836 }
8837
8838 n = (int)snprintf(buf, size_left, "\nExternal Memory\n");
8839 buf += n; size_left -= n;
8840
8841 addr = 0x100000;
8842 endaddr = (((uint32_t)(qlt->fw_endaddrhi)) << 16) | qlt->fw_endaddrlo;
8843 endaddr++;
8844 if (endaddr & 7) {
8845 endaddr = (endaddr + 7) & 0xFFFFFFF8;
8846 }
8847
8848 words_to_read = 0;
8849 while (addr < endaddr) {
8850 words_to_read = MBOX_DMA_MEM_SIZE >> 2;
8851 if ((words_to_read + addr) > endaddr) {
8852 words_to_read = endaddr - addr;
8853 }
8854 if ((ret = qlt_read_risc_ram(qlt, addr, words_to_read)) !=
8855 QLT_SUCCESS) {
8856 EL(qlt, "Error reading risc ram - EXT RAM status="
8857 "%llxh\n", ret);
8858 goto dump_fail;
8859 }
8860 n = qlt_dump_risc_ram(qlt, addr, words_to_read, buf, size_left);
8861 buf += n; size_left -= n;
8862 if (size_left < 100000) {
8863 EL(qlt, "run out of space - EXT RAM\n");
8864 goto dump_ok;
8865 }
8866 addr += words_to_read;
8867 }
8868
8869 /*
8870 * Label the end tag
8871 */
8872 n = (int)snprintf(buf, size_left, "[<==END] ISP Debug Dump\n");
8873 buf += n; size_left -= n;
8874
8875 /*
8876 * Queue dumping
8877 */
8878 n = (int)snprintf(buf, size_left, "\nRequest Queue\n");
8879 buf += n; size_left -= n;
8880
8881 if (qlt->qlt_mq_enabled) {
8882 for (i = 0; i < qlt->qlt_queue_cnt; i++) {
8883 if (qlt->mq_req[i].queue_mem_mq_base_addr) {
8884 n = (int)snprintf(buf, size_left,
8885 "\nQueue %d:\n", i);
8886 buf += n; size_left -= n;
8887 n = qlt_dump_queue(qlt,
8888 qlt->mq_req[i].queue_mem_mq_base_addr,
8889 REQUEST_QUEUE_MQ_ENTRIES,
8890 buf, size_left);
8891 buf += n; size_left -= n;
8892 }
8893 }
8894 } else {
8895 n = (int)snprintf(buf, size_left, "\nQueue 0:\n");
8896 buf += n; size_left -= n;
8897 n = qlt_dump_queue(qlt,
8898 qlt->queue_mem_ptr + REQUEST_QUEUE_OFFSET,
8899 REQUEST_QUEUE_ENTRIES, buf, size_left);
8900 buf += n; size_left -= n;
8901 }
8902
8903 if (!qlt->qlt_83xx_chip) {
8904 n = (int)snprintf(buf, size_left, "\nPriority Queue\n");
8905 buf += n; size_left -= n;
8906 n = qlt_dump_queue(qlt,
8907 qlt->queue_mem_ptr + PRIORITY_QUEUE_OFFSET,
8908 PRIORITY_QUEUE_ENTRIES, buf, size_left);
8909 buf += n; size_left -= n;
8910 }
8911
8912 n = (int)snprintf(buf, size_left, "\nResponse Queue\n");
8913 buf += n; size_left -= n;
8914
8915 if (qlt->qlt_mq_enabled) {
8916 for (i = 0; i < qlt->qlt_queue_cnt; i++) {
8917 if (qlt->mq_resp[i].queue_mem_mq_base_addr) {
8918 n = (int)snprintf(buf, size_left,
8919 "\nQueue %d:\n", i);
8920 buf += n; size_left -= n;
8921 n = qlt_dump_queue(qlt,
8922 qlt->mq_resp[i].queue_mem_mq_base_addr,
8923 RESPONSE_QUEUE_MQ_ENTRIES,
8924 buf, size_left);
8925 buf += n; size_left -= n;
8926 }
8927 }
8928 } else {
8929 n = (int)snprintf(buf, size_left, "\nQueue 0:\n");
8930 buf += n; size_left -= n;
8931 n = qlt_dump_queue(qlt,
8932 qlt->queue_mem_ptr + RESPONSE_QUEUE_OFFSET,
8933 RESPONSE_QUEUE_ENTRIES, buf, size_left);
8934 buf += n; size_left -= n;
8935 }
8936
8937 n = (int)snprintf(buf, size_left, "\nATIO Queue\nQueue 0:\n");
8938 buf += n; size_left -= n;
8939 n = qlt_dump_queue(qlt, qlt->queue_mem_ptr + ATIO_QUEUE_OFFSET,
8940 ATIO_QUEUE_ENTRIES, buf, size_left);
8941 buf += n; size_left -= n;
8942
8943 /*
8944 * Label dump reason
8945 */
8946 if (ssci != NULL) {
8947 n = (int)snprintf(buf, size_left,
8948 "\nFirmware dump reason: %s-%s\n",
8949 qlt->qlt_port_alias, ssci->st_additional_info);
8950 } else {
8951 n = (int)snprintf(buf, size_left,
8952 "\nFirmware dump reason: %s-%s\n",
8953 qlt->qlt_port_alias, "no additional infor");
8954 }
8955 buf += n; size_left -= n;
8956
8957 dump_ok:
8958 EL(qlt, "left-%d\n", size_left);
8959 mutex_enter(&qlt->qlt_ioctl_lock);
8960 qlt->qlt_ioctl_flags &=
8961 ~(QLT_FWDUMP_INPROGRESS | QLT_FWDUMP_FETCHED_BY_USER);
8962 qlt->qlt_ioctl_flags |= QLT_FWDUMP_ISVALID;
8963 mutex_exit(&qlt->qlt_ioctl_lock);
8964 return (FCT_SUCCESS);
8965
8966 dump_fail:
8967 EL(qlt, "dump not done\n");
8968 mutex_enter(&qlt->qlt_ioctl_lock);
8969 qlt->qlt_ioctl_flags &= QLT_IOCTL_FLAG_MASK;
8970 mutex_exit(&qlt->qlt_ioctl_lock);
8971 return (FCT_FAILURE);
8972 }
8973
8974 static int
qlt_fwdump_dump_regs(qlt_state_t * qlt,caddr_t buf,int startaddr,int count,uint_t size_left)8975 qlt_fwdump_dump_regs(qlt_state_t *qlt, caddr_t buf, int startaddr, int count,
8976 uint_t size_left)
8977 {
8978 int i;
8979 int n;
8980 char c = ' ';
8981
8982 for (i = 0, n = 0; i < count; i++) {
8983 if ((i + 1) & 7) {
8984 c = ' ';
8985 } else {
8986 c = '\n';
8987 }
8988 n = (int)(n + (int)snprintf(&buf[n], (uint_t)(size_left - n),
8989 "%08x%c", REG_RD32(qlt, startaddr + (i << 2)), c));
8990 }
8991 return (n);
8992 }
8993
8994 static int
qlt_dump_risc_ram(qlt_state_t * qlt,uint32_t addr,uint32_t words,caddr_t buf,uint_t size_left)8995 qlt_dump_risc_ram(qlt_state_t *qlt, uint32_t addr, uint32_t words,
8996 caddr_t buf, uint_t size_left)
8997 {
8998 int i;
8999 int n;
9000 char c = ' ';
9001 uint32_t *ptr;
9002
9003 ptr = (uint32_t *)((caddr_t)qlt->queue_mem_ptr + MBOX_DMA_MEM_OFFSET);
9004 for (i = 0, n = 0; i < words; i++) {
9005 if ((i & 7) == 0) {
9006 n = (int)(n + (int)snprintf(&buf[n],
9007 (uint_t)(size_left - n), "%08x: ", addr + i));
9008 }
9009 if ((i + 1) & 7) {
9010 c = ' ';
9011 } else {
9012 c = '\n';
9013 }
9014 n = (int)(n + (int)snprintf(&buf[n], (uint_t)(size_left - n),
9015 "%08x%c", ptr[i], c));
9016 }
9017 return (n);
9018 }
9019
9020 static int
qlt_dump_queue(qlt_state_t * qlt,caddr_t qadr,int entries,caddr_t buf,uint_t size_left)9021 qlt_dump_queue(qlt_state_t *qlt, caddr_t qadr, int entries, caddr_t buf,
9022 uint_t size_left)
9023 {
9024 int i;
9025 int n;
9026 char c = ' ';
9027 int words;
9028 uint32_t *ptr;
9029 uint32_t w;
9030
9031 words = entries * 16;
9032 ptr = (uint32_t *)qadr;
9033 for (i = 0, n = 0; i < words; i++) {
9034 if ((i & 7) == 0) {
9035 n = (int)(n + (int)snprintf(&buf[n],
9036 (uint_t)(size_left - n), "%05x: ", i));
9037 }
9038 if ((i + 1) & 7) {
9039 c = ' ';
9040 } else {
9041 c = '\n';
9042 }
9043 w = QMEM_RD32(qlt, &ptr[i]);
9044 n = (int)(n + (int)snprintf(&buf[n], (size_left - n), "%08x%c",
9045 w, c));
9046 }
9047 return (n);
9048 }
9049
9050 /*
9051 * Only called by debug dump. Interrupts are disabled and mailboxes alongwith
9052 * mailbox ram is available.
9053 * Copy data from RISC RAM to system memory
9054 */
9055 static fct_status_t
qlt_read_risc_ram(qlt_state_t * qlt,uint32_t addr,uint32_t words)9056 qlt_read_risc_ram(qlt_state_t *qlt, uint32_t addr, uint32_t words)
9057 {
9058 uint64_t da;
9059 fct_status_t ret;
9060
9061 REG_WR16(qlt, REG_MBOX(0), MBC_DUMP_RAM_EXTENDED);
9062 da = qlt->queue_mem_cookie.dmac_laddress;
9063 da += MBOX_DMA_MEM_OFFSET;
9064
9065 /* System destination address */
9066 REG_WR16(qlt, REG_MBOX(3), LSW(LSD(da)));
9067 REG_WR16(qlt, REG_MBOX(2), MSW(LSD(da)));
9068 REG_WR16(qlt, REG_MBOX(7), LSW(MSD(da)));
9069 REG_WR16(qlt, REG_MBOX(6), MSW(MSD(da)));
9070
9071 /* Length */
9072 REG_WR16(qlt, REG_MBOX(5), LSW(words));
9073 REG_WR16(qlt, REG_MBOX(4), MSW(words));
9074
9075 /* RISC source address */
9076 REG_WR16(qlt, REG_MBOX(1), LSW(addr));
9077 REG_WR16(qlt, REG_MBOX(8), MSW(addr));
9078
9079 ret = qlt_raw_mailbox_command(qlt);
9080 REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
9081 if (ret == QLT_SUCCESS) {
9082 (void) ddi_dma_sync(qlt->queue_mem_dma_handle,
9083 MBOX_DMA_MEM_OFFSET, words << 2, DDI_DMA_SYNC_FORCPU);
9084 } else {
9085 EL(qlt, "qlt_raw_mailbox_command=0x0ch status=%llxh\n", ret);
9086 }
9087 return (ret);
9088 }
9089
9090 static fct_status_t
qlt_mbx_mpi_ram(qlt_state_t * qlt,uint32_t addr,uint32_t words,uint16_t direction)9091 qlt_mbx_mpi_ram(qlt_state_t *qlt, uint32_t addr, uint32_t words,
9092 uint16_t direction)
9093 {
9094 uint64_t da;
9095 fct_status_t ret;
9096
9097 REG_WR16(qlt, REG_MBOX(0), MBC_MPI_RAM);
9098 da = qlt->queue_mem_cookie.dmac_laddress;
9099 da += MBOX_DMA_MEM_OFFSET;
9100
9101 /* System destination address */
9102 REG_WR16(qlt, REG_MBOX(3), LSW(LSD(da)));
9103 REG_WR16(qlt, REG_MBOX(2), MSW(LSD(da)));
9104 REG_WR16(qlt, REG_MBOX(7), LSW(MSD(da)));
9105 REG_WR16(qlt, REG_MBOX(6), MSW(MSD(da)));
9106
9107 /* Length */
9108 REG_WR16(qlt, REG_MBOX(5), LSW(words));
9109 REG_WR16(qlt, REG_MBOX(4), MSW(words));
9110
9111 /* RISC source address */
9112 REG_WR16(qlt, REG_MBOX(1), LSW(addr));
9113 REG_WR16(qlt, REG_MBOX(8), MSW(addr));
9114
9115 REG_WR16(qlt, REG_MBOX(9), direction);
9116 ret = qlt_raw_mailbox_command(qlt);
9117 REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
9118 if (ret == QLT_SUCCESS) {
9119 (void) ddi_dma_sync(qlt->queue_mem_dma_handle,
9120 MBOX_DMA_MEM_OFFSET, words << 2, DDI_DMA_SYNC_FORCPU);
9121 } else {
9122 EL(qlt, "qlt_raw_mailbox_command=0x05h status=%llxh\n", ret);
9123 }
9124 return (ret);
9125 }
9126
9127 static void
qlt_verify_fw(qlt_state_t * qlt)9128 qlt_verify_fw(qlt_state_t *qlt)
9129 {
9130 caddr_t req;
9131 uint16_t qi = 0;
9132
9133 /* Just put it on the request queue */
9134 mutex_enter(&qlt->mq_req[qi].mq_lock);
9135 req = qlt_get_req_entries(qlt, 1, qi);
9136 if (req == NULL) {
9137 EL(qlt, "req = NULL\n");
9138 mutex_exit(&qlt->mq_req[qi].mq_lock);
9139 return;
9140 }
9141
9142 bzero(req, IOCB_SIZE);
9143
9144 req[0] = 0x1b;
9145 req[1] = 1;
9146
9147 QMEM_WR32(qlt, (&req[4]), 0xffffffff);
9148 QMEM_WR16(qlt, (&req[0x8]), 1); /* options - don't update */
9149 QMEM_WR32(qlt, (&req[0x14]), 0x80010300);
9150
9151 qlt_submit_req_entries(qlt, 1, qi);
9152 mutex_exit(&qlt->mq_req[qi].mq_lock);
9153 }
9154
9155 static fct_status_t
qlt_mq_destroy(qlt_state_t * qlt)9156 qlt_mq_destroy(qlt_state_t *qlt)
9157 {
9158 int idx;
9159
9160 for (idx = 1; idx < qlt->qlt_queue_cnt; idx++) {
9161 (void) ddi_dma_unbind_handle(
9162 qlt->mq_req[idx].queue_mem_mq_dma_handle);
9163 ddi_dma_mem_free(&qlt->mq_req[idx].queue_mem_mq_acc_handle);
9164 ddi_dma_free_handle(&qlt->mq_req[idx].queue_mem_mq_dma_handle);
9165 (void) ddi_dma_unbind_handle(
9166 qlt->mq_resp[idx].queue_mem_mq_dma_handle);
9167 ddi_dma_mem_free(&qlt->mq_resp[idx].queue_mem_mq_acc_handle);
9168 ddi_dma_free_handle(&qlt->mq_resp[idx].queue_mem_mq_dma_handle);
9169 }
9170 return (QLT_SUCCESS);
9171 }
9172
9173 static fct_status_t
qlt_mq_create(qlt_state_t * qlt,int idx)9174 qlt_mq_create(qlt_state_t *qlt, int idx)
9175 {
9176 ddi_device_acc_attr_t dev_acc_attr;
9177 size_t discard;
9178 uint_t ncookies;
9179
9180 dev_acc_attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
9181 dev_acc_attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
9182 dev_acc_attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
9183
9184 /*
9185 * MQ Request queue
9186 */
9187 if (ddi_dma_alloc_handle(qlt->dip, &qlt_queue_dma_attr_mq_req1,
9188 DDI_DMA_SLEEP, 0,
9189 &qlt->mq_req[idx].queue_mem_mq_dma_handle) != DDI_SUCCESS) {
9190 return (QLT_FAILURE);
9191 }
9192 if (ddi_dma_mem_alloc(qlt->mq_req[idx].queue_mem_mq_dma_handle,
9193 REQUEST_QUEUE_MQ_SIZE,
9194 &dev_acc_attr, DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, 0,
9195 &qlt->mq_req[idx].queue_mem_mq_base_addr, &discard,
9196 &qlt->mq_req[idx].queue_mem_mq_acc_handle) != DDI_SUCCESS) {
9197 ddi_dma_free_handle(&qlt->mq_req[idx].queue_mem_mq_dma_handle);
9198 return (QLT_FAILURE);
9199 }
9200 if (ddi_dma_addr_bind_handle(
9201 qlt->mq_req[idx].queue_mem_mq_dma_handle,
9202 NULL, qlt->mq_req[idx].queue_mem_mq_base_addr,
9203 REQUEST_QUEUE_MQ_SIZE,
9204 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, 0,
9205 &qlt->mq_req[idx].queue_mem_mq_cookie,
9206 &ncookies) != DDI_SUCCESS) {
9207 ddi_dma_mem_free(&qlt->mq_req[idx].queue_mem_mq_acc_handle);
9208 ddi_dma_free_handle(&qlt->mq_req[idx].queue_mem_mq_dma_handle);
9209 return (QLT_FAILURE);
9210 }
9211 if (ncookies != 1) {
9212 (void) ddi_dma_unbind_handle(
9213 qlt->mq_req[idx].queue_mem_mq_dma_handle);
9214 ddi_dma_mem_free(&qlt->mq_req[idx].queue_mem_mq_acc_handle);
9215 ddi_dma_free_handle(&qlt->mq_req[idx].queue_mem_mq_dma_handle);
9216 return (QLT_FAILURE);
9217 }
9218
9219 /*
9220 * MQ Response queue
9221 */
9222 if (ddi_dma_alloc_handle(qlt->dip, &qlt_queue_dma_attr_mq_rsp1,
9223 DDI_DMA_SLEEP, 0,
9224 &qlt->mq_resp[idx].queue_mem_mq_dma_handle) != DDI_SUCCESS) {
9225 (void) ddi_dma_unbind_handle(
9226 qlt->mq_req[idx].queue_mem_mq_dma_handle);
9227 ddi_dma_mem_free(&qlt->mq_req[idx].queue_mem_mq_acc_handle);
9228 ddi_dma_free_handle(&qlt->mq_req[idx].queue_mem_mq_dma_handle);
9229 return (QLT_FAILURE);
9230 }
9231 if (ddi_dma_mem_alloc(qlt->mq_resp[idx].queue_mem_mq_dma_handle,
9232 RESPONSE_QUEUE_MQ_SIZE,
9233 &dev_acc_attr, DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, 0,
9234 &qlt->mq_resp[idx].queue_mem_mq_base_addr, &discard,
9235 &qlt->mq_resp[idx].queue_mem_mq_acc_handle) != DDI_SUCCESS) {
9236 (void) ddi_dma_unbind_handle(
9237 qlt->mq_req[idx].queue_mem_mq_dma_handle);
9238 ddi_dma_mem_free(&qlt->mq_req[idx].queue_mem_mq_acc_handle);
9239 ddi_dma_free_handle(&qlt->mq_req[idx].queue_mem_mq_dma_handle);
9240 ddi_dma_free_handle(&qlt->mq_resp[idx].queue_mem_mq_dma_handle);
9241 return (QLT_FAILURE);
9242 }
9243 if (ddi_dma_addr_bind_handle(
9244 qlt->mq_resp[idx].queue_mem_mq_dma_handle,
9245 NULL, qlt->mq_resp[idx].queue_mem_mq_base_addr,
9246 RESPONSE_QUEUE_MQ_SIZE,
9247 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, 0,
9248 &qlt->mq_resp[idx].queue_mem_mq_cookie,
9249 &ncookies) != DDI_SUCCESS) {
9250 (void) ddi_dma_unbind_handle(
9251 qlt->mq_req[idx].queue_mem_mq_dma_handle);
9252 ddi_dma_mem_free(&qlt->mq_req[idx].queue_mem_mq_acc_handle);
9253 ddi_dma_free_handle(&qlt->mq_req[idx].queue_mem_mq_dma_handle);
9254 ddi_dma_mem_free(&qlt->mq_resp[idx].queue_mem_mq_acc_handle);
9255 ddi_dma_free_handle(&qlt->mq_resp[idx].queue_mem_mq_dma_handle);
9256 return (QLT_FAILURE);
9257 }
9258 if (ncookies != 1) {
9259 (void) ddi_dma_unbind_handle(
9260 qlt->mq_req[idx].queue_mem_mq_dma_handle);
9261 ddi_dma_mem_free(&qlt->mq_req[idx].queue_mem_mq_acc_handle);
9262 ddi_dma_free_handle(&qlt->mq_req[idx].queue_mem_mq_dma_handle);
9263 (void) ddi_dma_unbind_handle(
9264 qlt->mq_resp[idx].queue_mem_mq_dma_handle);
9265 ddi_dma_mem_free(&qlt->mq_resp[idx].queue_mem_mq_acc_handle);
9266 ddi_dma_free_handle(&qlt->mq_resp[idx].queue_mem_mq_dma_handle);
9267 return (QLT_FAILURE);
9268 }
9269
9270 qlt->mq_req[idx].mq_ptr = qlt->mq_req[idx].queue_mem_mq_base_addr;
9271 qlt->mq_req[idx].mq_ndx_to_fw = qlt->mq_req[idx].mq_ndx_from_fw = 0;
9272 qlt->mq_req[idx].mq_available = REQUEST_QUEUE_MQ_ENTRIES - 1;
9273 bzero(qlt->mq_req[idx].mq_ptr, REQUEST_QUEUE_MQ_SIZE);
9274
9275 qlt->mq_resp[idx].mq_ptr = qlt->mq_resp[idx].queue_mem_mq_base_addr;
9276 qlt->mq_resp[idx].mq_ndx_to_fw = qlt->mq_resp[idx].mq_ndx_from_fw = 0;
9277 bzero(qlt->mq_resp[idx].mq_ptr, RESPONSE_QUEUE_MQ_SIZE);
9278
9279 return (QLT_SUCCESS);
9280 }
9281
9282 static void
qlt_handle_verify_fw_completion(qlt_state_t * qlt,uint8_t * rsp)9283 qlt_handle_verify_fw_completion(qlt_state_t *qlt, uint8_t *rsp)
9284 {
9285 uint16_t status;
9286 char info[80];
9287
9288 status = QMEM_RD16(qlt, rsp+8);
9289 if (status != 0) {
9290 (void) snprintf(info, 80, "qlt_handle_verify_fw_completion: "
9291 "status:%x, rsp:%p", status, (void *)rsp);
9292 if (status == 3) {
9293 uint16_t error_code;
9294
9295 error_code = QMEM_RD16(qlt, rsp+0xA);
9296 (void) snprintf(info, 80, "qlt_handle_verify_fw_"
9297 "completion: error code:%x", error_code);
9298 }
9299 }
9300 }
9301
9302 /*
9303 * qlt_el_trace_desc_ctor - Construct an extended logging trace descriptor.
9304 *
9305 * Input: Pointer to the adapter state structure.
9306 * Returns: Success or Failure.
9307 * Context: Kernel context.
9308 */
9309 static int
qlt_el_trace_desc_ctor(qlt_state_t * qlt)9310 qlt_el_trace_desc_ctor(qlt_state_t *qlt)
9311 {
9312 qlt_trace_entry_t *entry;
9313 size_t maxsize;
9314
9315 qlt->qlt_trace_desc =
9316 (qlt_trace_desc_t *)kmem_zalloc(
9317 sizeof (qlt_trace_desc_t), KM_SLEEP);
9318
9319 qlt->qlt_log_entries = QL_LOG_ENTRIES;
9320 maxsize = qlt->qlt_log_entries * sizeof (qlt_trace_entry_t);
9321 entry = kmem_zalloc(maxsize, KM_SLEEP);
9322
9323 mutex_init(&qlt->qlt_trace_desc->mutex, NULL,
9324 MUTEX_DRIVER, NULL);
9325
9326 qlt->qlt_trace_desc->trace_buffer = entry;
9327 qlt->qlt_trace_desc->trace_buffer_size = maxsize;
9328 qlt->qlt_trace_desc->nindex = 0;
9329
9330 qlt->qlt_trace_desc->nentries = qlt->qlt_log_entries;
9331 qlt->qlt_trace_desc->start = qlt->qlt_trace_desc->end = 0;
9332 qlt->qlt_trace_desc->csize = 0;
9333 qlt->qlt_trace_desc->count = 0;
9334
9335 return (DDI_SUCCESS);
9336 }
9337
9338 /*
9339 * qlt_el_trace_desc_dtor - Destroy an extended logging trace descriptor.
9340 *
9341 * Input: Pointer to the adapter state structure.
9342 * Returns: Success or Failure.
9343 * Context: Kernel context.
9344 */
9345 static int
qlt_el_trace_desc_dtor(qlt_state_t * qlt)9346 qlt_el_trace_desc_dtor(qlt_state_t *qlt)
9347 {
9348 int rval = DDI_SUCCESS;
9349
9350 if (qlt->qlt_trace_desc != NULL) {
9351 if (qlt->qlt_trace_desc->trace_buffer != NULL) {
9352 kmem_free(qlt->qlt_trace_desc->trace_buffer,
9353 qlt->qlt_trace_desc->trace_buffer_size);
9354 }
9355 mutex_destroy(&qlt->qlt_trace_desc->mutex);
9356 kmem_free(qlt->qlt_trace_desc, sizeof (qlt_trace_desc_t));
9357 }
9358
9359 return (rval);
9360 }
9361
9362 /*
9363 * qlt_el_msg
9364 * Extended logging message
9365 *
9366 * Input:
9367 * qlt: adapter state pointer.
9368 * fn: function name.
9369 * ce: level
9370 * ...: Variable argument list.
9371 *
9372 * Context:
9373 * Kernel/Interrupt context.
9374 */
9375 void
qlt_el_msg(qlt_state_t * qlt,const char * fn,int ce,...)9376 qlt_el_msg(qlt_state_t *qlt, const char *fn, int ce, ...)
9377 {
9378 char *s, *fmt = 0, *fmt1 = 0;
9379
9380 /*
9381 * EL_BUFFER_RESERVE 256 is the max # of bytes
9382 * that driver's log could be collected.
9383 * add 3 more buytes for safely maniplulation.
9384 */
9385 char buf[EL_BUFFER_RESERVE + 3];
9386 char buf1[QL_LOG_LENGTH];
9387 size_t tmp;
9388 size_t rval, rval1;
9389 va_list vl;
9390 qlt_trace_desc_t *desc = qlt->qlt_trace_desc;
9391 qlt_trace_entry_t *entry;
9392 uint32_t cindex;
9393 timespec_t time;
9394 uint32_t count;
9395 size_t left;
9396
9397 (void) bzero((void *)&buf[0], EL_BUFFER_RESERVE + 3);
9398 fmt1 = &buf[0];
9399
9400 TRACE_BUFFER_LOCK(qlt);
9401
9402 /* locate the entry to be filled out */
9403 cindex = desc->nindex;
9404 entry = &desc->trace_buffer[cindex];
9405
9406 count = desc->count;
9407
9408 desc->end = desc->nindex;
9409 desc->nindex++;
9410 if (desc->nindex == desc->nentries) {
9411 desc->nindex = 0;
9412 }
9413
9414 if (desc->csize < desc->nentries) {
9415 desc->csize ++;
9416 } else {
9417 /*
9418 * once wrapped, csize is fixed.
9419 * so we have to adjust start point
9420 */
9421 desc->start = desc->nindex;
9422 }
9423
9424 gethrestime(&time);
9425
9426 rval = snprintf(fmt1, (size_t)EL_BUFFER_RESERVE,
9427 QL_BANG "%d=>QEL %s(%d,%d):: %s, ", count, QL_NAME,
9428 qlt->instance, 0, fn);
9429
9430 rval1 = rval;
9431
9432 va_start(vl, ce);
9433 s = va_arg(vl, char *);
9434 fmt = fmt1 + rval;
9435 tmp = vsnprintf(fmt,
9436 (size_t)(uint32_t)((int)EL_BUFFER_RESERVE - rval), s, vl);
9437 va_end(vl);
9438
9439 rval += tmp;
9440 if (rval > QL_LOG_LENGTH - 1) {
9441 left = rval - (QL_LOG_LENGTH - 1);
9442
9443 /* store the remaining string */
9444 (void) strncpy(buf1, fmt1 + (QL_LOG_LENGTH - 1), left);
9445 (void) strncpy(entry->buf, fmt1, (QL_LOG_LENGTH - 1));
9446 entry->buf[QL_LOG_LENGTH - 1] = '\n';
9447
9448 bcopy((void *)&time, (void *)&entry->hs_time,
9449 sizeof (timespec_t));
9450
9451 /*
9452 * remaining msg will be stored in the nex entry
9453 * with same timestamp and same sequence number
9454 */
9455 cindex = desc->nindex;
9456 entry = &desc->trace_buffer[cindex];
9457
9458 desc->end = desc->nindex;
9459 desc->nindex++;
9460 if (desc->nindex == desc->nentries) {
9461 desc->nindex = 0;
9462 }
9463
9464 if (desc->csize < desc->nentries) {
9465 desc->csize ++;
9466 } else {
9467 desc->start = desc->nindex;
9468 }
9469
9470 (void) strncpy(&entry->buf[0], fmt1, rval1);
9471 (void) strncpy(&entry->buf[rval1], &buf1[0], left);
9472 entry->buf[rval1 + left] = 0;
9473
9474 bcopy((void *)&time, (void *)&entry->hs_time,
9475 sizeof (timespec_t));
9476
9477 if (qlt->qlt_eel_level == 1) {
9478 cmn_err(ce, fmt1);
9479 }
9480
9481 desc->count++;
9482
9483 TRACE_BUFFER_UNLOCK(qlt);
9484 return;
9485 }
9486
9487 desc->count ++;
9488 bcopy((void *)&time, (void *)&entry->hs_time,
9489 sizeof (timespec_t));
9490
9491 /*
9492 * Here we know that fmt1 will fit within QL_LOG_LENGTH due to the
9493 * check above, but smatch identifies a potential problem.
9494 */
9495 (void) strncpy(entry->buf, fmt1, rval);
9496 entry->buf[rval] = 0;
9497
9498 TRACE_BUFFER_UNLOCK(qlt);
9499
9500 if (qlt->qlt_eel_level == 1) {
9501 cmn_err(ce, fmt1);
9502 }
9503 }
9504
9505 static int
qlt_read_int_prop(qlt_state_t * qlt,char * prop,int defval)9506 qlt_read_int_prop(qlt_state_t *qlt, char *prop, int defval)
9507 {
9508 return (ddi_getprop(DDI_DEV_T_ANY, qlt->dip,
9509 DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, prop, defval));
9510 }
9511
9512 static int
qlt_read_string_prop(qlt_state_t * qlt,char * prop,char ** prop_val)9513 qlt_read_string_prop(qlt_state_t *qlt, char *prop, char **prop_val)
9514 {
9515 return (ddi_prop_lookup_string(DDI_DEV_T_ANY, qlt->dip,
9516 DDI_PROP_DONTPASS, prop, prop_val));
9517 }
9518
9519 static int
qlt_read_int_instance_prop(qlt_state_t * qlt,char * prop,int defval)9520 qlt_read_int_instance_prop(qlt_state_t *qlt, char *prop, int defval)
9521 {
9522 char inst_prop[256];
9523 int val;
9524
9525 /*
9526 * Get adapter instance specific parameters. If the instance
9527 * specific parameter isn't there, try the global parameter.
9528 */
9529
9530 (void) sprintf(inst_prop, "hba%d-%s", qlt->instance, prop);
9531
9532 if ((val = qlt_read_int_prop(qlt, inst_prop, defval)) == defval) {
9533 val = qlt_read_int_prop(qlt, prop, defval);
9534 }
9535
9536 return (val);
9537 }
9538
9539 static int
qlt_read_string_instance_prop(qlt_state_t * qlt,char * prop,char ** prop_val)9540 qlt_read_string_instance_prop(qlt_state_t *qlt, char *prop, char **prop_val)
9541 {
9542 char instance_prop[256];
9543
9544 /* Get adapter instance specific parameter. */
9545 (void) sprintf(instance_prop, "hba%d-%s", qlt->instance, prop);
9546 return (qlt_read_string_prop(qlt, instance_prop, prop_val));
9547 }
9548
9549 static int
qlt_convert_string_to_ull(char * prop,int radix,u_longlong_t * result)9550 qlt_convert_string_to_ull(char *prop, int radix,
9551 u_longlong_t *result)
9552 {
9553 return (ddi_strtoull((const char *)prop, 0, radix, result));
9554 }
9555
9556 static boolean_t
qlt_wwn_overload_prop(qlt_state_t * qlt)9557 qlt_wwn_overload_prop(qlt_state_t *qlt)
9558 {
9559 char *prop_val = NULL;
9560 int rval;
9561 int radix;
9562 u_longlong_t wwnn = 0, wwpn = 0;
9563 boolean_t overloaded = FALSE;
9564
9565 radix = 16;
9566
9567 rval = qlt_read_string_instance_prop(qlt, "adapter-wwnn", &prop_val);
9568 if (rval == DDI_PROP_SUCCESS) {
9569 rval = qlt_convert_string_to_ull(prop_val, radix, &wwnn);
9570 }
9571 if (rval == DDI_PROP_SUCCESS) {
9572 rval = qlt_read_string_instance_prop(qlt, "adapter-wwpn",
9573 &prop_val);
9574 if (rval == DDI_PROP_SUCCESS) {
9575 rval = qlt_convert_string_to_ull(prop_val, radix,
9576 &wwpn);
9577 }
9578 }
9579 if (rval == DDI_PROP_SUCCESS) {
9580 overloaded = TRUE;
9581 /* Overload the current node/port name nvram copy */
9582 bcopy((char *)&wwnn, qlt->nvram->node_name, 8);
9583 BIG_ENDIAN_64(qlt->nvram->node_name);
9584 bcopy((char *)&wwpn, qlt->nvram->port_name, 8);
9585 BIG_ENDIAN_64(qlt->nvram->port_name);
9586 }
9587 return (overloaded);
9588 }
9589
9590 /*
9591 * prop_text - Return a pointer to a string describing the status
9592 *
9593 * Input: prop_status = the return status from a property function.
9594 * Returns: pointer to a string.
9595 * Context: Kernel context.
9596 */
9597 char *
prop_text(int prop_status)9598 prop_text(int prop_status)
9599 {
9600 string_table_t *entry = &prop_status_tbl[0];
9601
9602 return (value2string(entry, prop_status, 0xFFFF));
9603 }
9604
9605 /*
9606 * value2string Return a pointer to a string associated with the value
9607 *
9608 * Input: entry = the value to string table
9609 * value = the value
9610 * Returns: pointer to a string.
9611 * Context: Kernel context.
9612 */
9613 char *
value2string(string_table_t * entry,int value,int delimiter)9614 value2string(string_table_t *entry, int value, int delimiter)
9615 {
9616 for (; entry->value != delimiter; entry++) {
9617 if (entry->value == value) {
9618 break;
9619 }
9620 }
9621 return (entry->string);
9622 }
9623
9624 /*
9625 * qlt_chg_endian Change endianess of byte array.
9626 *
9627 * Input: buf = array pointer.
9628 * size = size of array in bytes.
9629 *
9630 * Context: Interrupt or Kernel context.
9631 */
9632 void
qlt_chg_endian(uint8_t buf[],size_t size)9633 qlt_chg_endian(uint8_t buf[], size_t size)
9634 {
9635 uint8_t byte;
9636 size_t cnt1;
9637 size_t cnt;
9638
9639 cnt1 = size - 1;
9640 for (cnt = 0; cnt < size / 2; cnt++) {
9641 byte = buf[cnt1];
9642 buf[cnt1] = buf[cnt];
9643 buf[cnt] = byte;
9644 cnt1--;
9645 }
9646 }
9647
9648 /*
9649 * ql_mps_reset
9650 * Reset MPS for FCoE functions.
9651 *
9652 * Input:
9653 * ha = virtual adapter state pointer.
9654 *
9655 * Context:
9656 * Kernel context.
9657 */
9658 static void
qlt_mps_reset(qlt_state_t * qlt)9659 qlt_mps_reset(qlt_state_t *qlt)
9660 {
9661 uint32_t data, dctl = 1000;
9662
9663 do {
9664 if (dctl-- == 0 || qlt_raw_wrt_risc_ram_word(qlt, 0x7c00, 1) !=
9665 QLT_SUCCESS) {
9666 EL(qlt, "qlt_mps_reset: semaphore request fail,"
9667 " cnt=%d\n", dctl);
9668 return;
9669 }
9670 if (qlt_raw_rd_risc_ram_word(qlt, 0x7c00, &data) !=
9671 QLT_SUCCESS) {
9672 (void) qlt_raw_wrt_risc_ram_word(qlt, 0x7c00, 0);
9673 EL(qlt, "qlt_mps_reset: semaphore read fail,"
9674 " cnt=%d\n", dctl);
9675 return;
9676 }
9677 } while (!(data & BIT_0));
9678
9679 if (qlt_raw_rd_risc_ram_word(qlt, 0x7A15, &data) == QLT_SUCCESS) {
9680 dctl = (uint16_t)PCICFG_RD16(qlt, 0x54);
9681 if ((data & 0xe0) != (dctl & 0xe0)) {
9682 data &= 0xff1f;
9683 data |= dctl & 0xe0;
9684 (void) qlt_raw_wrt_risc_ram_word(qlt, 0x7A15, data);
9685 }
9686 } else {
9687 EL(qlt, "qlt_mps_reset: read 0x7a15 failed.\n");
9688 }
9689 (void) qlt_raw_wrt_risc_ram_word(qlt, 0x7c00, 0);
9690 }
9691
9692 /*
9693 * qlt_raw_wrt_risc_ram_word
9694 * Write RISC RAM word.
9695 *
9696 * Input: qlt: adapter state pointer.
9697 * risc_address: risc ram word address.
9698 * data: data.
9699 *
9700 * Returns: qlt local function return status code.
9701 *
9702 * Context: Kernel context.
9703 */
9704 static fct_status_t
qlt_raw_wrt_risc_ram_word(qlt_state_t * qlt,uint32_t risc_address,uint32_t data)9705 qlt_raw_wrt_risc_ram_word(qlt_state_t *qlt, uint32_t risc_address,
9706 uint32_t data)
9707 {
9708 fct_status_t ret;
9709
9710 REG_WR16(qlt, REG_MBOX(0), MBC_WRITE_RAM_EXTENDED);
9711 REG_WR16(qlt, REG_MBOX(1), LSW(risc_address));
9712 REG_WR16(qlt, REG_MBOX(2), LSW(data));
9713 REG_WR16(qlt, REG_MBOX(3), MSW(data));
9714 REG_WR16(qlt, REG_MBOX(8), MSW(risc_address));
9715 ret = qlt_raw_mailbox_command(qlt);
9716 REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
9717 if (ret != QLT_SUCCESS) {
9718 EL(qlt, "qlt_raw_mailbox_command=MBC_WRITE_RAM_EXTENDED status"
9719 "=%llxh\n", ret);
9720 }
9721 return (ret);
9722 }
9723
9724 /*
9725 * ql_raw_rd_risc_ram_word
9726 * Read RISC RAM word.
9727 *
9728 * Input: qlt: adapter state pointer.
9729 * risc_address: risc ram word address.
9730 * data: data pointer.
9731 *
9732 * Returns: ql local function return status code.
9733 *
9734 * Context: Kernel context.
9735 */
9736 static fct_status_t
qlt_raw_rd_risc_ram_word(qlt_state_t * qlt,uint32_t risc_address,uint32_t * data)9737 qlt_raw_rd_risc_ram_word(qlt_state_t *qlt, uint32_t risc_address,
9738 uint32_t *data)
9739 {
9740 fct_status_t ret;
9741
9742 REG_WR16(qlt, REG_MBOX(0), MBC_READ_RAM_EXTENDED);
9743 REG_WR16(qlt, REG_MBOX(1), LSW(risc_address));
9744 REG_WR16(qlt, REG_MBOX(2), MSW(risc_address));
9745 ret = qlt_raw_mailbox_command(qlt);
9746 *data = REG_RD16(qlt, REG_MBOX(2));
9747 *data |= (REG_RD16(qlt, REG_MBOX(3)) << 16);
9748 REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
9749 if (ret != QLT_SUCCESS) {
9750 EL(qlt, "qlt_raw_mailbox_command=MBC_READ_RAM_EXTENDED status"
9751 "=%llxh\n", ret);
9752 }
9753 return (ret);
9754 }
9755
9756 static void
qlt_properties(qlt_state_t * qlt)9757 qlt_properties(qlt_state_t *qlt)
9758 {
9759 int32_t cnt = 0;
9760 int32_t defval = 0xffff;
9761
9762 if (qlt_wwn_overload_prop(qlt) == TRUE) {
9763 EL(qlt, "wwnn overloaded.\n");
9764 }
9765
9766 /* configure extended logging from conf file */
9767 if ((cnt = qlt_read_int_instance_prop(qlt, "extended-logging",
9768 defval)) != defval) {
9769 qlt->qlt_eel_level = (uint8_t)(cnt & 0xff);
9770 EL(qlt, "extended error logging=%d\n", cnt);
9771 }
9772
9773 if ((cnt = qlt_read_int_instance_prop(qlt, "bucketcnt2k", defval)) !=
9774 defval) {
9775 qlt->qlt_bucketcnt[0] = cnt;
9776 EL(qlt, "2k bucket o/l=%d\n", cnt);
9777 }
9778
9779 if ((cnt = qlt_read_int_instance_prop(qlt, "bucketcnt8k", defval)) !=
9780 defval) {
9781 qlt->qlt_bucketcnt[1] = cnt;
9782 EL(qlt, "8k bucket o/l=%d\n", cnt);
9783 }
9784
9785 if ((cnt = qlt_read_int_instance_prop(qlt, "bucketcnt64k", defval)) !=
9786 defval) {
9787 qlt->qlt_bucketcnt[2] = cnt;
9788 EL(qlt, "64k bucket o/l=%d\n", cnt);
9789 }
9790
9791 if ((cnt = qlt_read_int_instance_prop(qlt, "bucketcnt128k", defval)) !=
9792 defval) {
9793 qlt->qlt_bucketcnt[3] = cnt;
9794 EL(qlt, "128k bucket o/l=%d\n", cnt);
9795 }
9796
9797 if ((cnt = qlt_read_int_instance_prop(qlt, "bucketcnt256", defval)) !=
9798 defval) {
9799 qlt->qlt_bucketcnt[4] = cnt;
9800 EL(qlt, "256k bucket o/l=%d\n", cnt);
9801 }
9802 }
9803
9804 /* ******************************************************************* */
9805 /* ****************** 27xx Dump Template Functions ******************* */
9806 /* ******************************************************************* */
9807
9808 /*
9809 * qlt_get_dmp_template
9810 * Get dump template from firmware module
9811 *
9812 * Input:
9813 * qlt: qlt_state_t pointer.
9814 *
9815 * Returns:
9816 * qlt local function return status code.
9817 *
9818 * Context:
9819 * Kernel context.
9820 */
9821 static fct_status_t
qlt_27xx_get_dmp_template(qlt_state_t * qlt)9822 qlt_27xx_get_dmp_template(qlt_state_t *qlt)
9823 {
9824 ddi_device_acc_attr_t dev_acc_attr;
9825 dev_info_t *dip = qlt->dip;
9826 uint_t ncookies;
9827 size_t discard;
9828 uint32_t word_count, cnt, *bp, *dp;
9829
9830 if (qlt->dmp_template_dma_handle != NULL) {
9831 (void) ddi_dma_unbind_handle(qlt->dmp_template_dma_handle);
9832 if (qlt->dmp_template_acc_handle != NULL) {
9833 ddi_dma_mem_free(&qlt->dmp_template_acc_handle);
9834 }
9835 ddi_dma_free_handle(&qlt->dmp_template_dma_handle);
9836 }
9837
9838 if ((word_count = tmplt2700_length01) == 0) {
9839 EL(qlt, "No dump template, length=0\n");
9840 return (QLT_FAILURE);
9841 }
9842
9843 dev_acc_attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
9844 dev_acc_attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
9845 dev_acc_attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
9846
9847 if (ddi_dma_alloc_handle(dip, &qlt_queue_dma_attr,
9848 DDI_DMA_SLEEP, 0, &qlt->dmp_template_dma_handle) !=
9849 DDI_SUCCESS) {
9850 EL(qlt, "Unable to allocate template handle");
9851 return (QLT_FAILURE);
9852 }
9853
9854 if (ddi_dma_mem_alloc(qlt->dmp_template_dma_handle,
9855 (word_count << 2), &dev_acc_attr, DDI_DMA_CONSISTENT,
9856 DDI_DMA_SLEEP, 0, &qlt->dmp_template_addr, &discard,
9857 &qlt->dmp_template_acc_handle) != DDI_SUCCESS) {
9858 ddi_dma_free_handle(&qlt->dmp_template_dma_handle);
9859 EL(qlt, "Unable to allocate template buffer");
9860 return (QLT_FAILURE);
9861 }
9862
9863 if (ddi_dma_addr_bind_handle(qlt->dmp_template_dma_handle, NULL,
9864 qlt->dmp_template_addr, (word_count << 2),
9865 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, 0,
9866 &qlt->dmp_template_cookie, &ncookies) != DDI_SUCCESS) {
9867 ddi_dma_mem_free(&qlt->dmp_template_acc_handle);
9868 ddi_dma_free_handle(&qlt->dmp_template_dma_handle);
9869 EL(qlt, "Unable to bind template handle");
9870 return (QLT_FAILURE);
9871 }
9872
9873 if (ncookies != 1) {
9874 (void) ddi_dma_unbind_handle(qlt->dmp_template_dma_handle);
9875 ddi_dma_mem_free(&qlt->dmp_template_acc_handle);
9876 ddi_dma_free_handle(&qlt->dmp_template_dma_handle);
9877 EL(qlt, "cookies (%d) > 1.\n", ncookies);
9878 return (QLT_FAILURE);
9879 }
9880
9881 /* Get big endian template. */
9882 bp = (uint32_t *)qlt->dmp_template_addr;
9883 dp = (uint32_t *)tmplt2700_code01;
9884 for (cnt = 0; cnt < word_count; cnt++) {
9885 ddi_put32(qlt->dmp_template_acc_handle, bp, *dp++);
9886 if (cnt > 6) {
9887 qlt_chg_endian((uint8_t *)bp, 4);
9888 }
9889 bp++;
9890 }
9891
9892 return (QLT_SUCCESS);
9893 }
9894
9895 static int
qlt_27xx_dt_riob1(qlt_state_t * qlt,qlt_dt_riob1_t * entry,uint8_t * dbuff,uint8_t * dbuff_end)9896 qlt_27xx_dt_riob1(qlt_state_t *qlt, qlt_dt_riob1_t *entry,
9897 uint8_t *dbuff, uint8_t *dbuff_end)
9898 {
9899 int esize;
9900 uint32_t i, cnt;
9901 uint8_t *bp = dbuff;
9902 uint32_t addr = entry->addr;
9903 uint32_t reg = entry->pci_offset;
9904
9905 cnt = CHAR_TO_SHORT(entry->reg_count_l, entry->reg_count_h);
9906 esize = cnt * 4; /* addr */
9907 esize += cnt * entry->reg_size; /* data */
9908
9909 if (dbuff == NULL) {
9910 return (esize);
9911 }
9912 if (esize + dbuff >= dbuff_end) {
9913 EL(qlt, "skipped, no buffer space, needed=%xh\n", esize);
9914 entry->h.driver_flags = (uint8_t)
9915 (entry->h.driver_flags | SKIPPED_FLAG);
9916 return (0);
9917 }
9918
9919 REG_WR32(qlt, REG_IOBUS_BASE_ADDR, addr);
9920 while (cnt--) {
9921 *bp++ = LSB(LSW(addr));
9922 *bp++ = MSB(LSW(addr));
9923 *bp++ = LSB(MSW(addr));
9924 *bp++ = MSB(MSW(addr));
9925 for (i = 0; i < entry->reg_size; i++) {
9926 *bp++ = REG_RD8(qlt, reg++);
9927 }
9928 addr++;
9929 }
9930
9931 return (esize);
9932 }
9933
9934 static void
qlt_27xx_dt_wiob1(qlt_state_t * qlt,qlt_dt_wiob1_t * entry,uint8_t * dbuff,uint8_t * dbuff_end)9935 qlt_27xx_dt_wiob1(qlt_state_t *qlt, qlt_dt_wiob1_t *entry,
9936 uint8_t *dbuff, uint8_t *dbuff_end)
9937 {
9938 uint32_t reg = entry->pci_offset;
9939
9940 if (dbuff == NULL) {
9941 return;
9942 }
9943 if (dbuff >= dbuff_end) {
9944 EL(qlt, "skipped, no buffer space, needed=0\n");
9945 entry->h.driver_flags = (uint8_t)
9946 (entry->h.driver_flags | SKIPPED_FLAG);
9947 return;
9948 }
9949
9950 REG_WR32(qlt, REG_IOBUS_BASE_ADDR, entry->addr);
9951 REG_WR32(qlt, reg, entry->data);
9952 }
9953
9954 static int
qlt_27xx_dt_riob2(qlt_state_t * qlt,qlt_dt_riob2_t * entry,uint8_t * dbuff,uint8_t * dbuff_end)9955 qlt_27xx_dt_riob2(qlt_state_t *qlt, qlt_dt_riob2_t *entry,
9956 uint8_t *dbuff, uint8_t *dbuff_end)
9957 {
9958 int esize;
9959 uint32_t i, cnt;
9960 uint8_t *bp = dbuff;
9961 uint32_t reg = entry->pci_offset;
9962 uint32_t addr = entry->addr;
9963
9964 cnt = CHAR_TO_SHORT(entry->reg_count_l, entry->reg_count_h);
9965 esize = cnt * 4; /* addr */
9966 esize += cnt * entry->reg_size; /* data */
9967
9968 if (dbuff == NULL) {
9969 return (esize);
9970 }
9971 if (esize + dbuff >= dbuff_end) {
9972 EL(qlt, "skipped, no buffer space, needed=%xh\n", esize);
9973 entry->h.driver_flags = (uint8_t)
9974 (entry->h.driver_flags | SKIPPED_FLAG);
9975 return (0);
9976 }
9977
9978 REG_WR32(qlt, REG_IOBUS_BASE_ADDR, addr);
9979 REG_WR32(qlt, entry->bank_sel_offset, entry->reg_bank);
9980 while (cnt--) {
9981 *bp++ = LSB(LSW(addr));
9982 *bp++ = MSB(LSW(addr));
9983 *bp++ = LSB(MSW(addr));
9984 *bp++ = MSB(MSW(addr));
9985 for (i = 0; i < entry->reg_size; i++) {
9986 *bp++ = REG_RD8(qlt, reg++);
9987 }
9988 addr++;
9989 }
9990
9991 return (esize);
9992 }
9993
9994 static void
qlt_27xx_dt_wiob2(qlt_state_t * qlt,qlt_dt_wiob2_t * entry,uint8_t * dbuff,uint8_t * dbuff_end)9995 qlt_27xx_dt_wiob2(qlt_state_t *qlt, qlt_dt_wiob2_t *entry,
9996 uint8_t *dbuff, uint8_t *dbuff_end)
9997 {
9998 uint16_t data;
9999 uint32_t reg = entry->pci_offset;
10000
10001 if (dbuff == NULL) {
10002 return;
10003 }
10004 if (dbuff >= dbuff_end) {
10005 EL(qlt, "skipped, no buffer space, needed=0\n");
10006 entry->h.driver_flags = (uint8_t)
10007 (entry->h.driver_flags | SKIPPED_FLAG);
10008 return;
10009 }
10010
10011 data = CHAR_TO_SHORT(entry->data_l, entry->data_h);
10012
10013 REG_WR32(qlt, REG_IOBUS_BASE_ADDR, entry->addr);
10014 REG_WR32(qlt, entry->bank_sel_offset, entry->reg_bank);
10015 REG_WR16(qlt, reg, data);
10016 }
10017
10018 static int
qlt_27xx_dt_rpci(qlt_state_t * qlt,qlt_dt_rpci_t * entry,uint8_t * dbuff,uint8_t * dbuff_end)10019 qlt_27xx_dt_rpci(qlt_state_t *qlt, qlt_dt_rpci_t *entry, uint8_t *dbuff,
10020 uint8_t *dbuff_end)
10021 {
10022 int esize;
10023 uint32_t i;
10024 uint8_t *bp = dbuff;
10025 uint32_t reg = entry->addr;
10026
10027 esize = 4; /* addr */
10028 esize += 4; /* data */
10029
10030 if (dbuff == NULL) {
10031 return (esize);
10032 }
10033 if (esize + dbuff >= dbuff_end) {
10034 EL(qlt, "skipped, no buffer space, needed=%xh\n", esize);
10035 entry->h.driver_flags = (uint8_t)
10036 (entry->h.driver_flags | SKIPPED_FLAG);
10037 return (0);
10038 }
10039
10040 *bp++ = LSB(LSW(entry->addr));
10041 *bp++ = MSB(LSW(entry->addr));
10042 *bp++ = LSB(MSW(entry->addr));
10043 *bp++ = MSB(MSW(entry->addr));
10044 for (i = 0; i < 4; i++) {
10045 *bp++ = REG_RD8(qlt, reg++);
10046 }
10047
10048 return (esize);
10049 }
10050
10051 static void
qlt_27xx_dt_wpci(qlt_state_t * qlt,qlt_dt_wpci_t * entry,uint8_t * dbuff,uint8_t * dbuff_end)10052 qlt_27xx_dt_wpci(qlt_state_t *qlt, qlt_dt_wpci_t *entry,
10053 uint8_t *dbuff, uint8_t *dbuff_end)
10054 {
10055 uint32_t reg = entry->addr;
10056
10057 if (dbuff == NULL) {
10058 return;
10059 }
10060 if (dbuff >= dbuff_end) {
10061 EL(qlt, "skipped, no buffer space, needed=0\n");
10062 entry->h.driver_flags = (uint8_t)
10063 (entry->h.driver_flags | SKIPPED_FLAG);
10064 return;
10065 }
10066
10067 REG_WR32(qlt, reg, entry->data);
10068 }
10069
10070 static int
qlt_27xx_dt_rram(qlt_state_t * qlt,qlt_dt_rram_t * entry,uint8_t * dbuff,uint8_t * dbuff_end)10071 qlt_27xx_dt_rram(qlt_state_t *qlt, qlt_dt_rram_t *entry,
10072 uint8_t *dbuff, uint8_t *dbuff_end)
10073 {
10074 int esize, rval;
10075 uint32_t start = entry->start_addr;
10076 uint32_t end = entry->end_addr;
10077
10078 if (entry->ram_area == 2) {
10079 end = qlt->fw_ext_memory_end;
10080 } else if (entry->ram_area == 3) {
10081 start = qlt->fw_shared_ram_start;
10082 end = qlt->fw_shared_ram_end;
10083 } else if (entry->ram_area == 4) {
10084 start = qlt->fw_ddr_ram_start;
10085 end = qlt->fw_ddr_ram_end;
10086 } else if (entry->ram_area != 1) {
10087 EL(qlt, "skipped, unknown RAM_AREA %d\n", entry->ram_area);
10088 start = 0;
10089 end = 0;
10090 }
10091 esize = end > start ? end - start : 0;
10092 if (esize) {
10093 esize = (esize + 1) * 4;
10094 }
10095
10096 if (dbuff == NULL) {
10097 return (esize);
10098 }
10099 if (esize == 0 || esize + dbuff >= dbuff_end) {
10100 if (esize != 0) {
10101 EL(qlt, "skipped, no buffer space, needed=%xh\n",
10102 esize);
10103 } else {
10104 EL(qlt, "skipped, no ram_area=%xh, start=%xh "
10105 "end=%xh\n", entry->ram_area, start, end);
10106 }
10107 entry->h.driver_flags = (uint8_t)
10108 (entry->h.driver_flags | SKIPPED_FLAG);
10109 return (0);
10110 }
10111 entry->end_addr = end;
10112 entry->start_addr = start;
10113
10114 if ((rval = qlt_27xx_dump_ram(qlt, MBC_DUMP_RAM_EXTENDED,
10115 start, esize / 4, dbuff)) != QLT_SUCCESS) {
10116 EL(qlt, "dump_ram failed, rval=%xh, addr=%xh, len=%xh, "
10117 "esize=0\n", rval, start, esize / 4);
10118 return (0);
10119 }
10120
10121 return (esize);
10122 }
10123
10124 static int
qlt_27xx_dt_gque(qlt_state_t * qlt,qlt_dt_gque_t * entry,uint8_t * dbuff,uint8_t * dbuff_end)10125 qlt_27xx_dt_gque(qlt_state_t *qlt, qlt_dt_gque_t *entry,
10126 uint8_t *dbuff, uint8_t *dbuff_end)
10127 {
10128 int esize;
10129 uint32_t cnt, q_cnt, e_cnt, i;
10130 uint8_t *bp = dbuff, *dp;
10131
10132 if (entry->queue_type == 1) {
10133 e_cnt = qlt->qlt_queue_cnt;
10134 esize = e_cnt * 2; /* queue number */
10135 esize += e_cnt * 2; /* queue entries */
10136
10137 /* queue size */
10138 esize += REQUEST_QUEUE_ENTRIES * IOCB_SIZE;
10139 for (q_cnt = 1; q_cnt < qlt->qlt_queue_cnt; q_cnt++) {
10140 esize += REQUEST_QUEUE_MQ_ENTRIES * IOCB_SIZE;
10141 }
10142
10143 if (dbuff == NULL) {
10144 return (esize);
10145 }
10146 if (esize + dbuff >= dbuff_end) {
10147 EL(qlt, "skipped, no buffer space, needed=%xh\n",
10148 esize);
10149 entry->h.driver_flags = (uint8_t)
10150 (entry->h.driver_flags | SKIPPED_FLAG);
10151 return (0);
10152 }
10153 entry->num_queues = e_cnt;
10154
10155 for (q_cnt = 0; q_cnt < entry->num_queues; q_cnt++) {
10156 e_cnt = q_cnt == 0 ?
10157 REQUEST_QUEUE_ENTRIES : REQUEST_QUEUE_MQ_ENTRIES;
10158 dp = (uint8_t *)qlt->mq_req[q_cnt].mq_ptr;
10159 *bp++ = LSB(q_cnt);
10160 *bp++ = MSB(q_cnt);
10161 *bp++ = LSB(e_cnt);
10162 *bp++ = MSB(e_cnt);
10163 for (cnt = 0; cnt < e_cnt; cnt++) {
10164 for (i = 0; i < IOCB_SIZE; i++) {
10165 *bp++ = *dp++;
10166 }
10167 }
10168 }
10169 } else if (entry->queue_type == 2) {
10170
10171 e_cnt = qlt->qlt_queue_cnt;
10172 esize = e_cnt * 2; /* queue number */
10173 esize += e_cnt * 2; /* queue entries */
10174
10175 /* queue size */
10176 esize += RESPONSE_QUEUE_ENTRIES * IOCB_SIZE;
10177 for (q_cnt = 1; q_cnt < qlt->qlt_queue_cnt; q_cnt++) {
10178 esize += RESPONSE_QUEUE_MQ_ENTRIES * IOCB_SIZE;
10179 }
10180
10181 if (dbuff == NULL) {
10182 return (esize);
10183 }
10184 if (esize + dbuff >= dbuff_end) {
10185 EL(qlt, "skipped2, no buffer space, needed=%xh\n",
10186 esize);
10187 entry->h.driver_flags = (uint8_t)
10188 (entry->h.driver_flags | SKIPPED_FLAG);
10189 return (0);
10190 }
10191 entry->num_queues = e_cnt;
10192
10193 for (q_cnt = 0; q_cnt < entry->num_queues; q_cnt++) {
10194 e_cnt = q_cnt == 0 ?
10195 RESPONSE_QUEUE_ENTRIES : RESPONSE_QUEUE_MQ_ENTRIES;
10196 dp = (uint8_t *)qlt->mq_resp[q_cnt].mq_ptr;
10197 *bp++ = LSB(q_cnt);
10198 *bp++ = MSB(q_cnt);
10199 *bp++ = LSB(e_cnt);
10200 *bp++ = MSB(e_cnt);
10201 for (cnt = 0; cnt < e_cnt; cnt++) {
10202 for (i = 0; i < IOCB_SIZE; i++) {
10203 *bp++ = *dp++;
10204 }
10205 }
10206 }
10207 } else if (entry->queue_type == 3) {
10208 e_cnt = 1;
10209 esize = e_cnt * 2; /* queue number */
10210 esize += e_cnt * 2; /* queue entries */
10211
10212 /* queue size */
10213 esize += RESPONSE_QUEUE_ENTRIES * IOCB_SIZE;
10214
10215 if (dbuff == NULL) {
10216 return (esize);
10217 }
10218 if (esize + dbuff >= dbuff_end) {
10219 EL(qlt, "skipped2, no buffer space, needed=%xh\n",
10220 esize);
10221 entry->h.driver_flags = (uint8_t)
10222 (entry->h.driver_flags | SKIPPED_FLAG);
10223 return (0);
10224 }
10225 entry->num_queues = e_cnt;
10226
10227 for (q_cnt = 0; q_cnt < entry->num_queues; q_cnt++) {
10228 e_cnt = ATIO_QUEUE_ENTRIES;
10229 dp = (uint8_t *)qlt->atio_ptr;
10230 *bp++ = LSB(q_cnt);
10231 *bp++ = MSB(q_cnt);
10232 *bp++ = LSB(e_cnt);
10233 *bp++ = MSB(e_cnt);
10234 for (cnt = 0; cnt < e_cnt; cnt++) {
10235 for (i = 0; i < IOCB_SIZE; i++) {
10236 *bp++ = *dp++;
10237 }
10238 }
10239 }
10240 } else {
10241 EL(qlt, "skipped, unknown queue_type %d, esize=0\n",
10242 entry->queue_type);
10243 if (dbuff != NULL) {
10244 entry->h.driver_flags = (uint8_t)
10245 (entry->h.driver_flags | SKIPPED_FLAG);
10246 }
10247 return (0);
10248 }
10249
10250 return (esize);
10251 }
10252
10253 /*ARGSUSED*/
10254 static int
qlt_27xx_dt_gfce(qlt_state_t * qlt,qlt_dt_gfce_t * entry,uint8_t * dbuff,uint8_t * dbuff_end)10255 qlt_27xx_dt_gfce(qlt_state_t *qlt, qlt_dt_gfce_t *entry,
10256 uint8_t *dbuff, uint8_t *dbuff_end)
10257 {
10258 if (dbuff != NULL) {
10259 entry->h.driver_flags = (uint8_t)
10260 (entry->h.driver_flags | SKIPPED_FLAG);
10261 }
10262
10263 return (0);
10264 }
10265
10266 static void
qlt_27xx_dt_prisc(qlt_state_t * qlt,qlt_dt_prisc_t * entry,uint8_t * dbuff,uint8_t * dbuff_end)10267 qlt_27xx_dt_prisc(qlt_state_t *qlt, qlt_dt_prisc_t *entry,
10268 uint8_t *dbuff, uint8_t *dbuff_end)
10269 {
10270 clock_t timer;
10271
10272 if (dbuff == NULL) {
10273 return;
10274 }
10275 if (dbuff >= dbuff_end) {
10276 EL(qlt, "skipped, no buffer space, needed=0\n");
10277 entry->h.driver_flags = (uint8_t)
10278 (entry->h.driver_flags | SKIPPED_FLAG);
10279 return;
10280 }
10281
10282 /* Pause RISC. */
10283 if ((REG_RD32(qlt, REG_RISC_STATUS) & BIT_8) == 0) {
10284 REG_WR32(qlt, REG_HCCR, 0x30000000);
10285 for (timer = 30000;
10286 (REG_RD32(qlt, REG_RISC_STATUS) & BIT_8) == 0;
10287 timer--) {
10288 if (timer) {
10289 drv_usecwait(100);
10290 if (timer % 10000 == 0) {
10291 EL(qlt, "risc pause %d\n", timer);
10292 }
10293 } else {
10294 EL(qlt, "risc pause timeout\n");
10295 break;
10296 }
10297 }
10298 }
10299 }
10300
10301 static void
qlt_27xx_dt_rrisc(qlt_state_t * qlt,qlt_dt_rrisc_t * entry,uint8_t * dbuff,uint8_t * dbuff_end)10302 qlt_27xx_dt_rrisc(qlt_state_t *qlt, qlt_dt_rrisc_t *entry,
10303 uint8_t *dbuff, uint8_t *dbuff_end)
10304 {
10305 clock_t timer;
10306 uint16_t rom_status;
10307
10308 if (dbuff == NULL) {
10309 return;
10310 }
10311 if (dbuff >= dbuff_end) {
10312 EL(qlt, "skipped, no buffer space, needed=0\n");
10313 entry->h.driver_flags = (uint8_t)
10314 (entry->h.driver_flags | SKIPPED_FLAG);
10315 return;
10316 }
10317
10318 /* Shutdown DMA. */
10319 REG_WR32(qlt, REG_CTRL_STATUS, DMA_SHUTDOWN_CTRL);
10320
10321 /* Wait for DMA to stop. */
10322 for (timer = 0; timer < 30000; timer++) {
10323 if (!(REG_RD32(qlt, REG_CTRL_STATUS) & DMA_ACTIVE_STATUS)) {
10324 break;
10325 }
10326 drv_usecwait(100);
10327 }
10328
10329 /* Reset the chip. */
10330 REG_WR32(qlt, REG_CTRL_STATUS, CHIP_SOFT_RESET);
10331 drv_usecwait(200);
10332
10333 /* Wait for RISC to recover from reset. */
10334 for (timer = 30000; timer; timer--) {
10335 rom_status = REG_RD16(qlt, REG_MBOX0);
10336 if ((rom_status & MBS_ROM_STATUS_MASK) != MBS_ROM_BUSY) {
10337 break;
10338 }
10339 drv_usecwait(100);
10340 }
10341
10342 /* Wait for reset to finish. */
10343 for (timer = 30000; timer; timer--) {
10344 if (!(REG_RD32(qlt, REG_CTRL_STATUS) & CHIP_SOFT_RESET)) {
10345 break;
10346 }
10347 drv_usecwait(100);
10348 }
10349
10350 /* XXX: Disable Interrupts (Probably not needed) */
10351 REG_WR32(qlt, REG_INTR_CTRL, 0);
10352
10353 qlt->qlt_intr_enabled = 0;
10354 }
10355
10356 static void
qlt_27xx_dt_dint(qlt_state_t * qlt,qlt_dt_dint_t * entry,uint8_t * dbuff,uint8_t * dbuff_end)10357 qlt_27xx_dt_dint(qlt_state_t *qlt, qlt_dt_dint_t *entry,
10358 uint8_t *dbuff, uint8_t *dbuff_end)
10359 {
10360 if (dbuff == NULL) {
10361 return;
10362 }
10363 if (dbuff >= dbuff_end) {
10364 EL(qlt, "skipped, no buffer space, needed=0\n");
10365 entry->h.driver_flags = (uint8_t)
10366 (entry->h.driver_flags | SKIPPED_FLAG);
10367 return;
10368 }
10369
10370 PCICFG_WR32(qlt, entry->pci_offset, entry->data);
10371 }
10372
10373 /*ARGSUSED*/
10374 static int
qlt_27xx_dt_ghbd(qlt_state_t * qlt,qlt_dt_ghbd_t * entry,uint8_t * dbuff,uint8_t * dbuff_end)10375 qlt_27xx_dt_ghbd(qlt_state_t *qlt, qlt_dt_ghbd_t *entry,
10376 uint8_t *dbuff, uint8_t *dbuff_end)
10377 {
10378 if (dbuff != NULL) {
10379 entry->h.driver_flags = (uint8_t)
10380 (entry->h.driver_flags | SKIPPED_FLAG);
10381 }
10382
10383 return (0);
10384 }
10385
10386 /*ARGSUSED*/
10387 static int
qlt_27xx_dt_scra(qlt_state_t * qlt,qlt_dt_scra_t * entry,uint8_t * dbuff,uint8_t * dbuff_end)10388 qlt_27xx_dt_scra(qlt_state_t *qlt, qlt_dt_scra_t *entry,
10389 uint8_t *dbuff, uint8_t *dbuff_end)
10390 {
10391 if (dbuff != NULL) {
10392 entry->h.driver_flags = (uint8_t)
10393 (entry->h.driver_flags | SKIPPED_FLAG);
10394 }
10395
10396 return (0);
10397 }
10398
10399 static int
qlt_27xx_dt_rrreg(qlt_state_t * qlt,qlt_dt_rrreg_t * entry,uint8_t * dbuff,uint8_t * dbuff_end)10400 qlt_27xx_dt_rrreg(qlt_state_t *qlt, qlt_dt_rrreg_t *entry,
10401 uint8_t *dbuff, uint8_t *dbuff_end)
10402 {
10403 int esize;
10404 uint32_t i;
10405 uint8_t *bp = dbuff;
10406 uint32_t addr = entry->addr;
10407 uint32_t cnt = entry->count;
10408
10409 esize = cnt * 4; /* addr */
10410 esize += cnt * 4; /* data */
10411
10412 if (dbuff == NULL) {
10413 return (esize);
10414 }
10415 if (esize + dbuff >= dbuff_end) {
10416 EL(qlt, "skipped, no buffer space, needed=%xh\n", esize);
10417 entry->h.driver_flags = (uint8_t)
10418 (entry->h.driver_flags | SKIPPED_FLAG);
10419 return (0);
10420 }
10421
10422 REG_WR32(qlt, REG_IOBUS_BASE_ADDR, 0x40);
10423 while (cnt--) {
10424 REG_WR32(qlt, 0xc0, addr | 0x80000000);
10425 *bp++ = LSB(LSW(addr));
10426 *bp++ = MSB(LSW(addr));
10427 *bp++ = LSB(MSW(addr));
10428 *bp++ = MSB(MSW(addr));
10429 for (i = 0; i < 4; i++) {
10430 *bp++ = REG_RD8(qlt, i);
10431 }
10432 addr += 4;
10433 }
10434
10435 return (esize);
10436 }
10437
10438 static void
qlt_27xx_dt_wrreg(qlt_state_t * qlt,qlt_dt_wrreg_t * entry,uint8_t * dbuff,uint8_t * dbuff_end)10439 qlt_27xx_dt_wrreg(qlt_state_t *qlt, qlt_dt_wrreg_t *entry,
10440 uint8_t *dbuff, uint8_t *dbuff_end)
10441 {
10442 if (dbuff == NULL) {
10443 return;
10444 }
10445 if (dbuff >= dbuff_end) {
10446 EL(qlt, "skipped, no buffer space, needed=0\n");
10447 entry->h.driver_flags = (uint8_t)
10448 (entry->h.driver_flags | SKIPPED_FLAG);
10449 return;
10450 }
10451
10452 REG_WR32(qlt, REG_IOBUS_BASE_ADDR, 0x40);
10453 REG_WR32(qlt, 0xc4, entry->data);
10454 REG_WR32(qlt, 0xc0, entry->addr);
10455 }
10456
10457 static int
qlt_27xx_dt_rrram(qlt_state_t * qlt,qlt_dt_rrram_t * entry,uint8_t * dbuff,uint8_t * dbuff_end)10458 qlt_27xx_dt_rrram(qlt_state_t *qlt, qlt_dt_rrram_t *entry,
10459 uint8_t *dbuff, uint8_t *dbuff_end)
10460 {
10461 int rval, esize;
10462
10463 esize = entry->count * 4; /* data */
10464
10465 if (dbuff == NULL) {
10466 return (esize);
10467 }
10468 if (esize + dbuff >= dbuff_end) {
10469 EL(qlt, "skipped, no buffer space, needed=%xh\n", esize);
10470 entry->h.driver_flags = (uint8_t)
10471 (entry->h.driver_flags | SKIPPED_FLAG);
10472 return (0);
10473 }
10474
10475 if ((rval = qlt_27xx_dump_ram(qlt, MBC_MPI_RAM, entry->addr,
10476 entry->count, dbuff)) != QLT_SUCCESS) {
10477 EL(qlt, "dump_ram failed, rval=%xh, addr=%xh, len=%xh, "
10478 "esize=0\n", rval, entry->addr, entry->count);
10479 return (0);
10480 }
10481
10482 return (esize);
10483 }
10484
10485 static int
qlt_27xx_dt_rpcic(qlt_state_t * qlt,qlt_dt_rpcic_t * entry,uint8_t * dbuff,uint8_t * dbuff_end)10486 qlt_27xx_dt_rpcic(qlt_state_t *qlt, qlt_dt_rpcic_t *entry,
10487 uint8_t *dbuff, uint8_t *dbuff_end)
10488 {
10489 int esize;
10490 uint32_t i;
10491 uint8_t *bp = dbuff;
10492 uint32_t addr = entry->addr;
10493 uint32_t cnt = entry->count;
10494
10495 esize = cnt * 4; /* addr */
10496 esize += cnt * 4; /* data */
10497
10498 if (dbuff == NULL) {
10499 return (esize);
10500 }
10501 if (esize + dbuff >= dbuff_end) {
10502 EL(qlt, "skipped, no buffer space, needed=%xh\n", esize);
10503 entry->h.driver_flags = (uint8_t)
10504 (entry->h.driver_flags | SKIPPED_FLAG);
10505 return (0);
10506 }
10507
10508 while (cnt--) {
10509 *bp++ = LSB(LSW(addr));
10510 *bp++ = MSB(LSW(addr));
10511 *bp++ = LSB(MSW(addr));
10512 *bp++ = MSB(MSW(addr));
10513 for (i = 0; i < 4; i++) {
10514 *bp++ = PCICFG_RD8(qlt, addr++);
10515 }
10516 }
10517
10518 return (esize);
10519 }
10520
10521 /*ARGSUSED*/
10522 static int
qlt_27xx_dt_gques(qlt_state_t * qlt,qlt_dt_gques_t * entry,uint8_t * dbuff,uint8_t * dbuff_end)10523 qlt_27xx_dt_gques(qlt_state_t *qlt, qlt_dt_gques_t *entry,
10524 uint8_t *dbuff, uint8_t *dbuff_end)
10525 {
10526 if (entry->queue_type == 1) {
10527 EL(qlt, "skipped, no request queue shadowing, esize=0\n");
10528 if (dbuff != NULL) {
10529 entry->num_queues = 0;
10530 entry->h.driver_flags = (uint8_t)
10531 (entry->h.driver_flags | SKIPPED_FLAG);
10532 }
10533 return (0);
10534 } else if (entry->queue_type == 2) {
10535 EL(qlt, "skipped, no response queue shadowing, esize=0\n");
10536 if (dbuff != NULL) {
10537 entry->num_queues = 0;
10538 entry->h.driver_flags = (uint8_t)
10539 (entry->h.driver_flags | SKIPPED_FLAG);
10540 }
10541 return (0);
10542 } else if (entry->queue_type == 3) {
10543 EL(qlt, "skipped, no ATIO queue, esize=0\n");
10544 if (dbuff != NULL) {
10545 entry->num_queues = 0;
10546 entry->h.driver_flags = (uint8_t)
10547 (entry->h.driver_flags | SKIPPED_FLAG);
10548 }
10549 return (0);
10550 } else {
10551 EL(qlt, "skipped, unknown queue_type %d, esize=0\n",
10552 entry->queue_type);
10553 if (dbuff != NULL) {
10554 entry->h.driver_flags = (uint8_t)
10555 (entry->h.driver_flags | SKIPPED_FLAG);
10556 }
10557 return (0);
10558 }
10559 }
10560
10561 static int
qlt_27xx_dt_wdmp(qlt_state_t * qlt,qlt_dt_wdmp_t * entry,uint8_t * dbuff,uint8_t * dbuff_end)10562 qlt_27xx_dt_wdmp(qlt_state_t *qlt, qlt_dt_wdmp_t *entry,
10563 uint8_t *dbuff, uint8_t *dbuff_end)
10564 {
10565 int esize;
10566 uint8_t *bp = dbuff;
10567 uint32_t data, cnt = entry->length, *dp = entry->data;
10568
10569 esize = cnt;
10570 if (dbuff == NULL) {
10571 return (esize);
10572 }
10573 if (esize + dbuff >= dbuff_end) {
10574 EL(qlt, "skipped, no buffer space, needed=%xh\n", esize);
10575 entry->h.driver_flags = (uint8_t)
10576 (entry->h.driver_flags | SKIPPED_FLAG);
10577 return (0);
10578 }
10579
10580 while (cnt--) {
10581 data = *dp++;
10582 *bp++ = LSB(LSW(data));
10583 *bp++ = MSB(LSW(data));
10584 *bp++ = LSB(MSW(data));
10585 *bp++ = MSB(MSW(data));
10586 }
10587
10588 return (esize);
10589 }
10590
10591 /*
10592 * qlt_27xx_dump_ram
10593 * Dumps RAM.
10594 * Risc interrupts must be disabled when this routine is called.
10595 *
10596 * Input:
10597 * pi: port info pointer.
10598 * cmd: MBC_DUMP_RAM_EXTENDED/MBC_MPI_RAM.
10599 * risc_address: RISC code start address.
10600 * len: Number of words.
10601 * bp: buffer pointer.
10602 *
10603 * Returns:
10604 * qlt local function return status code.
10605 *
10606 * Context:
10607 * Interrupt or Kernel context, no mailbox commands allowed.
10608 */
10609 /*ARGSUSED*/
10610 static int
qlt_27xx_dump_ram(qlt_state_t * qlt,uint16_t cmd,uint32_t risc_address,uint32_t len,uint8_t * bp)10611 qlt_27xx_dump_ram(qlt_state_t *qlt, uint16_t cmd, uint32_t risc_address,
10612 uint32_t len, uint8_t *bp)
10613 {
10614 uint8_t *dp;
10615 uint32_t words_to_read, endaddr;
10616 uint32_t i;
10617 int rval = QLT_SUCCESS;
10618
10619 endaddr = risc_address + len;
10620 words_to_read = 0;
10621 while (risc_address < endaddr) {
10622 words_to_read = MBOX_DMA_MEM_SIZE >> 2;
10623 if ((words_to_read + risc_address) > endaddr) {
10624 words_to_read = endaddr - risc_address;
10625 }
10626
10627 if (cmd == MBC_DUMP_RAM_EXTENDED) {
10628 rval = qlt_read_risc_ram(qlt, risc_address,
10629 words_to_read);
10630 } else {
10631 rval = qlt_mbx_mpi_ram(qlt, risc_address,
10632 words_to_read, 0);
10633 }
10634
10635 if (rval != QLT_SUCCESS) {
10636 EL(qlt, "Error reading risc ram = %xh len = %x\n",
10637 risc_address, words_to_read);
10638 return (rval);
10639 }
10640
10641 dp = (uint8_t *)(qlt->queue_mem_ptr + MBOX_DMA_MEM_OFFSET);
10642 for (i = 0; i < (words_to_read * 4); i++) {
10643 *bp++ = *dp++;
10644 }
10645 risc_address += words_to_read;
10646 }
10647
10648 return (rval);
10649 }
10650
10651 static uint32_t
qlt_27xx_dmp_parse_template(qlt_state_t * qlt,qlt_dt_hdr_t * template_hdr,uint8_t * dump_buff,uint32_t buff_size)10652 qlt_27xx_dmp_parse_template(qlt_state_t *qlt, qlt_dt_hdr_t *template_hdr,
10653 uint8_t *dump_buff, uint32_t buff_size)
10654 {
10655 int e_cnt, esize, num_of_entries;
10656 uint32_t bsize;
10657 time_t time;
10658 uint8_t *dbuff, *dbuff_end;
10659 qlt_dt_entry_t *entry;
10660 int sane_end = 0;
10661
10662 dbuff = dump_buff; /* dbuff = NULL size determination. */
10663 dbuff_end = dump_buff + buff_size;
10664
10665 if (template_hdr->type != DT_THDR) {
10666 EL(qlt, "Template header not found\n");
10667 return (0);
10668 }
10669 if (dbuff != NULL) {
10670 (void) drv_getparm(TIME, &time);
10671 template_hdr->driver_timestamp = LSD(time);
10672 }
10673
10674 num_of_entries = template_hdr->num_of_entries;
10675 entry = (qlt_dt_entry_t *)((caddr_t)template_hdr +
10676 template_hdr->first_entry_offset);
10677
10678 bsize = template_hdr->size_of_template;
10679 for (e_cnt = 0; e_cnt < num_of_entries; e_cnt++) {
10680 /*
10681 * Decode the entry type and process it accordingly
10682 */
10683 esize = 0;
10684 switch (entry->h.type) {
10685 case DT_NOP:
10686 if (dbuff != NULL) {
10687 entry->h.driver_flags = (uint8_t)
10688 (entry->h.driver_flags | SKIPPED_FLAG);
10689 }
10690 break;
10691 case DT_TEND:
10692 if (dbuff != NULL) {
10693 entry->h.driver_flags = (uint8_t)
10694 (entry->h.driver_flags | SKIPPED_FLAG);
10695 }
10696 sane_end++;
10697 break;
10698 case DT_RIOB1:
10699 esize = qlt_27xx_dt_riob1(qlt, (qlt_dt_riob1_t *)entry,
10700 dbuff, dbuff_end);
10701 break;
10702 case DT_WIOB1:
10703 qlt_27xx_dt_wiob1(qlt, (qlt_dt_wiob1_t *)entry,
10704 dbuff, dbuff_end);
10705 break;
10706 case DT_RIOB2:
10707 esize = qlt_27xx_dt_riob2(qlt, (qlt_dt_riob2_t *)entry,
10708 dbuff, dbuff_end);
10709 break;
10710 case DT_WIOB2:
10711 qlt_27xx_dt_wiob2(qlt, (qlt_dt_wiob2_t *)entry,
10712 dbuff, dbuff_end);
10713 break;
10714 case DT_RPCI:
10715 esize = qlt_27xx_dt_rpci(qlt, (qlt_dt_rpci_t *)entry,
10716 dbuff, dbuff_end);
10717 break;
10718 case DT_WPCI:
10719 qlt_27xx_dt_wpci(qlt, (qlt_dt_wpci_t *)entry,
10720 dbuff, dbuff_end);
10721 break;
10722 case DT_RRAM:
10723 esize = qlt_27xx_dt_rram(qlt, (qlt_dt_rram_t *)entry,
10724 dbuff, dbuff_end);
10725 break;
10726 case DT_GQUE:
10727 esize = qlt_27xx_dt_gque(qlt, (qlt_dt_gque_t *)entry,
10728 dbuff, dbuff_end);
10729 break;
10730 case DT_GFCE:
10731 esize = qlt_27xx_dt_gfce(qlt, (qlt_dt_gfce_t *)entry,
10732 dbuff, dbuff_end);
10733 break;
10734 case DT_PRISC:
10735 qlt_27xx_dt_prisc(qlt, (qlt_dt_prisc_t *)entry,
10736 dbuff, dbuff_end);
10737 break;
10738 case DT_RRISC:
10739 qlt_27xx_dt_rrisc(qlt, (qlt_dt_rrisc_t *)entry,
10740 dbuff, dbuff_end);
10741 break;
10742 case DT_DINT:
10743 qlt_27xx_dt_dint(qlt, (qlt_dt_dint_t *)entry,
10744 dbuff, dbuff_end);
10745 break;
10746 case DT_GHBD:
10747 esize = qlt_27xx_dt_ghbd(qlt, (qlt_dt_ghbd_t *)entry,
10748 dbuff, dbuff_end);
10749 break;
10750 case DT_SCRA:
10751 esize = qlt_27xx_dt_scra(qlt, (qlt_dt_scra_t *)entry,
10752 dbuff, dbuff_end);
10753 break;
10754 case DT_RRREG:
10755 esize = qlt_27xx_dt_rrreg(qlt, (qlt_dt_rrreg_t *)entry,
10756 dbuff, dbuff_end);
10757 break;
10758 case DT_WRREG:
10759 qlt_27xx_dt_wrreg(qlt, (qlt_dt_wrreg_t *)entry,
10760 dbuff, dbuff_end);
10761 break;
10762 case DT_RRRAM:
10763 esize = qlt_27xx_dt_rrram(qlt, (qlt_dt_rrram_t *)entry,
10764 dbuff, dbuff_end);
10765 break;
10766 case DT_RPCIC:
10767 esize = qlt_27xx_dt_rpcic(qlt, (qlt_dt_rpcic_t *)entry,
10768 dbuff, dbuff_end);
10769 break;
10770 case DT_GQUES:
10771 esize = qlt_27xx_dt_gques(qlt, (qlt_dt_gques_t *)entry,
10772 dbuff, dbuff_end);
10773 break;
10774 case DT_WDMP:
10775 esize = qlt_27xx_dt_wdmp(qlt, (qlt_dt_wdmp_t *)entry,
10776 dbuff, dbuff_end);
10777 break;
10778 default:
10779 entry->h.driver_flags = (uint8_t)
10780 (entry->h.driver_flags | SKIPPED_FLAG);
10781 EL(qlt, "Entry ID=%d, type=%d unknown\n", e_cnt,
10782 entry->h.type);
10783 break;
10784 }
10785 if (dbuff != NULL && esize) {
10786 dbuff += esize;
10787 }
10788 bsize += esize;
10789 /* next entry in the template */
10790 entry = (qlt_dt_entry_t *)((caddr_t)entry + entry->h.size);
10791 }
10792 if (sane_end > 1) {
10793 EL(qlt, "Template configuration error. Check Template\n");
10794 }
10795
10796 return (bsize);
10797 }
10798