1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /* Copyright 2010 QLogic Corporation */
23
24 /*
25 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
26 */
27
28 #pragma ident "Copyright 2010 QLogic Corporation; ql_mbx.c"
29
30 /*
31 * ISP2xxx Solaris Fibre Channel Adapter (FCA) driver source file.
32 *
33 * ***********************************************************************
34 * * **
35 * * NOTICE **
36 * * COPYRIGHT (C) 1996-2010 QLOGIC CORPORATION **
37 * * ALL RIGHTS RESERVED **
38 * * **
39 * ***********************************************************************
40 *
41 */
42
43 #include <ql_apps.h>
44 #include <ql_api.h>
45 #include <ql_debug.h>
46 #include <ql_iocb.h>
47 #include <ql_isr.h>
48 #include <ql_mbx.h>
49 #include <ql_xioctl.h>
50
51 /*
52 * Local data
53 */
54
55 /*
56 * Local prototypes
57 */
58 static int ql_mailbox_command(ql_adapter_state_t *, mbx_cmd_t *);
59 static int ql_task_mgmt_iocb(ql_adapter_state_t *, ql_tgt_t *, uint16_t,
60 uint32_t, uint16_t);
61 static int ql_abort_cmd_iocb(ql_adapter_state_t *, ql_srb_t *);
62 static int ql_setup_mbox_dma_transfer(ql_adapter_state_t *, dma_mem_t *,
63 caddr_t, uint32_t);
64 static int ql_setup_mbox_dma_resources(ql_adapter_state_t *, dma_mem_t *,
65 uint32_t);
66 static void ql_setup_mbox_dma_data(dma_mem_t *, caddr_t);
67 static void ql_get_mbox_dma_data(dma_mem_t *, caddr_t);
68
69 /*
70 * ql_mailbox_command
71 * Issue mailbox command and waits for completion.
72 *
73 * Input:
74 * ha = adapter state pointer.
75 * mcp = mailbox command parameter structure pointer.
76 *
77 * Returns:
78 * ql local function return status code.
79 *
80 * Context:
81 * Kernel context.
82 */
83 static int
84 ql_mailbox_command(ql_adapter_state_t *vha, mbx_cmd_t *mcp)
85 {
86 uint16_t cnt;
87 uint32_t data;
88 clock_t timer, cv_stat;
89 int rval;
90 uint32_t set_flags = 0;
91 uint32_t reset_flags = 0;
92 ql_adapter_state_t *ha = vha->pha;
93 int mbx_cmd = mcp->mb[0];
94
95 QL_PRINT_3(CE_CONT, "(%d): started, cmd=%xh\n", ha->instance, mbx_cmd);
96
97 /* Acquire mailbox register lock. */
98 MBX_REGISTER_LOCK(ha);
99
100 /* Check for mailbox available, if not wait for signal. */
101 while (ha->mailbox_flags & MBX_BUSY_FLG ||
102 (CFG_IST(ha, CFG_CTRL_8021) &&
103 RD32_IO_REG(ha, nx_host_int) & NX_MBX_CMD)) {
104 ha->mailbox_flags = (uint8_t)
105 (ha->mailbox_flags | MBX_WANT_FLG);
106
107 if (ha->task_daemon_flags & TASK_DAEMON_POWERING_DOWN) {
108 EL(vha, "failed availability cmd=%xh\n", mcp->mb[0]);
109 MBX_REGISTER_UNLOCK(ha);
110 return (QL_LOCK_TIMEOUT);
111 }
112
113 /* Set timeout after command that is running. */
114 timer = (mcp->timeout + 20) * drv_usectohz(1000000);
115 cv_stat = cv_reltimedwait_sig(&ha->cv_mbx_wait,
116 &ha->pha->mbx_mutex, timer, TR_CLOCK_TICK);
117 if (cv_stat == -1 || cv_stat == 0) {
118 /*
119 * The timeout time 'timer' was
120 * reached without the condition
121 * being signaled.
122 */
123 ha->mailbox_flags = (uint8_t)(ha->mailbox_flags &
124 ~MBX_WANT_FLG);
125 cv_broadcast(&ha->cv_mbx_wait);
126
127 /* Release mailbox register lock. */
128 MBX_REGISTER_UNLOCK(ha);
129
130 if (cv_stat == 0) {
131 EL(vha, "waiting for availability aborted, "
132 "cmd=%xh\n", mcp->mb[0]);
133 return (QL_ABORTED);
134 }
135 EL(vha, "failed availability cmd=%xh\n", mcp->mb[0]);
136 return (QL_LOCK_TIMEOUT);
137 }
138 }
139
140 ha->mailbox_flags = (uint8_t)(ha->mailbox_flags | MBX_BUSY_FLG);
141
142 /* Structure pointer for return mailbox registers. */
143 ha->mcp = mcp;
144
145 /* Load mailbox registers. */
146 data = mcp->out_mb;
147 for (cnt = 0; cnt < ha->reg_off->mbox_cnt && data; cnt++) {
148 if (data & MBX_0) {
149 WRT16_IO_REG(ha, mailbox_in[cnt], mcp->mb[cnt]);
150 }
151 data >>= 1;
152 }
153
154 /* Issue set host interrupt command. */
155 ha->mailbox_flags = (uint8_t)(ha->mailbox_flags & ~MBX_INTERRUPT);
156 if (CFG_IST(ha, CFG_CTRL_8021)) {
157 WRT32_IO_REG(ha, nx_host_int, NX_MBX_CMD);
158 } else if (CFG_IST(ha, CFG_CTRL_242581)) {
159 WRT32_IO_REG(ha, hccr, HC24_SET_HOST_INT);
160 } else {
161 WRT16_IO_REG(ha, hccr, HC_SET_HOST_INT);
162 }
163
164 /* Wait for command to complete. */
165 if (ha->flags & INTERRUPTS_ENABLED &&
166 !(ha->task_daemon_flags & (TASK_THREAD_CALLED |
167 TASK_DAEMON_POWERING_DOWN)) &&
168 !ddi_in_panic()) {
169 timer = mcp->timeout * drv_usectohz(1000000);
170 while (!(ha->mailbox_flags & (MBX_INTERRUPT | MBX_ABORT)) &&
171 !(ha->task_daemon_flags & ISP_ABORT_NEEDED)) {
172
173 if (cv_reltimedwait(&ha->cv_mbx_intr,
174 &ha->pha->mbx_mutex, timer, TR_CLOCK_TICK) == -1) {
175 /*
176 * The timeout time 'timer' was
177 * reached without the condition
178 * being signaled.
179 */
180 MBX_REGISTER_UNLOCK(ha);
181 while (INTERRUPT_PENDING(ha)) {
182 (void) ql_isr((caddr_t)ha);
183 INTR_LOCK(ha);
184 ha->intr_claimed = B_TRUE;
185 INTR_UNLOCK(ha);
186 }
187 MBX_REGISTER_LOCK(ha);
188 break;
189 }
190 }
191 } else {
192 /* Release mailbox register lock. */
193 MBX_REGISTER_UNLOCK(ha);
194
195 /* Acquire interrupt lock. */
196 for (timer = mcp->timeout * 100; timer; timer--) {
197 /* Check for pending interrupts. */
198 while (INTERRUPT_PENDING(ha)) {
199 (void) ql_isr((caddr_t)ha);
200 INTR_LOCK(ha);
201 ha->intr_claimed = B_TRUE;
202 INTR_UNLOCK(ha);
203 if (ha->mailbox_flags &
204 (MBX_INTERRUPT | MBX_ABORT) ||
205 ha->task_daemon_flags & ISP_ABORT_NEEDED) {
206 break;
207 }
208 }
209 if (ha->mailbox_flags & (MBX_INTERRUPT | MBX_ABORT) ||
210 ha->task_daemon_flags & ISP_ABORT_NEEDED) {
211 break;
212 } else if (!ddi_in_panic() && timer % 101 == 0) {
213 delay(drv_usectohz(10000));
214 } else {
215 drv_usecwait(10000);
216 }
217 }
218
219 /* Acquire mailbox register lock. */
220 MBX_REGISTER_LOCK(ha);
221 }
222
223 /* Mailbox command timeout? */
224 if (ha->task_daemon_flags & ISP_ABORT_NEEDED ||
225 ha->mailbox_flags & MBX_ABORT) {
226 rval = QL_ABORTED;
227 } else if ((ha->mailbox_flags & MBX_INTERRUPT) == 0) {
228 if (!CFG_IST(ha, CFG_CTRL_8021)) {
229 if (CFG_IST(ha, CFG_DUMP_MAILBOX_TIMEOUT)) {
230 (void) ql_binary_fw_dump(ha, FALSE);
231 }
232 EL(vha, "command timeout, isp_abort_needed\n");
233 set_flags |= ISP_ABORT_NEEDED;
234 }
235 rval = QL_FUNCTION_TIMEOUT;
236 } else {
237 ha->mailbox_flags = (uint8_t)
238 (ha->mailbox_flags & ~MBX_INTERRUPT);
239 /*
240 * This is the expected completion path so
241 * return the actual mbx cmd completion status.
242 */
243 rval = mcp->mb[0];
244 }
245
246 /*
247 * Clear outbound to risc mailbox registers per spec. The exception
248 * is on 2200 mailbox 4 and 5 affect the req and resp que indexes
249 * so avoid writing them.
250 */
251 if (ha->cfg_flags & CFG_CTRL_2200) {
252 data = ((mcp->out_mb & ~(MBX_4 | MBX_5)) >> 1);
253 } else {
254 data = (mcp->out_mb >> 1);
255 }
256 for (cnt = 1; cnt < ha->reg_off->mbox_cnt && data; cnt++) {
257 if (data & MBX_0) {
258 WRT16_IO_REG(ha, mailbox_in[cnt], (uint16_t)0);
259 }
260 data >>= 1;
261 }
262
263 /* Reset busy status. */
264 ha->mailbox_flags = (uint8_t)(ha->mailbox_flags &
265 ~(MBX_BUSY_FLG | MBX_ABORT));
266 ha->mcp = NULL;
267
268 /* If thread is waiting for mailbox go signal it to start. */
269 if (ha->mailbox_flags & MBX_WANT_FLG) {
270 ha->mailbox_flags = (uint8_t)(ha->mailbox_flags &
271 ~MBX_WANT_FLG);
272 cv_broadcast(&ha->cv_mbx_wait);
273 }
274
275 /* Release mailbox register lock. */
276 MBX_REGISTER_UNLOCK(ha);
277
278 if (set_flags != 0 || reset_flags != 0) {
279 ql_awaken_task_daemon(ha, NULL, set_flags, reset_flags);
280 }
281
282 if (rval != QL_SUCCESS) {
283 EL(vha, "%s failed, rval=%xh, mcp->mb[0]=%xh\n",
284 mbx_cmd_text(mbx_cmd), rval, mcp->mb[0]);
285 } else {
286 /*EMPTY*/
287 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
288 }
289
290 return (rval);
291 }
292
293 /*
294 * ql_setup_mbox_dma_resources
295 * Prepare the data for a mailbox dma transfer.
296 *
297 * Input:
298 * ha = adapter state pointer.
299 * mem_desc = descriptor to contain the dma resource information.
300 * data = pointer to the data.
301 * size = size of the data in bytes.
302 *
303 * Returns:
304 * ql local function return status code.
305 *
306 * Context:
307 * Kernel context.
308 */
309 static int
310 ql_setup_mbox_dma_transfer(ql_adapter_state_t *ha, dma_mem_t *mem_desc,
311 caddr_t data, uint32_t size)
312 {
313 int rval = QL_SUCCESS;
314
315 if ((rval = ql_setup_mbox_dma_resources(ha, mem_desc, size)) ==
316 QL_SUCCESS) {
317 ql_setup_mbox_dma_data(mem_desc, data);
318 } else {
319 EL(ha, "failed, setup_mbox_dma_transfer: %xh\n", rval);
320 }
321
322 return (rval);
323 }
324
325 /*
326 * ql_setup_mbox_dma_resources
327 * Prepare a dma buffer.
328 *
329 * Input:
330 * ha = adapter state pointer.
331 * mem_desc = descriptor to contain the dma resource information.
332 * data = pointer to the data.
333 * size = size of the data in bytes.
334 *
335 * Returns:
336 * ql local function return status code.
337 *
338 * Context:
339 * Kernel context.
340 */
341 static int
342 ql_setup_mbox_dma_resources(ql_adapter_state_t *ha, dma_mem_t *mem_desc,
343 uint32_t size)
344 {
345 int rval = QL_SUCCESS;
346
347 if ((rval = ql_get_dma_mem(ha, mem_desc, size, LITTLE_ENDIAN_DMA,
348 QL_DMA_RING_ALIGN)) != QL_SUCCESS) {
349 EL(ha, "failed, ql_get_dma_mem FC_NOMEM\n");
350 rval = QL_MEMORY_ALLOC_FAILED;
351 }
352
353 return (rval);
354 }
355
356 /*
357 * ql_setup_mbox_dma_data
358 * Move data to the dma buffer.
359 *
360 * Input:
361 * mem_desc = descriptor to contain the dma resource information.
362 * data = pointer to the data.
363 *
364 * Returns:
365 *
366 * Context:
367 * Kernel context.
368 */
369 static void
370 ql_setup_mbox_dma_data(dma_mem_t *mem_desc, caddr_t data)
371 {
372 /* Copy out going data to DMA buffer. */
373 ddi_rep_put8(mem_desc->acc_handle, (uint8_t *)data,
374 (uint8_t *)mem_desc->bp, mem_desc->size, DDI_DEV_AUTOINCR);
375
376 /* Sync DMA buffer. */
377 (void) ddi_dma_sync(mem_desc->dma_handle, 0, mem_desc->size,
378 DDI_DMA_SYNC_FORDEV);
379 }
380
381 /*
382 * ql_get_mbox_dma_data
383 * Recover data from the dma buffer.
384 *
385 * Input:
386 * mem_desc = descriptor to contain the dma resource information.
387 * data = pointer to the data.
388 *
389 * Returns:
390 *
391 * Context:
392 * Kernel context.
393 */
394 static void
395 ql_get_mbox_dma_data(dma_mem_t *mem_desc, caddr_t data)
396 {
397 /* Sync in coming DMA buffer. */
398 (void) ddi_dma_sync(mem_desc->dma_handle, 0, mem_desc->size,
399 DDI_DMA_SYNC_FORKERNEL);
400 /* Copy in coming DMA data. */
401 ddi_rep_get8(mem_desc->acc_handle, (uint8_t *)data,
402 (uint8_t *)mem_desc->bp, mem_desc->size, DDI_DEV_AUTOINCR);
403 }
404
405 /*
406 * ql_initialize_ip
407 * Initialize IP receive buffer queue.
408 *
409 * Input:
410 * ha = adapter state pointer.
411 * ha->ip_init_ctrl_blk = setup for transmit.
412 *
413 * Returns:
414 * ql local function return status code.
415 *
416 * Context:
417 * Kernel context.
418 */
419 int
420 ql_initialize_ip(ql_adapter_state_t *ha)
421 {
422 ql_link_t *link;
423 ql_tgt_t *tq;
424 uint16_t index;
425 int rval;
426 dma_mem_t mem_desc;
427 mbx_cmd_t mc = {0};
428 mbx_cmd_t *mcp = &mc;
429
430 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
431
432 if (CFG_IST(ha, (CFG_CTRL_6322 | CFG_CTRL_258081)) ||
433 ha->vp_index != 0) {
434 ha->flags &= ~IP_INITIALIZED;
435 EL(ha, "HBA does not support IP\n");
436 return (QL_FUNCTION_FAILED);
437 }
438
439 ha->rcvbuf_ring_ptr = ha->rcvbuf_ring_bp;
440 ha->rcvbuf_ring_index = 0;
441
442 /* Reset all sequence counts. */
443 for (index = 0; index < DEVICE_HEAD_LIST_SIZE; index++) {
444 for (link = ha->dev[index].first; link != NULL;
445 link = link->next) {
446 tq = link->base_address;
447 tq->ub_total_seg_cnt = 0;
448 }
449 }
450
451 rval = ql_setup_mbox_dma_transfer(ha, &mem_desc,
452 (caddr_t)&ha->ip_init_ctrl_blk, sizeof (ql_comb_ip_init_cb_t));
453 if (rval != QL_SUCCESS) {
454 EL(ha, "failed, setup_mbox_dma_transfer: %xh\n", rval);
455 return (rval);
456 }
457
458 mcp->mb[0] = MBC_INITIALIZE_IP;
459 mcp->mb[2] = MSW(LSD(mem_desc.cookie.dmac_laddress));
460 mcp->mb[3] = LSW(LSD(mem_desc.cookie.dmac_laddress));
461 mcp->mb[6] = MSW(MSD(mem_desc.cookie.dmac_laddress));
462 mcp->mb[7] = LSW(MSD(mem_desc.cookie.dmac_laddress));
463 mcp->mb[8] = 0;
464 mcp->out_mb = MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_0;
465 mcp->in_mb = MBX_8|MBX_0;
466 mcp->timeout = MAILBOX_TOV;
467 rval = ql_mailbox_command(ha, mcp);
468
469 ql_free_dma_resource(ha, &mem_desc);
470
471 if (rval == QL_SUCCESS) {
472 ADAPTER_STATE_LOCK(ha);
473 ha->flags |= IP_INITIALIZED;
474 ADAPTER_STATE_UNLOCK(ha);
475 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
476 } else {
477 ha->flags &= ~IP_INITIALIZED;
478 EL(ha, "failed, rval = %xh\n", rval);
479 }
480 return (rval);
481 }
482
483 /*
484 * ql_shutdown_ip
485 * Disconnects firmware IP from system buffers.
486 *
487 * Input:
488 * ha = adapter state pointer.
489 *
490 * Returns:
491 * ql local function return status code.
492 *
493 * Context:
494 * Kernel context.
495 */
496 int
497 ql_shutdown_ip(ql_adapter_state_t *ha)
498 {
499 int rval;
500 mbx_cmd_t mc = {0};
501 mbx_cmd_t *mcp = &mc;
502 fc_unsol_buf_t *ubp;
503 ql_srb_t *sp;
504 uint16_t index;
505
506 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
507
508 mcp->mb[0] = MBC_UNLOAD_IP;
509 mcp->out_mb = MBX_0;
510 mcp->in_mb = MBX_0;
511 mcp->timeout = MAILBOX_TOV;
512 rval = ql_mailbox_command(ha, mcp);
513
514 ADAPTER_STATE_LOCK(ha);
515 QL_UB_LOCK(ha);
516 /* Return all unsolicited buffers that ISP-IP has. */
517 for (index = 0; index < QL_UB_LIMIT; index++) {
518 ubp = ha->ub_array[index];
519 if (ubp != NULL) {
520 sp = ubp->ub_fca_private;
521 sp->flags &= ~SRB_UB_IN_ISP;
522 }
523 }
524
525 ha->ub_outcnt = 0;
526 QL_UB_UNLOCK(ha);
527 ha->flags &= ~IP_INITIALIZED;
528 ADAPTER_STATE_UNLOCK(ha);
529
530 if (rval == QL_SUCCESS) {
531 /* EMPTY - no need to check return value of MBC_SHUTDOWN_IP */
532 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
533 } else {
534 EL(ha, "failed, rval = %xh\n", rval);
535 }
536 return (rval);
537 }
538
539 /*
540 * ql_online_selftest
541 * Issue online self test mailbox command.
542 *
543 * Input:
544 * ha = adapter state pointer.
545 *
546 * Returns:
547 * ql local function return status code.
548 *
549 * Context:
550 * Kernel context.
551 */
552 int
553 ql_online_selftest(ql_adapter_state_t *ha)
554 {
555 int rval;
556 mbx_cmd_t mc = {0};
557 mbx_cmd_t *mcp = &mc;
558
559 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
560
561 mcp->mb[0] = MBC_ONLINE_SELF_TEST;
562 mcp->out_mb = MBX_0;
563 mcp->in_mb = MBX_0 | MBX_1 | MBX_2 | MBX_3;
564 mcp->timeout = MAILBOX_TOV;
565 rval = ql_mailbox_command(ha, mcp);
566
567 if (rval != QL_SUCCESS) {
568 EL(ha, "failed, rval = %xh, mb1=%xh, mb2=%xh, mb3=%xh\n",
569 rval, mcp->mb[1], mcp->mb[2], mcp->mb[3]);
570 } else {
571 /*EMPTY*/
572 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
573 }
574 return (rval);
575 }
576
577 /*
578 * ql_loop_back
579 * Issue diagnostic loop back frame mailbox command.
580 *
581 * Input:
582 * ha: adapter state pointer.
583 * findex: FCF index.
584 * lb: loop back parameter structure pointer.
585 *
586 * Returns:
587 * ql local function return status code.
588 *
589 * Context:
590 * Kernel context.
591 */
592 #ifndef apps_64bit
593 int
594 ql_loop_back(ql_adapter_state_t *ha, uint16_t findex, lbp_t *lb,
595 uint32_t h_xmit, uint32_t h_rcv)
596 {
597 int rval;
598 mbx_cmd_t mc = {0};
599 mbx_cmd_t *mcp = &mc;
600
601 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
602
603 mcp->mb[0] = MBC_DIAGNOSTIC_LOOP_BACK;
604 mcp->mb[1] = lb->options;
605 mcp->mb[2] = findex;
606 mcp->mb[6] = LSW(h_rcv);
607 mcp->mb[7] = MSW(h_rcv);
608 mcp->mb[10] = LSW(lb->transfer_count);
609 mcp->mb[11] = MSW(lb->transfer_count);
610 mcp->mb[12] = lb->transfer_segment_count;
611 mcp->mb[13] = lb->receive_segment_count;
612 mcp->mb[14] = LSW(lb->transfer_data_address);
613 mcp->mb[15] = MSW(lb->transfer_data_address);
614 mcp->mb[16] = LSW(lb->receive_data_address);
615 mcp->mb[17] = MSW(lb->receive_data_address);
616 mcp->mb[18] = LSW(lb->iteration_count);
617 mcp->mb[19] = MSW(lb->iteration_count);
618 mcp->mb[20] = LSW(h_xmit);
619 mcp->mb[21] = MSW(h_xmit);
620 mcp->out_mb = MBX_21|MBX_20|MBX_19|MBX_18|MBX_17|MBX_16|MBX_15|
621 MBX_14|MBX_13|MBX_12|MBX_11|MBX_10|MBX_7|MBX_6|MBX_2|MBX_1|MBX_0;
622 mcp->in_mb = MBX_19|MBX_18|MBX_3|MBX_2|MBX_1|MBX_0;
623 mcp->timeout = lb->iteration_count / 300;
624
625 if (mcp->timeout < MAILBOX_TOV) {
626 mcp->timeout = MAILBOX_TOV;
627 }
628
629 rval = ql_mailbox_command(ha, mcp);
630
631 if (rval != QL_SUCCESS) {
632 EL(ha, "failed, rval = %xh, mb1=%xh, mb2=%xh, mb3=%xh\n",
633 rval, mcp->mb[1], mcp->mb[2], mcp->mb[3]);
634 } else {
635 /*EMPTY*/
636 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
637 }
638 return (rval);
639 }
640 #else
641 int
642 ql_loop_back(ql_adapter_state_t *ha, uint16_t findex, lbp_t *lb)
643 {
644 int rval;
645 mbx_cmd_t mc = {0};
646 mbx_cmd_t *mcp = &mc;
647
648 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
649
650 mcp->mb[0] = MBC_DIAGNOSTIC_LOOP_BACK;
651 mcp->mb[1] = lb->options;
652 mcp->mb[2] = findex;
653 mcp->mb[6] = LSW(h_rcv);
654 mcp->mb[7] = MSW(h_rcv);
655 mcp->mb[6] = LSW(MSD(lb->receive_data_address));
656 mcp->mb[7] = MSW(MSD(lb->receive_data_address));
657 mcp->mb[10] = LSW(lb->transfer_count);
658 mcp->mb[11] = MSW(lb->transfer_count);
659 mcp->mb[12] = lb->transfer_segment_count;
660 mcp->mb[13] = lb->receive_segment_count;
661 mcp->mb[14] = LSW(lb->transfer_data_address);
662 mcp->mb[15] = MSW(lb->transfer_data_address);
663 mcp->mb[14] = LSW(LSD(lb->transfer_data_address));
664 mcp->mb[15] = MSW(LSD(lb->transfer_data_address));
665 mcp->mb[16] = LSW(lb->receive_data_address);
666 mcp->mb[17] = MSW(lb->receive_data_address);
667 mcp->mb[16] = LSW(LSD(lb->receive_data_address));
668 mcp->mb[17] = MSW(LSD(lb->receive_data_address));
669 mcp->mb[18] = LSW(lb->iteration_count);
670 mcp->mb[19] = MSW(lb->iteration_count);
671 mcp->mb[20] = LSW(h_xmit);
672 mcp->mb[21] = MSW(h_xmit);
673 mcp->mb[20] = LSW(MSD(lb->transfer_data_address));
674 mcp->mb[21] = MSW(MSD(lb->transfer_data_address));
675 mcp->out_mb = MBX_21|MBX_20|MBX_19|MBX_18|MBX_17|MBX_16|MBX_15|
676 MBX_14|MBX_13|MBX_12|MBX_11|MBX_10|MBX_7|MBX_6|MBX_2|MBX_1|MBX_0;
677 mcp->in_mb = MBX_19|MBX_18|MBX_3|MBX_2|MBX_1|MBX_0;
678 mcp->timeout = lb->iteration_count / 300;
679
680 if (mcp->timeout < MAILBOX_TOV) {
681 mcp->timeout = MAILBOX_TOV;
682 }
683
684 rval = ql_mailbox_command(ha, mcp);
685
686 if (rval != QL_SUCCESS) {
687 EL(ha, "failed, rval = %xh\n", rval);
688 } else {
689 /*EMPTY*/
690 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
691 }
692 return (rval);
693 }
694 #endif
695
696 /*
697 * ql_echo
698 * Issue an ELS echo using the user specified data to a user specified
699 * destination
700 *
701 * Input:
702 * ha: adapter state pointer.
703 * findex: FCF index.
704 * echo_pt: echo parameter structure pointer.
705 *
706 * Returns:
707 * ql local function return status code.
708 *
709 * Context:
710 * Kernel context.
711 */
712 int
713 ql_echo(ql_adapter_state_t *ha, uint16_t findex, echo_t *echo_pt)
714 {
715 int rval;
716 mbx_cmd_t mc = {0};
717 mbx_cmd_t *mcp = &mc;
718
719 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
720
721 mcp->mb[0] = MBC_ECHO; /* ECHO command */
722 mcp->mb[1] = echo_pt->options; /* command options; 64 bit */
723 /* addressing (bit 6) and */
724 /* real echo (bit 15 */
725 mcp->mb[2] = findex;
726
727 /*
728 * I know this looks strange, using a field labled "not used"
729 * The way the ddi_dma_cookie_t structure/union is defined
730 * is a union of one 64 bit entity with an array of two 32
731 * bit enititys. Since we have routines to convert 32 bit
732 * entities into 16 bit entities it is easier to use
733 * both 32 bit union members then the one 64 bit union
734 * member
735 */
736 if (echo_pt->options & BIT_6) {
737 /* 64 bit addressing */
738 /* Receive data dest add in system memory bits 47-32 */
739 mcp->mb[6] = LSW(echo_pt->receive_data_address.dmac_notused);
740
741 /* Receive data dest add in system memory bits 63-48 */
742 mcp->mb[7] = MSW(echo_pt->receive_data_address.dmac_notused);
743
744 /* Transmit data source address in system memory bits 47-32 */
745 mcp->mb[20] = LSW(echo_pt->transfer_data_address.dmac_notused);
746
747 /* Transmit data source address in system memory bits 63-48 */
748 mcp->mb[21] = MSW(echo_pt->transfer_data_address.dmac_notused);
749 }
750
751 /* transfer count bits 15-0 */
752 mcp->mb[10] = LSW(echo_pt->transfer_count);
753
754 /* Transmit data source address in system memory bits 15-0 */
755 mcp->mb[14] = LSW(echo_pt->transfer_data_address.dmac_address);
756
757 /* Transmit data source address in system memory bits 31-16 */
758 mcp->mb[15] = MSW(echo_pt->transfer_data_address.dmac_address);
759
760 /* Receive data destination address in system memory bits 15-0 */
761 mcp->mb[16] = LSW(echo_pt->receive_data_address.dmac_address);
762
763 /* Receive data destination address in system memory bits 31-16 */
764 mcp->mb[17] = MSW(echo_pt->receive_data_address.dmac_address);
765
766 mcp->out_mb = MBX_21|MBX_20|MBX_17|MBX_16|MBX_15|MBX_14|MBX_10|
767 MBX_7|MBX_6|MBX_2|MBX_1|MBX_0;
768 mcp->in_mb = MBX_3|MBX_1|MBX_0;
769 mcp->timeout = MAILBOX_TOV;
770
771 rval = ql_mailbox_command(ha, mcp);
772
773 if (rval != QL_SUCCESS) {
774 EL(ha, "failed, rval = %xh\n", rval);
775 } else {
776 /*EMPTY*/
777 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
778 }
779 return (rval);
780 }
781
782 /*
783 * ql_send_change_request
784 * Issue send change request mailbox command.
785 *
786 * Input:
787 * ha: adapter state pointer.
788 * fmt: Registration format.
789 *
790 * Returns:
791 * ql local function return status code.
792 *
793 * Context:
794 * Kernel context.
795 */
796 int
797 ql_send_change_request(ql_adapter_state_t *ha, uint16_t fmt)
798 {
799 int rval;
800 mbx_cmd_t mc = {0};
801 mbx_cmd_t *mcp = &mc;
802
803 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
804
805 mcp->mb[0] = MBC_SEND_CHANGE_REQUEST;
806 mcp->mb[1] = fmt;
807 mcp->out_mb = MBX_1|MBX_0;
808 if (ha->flags & VP_ENABLED) {
809 mcp->mb[9] = ha->vp_index;
810 mcp->out_mb |= MBX_9;
811 }
812 mcp->in_mb = MBX_0;
813 mcp->timeout = MAILBOX_TOV;
814 rval = ql_mailbox_command(ha, mcp);
815
816 if (rval != QL_SUCCESS) {
817 EL(ha, "failed=%xh\n", rval);
818 } else {
819 /*EMPTY*/
820 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
821 }
822 return (rval);
823 }
824
825 /*
826 * ql_send_lfa
827 * Send a Loop Fabric Address mailbox command.
828 *
829 * Input:
830 * ha: adapter state pointer.
831 * lfa: LFA command structure pointer.
832 *
833 * Returns:
834 * ql local function return status code.
835 *
836 * Context:
837 * Kernel context.
838 */
839 int
840 ql_send_lfa(ql_adapter_state_t *ha, lfa_cmd_t *lfa)
841 {
842 int rval;
843 uint16_t size;
844 dma_mem_t mem_desc;
845 mbx_cmd_t mc = {0};
846 mbx_cmd_t *mcp = &mc;
847
848 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
849
850 /* LFA_CB sz = 4 16bit words subcommand + 10 16bit words header. */
851 size = (uint16_t)((lfa->subcommand_length[0] + 10) << 1);
852
853 rval = ql_setup_mbox_dma_transfer(ha, &mem_desc, (caddr_t)lfa, size);
854 if (rval != QL_SUCCESS) {
855 EL(ha, "failed, setup_mbox_dma_transfer: %xh\n", rval);
856 return (rval);
857 }
858
859 mcp->mb[0] = MBC_SEND_LFA_COMMAND;
860 mcp->mb[1] = (uint16_t)(size >> 1);
861 mcp->mb[2] = MSW(LSD(mem_desc.cookie.dmac_laddress));
862 mcp->mb[3] = LSW(LSD(mem_desc.cookie.dmac_laddress));
863 mcp->mb[6] = MSW(MSD(mem_desc.cookie.dmac_laddress));
864 mcp->mb[7] = LSW(MSD(mem_desc.cookie.dmac_laddress));
865 mcp->in_mb = MBX_0;
866 mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
867 if (ha->flags & VP_ENABLED) {
868 mcp->mb[9] = ha->vp_index;
869 mcp->out_mb |= MBX_9;
870 }
871 mcp->timeout = MAILBOX_TOV;
872 rval = ql_mailbox_command(ha, mcp);
873
874 ql_free_dma_resource(ha, &mem_desc);
875
876 if (rval != QL_SUCCESS) {
877 EL(ha, "failed, rval = %xh\n", rval);
878 } else {
879 /*EMPTY*/
880 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
881 }
882
883 return (rval);
884 }
885
886 /*
887 * ql_clear_aca
888 * Issue clear ACA mailbox command.
889 *
890 * Input:
891 * ha: adapter state pointer.
892 * tq: target queue pointer.
893 * lun: LUN.
894 *
895 * Returns:
896 * ql local function return status code.
897 *
898 * Context:
899 * Kernel context.
900 */
901 int
902 ql_clear_aca(ql_adapter_state_t *ha, ql_tgt_t *tq, uint16_t lun)
903 {
904 int rval;
905 mbx_cmd_t mc = {0};
906 mbx_cmd_t *mcp = &mc;
907
908 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
909
910 if (CFG_IST(ha, CFG_CTRL_24258081)) {
911 rval = ql_task_mgmt_iocb(ha, tq, lun, CF_CLEAR_ACA, 0);
912 } else {
913 mcp->mb[0] = MBC_CLEAR_ACA;
914 if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
915 mcp->mb[1] = tq->loop_id;
916 } else {
917 mcp->mb[1] = (uint16_t)(tq->loop_id << 8);
918 }
919 mcp->mb[2] = lun;
920 mcp->out_mb = MBX_2|MBX_1|MBX_0;
921 mcp->in_mb = MBX_0;
922 mcp->timeout = MAILBOX_TOV;
923 rval = ql_mailbox_command(ha, mcp);
924 }
925
926 (void) ql_marker(ha, tq->loop_id, lun, MK_SYNC_ID);
927
928 if (rval != QL_SUCCESS) {
929 EL(ha, "failed, rval = %xh\n", rval);
930 } else {
931 /*EMPTY*/
932 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
933 }
934
935 return (rval);
936 }
937
938 /*
939 * ql_target_reset
940 * Issue target reset mailbox command.
941 *
942 * Input:
943 * ha: adapter state pointer.
944 * tq: target queue pointer.
945 * delay: seconds.
946 *
947 * Returns:
948 * ql local function return status code.
949 *
950 * Context:
951 * Kernel context.
952 */
953 int
954 ql_target_reset(ql_adapter_state_t *ha, ql_tgt_t *tq, uint16_t delay)
955 {
956 ql_link_t *link;
957 uint16_t index;
958 int rval;
959 mbx_cmd_t mc = {0};
960 mbx_cmd_t *mcp = &mc;
961
962 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
963
964 if (CFG_IST(ha, CFG_CTRL_24258081)) {
965 /* queue = NULL, all targets. */
966 if (tq == NULL) {
967 for (index = 0; index < DEVICE_HEAD_LIST_SIZE;
968 index++) {
969 for (link = ha->dev[index].first; link !=
970 NULL; link = link->next) {
971 tq = link->base_address;
972 if (!VALID_DEVICE_ID(ha,
973 tq->loop_id)) {
974 continue;
975 }
976
977 if (CFG_IST(ha, CFG_FAST_TIMEOUT)) {
978 rval = ql_task_mgmt_iocb(ha,
979 tq, 0, CF_DO_NOT_SEND |
980 CF_TARGET_RESET, delay);
981 } else {
982 rval = ql_task_mgmt_iocb(ha,
983 tq, 0, CF_TARGET_RESET,
984 delay);
985 }
986
987 if (rval != QL_SUCCESS) {
988 break;
989 }
990 }
991
992 if (link != NULL) {
993 break;
994 }
995 }
996 tq = NULL;
997 } else {
998
999 if (CFG_IST(ha, CFG_FAST_TIMEOUT)) {
1000 rval = ql_task_mgmt_iocb(ha, tq, 0,
1001 CF_TARGET_RESET | CF_DO_NOT_SEND, delay);
1002 } else {
1003 rval = ql_task_mgmt_iocb(ha, tq, 0,
1004 CF_TARGET_RESET, delay);
1005 }
1006 }
1007 } else {
1008 /* queue = NULL, all targets. */
1009 if (tq == NULL) {
1010 mcp->mb[0] = MBC_RESET;
1011 mcp->mb[1] = delay;
1012 mcp->out_mb = MBX_1|MBX_0;
1013 } else {
1014 mcp->mb[0] = MBC_TARGET_RESET;
1015 if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
1016 mcp->mb[1] = tq->loop_id;
1017 } else {
1018 mcp->mb[1] = (uint16_t)(tq->loop_id << 8);
1019 }
1020 mcp->mb[2] = delay;
1021 mcp->out_mb = MBX_2|MBX_1|MBX_0;
1022 }
1023 mcp->in_mb = MBX_0;
1024 mcp->timeout = MAILBOX_TOV;
1025 rval = ql_mailbox_command(ha, mcp);
1026 }
1027
1028 tq == NULL ? (void) ql_marker(ha, 0, 0, MK_SYNC_ALL) :
1029 (void) ql_marker(ha, tq->loop_id, 0, MK_SYNC_ID);
1030
1031 if (rval != QL_SUCCESS) {
1032 EL(ha, "failed, rval = %xh\n", rval);
1033 } else {
1034 /*EMPTY*/
1035 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1036 }
1037
1038 return (rval);
1039 }
1040
1041 /*
1042 * ql_abort_target
1043 * Issue abort target mailbox command.
1044 *
1045 * Input:
1046 * ha: adapter state pointer.
1047 * tq: target queue pointer.
1048 * delay: in seconds.
1049 *
1050 * Returns:
1051 * ql local function return status code.
1052 *
1053 * Context:
1054 * Kernel context.
1055 */
1056 int
1057 ql_abort_target(ql_adapter_state_t *ha, ql_tgt_t *tq, uint16_t delay)
1058 {
1059 int rval;
1060 mbx_cmd_t mc = {0};
1061 mbx_cmd_t *mcp = &mc;
1062
1063 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
1064
1065 if (CFG_IST(ha, CFG_CTRL_24258081)) {
1066 rval = ql_task_mgmt_iocb(ha, tq, 0,
1067 CF_DO_NOT_SEND | CF_TARGET_RESET, delay);
1068 } else {
1069 mcp->mb[0] = MBC_ABORT_TARGET;
1070 /* Don't send Task Mgt */
1071 if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
1072 mcp->mb[1] = tq->loop_id;
1073 mcp->mb[10] = BIT_0;
1074 mcp->out_mb = MBX_10|MBX_2|MBX_1|MBX_0;
1075 } else {
1076 mcp->mb[1] = (uint16_t)(tq->loop_id << 8 | BIT_0);
1077 mcp->out_mb = MBX_2|MBX_1|MBX_0;
1078 }
1079 mcp->mb[2] = delay;
1080 mcp->in_mb = MBX_0;
1081 mcp->timeout = MAILBOX_TOV;
1082 rval = ql_mailbox_command(ha, mcp);
1083 }
1084
1085 (void) ql_marker(ha, tq->loop_id, 0, MK_SYNC_ID);
1086
1087 if (rval != QL_SUCCESS) {
1088 EL(ha, "failed=%xh, d_id=%xh\n", rval, tq->d_id.b24);
1089 } else {
1090 /*EMPTY*/
1091 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1092 }
1093 return (rval);
1094 }
1095
1096 /*
1097 * ql_lun_reset
1098 * Issue LUN reset task management mailbox command.
1099 *
1100 * Input:
1101 * ha: adapter state pointer.
1102 * tq: target queue pointer.
1103 * lun: LUN.
1104 *
1105 * Returns:
1106 * ql local function return status code.
1107 *
1108 * Context:
1109 * Kernel context.
1110 */
1111 int
1112 ql_lun_reset(ql_adapter_state_t *ha, ql_tgt_t *tq, uint16_t lun)
1113 {
1114 int rval;
1115 mbx_cmd_t mc = {0};
1116 mbx_cmd_t *mcp = &mc;
1117
1118 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
1119
1120 if (CFG_IST(ha, CFG_CTRL_24258081)) {
1121 rval = ql_task_mgmt_iocb(ha, tq, lun, CF_LUN_RESET, 0);
1122 } else {
1123 mcp->mb[0] = MBC_LUN_RESET;
1124 if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
1125 mcp->mb[1] = tq->loop_id;
1126 } else {
1127 mcp->mb[1] = (uint16_t)(tq->loop_id << 8);
1128 }
1129 mcp->mb[2] = lun;
1130 mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
1131 mcp->in_mb = MBX_0;
1132 mcp->timeout = MAILBOX_TOV;
1133 rval = ql_mailbox_command(ha, mcp);
1134 }
1135
1136 (void) ql_marker(ha, tq->loop_id, lun, MK_SYNC_ID);
1137
1138 if (rval != QL_SUCCESS) {
1139 EL(ha, "failed=%xh, d_id=%xh\n", rval, tq->d_id.b24);
1140 } else {
1141 /*EMPTY*/
1142 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1143 }
1144 return (rval);
1145 }
1146
1147 /*
1148 * ql_clear_task_set
1149 * Issue clear task set mailbox command.
1150 *
1151 * Input:
1152 * ha: adapter state pointer.
1153 * tq: target queue pointer.
1154 * lun: LUN.
1155 *
1156 * Returns:
1157 * ql local function return status code.
1158 *
1159 * Context:
1160 * Kernel context.
1161 */
1162 int
1163 ql_clear_task_set(ql_adapter_state_t *ha, ql_tgt_t *tq, uint16_t lun)
1164 {
1165 int rval;
1166 mbx_cmd_t mc = {0};
1167 mbx_cmd_t *mcp = &mc;
1168
1169 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
1170
1171 if (CFG_IST(ha, CFG_CTRL_24258081)) {
1172 rval = ql_task_mgmt_iocb(ha, tq, lun, CF_CLEAR_TASK_SET, 0);
1173 } else {
1174 mcp->mb[0] = MBC_CLEAR_TASK_SET;
1175 if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
1176 mcp->mb[1] = tq->loop_id;
1177 } else {
1178 mcp->mb[1] = (uint16_t)(tq->loop_id << 8);
1179 }
1180 mcp->mb[2] = lun;
1181 mcp->out_mb = MBX_2|MBX_1|MBX_0;
1182 mcp->in_mb = MBX_0;
1183 mcp->timeout = MAILBOX_TOV;
1184 rval = ql_mailbox_command(ha, mcp);
1185 }
1186
1187 (void) ql_marker(ha, tq->loop_id, lun, MK_SYNC_ID);
1188
1189 if (rval != QL_SUCCESS) {
1190 EL(ha, "failed=%xh, d_id=%xh\n", rval, tq->d_id.b24);
1191 } else {
1192 /*EMPTY*/
1193 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1194 }
1195
1196 return (rval);
1197 }
1198
1199 /*
1200 * ql_abort_task_set
1201 * Issue abort task set mailbox command.
1202 *
1203 * Input:
1204 * ha: adapter state pointer.
1205 * tq: target queue pointer.
1206 * lun: LUN.
1207 *
1208 * Returns:
1209 * ql local function return status code.
1210 *
1211 * Context:
1212 * Kernel context.
1213 */
1214 int
1215 ql_abort_task_set(ql_adapter_state_t *ha, ql_tgt_t *tq, uint16_t lun)
1216 {
1217 int rval;
1218 mbx_cmd_t mc = {0};
1219 mbx_cmd_t *mcp = &mc;
1220
1221 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
1222
1223 if (CFG_IST(ha, CFG_CTRL_24258081)) {
1224 rval = ql_task_mgmt_iocb(ha, tq, lun, CF_ABORT_TASK_SET, 0);
1225 } else {
1226 mcp->mb[0] = MBC_ABORT_TASK_SET;
1227 if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
1228 mcp->mb[1] = tq->loop_id;
1229 } else {
1230 mcp->mb[1] = (uint16_t)(tq->loop_id << 8);
1231 }
1232 mcp->mb[2] = lun;
1233 mcp->out_mb = MBX_2|MBX_1|MBX_0;
1234 mcp->in_mb = MBX_0;
1235 mcp->timeout = MAILBOX_TOV;
1236 rval = ql_mailbox_command(ha, mcp);
1237 }
1238
1239 (void) ql_marker(ha, tq->loop_id, lun, MK_SYNC_ID);
1240
1241 if (rval != QL_SUCCESS) {
1242 EL(ha, "failed=%xh, d_id=%xh\n", rval, tq->d_id.b24);
1243 } else {
1244 /*EMPTY*/
1245 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1246 }
1247
1248 return (rval);
1249 }
1250
1251 /*
1252 * ql_task_mgmt_iocb
1253 * Function issues task management IOCB.
1254 *
1255 * Input:
1256 * ha: adapter state pointer.
1257 * tq: target queue pointer.
1258 * lun: LUN.
1259 * flags: control flags.
1260 * delay: seconds.
1261 *
1262 * Returns:
1263 * ql local function return status code.
1264 *
1265 * Context:
1266 * Kernel context
1267 */
1268 static int
1269 ql_task_mgmt_iocb(ql_adapter_state_t *ha, ql_tgt_t *tq, uint16_t lun,
1270 uint32_t flags, uint16_t delay)
1271 {
1272 ql_mbx_iocb_t *pkt;
1273 int rval;
1274 uint32_t pkt_size;
1275
1276 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
1277
1278 pkt_size = sizeof (ql_mbx_iocb_t);
1279 pkt = kmem_zalloc(pkt_size, KM_SLEEP);
1280
1281 pkt->mgmt.entry_type = TASK_MGMT_TYPE;
1282 pkt->mgmt.entry_count = 1;
1283
1284 pkt->mgmt.n_port_hdl = (uint16_t)LE_16(tq->loop_id);
1285 pkt->mgmt.delay = (uint16_t)LE_16(delay);
1286 pkt->mgmt.timeout = LE_16(MAILBOX_TOV);
1287 pkt->mgmt.fcp_lun[2] = LSB(lun);
1288 pkt->mgmt.fcp_lun[3] = MSB(lun);
1289 pkt->mgmt.control_flags = LE_32(flags);
1290 pkt->mgmt.target_id[0] = tq->d_id.b.al_pa;
1291 pkt->mgmt.target_id[1] = tq->d_id.b.area;
1292 pkt->mgmt.target_id[2] = tq->d_id.b.domain;
1293 pkt->mgmt.vp_index = ha->vp_index;
1294
1295 rval = ql_issue_mbx_iocb(ha, (caddr_t)pkt, pkt_size);
1296 if (rval == QL_SUCCESS && (pkt->sts24.entry_status & 0x3c) != 0) {
1297 EL(ha, "failed, entry_status=%xh, d_id=%xh\n",
1298 pkt->sts24.entry_status, tq->d_id.b24);
1299 rval = QL_FUNCTION_PARAMETER_ERROR;
1300 }
1301
1302 LITTLE_ENDIAN_16(&pkt->sts24.comp_status);
1303
1304 if (rval == QL_SUCCESS && pkt->sts24.comp_status != CS_COMPLETE) {
1305 EL(ha, "failed, comp_status=%xh, d_id=%xh\n",
1306 pkt->sts24.comp_status, tq->d_id.b24);
1307 rval = QL_FUNCTION_FAILED;
1308 }
1309
1310 kmem_free(pkt, pkt_size);
1311
1312 if (rval != QL_SUCCESS) {
1313 EL(ha, "failed, rval = %xh\n", rval);
1314 } else {
1315 /*EMPTY*/
1316 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1317 }
1318
1319 return (rval);
1320 }
1321
1322 /*
1323 * ql_loop_port_bypass
1324 * Issue loop port bypass mailbox command.
1325 *
1326 * Input:
1327 * ha: adapter state pointer.
1328 * tq: target queue pointer.
1329 *
1330 * Returns:
1331 * ql local function return status code.
1332 *
1333 * Context:
1334 * Kernel context.
1335 */
1336 int
1337 ql_loop_port_bypass(ql_adapter_state_t *ha, ql_tgt_t *tq)
1338 {
1339 int rval;
1340 mbx_cmd_t mc = {0};
1341 mbx_cmd_t *mcp = &mc;
1342
1343 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
1344
1345 mcp->mb[0] = MBC_LOOP_PORT_BYPASS;
1346
1347 if (CFG_IST(ha, CFG_CTRL_24258081)) {
1348 mcp->mb[1] = tq->d_id.b.al_pa;
1349 } else if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
1350 mcp->mb[1] = tq->loop_id;
1351 } else {
1352 mcp->mb[1] = (uint16_t)(tq->loop_id << 8);
1353 }
1354
1355 mcp->out_mb = MBX_1|MBX_0;
1356 mcp->in_mb = MBX_0;
1357 mcp->timeout = MAILBOX_TOV;
1358 rval = ql_mailbox_command(ha, mcp);
1359
1360 if (rval != QL_SUCCESS) {
1361 EL(ha, "failed=%xh, d_id=%xh\n", rval, tq->d_id.b24);
1362 } else {
1363 /*EMPTY*/
1364 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1365 }
1366
1367 return (rval);
1368 }
1369
1370 /*
1371 * ql_loop_port_enable
1372 * Issue loop port enable mailbox command.
1373 *
1374 * Input:
1375 * ha: adapter state pointer.
1376 * tq: target queue pointer.
1377 *
1378 * Returns:
1379 * ql local function return status code.
1380 *
1381 * Context:
1382 * Kernel context.
1383 */
1384 int
1385 ql_loop_port_enable(ql_adapter_state_t *ha, ql_tgt_t *tq)
1386 {
1387 int rval;
1388 mbx_cmd_t mc = {0};
1389 mbx_cmd_t *mcp = &mc;
1390
1391 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
1392
1393 mcp->mb[0] = MBC_LOOP_PORT_ENABLE;
1394
1395 if (CFG_IST(ha, CFG_CTRL_24258081)) {
1396 mcp->mb[1] = tq->d_id.b.al_pa;
1397 } else if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
1398 mcp->mb[1] = tq->loop_id;
1399 } else {
1400 mcp->mb[1] = (uint16_t)(tq->loop_id << 8);
1401 }
1402 mcp->out_mb = MBX_1|MBX_0;
1403 mcp->in_mb = MBX_0;
1404 mcp->timeout = MAILBOX_TOV;
1405 rval = ql_mailbox_command(ha, mcp);
1406
1407 if (rval != QL_SUCCESS) {
1408 EL(ha, "failed=%xh, d_id=%xh\n", rval, tq->d_id.b24);
1409 } else {
1410 /*EMPTY*/
1411 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1412 }
1413
1414 return (rval);
1415 }
1416
1417 /*
1418 * ql_login_lport
1419 * Issue login loop port mailbox command.
1420 *
1421 * Input:
1422 * ha: adapter state pointer.
1423 * tq: target queue pointer.
1424 * loop_id: FC loop id.
1425 * opt: options.
1426 * LLF_NONE, LLF_PLOGI
1427 *
1428 * Returns:
1429 * ql local function return status code.
1430 *
1431 * Context:
1432 * Kernel context.
1433 */
1434 int
1435 ql_login_lport(ql_adapter_state_t *ha, ql_tgt_t *tq, uint16_t loop_id,
1436 uint16_t opt)
1437 {
1438 int rval;
1439 uint16_t flags;
1440 ql_mbx_data_t mr;
1441 mbx_cmd_t mc = {0};
1442 mbx_cmd_t *mcp = &mc;
1443
1444 QL_PRINT_3(CE_CONT, "(%d): started, d_id=%xh, loop_id=%xh\n",
1445 ha->instance, tq->d_id.b24, loop_id);
1446
1447 if (CFG_IST(ha, CFG_CTRL_24258081)) {
1448 flags = CF_CMD_PLOGI;
1449 if ((opt & LLF_PLOGI) == 0) {
1450 flags = (uint16_t)(flags | CFO_COND_PLOGI);
1451 }
1452 rval = ql_log_iocb(ha, tq, loop_id, flags, &mr);
1453 } else {
1454 mcp->mb[0] = MBC_LOGIN_LOOP_PORT;
1455 if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
1456 mcp->mb[1] = loop_id;
1457 } else {
1458 mcp->mb[1] = (uint16_t)(loop_id << 8);
1459 }
1460 mcp->mb[2] = opt;
1461 mcp->out_mb = MBX_2|MBX_1|MBX_0;
1462 mcp->in_mb = MBX_0;
1463 mcp->timeout = MAILBOX_TOV;
1464 rval = ql_mailbox_command(ha, mcp);
1465 }
1466
1467 if (rval != QL_SUCCESS) {
1468 EL(ha, "d_id=%xh, loop_id=%xh, failed=%xh\n", tq->d_id.b24,
1469 loop_id, rval);
1470 } else {
1471 /*EMPTY*/
1472 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1473 }
1474
1475 return (rval);
1476 }
1477
1478 /*
1479 * ql_login_fport
1480 * Issue login fabric port mailbox command.
1481 *
1482 * Input:
1483 * ha: adapter state pointer.
1484 * tq: target queue pointer.
1485 * loop_id: FC loop id.
1486 * opt: options.
1487 * LFF_NONE, LFF_NO_PLOGI, LFF_NO_PRLI
1488 * mr: pointer for mailbox data.
1489 *
1490 * Returns:
1491 * ql local function return status code.
1492 *
1493 * Context:
1494 * Kernel context.
1495 */
1496 int
1497 ql_login_fport(ql_adapter_state_t *ha, ql_tgt_t *tq, uint16_t loop_id,
1498 uint16_t opt, ql_mbx_data_t *mr)
1499 {
1500 int rval;
1501 uint16_t flags;
1502 mbx_cmd_t mc = {0};
1503 mbx_cmd_t *mcp = &mc;
1504
1505 QL_PRINT_3(CE_CONT, "(%d): started, d_id=%xh, loop_id=%xh\n",
1506 ha->instance, tq->d_id.b24, loop_id);
1507
1508 if ((tq->d_id.b24 & 0xffffff) == 0xfffffa) {
1509 opt = (uint16_t)(opt | LFF_NO_PRLI);
1510 }
1511
1512 if (CFG_IST(ha, CFG_CTRL_24258081)) {
1513 flags = CF_CMD_PLOGI;
1514 if (opt & LFF_NO_PLOGI) {
1515 flags = (uint16_t)(flags | CFO_COND_PLOGI);
1516 }
1517 if (opt & LFF_NO_PRLI) {
1518 flags = (uint16_t)(flags | CFO_SKIP_PRLI);
1519 }
1520 rval = ql_log_iocb(ha, tq, loop_id, flags, mr);
1521 } else {
1522 mcp->mb[0] = MBC_LOGIN_FABRIC_PORT;
1523 if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
1524 mcp->mb[1] = loop_id;
1525 mcp->mb[10] = opt;
1526 mcp->out_mb = MBX_10|MBX_3|MBX_2|MBX_1|MBX_0;
1527 } else {
1528 mcp->mb[1] = (uint16_t)(loop_id << 8 | opt);
1529 mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
1530 }
1531 mcp->mb[2] = MSW(tq->d_id.b24);
1532 mcp->mb[3] = LSW(tq->d_id.b24);
1533 mcp->in_mb = MBX_7|MBX_6|MBX_2|MBX_1|MBX_0;
1534 mcp->timeout = MAILBOX_TOV;
1535 rval = ql_mailbox_command(ha, mcp);
1536
1537 /* Return mailbox data. */
1538 if (mr != NULL) {
1539 mr->mb[0] = mcp->mb[0];
1540 mr->mb[1] = mcp->mb[1];
1541 mr->mb[2] = mcp->mb[2];
1542 mr->mb[6] = mcp->mb[6];
1543 mr->mb[7] = mcp->mb[7];
1544 }
1545 }
1546
1547 if (rval != QL_SUCCESS) {
1548 EL(ha, "d_id=%xh, loop_id=%xh, failed=%xh, mb1=%02xh, "
1549 "mb2=%04x\n", tq->d_id.b24, loop_id, rval, mr->mb[1],
1550 mr->mb[2]);
1551 } else {
1552 /*EMPTY*/
1553 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1554 }
1555
1556 return (rval);
1557 }
1558
1559 /*
1560 * ql_logout_fabric_port
1561 * Issue logout fabric port mailbox command.
1562 *
1563 * Input:
1564 * ha: adapter state pointer.
1565 * tq: target queue pointer.
1566 *
1567 * Returns:
1568 * ql local function return status code.
1569 *
1570 * Context:
1571 * Kernel context.
1572 */
1573 int
1574 ql_logout_fabric_port(ql_adapter_state_t *ha, ql_tgt_t *tq)
1575 {
1576 int rval;
1577 uint16_t flag;
1578 ql_mbx_data_t mr;
1579 mbx_cmd_t mc = {0};
1580 mbx_cmd_t *mcp = &mc;
1581
1582 QL_PRINT_3(CE_CONT, "(%d): started, loop_id=%xh d_id=%xh\n",
1583 ha->instance, tq->loop_id, tq->d_id.b24);
1584
1585 if (CFG_IST(ha, CFG_CTRL_24258081)) {
1586 flag = (uint16_t)(RESERVED_LOOP_ID(ha, tq->loop_id) ?
1587 CFO_EXPLICIT_LOGO |CF_CMD_LOGO | CFO_FREE_N_PORT_HANDLE :
1588 CFO_IMPLICIT_LOGO |CF_CMD_LOGO | CFO_FREE_N_PORT_HANDLE);
1589 rval = ql_log_iocb(ha, tq, tq->loop_id, flag, &mr);
1590 } else {
1591 flag = (uint16_t)(RESERVED_LOOP_ID(ha, tq->loop_id) ? 1 : 0);
1592 mcp->mb[0] = MBC_LOGOUT_FABRIC_PORT;
1593 if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
1594 mcp->mb[1] = tq->loop_id;
1595 mcp->mb[10] = flag;
1596 mcp->out_mb = MBX_10|MBX_1|MBX_0;
1597 } else {
1598 mcp->mb[1] = (uint16_t)(tq->loop_id << 8 | flag);
1599 mcp->out_mb = MBX_1|MBX_0;
1600 }
1601 mcp->in_mb = MBX_0;
1602 mcp->timeout = MAILBOX_TOV;
1603 rval = ql_mailbox_command(ha, mcp);
1604 }
1605
1606 if (rval != QL_SUCCESS) {
1607 EL(ha, "d_id=%xh, loop_id=%xh, failed=%xh\n", rval,
1608 tq->d_id.b24, tq->loop_id);
1609 } else {
1610 /*EMPTY*/
1611 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1612 }
1613
1614 return (rval);
1615 }
1616
1617 /*
1618 * ql_log_iocb
1619 * Function issues login/logout IOCB.
1620 *
1621 * Input:
1622 * ha: adapter state pointer.
1623 * tq: target queue pointer.
1624 * loop_id: FC Loop ID.
1625 * flags: control flags.
1626 * mr: pointer for mailbox data.
1627 *
1628 * Returns:
1629 * ql local function return status code.
1630 *
1631 * Context:
1632 * Kernel context.
1633 */
1634 int
1635 ql_log_iocb(ql_adapter_state_t *ha, ql_tgt_t *tq, uint16_t loop_id,
1636 uint16_t flags, ql_mbx_data_t *mr)
1637 {
1638 ql_mbx_iocb_t *pkt;
1639 int rval;
1640 uint32_t pkt_size;
1641
1642 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
1643
1644 pkt_size = sizeof (ql_mbx_iocb_t);
1645 pkt = kmem_zalloc(pkt_size, KM_SLEEP);
1646
1647 pkt->log.entry_type = LOG_TYPE;
1648 pkt->log.entry_count = 1;
1649 pkt->log.n_port_hdl = (uint16_t)LE_16(loop_id);
1650 pkt->log.control_flags = (uint16_t)LE_16(flags);
1651 pkt->log.port_id[0] = tq->d_id.b.al_pa;
1652 pkt->log.port_id[1] = tq->d_id.b.area;
1653 pkt->log.port_id[2] = tq->d_id.b.domain;
1654 pkt->log.vp_index = ha->vp_index;
1655
1656 rval = ql_issue_mbx_iocb(ha, (caddr_t)pkt, pkt_size);
1657 if (rval == QL_SUCCESS && (pkt->log.entry_status & 0x3c) != 0) {
1658 EL(ha, "failed, entry_status=%xh, d_id=%xh\n",
1659 pkt->log.entry_status, tq->d_id.b24);
1660 rval = QL_FUNCTION_PARAMETER_ERROR;
1661 }
1662
1663 if (rval == QL_SUCCESS) {
1664 if (pkt->log.rsp_size == 0xB) {
1665 LITTLE_ENDIAN_32(&pkt->log.io_param[5]);
1666 tq->cmn_features = MSW(pkt->log.io_param[5]);
1667 LITTLE_ENDIAN_32(&pkt->log.io_param[6]);
1668 tq->conc_sequences = MSW(pkt->log.io_param[6]);
1669 tq->relative_offset = LSW(pkt->log.io_param[6]);
1670 LITTLE_ENDIAN_32(&pkt->log.io_param[9]);
1671 tq->class3_recipient_ctl = MSW(pkt->log.io_param[9]);
1672 tq->class3_conc_sequences = LSW(pkt->log.io_param[9]);
1673 LITTLE_ENDIAN_32(&pkt->log.io_param[10]);
1674 tq->class3_open_sequences_per_exch =
1675 MSW(pkt->log.io_param[10]);
1676 tq->prli_payload_length = 0x14;
1677 }
1678 if (mr != NULL) {
1679 LITTLE_ENDIAN_16(&pkt->log.status);
1680 LITTLE_ENDIAN_32(&pkt->log.io_param[0]);
1681 LITTLE_ENDIAN_32(&pkt->log.io_param[1]);
1682
1683 if (pkt->log.status != CS_COMPLETE) {
1684 EL(ha, "failed, status=%xh, iop0=%xh, iop1="
1685 "%xh\n", pkt->log.status,
1686 pkt->log.io_param[0],
1687 pkt->log.io_param[1]);
1688
1689 switch (pkt->log.io_param[0]) {
1690 case CS0_NO_LINK:
1691 case CS0_FIRMWARE_NOT_READY:
1692 mr->mb[0] = MBS_COMMAND_ERROR;
1693 mr->mb[1] = 1;
1694 break;
1695 case CS0_NO_IOCB:
1696 case CS0_NO_PCB_ALLOCATED:
1697 mr->mb[0] = MBS_COMMAND_ERROR;
1698 mr->mb[1] = 2;
1699 break;
1700 case CS0_NO_EXCH_CTRL_BLK:
1701 mr->mb[0] = MBS_COMMAND_ERROR;
1702 mr->mb[1] = 3;
1703 break;
1704 case CS0_COMMAND_FAILED:
1705 mr->mb[0] = MBS_COMMAND_ERROR;
1706 mr->mb[1] = 4;
1707 switch (LSB(pkt->log.io_param[1])) {
1708 case CS1_PLOGI_RESPONSE_FAILED:
1709 mr->mb[2] = 3;
1710 break;
1711 case CS1_PRLI_FAILED:
1712 mr->mb[2] = 4;
1713 break;
1714 case CS1_PRLI_RESPONSE_FAILED:
1715 mr->mb[2] = 5;
1716 break;
1717 case CS1_COMMAND_LOGGED_OUT:
1718 mr->mb[2] = 7;
1719 break;
1720 case CS1_PLOGI_FAILED:
1721 default:
1722 EL(ha, "log iop1 = %xh\n",
1723 LSB(pkt->log.io_param[1]))
1724 mr->mb[2] = 2;
1725 break;
1726 }
1727 break;
1728 case CS0_PORT_NOT_LOGGED_IN:
1729 mr->mb[0] = MBS_COMMAND_ERROR;
1730 mr->mb[1] = 4;
1731 mr->mb[2] = 7;
1732 break;
1733 case CS0_NO_FLOGI_ACC:
1734 case CS0_NO_FABRIC_PRESENT:
1735 mr->mb[0] = MBS_COMMAND_ERROR;
1736 mr->mb[1] = 5;
1737 break;
1738 case CS0_ELS_REJECT_RECEIVED:
1739 mr->mb[0] = MBS_COMMAND_ERROR;
1740 mr->mb[1] = 0xd;
1741 break;
1742 case CS0_PORT_ID_USED:
1743 mr->mb[0] = MBS_PORT_ID_USED;
1744 mr->mb[1] = LSW(pkt->log.io_param[1]);
1745 break;
1746 case CS0_N_PORT_HANDLE_USED:
1747 mr->mb[0] = MBS_LOOP_ID_USED;
1748 mr->mb[1] = MSW(pkt->log.io_param[1]);
1749 mr->mb[2] = LSW(pkt->log.io_param[1]);
1750 break;
1751 case CS0_NO_N_PORT_HANDLE_AVAILABLE:
1752 mr->mb[0] = MBS_ALL_IDS_IN_USE;
1753 break;
1754 case CS0_CMD_PARAMETER_ERROR:
1755 default:
1756 EL(ha, "pkt->log iop[0]=%xh\n",
1757 pkt->log.io_param[0]);
1758 mr->mb[0] =
1759 MBS_COMMAND_PARAMETER_ERROR;
1760 break;
1761 }
1762 } else {
1763 QL_PRINT_3(CE_CONT, "(%d): status=%xh\n",
1764 ha->instance, pkt->log.status);
1765
1766 mr->mb[0] = MBS_COMMAND_COMPLETE;
1767 mr->mb[1] = (uint16_t)
1768 (pkt->log.io_param[0] & BIT_4 ? 0 : BIT_0);
1769 if (pkt->log.io_param[0] & BIT_8) {
1770 mr->mb[1] = (uint16_t)
1771 (mr->mb[1] | BIT_1);
1772 }
1773 }
1774 rval = mr->mb[0];
1775 }
1776
1777 }
1778
1779 kmem_free(pkt, pkt_size);
1780
1781 if (rval != QL_SUCCESS) {
1782 EL(ha, "failed=%xh, d_id=%xh\n", rval, tq->d_id.b24);
1783 } else {
1784 /*EMPTY*/
1785 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1786 }
1787
1788 return (rval);
1789 }
1790
1791 /*
1792 * ql_get_port_database
1793 * Issue get port database mailbox command
1794 * and copy context to device queue.
1795 *
1796 * Input:
1797 * ha: adapter state pointer.
1798 * tq: target queue pointer.
1799 * opt: options.
1800 * PDF_NONE, PDF_PLOGI, PDF_ADISC
1801 * Returns:
1802 * ql local function return status code.
1803 *
1804 * Context:
1805 * Kernel context.
1806 */
1807 int
1808 ql_get_port_database(ql_adapter_state_t *ha, ql_tgt_t *tq, uint8_t opt)
1809 {
1810 int rval;
1811 dma_mem_t mem_desc;
1812 mbx_cmd_t mc = {0};
1813 mbx_cmd_t *mcp = &mc;
1814 port_database_23_t *pd23;
1815
1816 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
1817
1818 pd23 = (port_database_23_t *)kmem_zalloc(PORT_DATABASE_SIZE, KM_SLEEP);
1819 if (pd23 == NULL) {
1820 rval = QL_MEMORY_ALLOC_FAILED;
1821 EL(ha, "failed, rval = %xh\n", rval);
1822 return (rval);
1823 }
1824
1825 if ((rval = ql_setup_mbox_dma_resources(ha, &mem_desc,
1826 PORT_DATABASE_SIZE)) != QL_SUCCESS) {
1827 return (QL_MEMORY_ALLOC_FAILED);
1828 }
1829
1830 if (CFG_IST(ha, CFG_CTRL_24258081)) {
1831 mcp->mb[0] = MBC_GET_PORT_DATABASE;
1832 mcp->mb[1] = tq->loop_id;
1833 mcp->mb[4] = CHAR_TO_SHORT(tq->d_id.b.al_pa, tq->d_id.b.area);
1834 mcp->mb[5] = (uint16_t)tq->d_id.b.domain;
1835 mcp->mb[9] = ha->vp_index;
1836 mcp->mb[10] = (uint16_t)(opt | PDF_ADISC);
1837 mcp->out_mb = MBX_10|MBX_9|MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|
1838 MBX_2|MBX_1|MBX_0;
1839 } else {
1840 mcp->mb[0] = (uint16_t)(opt == PDF_NONE ?
1841 MBC_GET_PORT_DATABASE : MBC_ENHANCED_GET_PORT_DATABASE);
1842 if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
1843 mcp->mb[1] = tq->loop_id;
1844 mcp->mb[10] = opt;
1845 mcp->out_mb = MBX_10|MBX_7|MBX_6|MBX_3|
1846 MBX_2|MBX_1|MBX_0;
1847 } else {
1848 mcp->mb[1] = (uint16_t)(tq->loop_id << 8 | opt);
1849 mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
1850 }
1851 }
1852
1853 mcp->mb[2] = MSW(LSD(mem_desc.cookie.dmac_laddress));
1854 mcp->mb[3] = LSW(LSD(mem_desc.cookie.dmac_laddress));
1855 mcp->mb[6] = MSW(MSD(mem_desc.cookie.dmac_laddress));
1856 mcp->mb[7] = LSW(MSD(mem_desc.cookie.dmac_laddress));
1857 mcp->in_mb = MBX_0;
1858 mcp->timeout = MAILBOX_TOV;
1859 rval = ql_mailbox_command(ha, mcp);
1860
1861 if (rval == QL_SUCCESS) {
1862 ql_get_mbox_dma_data(&mem_desc, (caddr_t)pd23);
1863 }
1864
1865 ql_free_dma_resource(ha, &mem_desc);
1866
1867 if (rval == QL_SUCCESS) {
1868 if (CFG_IST(ha, CFG_CTRL_24258081)) {
1869 port_database_24_t *pd24 = (port_database_24_t *)pd23;
1870
1871 tq->master_state = pd24->current_login_state;
1872 tq->slave_state = pd24->last_stable_login_state;
1873 if (PD_PORT_LOGIN(tq)) {
1874 /* Names are big endian. */
1875 bcopy((void *)&pd24->port_name[0],
1876 (void *)&tq->port_name[0], 8);
1877 bcopy((void *)&pd24->node_name[0],
1878 (void *)&tq->node_name[0], 8);
1879 tq->hard_addr.b.al_pa = pd24->hard_address[2];
1880 tq->hard_addr.b.area = pd24->hard_address[1];
1881 tq->hard_addr.b.domain = pd24->hard_address[0];
1882 tq->class3_rcv_data_size =
1883 pd24->receive_data_size;
1884 LITTLE_ENDIAN_16(&tq->class3_rcv_data_size);
1885 tq->prli_svc_param_word_0 =
1886 pd24->PRLI_service_parameter_word_0;
1887 LITTLE_ENDIAN_16(&tq->prli_svc_param_word_0);
1888 tq->prli_svc_param_word_3 =
1889 pd24->PRLI_service_parameter_word_3;
1890 LITTLE_ENDIAN_16(&tq->prli_svc_param_word_3);
1891 }
1892 } else {
1893 tq->master_state = pd23->master_state;
1894 tq->slave_state = pd23->slave_state;
1895 if (PD_PORT_LOGIN(tq)) {
1896 /* Names are big endian. */
1897 bcopy((void *)&pd23->port_name[0],
1898 (void *)&tq->port_name[0], 8);
1899 bcopy((void *)&pd23->node_name[0],
1900 (void *)&tq->node_name[0], 8);
1901 tq->hard_addr.b.al_pa = pd23->hard_address[2];
1902 tq->hard_addr.b.area = pd23->hard_address[1];
1903 tq->hard_addr.b.domain = pd23->hard_address[0];
1904 tq->cmn_features = pd23->common_features;
1905 LITTLE_ENDIAN_16(&tq->cmn_features);
1906 tq->conc_sequences =
1907 pd23->total_concurrent_sequences;
1908 LITTLE_ENDIAN_16(&tq->conc_sequences);
1909 tq->relative_offset =
1910 pd23->RO_by_information_category;
1911 LITTLE_ENDIAN_16(&tq->relative_offset);
1912 tq->class3_recipient_ctl = pd23->recipient;
1913 LITTLE_ENDIAN_16(&tq->class3_recipient_ctl);
1914 tq->class3_rcv_data_size =
1915 pd23->receive_data_size;
1916 LITTLE_ENDIAN_16(&tq->class3_rcv_data_size);
1917 tq->class3_conc_sequences =
1918 pd23->concurrent_sequences;
1919 LITTLE_ENDIAN_16(&tq->class3_conc_sequences);
1920 tq->class3_open_sequences_per_exch =
1921 pd23->open_sequences_per_exchange;
1922 LITTLE_ENDIAN_16(
1923 &tq->class3_open_sequences_per_exch);
1924 tq->prli_payload_length =
1925 pd23->PRLI_payload_length;
1926 LITTLE_ENDIAN_16(&tq->prli_payload_length);
1927 tq->prli_svc_param_word_0 =
1928 pd23->PRLI_service_parameter_word_0;
1929 LITTLE_ENDIAN_16(&tq->prli_svc_param_word_0);
1930 tq->prli_svc_param_word_3 =
1931 pd23->PRLI_service_parameter_word_3;
1932 LITTLE_ENDIAN_16(&tq->prli_svc_param_word_3);
1933 }
1934 }
1935
1936 if (!PD_PORT_LOGIN(tq)) {
1937 EL(ha, "d_id=%xh, loop_id=%xh, not logged in "
1938 "master=%xh, slave=%xh\n", tq->d_id.b24,
1939 tq->loop_id, tq->master_state, tq->slave_state);
1940 rval = QL_NOT_LOGGED_IN;
1941 } else {
1942 tq->flags = tq->prli_svc_param_word_3 &
1943 PRLI_W3_TARGET_FUNCTION ?
1944 tq->flags & ~TQF_INITIATOR_DEVICE :
1945 tq->flags | TQF_INITIATOR_DEVICE;
1946
1947 if ((tq->flags & TQF_INITIATOR_DEVICE) == 0) {
1948 tq->flags = tq->prli_svc_param_word_3 &
1949 PRLI_W3_RETRY ?
1950 tq->flags | TQF_TAPE_DEVICE :
1951 tq->flags & ~TQF_TAPE_DEVICE;
1952 } else {
1953 tq->flags &= ~TQF_TAPE_DEVICE;
1954 }
1955 }
1956 }
1957
1958 kmem_free(pd23, PORT_DATABASE_SIZE);
1959
1960 if ((rval != QL_SUCCESS) && (rval != QL_PARAMETER_ERROR)) {
1961 EL(ha, "d_id=%xh, loop_id=%xh, failed=%xh\n", tq->d_id.b24,
1962 tq->loop_id, rval);
1963 } else {
1964 /*EMPTY*/
1965 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1966 }
1967
1968 return (rval);
1969 }
1970
1971 /*
1972 * ql_get_loop_position_map
1973 * Issue get loop position map mailbox command.
1974 *
1975 * Input:
1976 * ha: adapter state pointer.
1977 * size: size of data buffer.
1978 * bufp: data pointer for DMA data.
1979 *
1980 * Returns:
1981 * ql local function return status code.
1982 *
1983 * Context:
1984 * Kernel context.
1985 */
1986 int
1987 ql_get_loop_position_map(ql_adapter_state_t *ha, size_t size, caddr_t bufp)
1988 {
1989 int rval;
1990 dma_mem_t mem_desc;
1991 mbx_cmd_t mc = {0};
1992 mbx_cmd_t *mcp = &mc;
1993
1994 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
1995
1996 if ((rval = ql_setup_mbox_dma_resources(ha, &mem_desc,
1997 (uint32_t)size)) != QL_SUCCESS) {
1998 EL(ha, "setup_mbox_dma_resources failed: %xh\n", rval);
1999 return (QL_MEMORY_ALLOC_FAILED);
2000 }
2001
2002 mcp->mb[0] = MBC_GET_FC_AL_POSITION_MAP;
2003 mcp->mb[2] = MSW(LSD(mem_desc.cookie.dmac_laddress));
2004 mcp->mb[3] = LSW(LSD(mem_desc.cookie.dmac_laddress));
2005 mcp->mb[6] = MSW(MSD(mem_desc.cookie.dmac_laddress));
2006 mcp->mb[7] = LSW(MSD(mem_desc.cookie.dmac_laddress));
2007 mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_0;
2008 mcp->in_mb = MBX_1|MBX_0;
2009 mcp->timeout = MAILBOX_TOV;
2010 rval = ql_mailbox_command(ha, mcp);
2011
2012 if (rval == QL_SUCCESS) {
2013 ql_get_mbox_dma_data(&mem_desc, bufp);
2014 }
2015
2016 ql_free_dma_resource(ha, &mem_desc);
2017
2018 if (rval != QL_SUCCESS) {
2019 EL(ha, "failed=%xh\n", rval);
2020 } else {
2021 /*EMPTY*/
2022 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2023 }
2024
2025 return (rval);
2026 }
2027
2028 /*
2029 * ql_set_rnid_params
2030 * Issue set RNID parameters mailbox command.
2031 *
2032 * Input:
2033 * ha: adapter state pointer.
2034 * size: size of data buffer.
2035 * bufp: data pointer for DMA data.
2036 *
2037 * Returns:
2038 * ql local function return status code.
2039 *
2040 * Context:
2041 * Kernel context.
2042 */
2043 int
2044 ql_set_rnid_params(ql_adapter_state_t *ha, size_t size, caddr_t bufp)
2045 {
2046 int rval;
2047 dma_mem_t mem_desc;
2048 mbx_cmd_t mc = {0};
2049 mbx_cmd_t *mcp = &mc;
2050
2051 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2052
2053 if ((rval = ql_setup_mbox_dma_transfer(ha, &mem_desc, bufp,
2054 (uint32_t)size)) != QL_SUCCESS) {
2055 EL(ha, "failed, setup_mbox_dma_transfer: %x\n", rval);
2056 return (rval);
2057 }
2058
2059 mcp->mb[0] = MBC_SET_PARAMETERS;
2060 mcp->mb[2] = MSW(LSD(mem_desc.cookie.dmac_laddress));
2061 mcp->mb[3] = LSW(LSD(mem_desc.cookie.dmac_laddress));
2062 mcp->mb[6] = MSW(MSD(mem_desc.cookie.dmac_laddress));
2063 mcp->mb[7] = LSW(MSD(mem_desc.cookie.dmac_laddress));
2064 mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
2065 mcp->in_mb = MBX_0;
2066 mcp->timeout = MAILBOX_TOV;
2067 rval = ql_mailbox_command(ha, mcp);
2068
2069 ql_free_dma_resource(ha, &mem_desc);
2070
2071 if (rval != QL_SUCCESS) {
2072 EL(ha, "failed, rval = %xh\n", rval);
2073 } else {
2074 /*EMPTY*/
2075 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2076 }
2077
2078 return (rval);
2079 }
2080
2081 /*
2082 * ql_send_rnid_els
2083 * Issue a send node identfication data mailbox command.
2084 *
2085 * Input:
2086 * ha: adapter state pointer.
2087 * loop_id: FC loop id.
2088 * opt: options.
2089 * size: size of data buffer.
2090 * bufp: data pointer for DMA data.
2091 *
2092 * Returns:
2093 * ql local function return status code.
2094 *
2095 * Context:
2096 * Kernel context.
2097 */
2098 int
2099 ql_send_rnid_els(ql_adapter_state_t *ha, uint16_t loop_id, uint8_t opt,
2100 size_t size, caddr_t bufp)
2101 {
2102 int rval;
2103 dma_mem_t mem_desc;
2104 mbx_cmd_t mc = {0};
2105 mbx_cmd_t *mcp = &mc;
2106
2107 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2108
2109 if ((rval = ql_setup_mbox_dma_resources(ha, &mem_desc,
2110 (uint32_t)size)) != QL_SUCCESS) {
2111 return (QL_MEMORY_ALLOC_FAILED);
2112 }
2113
2114 mcp->mb[0] = MBC_SEND_RNID_ELS;
2115 if (CFG_IST(ha, CFG_CTRL_24258081)) {
2116 mcp->mb[1] = loop_id;
2117 mcp->mb[9] = ha->vp_index;
2118 mcp->mb[10] = opt;
2119 mcp->out_mb = MBX_10|MBX_9|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
2120 } else if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
2121 mcp->mb[1] = loop_id;
2122 mcp->mb[10] = opt;
2123 mcp->out_mb = MBX_10|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
2124 } else {
2125 mcp->mb[1] = (uint16_t)(loop_id << 8 | opt);
2126 mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
2127 }
2128 mcp->mb[2] = MSW(LSD(mem_desc.cookie.dmac_laddress));
2129 mcp->mb[3] = LSW(LSD(mem_desc.cookie.dmac_laddress));
2130 mcp->mb[6] = MSW(MSD(mem_desc.cookie.dmac_laddress));
2131 mcp->mb[7] = LSW(MSD(mem_desc.cookie.dmac_laddress));
2132 mcp->in_mb = MBX_0;
2133 mcp->timeout = MAILBOX_TOV;
2134 rval = ql_mailbox_command(ha, mcp);
2135
2136 if (rval == QL_SUCCESS) {
2137 ql_get_mbox_dma_data(&mem_desc, bufp);
2138 }
2139
2140 ql_free_dma_resource(ha, &mem_desc);
2141
2142 if (rval != QL_SUCCESS) {
2143 EL(ha, "failed, rval = %xh\n", rval);
2144 } else {
2145 /*EMPTY*/
2146 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2147 }
2148
2149 return (rval);
2150 }
2151
2152 /*
2153 * ql_get_rnid_params
2154 * Issue get RNID parameters mailbox command.
2155 *
2156 * Input:
2157 * ha: adapter state pointer.
2158 * size: size of data buffer.
2159 * bufp: data pointer for DMA data.
2160 *
2161 * Returns:
2162 * ql local function return status code.
2163 *
2164 * Context:
2165 * Kernel context.
2166 */
2167 int
2168 ql_get_rnid_params(ql_adapter_state_t *ha, size_t size, caddr_t bufp)
2169 {
2170 int rval;
2171 dma_mem_t mem_desc;
2172 mbx_cmd_t mc = {0};
2173 mbx_cmd_t *mcp = &mc;
2174
2175 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2176
2177 if ((rval = ql_setup_mbox_dma_resources(ha, &mem_desc,
2178 (uint32_t)size)) != QL_SUCCESS) {
2179 return (QL_MEMORY_ALLOC_FAILED);
2180 }
2181
2182 mcp->mb[0] = MBC_GET_PARAMETERS;
2183 mcp->mb[2] = MSW(LSD(mem_desc.cookie.dmac_laddress));
2184 mcp->mb[3] = LSW(LSD(mem_desc.cookie.dmac_laddress));
2185 mcp->mb[6] = MSW(MSD(mem_desc.cookie.dmac_laddress));
2186 mcp->mb[7] = LSW(MSD(mem_desc.cookie.dmac_laddress));
2187 mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
2188 mcp->in_mb = MBX_0;
2189 mcp->timeout = MAILBOX_TOV;
2190 rval = ql_mailbox_command(ha, mcp);
2191
2192 if (rval == QL_SUCCESS) {
2193 ql_get_mbox_dma_data(&mem_desc, bufp);
2194 }
2195
2196 ql_free_dma_resource(ha, &mem_desc);
2197
2198 if (rval != QL_SUCCESS) {
2199 EL(ha, "failed=%xh\n", rval);
2200 } else {
2201 /*EMPTY*/
2202 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2203 }
2204
2205 return (rval);
2206 }
2207
2208 /*
2209 * ql_get_link_status
2210 * Issue get link status mailbox command.
2211 *
2212 * Input:
2213 * ha: adapter state pointer.
2214 * loop_id: FC loop id or n_port_hdl.
2215 * size: size of data buffer.
2216 * bufp: data pointer for DMA data.
2217 * port_no: port number to query.
2218 *
2219 * Returns:
2220 * ql local function return status code.
2221 *
2222 * Context:
2223 * Kernel context.
2224 */
2225 int
2226 ql_get_link_status(ql_adapter_state_t *ha, uint16_t loop_id, size_t size,
2227 caddr_t bufp, uint8_t port_no)
2228 {
2229 dma_mem_t mem_desc;
2230 mbx_cmd_t mc = {0};
2231 mbx_cmd_t *mcp = &mc;
2232 int rval = QL_SUCCESS;
2233 int retry = 0;
2234
2235 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2236
2237 do {
2238 if ((rval = ql_setup_mbox_dma_resources(ha, &mem_desc,
2239 (uint32_t)size)) != QL_SUCCESS) {
2240 EL(ha, "setup_mbox_dma_resources failed: %xh\n", rval);
2241 return (QL_MEMORY_ALLOC_FAILED);
2242 }
2243
2244 mcp->mb[0] = MBC_GET_LINK_STATUS;
2245 if (CFG_IST(ha, CFG_CTRL_24258081)) {
2246 if (loop_id == ha->loop_id) {
2247 mcp->mb[0] = MBC_GET_STATUS_COUNTS;
2248 mcp->mb[8] = (uint16_t)(size >> 2);
2249 mcp->out_mb = MBX_10|MBX_8;
2250 } else {
2251 mcp->mb[1] = loop_id;
2252 mcp->mb[4] = port_no;
2253 mcp->mb[10] = (uint16_t)(retry ? BIT_3 : 0);
2254 mcp->out_mb = MBX_10|MBX_4;
2255 }
2256 } else {
2257 if (retry) {
2258 port_no = (uint8_t)(port_no | BIT_3);
2259 }
2260 if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
2261 mcp->mb[1] = loop_id;
2262 mcp->mb[10] = port_no;
2263 mcp->out_mb = MBX_10;
2264 } else {
2265 mcp->mb[1] = (uint16_t)((loop_id << 8) |
2266 port_no);
2267 mcp->out_mb = 0;
2268 }
2269 }
2270 mcp->mb[2] = MSW(LSD(mem_desc.cookie.dmac_laddress));
2271 mcp->mb[3] = LSW(LSD(mem_desc.cookie.dmac_laddress));
2272 mcp->mb[6] = MSW(MSD(mem_desc.cookie.dmac_laddress));
2273 mcp->mb[7] = LSW(MSD(mem_desc.cookie.dmac_laddress));
2274 mcp->in_mb = MBX_1|MBX_0;
2275 mcp->out_mb |= MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
2276 mcp->timeout = MAILBOX_TOV;
2277
2278 rval = ql_mailbox_command(ha, mcp);
2279
2280 if (rval == QL_SUCCESS) {
2281 ql_get_mbox_dma_data(&mem_desc, bufp);
2282 }
2283
2284 ql_free_dma_resource(ha, &mem_desc);
2285
2286 if (rval != QL_SUCCESS) {
2287 EL(ha, "failed=%xh, mbx1=%xh\n", rval, mcp->mb[1]);
2288 }
2289
2290 /*
2291 * Some of the devices want d_id in the payload,
2292 * strictly as per standard. Let's retry.
2293 */
2294
2295 } while (rval == QL_COMMAND_ERROR && !retry++);
2296
2297 if (rval != QL_SUCCESS) {
2298 EL(ha, "failed=%xh, mbx1=%xh\n", rval, mcp->mb[1]);
2299 } else {
2300 /*EMPTY*/
2301 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2302 }
2303
2304 return (rval);
2305 }
2306
2307 /*
2308 * ql_get_status_counts
2309 * Issue get adapter link status counts mailbox command.
2310 *
2311 * Input:
2312 * ha: adapter state pointer.
2313 * loop_id: FC loop id or n_port_hdl.
2314 * size: size of data buffer.
2315 * bufp: data pointer for DMA data.
2316 * port_no: port number to query.
2317 *
2318 * Returns:
2319 * ql local function return status code.
2320 *
2321 * Context:
2322 * Kernel context.
2323 */
2324 int
2325 ql_get_status_counts(ql_adapter_state_t *ha, uint16_t loop_id, size_t size,
2326 caddr_t bufp, uint8_t port_no)
2327 {
2328 dma_mem_t mem_desc;
2329 mbx_cmd_t mc = {0};
2330 mbx_cmd_t *mcp = &mc;
2331 int rval = QL_SUCCESS;
2332
2333 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2334
2335 if ((rval = ql_setup_mbox_dma_resources(ha, &mem_desc,
2336 (uint32_t)size)) != QL_SUCCESS) {
2337 EL(ha, "setup_mbox_dma_resources failed: %x\n", rval);
2338 return (QL_MEMORY_ALLOC_FAILED);
2339 }
2340
2341 if (CFG_IST(ha, CFG_CTRL_24258081)) {
2342 mcp->mb[0] = MBC_GET_STATUS_COUNTS;
2343 mcp->mb[8] = (uint16_t)(size / 4);
2344 mcp->out_mb = MBX_10|MBX_8;
2345 } else {
2346 mcp->mb[0] = MBC_GET_LINK_STATUS;
2347
2348 /* allows reporting when link is down */
2349 if (CFG_IST(ha, CFG_CTRL_2200) == 0) {
2350 port_no = (uint8_t)(port_no | BIT_6);
2351 }
2352
2353 if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
2354 mcp->mb[1] = loop_id;
2355 mcp->mb[10] = port_no;
2356 mcp->out_mb = MBX_10|MBX_1;
2357 } else {
2358 mcp->mb[1] = (uint16_t)((loop_id << 8) |
2359 port_no);
2360 mcp->out_mb = MBX_1;
2361 }
2362 }
2363 mcp->mb[2] = MSW(LSD(mem_desc.cookie.dmac_laddress));
2364 mcp->mb[3] = LSW(LSD(mem_desc.cookie.dmac_laddress));
2365 mcp->mb[6] = MSW(MSD(mem_desc.cookie.dmac_laddress));
2366 mcp->mb[7] = LSW(MSD(mem_desc.cookie.dmac_laddress));
2367 mcp->out_mb |= MBX_7|MBX_6|MBX_3|MBX_2|MBX_0;
2368 mcp->in_mb = MBX_2|MBX_1|MBX_0;
2369 mcp->timeout = MAILBOX_TOV;
2370 rval = ql_mailbox_command(ha, mcp);
2371
2372 if (rval == QL_SUCCESS) {
2373 ql_get_mbox_dma_data(&mem_desc, bufp);
2374 }
2375
2376 ql_free_dma_resource(ha, &mem_desc);
2377
2378 if (rval != QL_SUCCESS) {
2379 EL(ha, "failed=%xh, mbx1=%xh, mbx2=%xh\n", rval,
2380 mcp->mb[1], mcp->mb[2]);
2381 } else {
2382 /*EMPTY*/
2383 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2384 }
2385
2386 return (rval);
2387 }
2388
2389 /*
2390 * ql_reset_link_status
2391 * Issue Reset Link Error Status mailbox command
2392 *
2393 * Input:
2394 * ha: adapter state pointer.
2395 *
2396 * Returns:
2397 * ql local function return status code.
2398 *
2399 * Context:
2400 * Kernel context.
2401 */
2402 int
2403 ql_reset_link_status(ql_adapter_state_t *ha)
2404 {
2405 int rval;
2406 mbx_cmd_t mc = {0};
2407 mbx_cmd_t *mcp = &mc;
2408
2409 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2410
2411 mcp->mb[0] = MBC_RESET_LINK_STATUS;
2412 mcp->out_mb = MBX_0;
2413 mcp->in_mb = MBX_0;
2414 mcp->timeout = MAILBOX_TOV;
2415 rval = ql_mailbox_command(ha, mcp);
2416
2417 if (rval != QL_SUCCESS) {
2418 EL(ha, "failed=%xh\n", rval);
2419 } else {
2420 /*EMPTY*/
2421 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2422 }
2423
2424 return (rval);
2425 }
2426
2427 /*
2428 * ql_loop_reset
2429 * Issue loop reset.
2430 *
2431 * Input:
2432 * ha: adapter state pointer.
2433 *
2434 * Returns:
2435 * ql local function return status code.
2436 *
2437 * Context:
2438 * Kernel context.
2439 */
2440 int
2441 ql_loop_reset(ql_adapter_state_t *ha)
2442 {
2443 int rval;
2444
2445 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2446
2447 if (CFG_IST(ha, CFG_ENABLE_LIP_RESET)) {
2448 rval = ql_lip_reset(ha, 0xff);
2449 } else if (CFG_IST(ha, CFG_ENABLE_FULL_LIP_LOGIN)) {
2450 rval = ql_full_login_lip(ha);
2451 } else if (CFG_IST(ha, CFG_ENABLE_TARGET_RESET)) {
2452 rval = ql_target_reset(ha, NULL, ha->loop_reset_delay);
2453 } else {
2454 rval = ql_initiate_lip(ha);
2455 }
2456
2457 if (rval != QL_SUCCESS) {
2458 EL(ha, "failed, rval = %xh\n", rval);
2459 } else {
2460 /*EMPTY*/
2461 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2462 }
2463
2464 return (rval);
2465 }
2466
2467 /*
2468 * ql_initiate_lip
2469 * Initiate LIP mailbox command.
2470 *
2471 * Input:
2472 * ha: adapter state pointer.
2473 *
2474 * Returns:
2475 * ql local function return status code.
2476 *
2477 * Context:
2478 * Kernel context.
2479 */
2480 int
2481 ql_initiate_lip(ql_adapter_state_t *ha)
2482 {
2483 int rval;
2484 mbx_cmd_t mc = {0};
2485 mbx_cmd_t *mcp = &mc;
2486
2487 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2488
2489 if (CFG_IST(ha, CFG_CTRL_24258081)) {
2490 mcp->mb[0] = MBC_LIP_FULL_LOGIN;
2491 mcp->mb[1] = (uint16_t)(CFG_IST(ha, CFG_CTRL_8081) ?
2492 BIT_1 : BIT_4);
2493 mcp->mb[3] = ha->loop_reset_delay;
2494 mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
2495 } else {
2496 mcp->mb[0] = MBC_INITIATE_LIP;
2497 mcp->out_mb = MBX_0;
2498 }
2499 mcp->in_mb = MBX_0;
2500 mcp->timeout = MAILBOX_TOV;
2501 rval = ql_mailbox_command(ha, mcp);
2502
2503 if (rval != QL_SUCCESS) {
2504 EL(ha, "failed, rval = %xh\n", rval);
2505 } else {
2506 /*EMPTY*/
2507 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2508 }
2509
2510 return (rval);
2511 }
2512
2513 /*
2514 * ql_full_login_lip
2515 * Issue full login LIP mailbox command.
2516 *
2517 * Input:
2518 * ha: adapter state pointer.
2519 *
2520 * Returns:
2521 * ql local function return status code.
2522 *
2523 * Context:
2524 * Kernel context.
2525 */
2526 int
2527 ql_full_login_lip(ql_adapter_state_t *ha)
2528 {
2529 int rval;
2530 mbx_cmd_t mc = {0};
2531 mbx_cmd_t *mcp = &mc;
2532
2533 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2534
2535 mcp->mb[0] = MBC_LIP_FULL_LOGIN;
2536 if (CFG_IST(ha, CFG_CTRL_2425)) {
2537 mcp->mb[1] = BIT_3;
2538 } else if (CFG_IST(ha, CFG_CTRL_8081)) {
2539 mcp->mb[1] = BIT_1;
2540 }
2541 mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
2542 mcp->in_mb = MBX_0;
2543 mcp->timeout = MAILBOX_TOV;
2544 rval = ql_mailbox_command(ha, mcp);
2545
2546 if (rval != QL_SUCCESS) {
2547 EL(ha, "failed, rval = %xh\n", rval);
2548 } else {
2549 /*EMPTY*/
2550 QL_PRINT_3(CE_CONT, "(%d): done", ha->instance);
2551 }
2552
2553 return (rval);
2554 }
2555
2556 /*
2557 * ql_lip_reset
2558 * Issue lip reset to a port.
2559 *
2560 * Input:
2561 * ha: adapter state pointer.
2562 * loop_id: FC loop id.
2563 *
2564 * Returns:
2565 * ql local function return status code.
2566 *
2567 * Context:
2568 * Kernel context.
2569 */
2570 int
2571 ql_lip_reset(ql_adapter_state_t *ha, uint16_t loop_id)
2572 {
2573 int rval;
2574 mbx_cmd_t mc = {0};
2575 mbx_cmd_t *mcp = &mc;
2576
2577 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2578
2579 if (CFG_IST(ha, CFG_CTRL_24258081)) {
2580 mcp->mb[0] = MBC_LIP_FULL_LOGIN;
2581 mcp->mb[1] = (uint16_t)(CFG_IST(ha, CFG_CTRL_8081) ?
2582 BIT_1 : BIT_6);
2583 mcp->mb[3] = ha->loop_reset_delay;
2584 mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
2585 } else {
2586 mcp->mb[0] = MBC_LIP_RESET;
2587 if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
2588 mcp->mb[1] = loop_id;
2589 mcp->out_mb = MBX_10|MBX_3|MBX_2|MBX_1|MBX_0;
2590 } else {
2591 mcp->mb[1] = (uint16_t)(loop_id << 8);
2592 mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
2593 }
2594 mcp->mb[2] = ha->loop_reset_delay;
2595 }
2596 mcp->in_mb = MBX_0;
2597 mcp->timeout = MAILBOX_TOV;
2598 rval = ql_mailbox_command(ha, mcp);
2599
2600 if (rval != QL_SUCCESS) {
2601 EL(ha, "failed, rval = %xh\n", rval);
2602 } else {
2603 /*EMPTY*/
2604 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2605 }
2606
2607 return (rval);
2608 }
2609
2610 /*
2611 * ql_abort_command
2612 * Abort command aborts a specified IOCB.
2613 *
2614 * Input:
2615 * ha: adapter state pointer.
2616 * sp: SRB structure pointer.
2617 *
2618 * Returns:
2619 * ql local function return status code.
2620 *
2621 * Context:
2622 * Kernel context.
2623 */
2624 int
2625 ql_abort_command(ql_adapter_state_t *ha, ql_srb_t *sp)
2626 {
2627 int rval;
2628 mbx_cmd_t mc = {0};
2629 mbx_cmd_t *mcp = &mc;
2630 ql_tgt_t *tq = sp->lun_queue->target_queue;
2631
2632 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2633
2634 if (CFG_IST(ha, CFG_CTRL_24258081)) {
2635 rval = ql_abort_cmd_iocb(ha, sp);
2636 } else {
2637 mcp->mb[0] = MBC_ABORT_COMMAND_IOCB;
2638 if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
2639 mcp->mb[1] = tq->loop_id;
2640 } else {
2641 mcp->mb[1] = (uint16_t)(tq->loop_id << 8);
2642 }
2643 mcp->mb[2] = LSW(sp->handle);
2644 mcp->mb[3] = MSW(sp->handle);
2645 mcp->mb[6] = (uint16_t)(sp->flags & SRB_FCP_CMD_PKT ?
2646 sp->lun_queue->lun_no : 0);
2647 mcp->out_mb = MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
2648 mcp->in_mb = MBX_0;
2649 mcp->timeout = MAILBOX_TOV;
2650 rval = ql_mailbox_command(ha, mcp);
2651 }
2652
2653 if (rval != QL_SUCCESS) {
2654 EL(ha, "failed=%xh, d_id=%xh, handle=%xh\n", rval,
2655 tq->d_id.b24, sp->handle);
2656 } else {
2657 /*EMPTY*/
2658 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2659 }
2660
2661 return (rval);
2662 }
2663
2664 /*
2665 * ql_abort_cmd_iocb
2666 * Function issues abort command IOCB.
2667 *
2668 * Input:
2669 * ha: adapter state pointer.
2670 * sp: SRB structure pointer.
2671 *
2672 * Returns:
2673 * ql local function return status code.
2674 *
2675 * Context:
2676 * Interrupt or Kernel context, no mailbox commands allowed.
2677 */
2678 static int
2679 ql_abort_cmd_iocb(ql_adapter_state_t *ha, ql_srb_t *sp)
2680 {
2681 ql_mbx_iocb_t *pkt;
2682 int rval;
2683 uint32_t pkt_size;
2684 uint16_t comp_status;
2685 ql_tgt_t *tq = sp->lun_queue->target_queue;
2686
2687 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2688
2689 pkt_size = sizeof (ql_mbx_iocb_t);
2690 pkt = kmem_zalloc(pkt_size, KM_SLEEP);
2691
2692 pkt->abo.entry_type = ABORT_CMD_TYPE;
2693 pkt->abo.entry_count = 1;
2694 pkt->abo.n_port_hdl = (uint16_t)LE_16(tq->loop_id);
2695 if (!CFG_IST(ha, CFG_CTRL_8021)) {
2696 pkt->abo.options = AF_NO_ABTS;
2697 }
2698 pkt->abo.cmd_handle = LE_32(sp->handle);
2699 pkt->abo.target_id[0] = tq->d_id.b.al_pa;
2700 pkt->abo.target_id[1] = tq->d_id.b.area;
2701 pkt->abo.target_id[2] = tq->d_id.b.domain;
2702 pkt->abo.vp_index = ha->vp_index;
2703
2704 rval = ql_issue_mbx_iocb(ha, (caddr_t)pkt, pkt_size);
2705
2706 if (rval == QL_SUCCESS) {
2707 if ((pkt->abo.entry_status & 0x3c) != 0) {
2708 EL(ha, "failed, entry_status=%xh, d_id=%xh\n",
2709 pkt->abo.entry_status, tq->d_id.b24);
2710 rval = QL_FUNCTION_PARAMETER_ERROR;
2711 } else {
2712 comp_status = (uint16_t)LE_16(pkt->abo.n_port_hdl);
2713 if (comp_status != CS_COMPLETE) {
2714 EL(ha, "failed, comp_status=%xh, d_id=%xh\n",
2715 comp_status, tq->d_id.b24);
2716 rval = QL_FUNCTION_FAILED;
2717 }
2718 }
2719 }
2720
2721 kmem_free(pkt, pkt_size);
2722
2723 if (rval != QL_SUCCESS) {
2724 EL(ha, "failed=%xh, d_id=%xh\n", rval, tq->d_id.b24);
2725 } else {
2726 /*EMPTY*/
2727 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2728 }
2729
2730 return (rval);
2731 }
2732
2733 /*
2734 * ql_verify_checksum
2735 * Verify loaded RISC firmware.
2736 *
2737 * Input:
2738 * ha = adapter state pointer.
2739 *
2740 * Returns:
2741 * ql local function return status code.
2742 *
2743 * Context:
2744 * Kernel context.
2745 */
2746 int
2747 ql_verify_checksum(ql_adapter_state_t *ha)
2748 {
2749 int rval;
2750 mbx_cmd_t mc = {0};
2751 mbx_cmd_t *mcp = &mc;
2752
2753 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2754
2755 mcp->mb[0] = MBC_VERIFY_CHECKSUM;
2756 if (CFG_IST(ha, CFG_CTRL_24258081)) {
2757 mcp->mb[1] = MSW(ha->risc_fw[0].addr);
2758 mcp->mb[2] = LSW(ha->risc_fw[0].addr);
2759 } else {
2760 mcp->mb[1] = LSW(ha->risc_fw[0].addr);
2761 }
2762 mcp->out_mb = MBX_2|MBX_1|MBX_0;
2763 mcp->in_mb = MBX_2|MBX_1|MBX_0;
2764 mcp->timeout = MAILBOX_TOV;
2765 rval = ql_mailbox_command(ha, mcp);
2766
2767 if (rval != QL_SUCCESS) {
2768 EL(ha, "failed, rval = %xh\n", rval);
2769 } else {
2770 /*EMPTY*/
2771 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2772 }
2773
2774 return (rval);
2775 }
2776
2777 /*
2778 * ql_get_id_list
2779 * Get d_id and loop ID list.
2780 *
2781 * Input:
2782 * ha: adapter state pointer.
2783 * bp: data pointer for DMA data.
2784 * size: size of data buffer.
2785 * mr: pointer for mailbox data.
2786 *
2787 * Returns:
2788 * ql local function return status code.
2789 *
2790 * Context:
2791 * Kernel context.
2792 */
2793 int
2794 ql_get_id_list(ql_adapter_state_t *ha, caddr_t bp, uint32_t size,
2795 ql_mbx_data_t *mr)
2796 {
2797 int rval;
2798 dma_mem_t mem_desc;
2799 mbx_cmd_t mc = {0};
2800 mbx_cmd_t *mcp = &mc;
2801
2802 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2803
2804 if ((rval = ql_setup_mbox_dma_resources(ha, &mem_desc,
2805 (uint32_t)size)) != QL_SUCCESS) {
2806 EL(ha, "setup_mbox_dma_resources failed: %xh\n", rval);
2807 return (QL_MEMORY_ALLOC_FAILED);
2808 }
2809
2810 mcp->mb[0] = MBC_GET_ID_LIST;
2811 if (CFG_IST(ha, CFG_CTRL_24258081)) {
2812 mcp->mb[2] = MSW(LSD(mem_desc.cookie.dmac_laddress));
2813 mcp->mb[3] = LSW(LSD(mem_desc.cookie.dmac_laddress));
2814 mcp->mb[6] = MSW(MSD(mem_desc.cookie.dmac_laddress));
2815 mcp->mb[7] = LSW(MSD(mem_desc.cookie.dmac_laddress));
2816 mcp->mb[8] = (uint16_t)size;
2817 mcp->mb[9] = ha->vp_index;
2818 mcp->out_mb = MBX_9|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_0;
2819 } else {
2820 mcp->mb[1] = MSW(LSD(mem_desc.cookie.dmac_laddress));
2821 mcp->mb[2] = LSW(LSD(mem_desc.cookie.dmac_laddress));
2822 mcp->mb[3] = MSW(MSD(mem_desc.cookie.dmac_laddress));
2823 mcp->mb[6] = LSW(MSD(mem_desc.cookie.dmac_laddress));
2824 mcp->out_mb = MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
2825 }
2826 mcp->in_mb = MBX_1|MBX_0;
2827 mcp->timeout = MAILBOX_TOV;
2828 rval = ql_mailbox_command(ha, mcp);
2829
2830 if (rval == QL_SUCCESS) {
2831 ql_get_mbox_dma_data(&mem_desc, bp);
2832 }
2833
2834 ql_free_dma_resource(ha, &mem_desc);
2835
2836 /* Return mailbox data. */
2837 if (mr != NULL) {
2838 mr->mb[0] = mcp->mb[0];
2839 mr->mb[1] = mcp->mb[1];
2840 }
2841
2842 if (rval != QL_SUCCESS) {
2843 EL(ha, "failed, rval = %xh\n", rval);
2844 } else {
2845 /*EMPTY*/
2846 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2847 }
2848
2849 return (rval);
2850 }
2851
2852 /*
2853 * ql_wrt_risc_ram
2854 * Load RISC RAM.
2855 *
2856 * Input:
2857 * ha: adapter state pointer.
2858 * risc_address: risc ram word address.
2859 * bp: DMA pointer.
2860 * word_count: 16/32bit word count.
2861 *
2862 * Returns:
2863 * ql local function return status code.
2864 *
2865 * Context:
2866 * Kernel context.
2867 */
2868 int
2869 ql_wrt_risc_ram(ql_adapter_state_t *ha, uint32_t risc_address, uint64_t bp,
2870 uint32_t word_count)
2871 {
2872 int rval;
2873 mbx_cmd_t mc = {0};
2874 mbx_cmd_t *mcp = &mc;
2875
2876 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2877
2878 if (CFG_IST(ha, CFG_CTRL_242581)) {
2879 mcp->mb[0] = MBC_LOAD_RAM_EXTENDED;
2880 mcp->mb[4] = MSW(word_count);
2881 mcp->mb[5] = LSW(word_count);
2882 mcp->mb[6] = MSW(MSD(bp));
2883 mcp->mb[7] = LSW(MSD(bp));
2884 mcp->mb[8] = MSW(risc_address);
2885 mcp->out_mb = MBX_8|MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|
2886 MBX_0;
2887 } else {
2888 mcp->mb[0] = MBC_LOAD_RAM;
2889 mcp->mb[4] = LSW(word_count);
2890 mcp->out_mb = MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
2891 }
2892 mcp->mb[1] = LSW(risc_address);
2893 mcp->mb[2] = MSW(LSD(bp));
2894 mcp->mb[3] = LSW(LSD(bp));
2895 mcp->in_mb = MBX_0;
2896 mcp->timeout = MAILBOX_TOV;
2897
2898 rval = ql_mailbox_command(ha, mcp);
2899
2900 if (rval != QL_SUCCESS) {
2901 EL(ha, "failed, rval = %xh\n", rval);
2902 } else {
2903 /*EMPTY*/
2904 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2905 }
2906
2907 return (rval);
2908 }
2909
2910 /*
2911 * ql_rd_risc_ram
2912 * Get RISC RAM.
2913 *
2914 * Input:
2915 * ha: adapter state pointer.
2916 * risc_address: risc ram word address.
2917 * bp: direct data pointer.
2918 * word_count: 16/32bit word count.
2919 *
2920 * Returns:
2921 * ql local function return status code.
2922 *
2923 * Context:
2924 * Kernel context.
2925 */
2926 int
2927 ql_rd_risc_ram(ql_adapter_state_t *ha, uint32_t risc_address, uint64_t bp,
2928 uint32_t word_count)
2929 {
2930 int rval;
2931 mbx_cmd_t mc = {0};
2932 mbx_cmd_t *mcp = &mc;
2933
2934 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2935
2936 if (CFG_IST(ha, CFG_CTRL_242581)) {
2937 mcp->mb[0] = MBC_DUMP_RAM_EXTENDED;
2938 mcp->mb[1] = LSW(risc_address);
2939 mcp->mb[2] = MSW(LSD(bp));
2940 mcp->mb[3] = LSW(LSD(bp));
2941 mcp->mb[4] = MSW(word_count);
2942 mcp->mb[5] = LSW(word_count);
2943 mcp->mb[6] = MSW(MSD(bp));
2944 mcp->mb[7] = LSW(MSD(bp));
2945 mcp->mb[8] = MSW(risc_address);
2946 mcp->out_mb = MBX_8|MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|
2947 MBX_0;
2948 } else {
2949 mcp->mb[0] = MBC_DUMP_RAM; /* doesn't support 64bit addr */
2950 mcp->mb[1] = LSW(risc_address);
2951 mcp->mb[2] = MSW(LSD(bp));
2952 mcp->mb[3] = LSW(LSD(bp));
2953 mcp->mb[4] = LSW(word_count);
2954 mcp->out_mb = MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
2955 }
2956 mcp->in_mb = MBX_0;
2957 mcp->timeout = MAILBOX_TOV;
2958 rval = ql_mailbox_command(ha, mcp);
2959
2960 if (rval != QL_SUCCESS) {
2961 EL(ha, "failed, rval = %xh\n", rval);
2962 } else {
2963 /*EMPTY*/
2964 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2965 }
2966
2967 return (rval);
2968 }
2969
2970 /*
2971 * ql_wrt_risc_ram_word
2972 * Write RISC RAM word.
2973 *
2974 * Input:
2975 * ha: adapter state pointer.
2976 * risc_address: risc ram word address.
2977 * data: data.
2978 *
2979 * Returns:
2980 * ql local function return status code.
2981 *
2982 * Context:
2983 * Kernel context.
2984 */
2985 int
2986 ql_wrt_risc_ram_word(ql_adapter_state_t *ha, uint32_t risc_address,
2987 uint32_t data)
2988 {
2989 int rval;
2990 mbx_cmd_t mc = {0};
2991 mbx_cmd_t *mcp = &mc;
2992
2993 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2994
2995 mcp->mb[0] = MBC_WRITE_RAM_EXTENDED;
2996 mcp->mb[1] = LSW(risc_address);
2997 mcp->mb[2] = LSW(data);
2998 mcp->mb[3] = MSW(data);
2999 mcp->mb[8] = MSW(risc_address);
3000 mcp->out_mb = MBX_8|MBX_3|MBX_2|MBX_1|MBX_0;
3001 mcp->in_mb = MBX_0;
3002 mcp->timeout = MAILBOX_TOV;
3003
3004 rval = ql_mailbox_command(ha, mcp);
3005
3006 if (rval != QL_SUCCESS) {
3007 EL(ha, "failed, rval = %xh\n", rval);
3008 } else {
3009 /*EMPTY*/
3010 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3011 }
3012
3013 return (rval);
3014 }
3015
3016 /*
3017 * ql_rd_risc_ram_word
3018 * Read RISC RAM word.
3019 *
3020 * Input:
3021 * ha: adapter state pointer.
3022 * risc_address: risc ram word address.
3023 * data: data pointer.
3024 *
3025 * Returns:
3026 * ql local function return status code.
3027 *
3028 * Context:
3029 * Kernel context.
3030 */
3031 int
3032 ql_rd_risc_ram_word(ql_adapter_state_t *ha, uint32_t risc_address,
3033 uint32_t *data)
3034 {
3035 int rval;
3036 mbx_cmd_t mc = {0};
3037 mbx_cmd_t *mcp = &mc;
3038
3039 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3040
3041 mcp->mb[0] = MBC_READ_RAM_EXTENDED;
3042 mcp->mb[1] = LSW(risc_address);
3043 mcp->mb[8] = MSW(risc_address);
3044 mcp->out_mb = MBX_8|MBX_1|MBX_0;
3045 mcp->in_mb = MBX_3|MBX_2|MBX_0;
3046 mcp->timeout = MAILBOX_TOV;
3047
3048 rval = ql_mailbox_command(ha, mcp);
3049
3050 if (rval != QL_SUCCESS) {
3051 EL(ha, "failed, rval = %xh\n", rval);
3052 } else {
3053 *data = mcp->mb[2];
3054 if (CFG_IST(ha, CFG_CTRL_24258081)) {
3055 *data |= mcp->mb[3] << 16;
3056 }
3057 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3058 }
3059
3060 return (rval);
3061 }
3062
3063 /*
3064 * ql_issue_mbx_iocb
3065 * Issue IOCB using mailbox command
3066 *
3067 * Input:
3068 * ha: adapter state pointer.
3069 * bp: buffer pointer.
3070 * size: buffer size.
3071 *
3072 * Returns:
3073 * ql local function return status code.
3074 *
3075 * Context:
3076 * Kernel context.
3077 */
3078 int
3079 ql_issue_mbx_iocb(ql_adapter_state_t *ha, caddr_t bp, uint32_t size)
3080 {
3081 int rval;
3082 dma_mem_t mem_desc;
3083 mbx_cmd_t mc = {0};
3084 mbx_cmd_t *mcp = &mc;
3085
3086 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3087
3088 if ((rval = ql_setup_mbox_dma_transfer(ha, &mem_desc, bp, size)) !=
3089 QL_SUCCESS) {
3090 EL(ha, "setup_mbox_dma_transfer failed: %x\n", rval);
3091 return (rval);
3092 }
3093
3094 mcp->mb[0] = MBC_EXECUTE_IOCB;
3095 mcp->mb[2] = MSW(LSD(mem_desc.cookie.dmac_laddress));
3096 mcp->mb[3] = LSW(LSD(mem_desc.cookie.dmac_laddress));
3097 mcp->mb[6] = MSW(MSD(mem_desc.cookie.dmac_laddress));
3098 mcp->mb[7] = LSW(MSD(mem_desc.cookie.dmac_laddress));
3099 mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
3100 mcp->in_mb = MBX_1|MBX_0;
3101 mcp->timeout = MAILBOX_TOV + 5;
3102 rval = ql_mailbox_command(ha, mcp);
3103
3104 if (rval == QL_SUCCESS) {
3105 ql_get_mbox_dma_data(&mem_desc, bp);
3106 }
3107
3108 ql_free_dma_resource(ha, &mem_desc);
3109
3110 if (rval != QL_SUCCESS) {
3111 EL(ha, "failed=%xh, mbx1=%xh\n", rval, mcp->mb[1]);
3112 } else {
3113 /*EMPTY*/
3114 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3115 }
3116
3117 return (rval);
3118 }
3119
3120 /*
3121 * ql_mbx_wrap_test
3122 * Mailbox register wrap test.
3123 *
3124 * Input:
3125 * ha: adapter state pointer.
3126 * mr: pointer for in/out mailbox data.
3127 *
3128 * Returns:
3129 * ql local function return status code.
3130 *
3131 * Context:
3132 * Kernel context.
3133 */
3134 int
3135 ql_mbx_wrap_test(ql_adapter_state_t *ha, ql_mbx_data_t *mr)
3136 {
3137 int rval;
3138 mbx_cmd_t mc = {0};
3139 mbx_cmd_t *mcp = &mc;
3140
3141 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3142
3143 if (mr != NULL) {
3144 mcp->mb[0] = MBC_MAILBOX_REGISTER_TEST;
3145 mcp->mb[1] = mr->mb[1];
3146 mcp->mb[2] = mr->mb[2];
3147 mcp->mb[3] = mr->mb[3];
3148 mcp->mb[4] = mr->mb[4];
3149 mcp->mb[5] = mr->mb[5];
3150 mcp->mb[6] = mr->mb[6];
3151 mcp->mb[7] = mr->mb[7];
3152 mcp->out_mb = MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
3153 mcp->in_mb = MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
3154 mcp->timeout = MAILBOX_TOV;
3155 rval = ql_mailbox_command(ha, mcp);
3156 if (rval == QL_SUCCESS) {
3157 mr->mb[1] = mcp->mb[1];
3158 mr->mb[2] = mcp->mb[2];
3159 mr->mb[3] = mcp->mb[3];
3160 mr->mb[4] = mcp->mb[4];
3161 mr->mb[5] = mcp->mb[5];
3162 mr->mb[6] = mcp->mb[6];
3163 mr->mb[7] = mcp->mb[7];
3164 }
3165 } else {
3166 rval = QL_FUNCTION_PARAMETER_ERROR;
3167 }
3168
3169 if (rval != QL_SUCCESS) {
3170 EL(ha, "failed=%xh\n", rval);
3171 } else {
3172 /*EMPTY*/
3173 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3174 }
3175
3176 return (rval);
3177 }
3178
3179 /*
3180 * ql_execute_fw
3181 * Start adapter firmware.
3182 *
3183 * Input:
3184 * ha: adapter state pointer.
3185 *
3186 * Returns:
3187 * ql local function return status code.
3188 *
3189 * Context:
3190 * Kernel context.
3191 */
3192 int
3193 ql_execute_fw(ql_adapter_state_t *ha)
3194 {
3195 int rval;
3196 mbx_cmd_t mc = {0};
3197 mbx_cmd_t *mcp = &mc;
3198
3199 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3200
3201 if (CFG_IST(ha, CFG_CTRL_8021)) {
3202 return (QL_SUCCESS);
3203 }
3204
3205 mcp->mb[0] = MBC_EXECUTE_FIRMWARE;
3206 if (CFG_IST(ha, CFG_CTRL_242581)) {
3207 mcp->mb[1] = MSW(ha->risc_fw[0].addr);
3208 mcp->mb[2] = LSW(ha->risc_fw[0].addr);
3209 } else {
3210 mcp->mb[1] = LSW(ha->risc_fw[0].addr);
3211 }
3212 if (CFG_IST(ha, CFG_LR_SUPPORT)) {
3213 mcp->mb[4] = BIT_0;
3214 }
3215 mcp->out_mb = MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
3216 mcp->in_mb = MBX_0;
3217 mcp->timeout = MAILBOX_TOV;
3218 rval = ql_mailbox_command(ha, mcp);
3219
3220 if (CFG_IST(ha, CFG_CTRL_2200)) {
3221 rval = QL_SUCCESS;
3222 }
3223
3224 if (rval != QL_SUCCESS) {
3225 EL(ha, "failed=%xh\n", rval);
3226 } else {
3227 /*EMPTY*/
3228 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3229 }
3230
3231 return (rval);
3232 }
3233
3234 /*
3235 * ql_get_firmware_option
3236 * Get Firmware Options Mailbox Command.
3237 *
3238 * Input:
3239 * ha: adapter state pointer.
3240 * mr: pointer for mailbox data.
3241 *
3242 * Returns:
3243 * ql local function return status code.
3244 *
3245 * Context:
3246 * Kernel context.
3247 */
3248 int
3249 ql_get_firmware_option(ql_adapter_state_t *ha, ql_mbx_data_t *mr)
3250 {
3251 int rval;
3252 mbx_cmd_t mc = {0};
3253 mbx_cmd_t *mcp = &mc;
3254
3255 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3256
3257 mcp->mb[0] = MBC_GET_FIRMWARE_OPTIONS;
3258 mcp->out_mb = MBX_0;
3259 mcp->in_mb = MBX_3|MBX_2|MBX_1|MBX_0;
3260 mcp->timeout = MAILBOX_TOV;
3261 rval = ql_mailbox_command(ha, mcp);
3262
3263 /* Return mailbox data. */
3264 if (mr != NULL) {
3265 mr->mb[0] = mcp->mb[0];
3266 mr->mb[1] = mcp->mb[1];
3267 mr->mb[2] = mcp->mb[2];
3268 mr->mb[3] = mcp->mb[3];
3269 }
3270
3271 if (rval != QL_SUCCESS) {
3272 EL(ha, "failed=%xh\n", rval);
3273 } else {
3274 /*EMPTY*/
3275 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
3276 }
3277
3278 return (rval);
3279 }
3280
3281 /*
3282 * ql_set_firmware_option
3283 * Set Firmware Options Mailbox Command.
3284 *
3285 * Input:
3286 * ha: adapter state pointer.
3287 * mr: pointer for mailbox data.
3288 *
3289 * Returns:
3290 * ql local function return status code.
3291 *
3292 * Context:
3293 * Kernel context.
3294 */
3295 int
3296 ql_set_firmware_option(ql_adapter_state_t *ha, ql_mbx_data_t *mr)
3297 {
3298 int rval;
3299 mbx_cmd_t mc = {0};
3300 mbx_cmd_t *mcp = &mc;
3301
3302 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3303
3304 if (mr != NULL) {
3305 mcp->mb[0] = MBC_SET_FIRMWARE_OPTIONS;
3306 mcp->mb[1] = mr->mb[1];
3307 mcp->mb[2] = mr->mb[2];
3308 mcp->mb[3] = mr->mb[3];
3309 mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
3310 mcp->in_mb = MBX_0;
3311 mcp->timeout = MAILBOX_TOV;
3312 rval = ql_mailbox_command(ha, mcp);
3313 } else {
3314 rval = QL_FUNCTION_PARAMETER_ERROR;
3315 }
3316
3317 if (rval != QL_SUCCESS) {
3318 EL(ha, "failed=%xh\n", rval);
3319 } else {
3320 /*EMPTY*/
3321 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3322 }
3323
3324 return (rval);
3325 }
3326
3327 /*
3328 * ql_init_firmware
3329 * Initialize firmware mailbox command.
3330 *
3331 * Input:
3332 * ha: adapter state pointer.
3333 * ha->init_ctrl_blk = setup for transmit.
3334 *
3335 * Returns:
3336 * ql local function return status code.
3337 *
3338 * Context:
3339 * Kernel context.
3340 */
3341 int
3342 ql_init_firmware(ql_adapter_state_t *ha)
3343 {
3344 int rval;
3345 dma_mem_t mem_desc;
3346 mbx_cmd_t mc = {0};
3347 mbx_cmd_t *mcp = &mc;
3348
3349 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3350
3351 if (CFG_IST(ha, CFG_CTRL_8021)) {
3352 WRT32_IO_REG(ha, req_out, 0);
3353 WRT32_IO_REG(ha, resp_in, 0);
3354 WRT32_IO_REG(ha, resp_out, 0);
3355 } else if (CFG_IST(ha, CFG_CTRL_242581)) {
3356 WRT32_IO_REG(ha, req_in, 0);
3357 WRT32_IO_REG(ha, resp_out, 0);
3358 WRT32_IO_REG(ha, pri_req_in, 0);
3359 WRT32_IO_REG(ha, atio_req_out, 0);
3360 } else {
3361 WRT16_IO_REG(ha, req_in, 0);
3362 WRT16_IO_REG(ha, resp_out, 0);
3363 }
3364
3365 if ((rval = ql_setup_mbox_dma_transfer(ha, &mem_desc,
3366 (caddr_t)&ha->init_ctrl_blk, sizeof (ql_comb_init_cb_t))) !=
3367 QL_SUCCESS) {
3368 EL(ha, "dma setup failed=%xh\n", rval);
3369 return (rval);
3370 }
3371
3372 mcp->mb[0] = (uint16_t)(ha->flags & VP_ENABLED ?
3373 MBC_INITIALIZE_MULTI_ID_FW : MBC_INITIALIZE_FIRMWARE);
3374
3375 if (CFG_IST(ha, CFG_SBUS_CARD)) {
3376 mcp->mb[1] = (uint16_t)(CFG_IST(ha, CFG_CTRL_2200) ?
3377 0x204c : 0x52);
3378 }
3379
3380 mcp->mb[2] = MSW(LSD(mem_desc.cookie.dmac_laddress));
3381 mcp->mb[3] = LSW(LSD(mem_desc.cookie.dmac_laddress));
3382 mcp->mb[6] = MSW(MSD(mem_desc.cookie.dmac_laddress));
3383 mcp->mb[7] = LSW(MSD(mem_desc.cookie.dmac_laddress));
3384 if (CFG_IST(ha, CFG_CTRL_8081)) {
3385 uint64_t ofst, addr;
3386 ql_init_24xx_cb_t *icb = (ql_init_24xx_cb_t *)
3387 &ha->init_ctrl_blk.cb24;
3388
3389 mcp->mb[0] = MBC_INITIALIZE_MULTI_ID_FW;
3390 if (icb->ext_blk.version[0] | icb->ext_blk.version[1]) {
3391 ofst = (uintptr_t)&icb->ext_blk - (uintptr_t)icb;
3392 addr = mem_desc.cookie.dmac_laddress + ofst;
3393 mcp->mb[10] = MSW(LSD(addr));
3394 mcp->mb[11] = LSW(LSD(addr));
3395 mcp->mb[12] = MSW(MSD(addr));
3396 mcp->mb[13] = LSW(MSD(addr));
3397 mcp->mb[14] = sizeof (ql_ext_icb_8100_t);
3398 mcp->mb[1] = BIT_0;
3399 }
3400 mcp->out_mb = MBX_14|MBX_13|MBX_12|MBX_11|MBX_10|MBX_7|MBX_6|
3401 MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
3402 } else {
3403 mcp->out_mb = MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
3404 }
3405 mcp->in_mb = MBX_5|MBX_4|MBX_2|MBX_0;
3406 mcp->timeout = MAILBOX_TOV;
3407 rval = ql_mailbox_command(ha, mcp);
3408
3409 if (rval == QL_SUCCESS) {
3410 ha->sfp_stat = mcp->mb[2];
3411 }
3412 ql_free_dma_resource(ha, &mem_desc);
3413
3414 if (rval != QL_SUCCESS) {
3415 EL(ha, "failed=%xh\n", rval);
3416 } else {
3417 /*EMPTY*/
3418 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3419 }
3420
3421 return (rval);
3422 }
3423
3424 /*
3425 * ql_get_firmware_state
3426 * Get adapter firmware state.
3427 *
3428 * Input:
3429 * ha: adapter state pointer.
3430 * mr: pointer for mailbox data.
3431 *
3432 * Returns:
3433 * ql local function return status code.
3434 *
3435 * Context:
3436 * Kernel context.
3437 */
3438 int
3439 ql_get_firmware_state(ql_adapter_state_t *ha, ql_mbx_data_t *mr)
3440 {
3441 int rval;
3442 mbx_cmd_t mc = {0};
3443 mbx_cmd_t *mcp = &mc;
3444
3445 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3446
3447 mcp->mb[0] = MBC_GET_FIRMWARE_STATE;
3448 mcp->out_mb = MBX_0;
3449 mcp->in_mb = MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
3450 mcp->timeout = MAILBOX_TOV;
3451 rval = ql_mailbox_command(ha, mcp);
3452
3453 /* Return mailbox data. */
3454 if (mr != NULL) {
3455 mr->mb[1] = mcp->mb[1];
3456 mr->mb[2] = mcp->mb[2];
3457 mr->mb[3] = mcp->mb[3];
3458 mr->mb[4] = mcp->mb[4];
3459 mr->mb[5] = mcp->mb[5];
3460 }
3461
3462 ha->sfp_stat = mcp->mb[2];
3463
3464 if (rval != QL_SUCCESS) {
3465 EL(ha, "failed=%xh\n", rval);
3466 } else {
3467 /*EMPTY*/
3468 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3469 }
3470
3471 return (rval);
3472 }
3473
3474 /*
3475 * ql_get_adapter_id
3476 * Get adapter ID and topology.
3477 *
3478 * Input:
3479 * ha: adapter state pointer.
3480 * mr: pointer for mailbox data.
3481 *
3482 * Returns:
3483 * ql local function return status code.
3484 *
3485 * Context:
3486 * Kernel context.
3487 */
3488 int
3489 ql_get_adapter_id(ql_adapter_state_t *ha, ql_mbx_data_t *mr)
3490 {
3491 int rval;
3492 mbx_cmd_t mc = {0};
3493 mbx_cmd_t *mcp = &mc;
3494
3495 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3496
3497 mcp->mb[0] = MBC_GET_ID;
3498 if (ha->flags & VP_ENABLED) {
3499 mcp->mb[9] = ha->vp_index;
3500 }
3501 mcp->out_mb = MBX_9|MBX_0;
3502 mcp->in_mb = MBX_13|MBX_12|MBX_11|MBX_10|MBX_9|MBX_8|MBX_7|MBX_6|
3503 MBX_3|MBX_2|MBX_1|MBX_0;
3504 mcp->timeout = MAILBOX_TOV;
3505
3506 rval = ql_mailbox_command(ha, mcp);
3507
3508 /* Return mailbox data. */
3509 if (mr != NULL) {
3510 mr->mb[1] = mcp->mb[1];
3511 mr->mb[1] = (uint16_t)(CFG_IST(ha, CFG_CTRL_24258081) ?
3512 0xffff : mcp->mb[1]);
3513 mr->mb[2] = mcp->mb[2];
3514 mr->mb[3] = mcp->mb[3];
3515 mr->mb[6] = mcp->mb[6];
3516 mr->mb[7] = mcp->mb[7];
3517 mr->mb[8] = mcp->mb[8];
3518 mr->mb[9] = mcp->mb[9];
3519 mr->mb[10] = mcp->mb[10];
3520 mr->mb[11] = mcp->mb[11];
3521 mr->mb[12] = mcp->mb[12];
3522 mr->mb[13] = mcp->mb[13];
3523 }
3524
3525 if (rval != QL_SUCCESS) {
3526 EL(ha, "failed=%xh\n", rval);
3527 } else {
3528 /*EMPTY*/
3529 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3530 }
3531
3532 return (rval);
3533 }
3534
3535 /*
3536 * ql_get_fw_version
3537 * Get firmware version.
3538 *
3539 * Input:
3540 * ha: adapter state pointer.
3541 * mr: pointer for mailbox data.
3542 *
3543 * Returns:
3544 * ql local function return status code.
3545 *
3546 * Context:
3547 * Kernel context.
3548 */
3549 int
3550 ql_get_fw_version(ql_adapter_state_t *ha, ql_mbx_data_t *mr, uint16_t timeout)
3551 {
3552 int rval;
3553 mbx_cmd_t mc = {0};
3554 mbx_cmd_t *mcp = &mc;
3555
3556 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3557
3558 mcp->mb[0] = MBC_ABOUT_FIRMWARE;
3559 mcp->out_mb = MBX_0;
3560 mcp->in_mb = MBX_13|MBX_12|MBX_11|MBX_10|MBX_9|MBX_8|MBX_6|MBX_5|
3561 MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
3562 mcp->timeout = timeout;
3563 rval = ql_mailbox_command(ha, mcp);
3564
3565 /* Return mailbox data. */
3566 if (mr != NULL) {
3567 mr->mb[1] = mcp->mb[1];
3568 mr->mb[2] = mcp->mb[2];
3569 mr->mb[3] = mcp->mb[3];
3570 mr->mb[4] = mcp->mb[4];
3571 mr->mb[5] = mcp->mb[5];
3572 mr->mb[6] = mcp->mb[6];
3573 mr->mb[8] = mcp->mb[8];
3574 mr->mb[9] = mcp->mb[9];
3575 mr->mb[10] = mcp->mb[10];
3576 mr->mb[11] = mcp->mb[11];
3577 mr->mb[12] = mcp->mb[12];
3578 mr->mb[13] = mcp->mb[13];
3579 }
3580
3581 if (rval != QL_SUCCESS) {
3582 EL(ha, "failed=%xh\n", rval);
3583 } else {
3584 /*EMPTY*/
3585 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3586 }
3587
3588 return (rval);
3589 }
3590
3591 /*
3592 * ql_data_rate
3593 * Issue data rate Mailbox Command.
3594 *
3595 * Input:
3596 * ha: adapter state pointer.
3597 * mr: pointer for mailbox data.
3598 *
3599 * Returns:
3600 * ql local function return status code.
3601 *
3602 * Context:
3603 * Kernel context.
3604 */
3605 int
3606 ql_data_rate(ql_adapter_state_t *ha, ql_mbx_data_t *mr)
3607 {
3608 int rval;
3609 mbx_cmd_t mc = {0};
3610 mbx_cmd_t *mcp = &mc;
3611
3612 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3613
3614 if (mr != NULL) {
3615 mcp->mb[0] = MBC_DATA_RATE;
3616 mcp->mb[1] = mr->mb[1];
3617 mcp->mb[2] = mr->mb[2];
3618 mcp->out_mb = MBX_2|MBX_1|MBX_0;
3619 mcp->in_mb = MBX_2|MBX_1|MBX_0;
3620 mcp->timeout = MAILBOX_TOV;
3621 rval = ql_mailbox_command(ha, mcp);
3622
3623 /* Return mailbox data. */
3624 mr->mb[1] = mcp->mb[1];
3625 mr->mb[2] = mcp->mb[2];
3626 } else {
3627 rval = QL_FUNCTION_PARAMETER_ERROR;
3628 }
3629
3630 ha->sfp_stat = mcp->mb[2];
3631
3632 if (rval != QL_SUCCESS) {
3633 EL(ha, "failed=%xh\n", rval);
3634 } else {
3635 /*EMPTY*/
3636 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3637 }
3638
3639 return (rval);
3640 }
3641
3642 /*
3643 * ql_Diag_Loopback
3644 * Issue Reset Link Status mailbox command
3645 *
3646 * Input:
3647 * ha: adapter state pointer.
3648 * findex: FCF index.
3649 * bp: buffer pointer.
3650 * size: buffer size.
3651 * opt: command options.
3652 * it_cnt: iteration count.
3653 * mr: pointer for mailbox data.
3654 *
3655 * Returns:
3656 * ql local function return status code.
3657 *
3658 * Context:
3659 * Kernel context.
3660 */
3661 int
3662 ql_diag_loopback(ql_adapter_state_t *ha, uint16_t findex, caddr_t bp,
3663 uint32_t size, uint16_t opt, uint32_t it_cnt, ql_mbx_data_t *mr)
3664 {
3665 int rval;
3666 dma_mem_t mem_desc;
3667 mbx_cmd_t mc = {0};
3668 mbx_cmd_t *mcp = &mc;
3669
3670 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3671
3672 if ((rval = ql_setup_mbox_dma_transfer(ha, &mem_desc, bp, size)) !=
3673 QL_SUCCESS) {
3674 EL(ha, "setup_mbox_dma_transfer failed: %x\n", rval);
3675 return (rval);
3676 }
3677
3678 mcp->mb[0] = MBC_DIAGNOSTIC_LOOP_BACK;
3679 mcp->mb[1] = opt;
3680 mcp->mb[2] = findex;
3681 mcp->mb[6] = LSW(MSD(mem_desc.cookie.dmac_laddress));
3682 mcp->mb[7] = MSW(MSD(mem_desc.cookie.dmac_laddress));
3683 mcp->mb[10] = LSW(size);
3684 mcp->mb[11] = MSW(size);
3685 mcp->mb[14] = LSW(LSD(mem_desc.cookie.dmac_laddress));
3686 mcp->mb[15] = MSW(LSD(mem_desc.cookie.dmac_laddress));
3687 mcp->mb[16] = LSW(LSD(mem_desc.cookie.dmac_laddress));
3688 mcp->mb[17] = MSW(LSD(mem_desc.cookie.dmac_laddress));
3689 mcp->mb[18] = LSW(it_cnt);
3690 mcp->mb[19] = MSW(it_cnt);
3691 mcp->mb[20] = LSW(MSD(mem_desc.cookie.dmac_laddress));
3692 mcp->mb[21] = MSW(MSD(mem_desc.cookie.dmac_laddress));
3693 mcp->out_mb = MBX_21|MBX_20|MBX_19|MBX_18|MBX_17|MBX_16|MBX_15|
3694 MBX_14|MBX_13|MBX_12|MBX_11|MBX_10|MBX_7|MBX_6|MBX_2|MBX_1|MBX_0;
3695 mcp->in_mb = MBX_19|MBX_18|MBX_3|MBX_2|MBX_1|MBX_0;
3696 mcp->timeout = it_cnt / 300;
3697 if (mcp->timeout < MAILBOX_TOV) {
3698 mcp->timeout = MAILBOX_TOV;
3699 }
3700 rval = ql_mailbox_command(ha, mcp);
3701
3702 if (rval == QL_SUCCESS) {
3703 ql_get_mbox_dma_data(&mem_desc, bp);
3704 }
3705
3706 ql_free_dma_resource(ha, &mem_desc);
3707
3708 /* Return mailbox data. */
3709 if (mr != NULL) {
3710 mr->mb[0] = mcp->mb[0];
3711 mr->mb[1] = mcp->mb[1];
3712 mr->mb[2] = mcp->mb[2];
3713 mr->mb[3] = mcp->mb[3];
3714 mr->mb[18] = mcp->mb[18];
3715 mr->mb[19] = mcp->mb[19];
3716 }
3717
3718 if (rval != QL_SUCCESS) {
3719 EL(ha, "failed=%xh, mb1=%xh\n", rval, mcp->mb[1]);
3720 } else {
3721 /*EMPTY*/
3722 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3723 }
3724
3725 return (rval);
3726 }
3727
3728 /*
3729 * ql_diag_echo
3730 * Issue Diag echo mailbox command. Valid for qla23xx HBA's.
3731 *
3732 * Input:
3733 * ha: adapter state pointer.
3734 * findex: FCF index.
3735 * bp: buffer pointer.
3736 * size: buffer size.
3737 * opt: command options.
3738 * mr: pointer to mailbox status.
3739 *
3740 * Returns:
3741 * ql local function return status code.
3742 *
3743 * Context:
3744 * Kernel context.
3745 */
3746 int
3747 ql_diag_echo(ql_adapter_state_t *ha, uint16_t findex, caddr_t bp,
3748 uint32_t size, uint16_t opt, ql_mbx_data_t *mr)
3749 {
3750 int rval;
3751 dma_mem_t mem_desc;
3752 mbx_cmd_t mc = {0};
3753 mbx_cmd_t *mcp = &mc;
3754
3755 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3756
3757 if ((rval = ql_setup_mbox_dma_transfer(ha, &mem_desc, bp, size)) !=
3758 QL_SUCCESS) {
3759 EL(ha, "setup_mbox_dma_transfer failed: %x\n", rval);
3760 return (rval);
3761 }
3762
3763 mcp->mb[0] = MBC_ECHO;
3764 mcp->mb[1] = opt;
3765 mcp->mb[2] = findex;
3766 mcp->mb[6] = LSW(MSD(mem_desc.cookie.dmac_laddress));
3767 mcp->mb[7] = MSW(MSD(mem_desc.cookie.dmac_laddress));
3768 mcp->mb[10] = LSW(size);
3769 mcp->mb[14] = LSW(LSD(mem_desc.cookie.dmac_laddress));
3770 mcp->mb[15] = MSW(LSD(mem_desc.cookie.dmac_laddress));
3771 mcp->mb[16] = LSW(LSD(mem_desc.cookie.dmac_laddress));
3772 mcp->mb[17] = MSW(LSD(mem_desc.cookie.dmac_laddress));
3773 mcp->mb[20] = LSW(MSD(mem_desc.cookie.dmac_laddress));
3774 mcp->mb[21] = MSW(MSD(mem_desc.cookie.dmac_laddress));
3775 mcp->out_mb = MBX_21|MBX_20|MBX_17|MBX_16|MBX_15|
3776 MBX_14|MBX_10|MBX_7|MBX_6|MBX_2|MBX_1|MBX_0;
3777 mcp->in_mb = MBX_1|MBX_0;
3778 mcp->timeout = MAILBOX_TOV;
3779 rval = ql_mailbox_command(ha, mcp);
3780
3781 if (rval == QL_SUCCESS) {
3782 ql_get_mbox_dma_data(&mem_desc, bp);
3783 }
3784
3785 ql_free_dma_resource(ha, &mem_desc);
3786
3787 if (mr != NULL) {
3788 mr->mb[0] = mcp->mb[0];
3789 }
3790
3791 if (rval != QL_SUCCESS) {
3792 EL(ha, "failed=%xh, mb1=%xh\n", rval,
3793 mcp->mb[1]);
3794 } else {
3795 /*EMPTY*/
3796 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3797 }
3798
3799 return (rval);
3800 }
3801
3802 /*
3803 * ql_serdes_param
3804 * Set/Get serdes transmit parameters mailbox command.
3805 *
3806 * Input:
3807 * ha: adapter state pointer.
3808 * mr: pointer to mailbox in/out parameters.
3809 *
3810 * Returns:
3811 * ql local function return status code.
3812 *
3813 * Context:
3814 * Kernel context.
3815 */
3816 int
3817 ql_serdes_param(ql_adapter_state_t *ha, ql_mbx_data_t *mr)
3818 {
3819 int rval;
3820 mbx_cmd_t mc = {0};
3821 mbx_cmd_t *mcp = &mc;
3822
3823 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3824
3825 mcp->mb[0] = MBC_SERDES_TRANSMIT_PARAMETERS;
3826 mcp->mb[1] = mr->mb[1];
3827 mcp->mb[2] = mr->mb[2];
3828 mcp->mb[3] = mr->mb[3];
3829 mcp->mb[4] = mr->mb[4];
3830 mcp->out_mb = MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
3831 mcp->in_mb = MBX_4|MBX_3|MBX_2|MBX_0;
3832 mcp->timeout = MAILBOX_TOV;
3833 rval = ql_mailbox_command(ha, mcp);
3834
3835 /* Return mailbox data. */
3836 if (mr != NULL) {
3837 mr->mb[0] = mcp->mb[0];
3838 mr->mb[2] = mcp->mb[2];
3839 mr->mb[3] = mcp->mb[3];
3840 mr->mb[4] = mcp->mb[4];
3841 }
3842
3843 if (rval != QL_SUCCESS) {
3844 EL(ha, "failed=%xh\n", rval);
3845 } else {
3846 /*EMPTY*/
3847 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3848 }
3849
3850 return (rval);
3851 }
3852
3853 /*
3854 * ql_get_timeout_parameters
3855 * Issue get timeout parameters mailbox command.
3856 *
3857 * Input:
3858 * ha: adapter state pointer.
3859 * mr: pointer to mailbox in/out parameters.
3860 *
3861 * Returns:
3862 * ql local function return status code.
3863 *
3864 * Context:
3865 * Kernel context.
3866 */
3867 int
3868 ql_get_timeout_parameters(ql_adapter_state_t *ha, uint16_t *tov)
3869 {
3870 int rval;
3871 mbx_cmd_t mc = {0};
3872 mbx_cmd_t *mcp = &mc;
3873
3874 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3875
3876 mcp->mb[0] = MBC_GET_TIMEOUT_PARAMETERS;
3877 mcp->out_mb = MBX_0;
3878 mcp->in_mb = MBX_3|MBX_0;
3879 mcp->timeout = MAILBOX_TOV;
3880 rval = ql_mailbox_command(ha, mcp);
3881 if (rval == QL_SUCCESS) {
3882 /* Get 2 * R_A_TOV in seconds */
3883 if (CFG_IST(ha, CFG_CTRL_2200) || mcp->mb[3] == 0) {
3884 *tov = R_A_TOV_DEFAULT;
3885 } else {
3886 *tov = (uint16_t)(mcp->mb[3] / 10);
3887 if (mcp->mb[3] % 10 != 0) {
3888 *tov = (uint16_t)(*tov + 1);
3889 }
3890 /*
3891 * Adjust value to prevent driver timeout at the same
3892 * time as device.
3893 */
3894 *tov = (uint16_t)(*tov + 5);
3895 }
3896 } else {
3897 *tov = R_A_TOV_DEFAULT;
3898 }
3899
3900 if (rval != QL_SUCCESS) {
3901 EL(ha, "failed=%xh\n", rval);
3902 } else {
3903 /*EMPTY*/
3904 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3905 }
3906
3907 return (rval);
3908 }
3909
3910 /*
3911 * ql_stop_firmware
3912 * Issue stop firmware Mailbox Command.
3913 *
3914 * Input:
3915 * ha: adapter state pointer.
3916 *
3917 * Returns:
3918 * ql local function return status code.
3919 *
3920 * Context:
3921 * Kernel context.
3922 */
3923 int
3924 ql_stop_firmware(ql_adapter_state_t *ha)
3925 {
3926 int rval;
3927 mbx_cmd_t mc = {0};
3928 mbx_cmd_t *mcp = &mc;
3929
3930 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3931
3932 mcp->mb[0] = MBC_STOP_FIRMWARE;
3933 mcp->out_mb = MBX_1|MBX_0;
3934 mcp->in_mb = MBX_0;
3935 mcp->timeout = 2;
3936 rval = ql_mailbox_command(ha, mcp);
3937
3938 if (rval != QL_SUCCESS) {
3939 EL(ha, "failed=%xh\n", rval);
3940 } else {
3941 /*EMPTY*/
3942 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3943 }
3944
3945 return (rval);
3946 }
3947
3948 /*
3949 * ql_read_sfp
3950 * Issue Read SFP Mailbox command
3951 *
3952 * Input:
3953 * ha: adapter state pointer.
3954 * mem: pointer to dma memory object for command.
3955 * dev: Device address (A0h or A2h).
3956 * addr: Data address on SFP EEPROM (0–255).
3957 *
3958 * Returns:
3959 * ql local function return status code.
3960 *
3961 * Context:
3962 * Kernel context.
3963 */
3964 int
3965 ql_read_sfp(ql_adapter_state_t *ha, dma_mem_t *mem, uint16_t dev,
3966 uint16_t addr)
3967 {
3968 int rval;
3969 mbx_cmd_t mc = {0};
3970 mbx_cmd_t *mcp = &mc;
3971
3972 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3973
3974 mcp->mb[0] = MBC_READ_SFP;
3975 mcp->mb[1] = dev;
3976 mcp->mb[2] = MSW(mem->cookies->dmac_address);
3977 mcp->mb[3] = LSW(mem->cookies->dmac_address);
3978 mcp->mb[6] = MSW(mem->cookies->dmac_notused);
3979 mcp->mb[7] = LSW(mem->cookies->dmac_notused);
3980 mcp->mb[8] = LSW(mem->size);
3981 mcp->mb[9] = addr;
3982 mcp->out_mb = MBX_10|MBX_9|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
3983 mcp->in_mb = MBX_1|MBX_0;
3984 mcp->timeout = MAILBOX_TOV;
3985 rval = ql_mailbox_command(ha, mcp);
3986
3987 (void) ddi_dma_sync(mem->dma_handle, 0, mem->size,
3988 DDI_DMA_SYNC_FORKERNEL);
3989
3990 if (rval != QL_SUCCESS) {
3991 EL(ha, "failed=%xh\n", rval);
3992 } else {
3993 /*EMPTY*/
3994 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3995 }
3996
3997 return (rval);
3998 }
3999
4000 /*
4001 * ql_iidma_rate
4002 * Issue get/set iidma rate command
4003 *
4004 * Input:
4005 * ha: adapter state pointer.
4006 * loop_id: n-port handle to set/get iidma rate.
4007 * idma_rate: Pointer to iidma rate.
4008 * option: iidma firmware option (set or get data).
4009 * 0 --> Get iidma rate
4010 * 1 --> Set iidma rate
4011 *
4012 * Returns:
4013 * ql local function return status code.
4014 *
4015 * Context:
4016 * Kernel context.
4017 */
4018 int
4019 ql_iidma_rate(ql_adapter_state_t *ha, uint16_t loop_id, uint32_t *idma_rate,
4020 uint32_t option)
4021 {
4022 int rval;
4023 mbx_cmd_t mc = {0};
4024 mbx_cmd_t *mcp = &mc;
4025
4026 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
4027
4028 mcp->mb[0] = MBC_PORT_PARAM;
4029 mcp->mb[1] = loop_id;
4030 mcp->mb[2] = (uint16_t)option;
4031 mcp->out_mb = MBX_0|MBX_1|MBX_2;
4032 mcp->in_mb = MBX_0|MBX_1;
4033
4034 if (option & BIT_0) {
4035 mcp->mb[3] = (uint16_t)*idma_rate;
4036 mcp->out_mb |= MBX_3;
4037 } else {
4038 mcp->in_mb |= MBX_3;
4039 }
4040
4041 mcp->timeout = MAILBOX_TOV;
4042 rval = ql_mailbox_command(ha, mcp);
4043
4044 if (rval != QL_SUCCESS) {
4045 EL(ha, "failed=%xh, mb1=%xh\n", rval, mcp->mb[1]);
4046 } else {
4047 if (option == 0) {
4048 *idma_rate = mcp->mb[3];
4049 }
4050
4051 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
4052 }
4053
4054 return (rval);
4055 }
4056
4057 /*
4058 * ql_set_xmit_parms
4059 * Set transmit parameters
4060 *
4061 * Input:
4062 * ha: adapter state pointer.
4063 *
4064 * Returns:
4065 * ql local function return status code.
4066 *
4067 * Context:
4068 * Kernel context.
4069 */
4070 int
4071 ql_set_xmit_parms(ql_adapter_state_t *ha)
4072 {
4073 int rval;
4074 mbx_cmd_t mc = {0};
4075 mbx_cmd_t *mcp = &mc;
4076
4077 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
4078
4079 mcp->mb[0] = MBC_XMIT_PARM;
4080 mcp->mb[1] = BIT_1;
4081 mcp->out_mb = MBX_1|MBX_0;
4082 mcp->in_mb = MBX_0;
4083 mcp->timeout = MAILBOX_TOV;
4084 rval = ql_mailbox_command(ha, mcp);
4085
4086 if (rval != QL_SUCCESS) {
4087 EL(ha, "failed=%xh\n", rval);
4088 } else {
4089 /*EMPTY*/
4090 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
4091 }
4092 return (rval);
4093 }
4094
4095 /*
4096 * ql_fw_etrace
4097 * Firmware extended tracing.
4098 *
4099 * Input:
4100 * ha: adapter state pointer.
4101 * mem: pointer to dma memory object for command.
4102 * opt: options and opcode.
4103 *
4104 * Returns:
4105 * ql local function return status code.
4106 *
4107 * Context:
4108 * Kernel context.
4109 */
4110 int
4111 ql_fw_etrace(ql_adapter_state_t *ha, dma_mem_t *mem, uint16_t opt)
4112 {
4113 int rval = QL_SUCCESS;
4114 mbx_cmd_t mc = {0};
4115 mbx_cmd_t *mcp = &mc;
4116 uint16_t op_code;
4117 uint64_t time;
4118
4119 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
4120
4121 /* currently no supported options */
4122 op_code = (uint16_t)(opt & ~0xFF00);
4123
4124 mcp->mb[0] = MBC_TRACE_CONTROL;
4125 mcp->mb[1] = op_code;
4126 mcp->in_mb = MBX_0;
4127 mcp->timeout = MAILBOX_TOV;
4128
4129 switch (op_code) {
4130 case FTO_INSERT_TIME_STAMP:
4131
4132 (void) drv_getparm(TIME, &time);
4133
4134 EL(ha, "insert time: %x %xh\n", MSD(time), LSD(time));
4135
4136 mcp->mb[2] = LSW(LSD(time));
4137 mcp->mb[3] = MSW(LSD(time));
4138 mcp->mb[4] = LSW(MSD(time));
4139 mcp->mb[5] = MSW(MSD(time));
4140 mcp->out_mb = MBX_0_THRU_5;
4141 break;
4142
4143 case FTO_FCE_TRACE_ENABLE:
4144 /* Firmware Fibre Channel Event Trace Buffer */
4145 mcp->mb[2] = LSW(mem->cookies->dmac_address);
4146 mcp->mb[3] = MSW(mem->cookies->dmac_address);
4147 mcp->mb[4] = LSW(mem->cookies->dmac_notused);
4148 mcp->mb[5] = MSW(mem->cookies->dmac_notused);
4149 mcp->mb[6] = (uint16_t)(mem->size / 0x4000); /* 16kb blks */
4150 mcp->mb[8] = (uint16_t)ha->fwfcetraceopt;
4151 mcp->mb[9] = FTO_FCEMAXTRACEBUF;
4152 mcp->mb[10] = FTO_FCEMAXTRACEBUF;
4153 mcp->out_mb = MBX_0_THRU_10;
4154 break;
4155
4156 case FTO_EXT_TRACE_ENABLE:
4157 /* Firmware Extended Trace Buffer */
4158 mcp->mb[2] = LSW(mem->cookies->dmac_address);
4159 mcp->mb[3] = MSW(mem->cookies->dmac_address);
4160 mcp->mb[4] = LSW(mem->cookies->dmac_notused);
4161 mcp->mb[5] = MSW(mem->cookies->dmac_notused);
4162 mcp->mb[6] = (uint16_t)(mem->size / 0x4000); /* 16kb blks */
4163 mcp->out_mb = MBX_0_THRU_7;
4164 break;
4165
4166 case FTO_FCE_TRACE_DISABLE:
4167 /* also causes ISP25xx to flush its internal FCE buffer. */
4168 mcp->mb[2] = BIT_0;
4169 mcp->out_mb = MBX_0_THRU_2;
4170 break;
4171
4172 case FTO_EXT_TRACE_DISABLE:
4173 /* just sending the opcode disables it */
4174 break;
4175
4176 default:
4177 EL(ha, "invalid option: %xh\n", opt);
4178 rval = QL_PARAMETER_ERROR;
4179 break;
4180 }
4181
4182 if (rval == QL_SUCCESS) {
4183 rval = ql_mailbox_command(ha, mcp);
4184 }
4185
4186 if (rval != QL_SUCCESS) {
4187 EL(ha, "failed=%xh\n", rval);
4188 } else {
4189 /*EMPTY*/
4190 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
4191 }
4192
4193 return (rval);
4194 }
4195
4196 /*
4197 * ql_reset_menlo
4198 * Reset Menlo Mailbox Command.
4199 *
4200 * Input:
4201 * ha: adapter state pointer.
4202 * mr: pointer to mailbox in/out parameters.
4203 * opt: options.
4204 *
4205 * Returns:
4206 * ql local function return status code.
4207 *
4208 * Context:
4209 * Kernel context.
4210 */
4211 int
4212 ql_reset_menlo(ql_adapter_state_t *ha, ql_mbx_data_t *mr, uint16_t opt)
4213 {
4214 int rval;
4215 mbx_cmd_t mc = {0};
4216 mbx_cmd_t *mcp = &mc;
4217
4218 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
4219
4220 mcp->mb[0] = MBC_RESET_MENLO;
4221 mcp->mb[1] = opt;
4222 mcp->out_mb = MBX_1|MBX_0;
4223 mcp->in_mb = MBX_1|MBX_0;
4224 mcp->timeout = MAILBOX_TOV;
4225 rval = ql_mailbox_command(ha, mcp);
4226
4227 /* Return mailbox data. */
4228 if (mr != NULL) {
4229 mr->mb[0] = mcp->mb[0];
4230 mr->mb[1] = mcp->mb[1];
4231 }
4232
4233 if (rval != QL_SUCCESS) {
4234 EL(ha, "failed=%xh\n", rval);
4235 } else {
4236 /*EMPTY*/
4237 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
4238 }
4239
4240 return (rval);
4241 }
4242
4243 /*
4244 * ql_restart_mpi
4245 * The Restart MPI Firmware Mailbox Command will reset the MPI RISC,
4246 * reload MPI firmware from Flash, and execute the firmware.
4247 *
4248 * Input:
4249 * ha: adapter state pointer.
4250 *
4251 * Returns:
4252 * ql local function return status code.
4253 *
4254 * Context:
4255 * Kernel context.
4256 */
4257 int
4258 ql_restart_mpi(ql_adapter_state_t *ha)
4259 {
4260 int rval;
4261 mbx_cmd_t mc = {0};
4262 mbx_cmd_t *mcp = &mc;
4263
4264 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
4265
4266 mcp->mb[0] = MBC_RESTART_MPI;
4267 mcp->out_mb = MBX_0;
4268 mcp->in_mb = MBX_1|MBX_0;
4269 mcp->timeout = MAILBOX_TOV;
4270 rval = ql_mailbox_command(ha, mcp);
4271
4272 /* Return mailbox data. */
4273 if (rval != QL_SUCCESS) {
4274 EL(ha, "status=%xh, mbx1=%xh\n", rval, mcp->mb[1]);
4275 } else {
4276 /*EMPTY*/
4277 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
4278 }
4279
4280 return (rval);
4281 }
4282
4283 /*
4284 * ql_idc_request
4285 * Inter-Driver Communication Request.
4286 *
4287 * Input:
4288 * ha: adapter state pointer.
4289 * mr: pointer for mailbox data.
4290 *
4291 * Returns:
4292 * ql local function return status code.
4293 *
4294 * Context:
4295 * Kernel context.
4296 */
4297 int
4298 ql_idc_request(ql_adapter_state_t *ha, ql_mbx_data_t *mr)
4299 {
4300 int rval;
4301 mbx_cmd_t mc = {0};
4302 mbx_cmd_t *mcp = &mc;
4303
4304 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
4305
4306 mcp->mb[0] = MBC_IDC_REQUEST;
4307 mcp->mb[1] = mr->mb[1];
4308 mcp->mb[2] = mr->mb[2];
4309 mcp->mb[3] = mr->mb[3];
4310 mcp->mb[4] = mr->mb[4];
4311 mcp->mb[5] = mr->mb[5];
4312 mcp->mb[6] = mr->mb[6];
4313 mcp->mb[7] = mr->mb[7];
4314 mcp->out_mb = MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
4315 mcp->in_mb = MBX_2|MBX_0;
4316 mcp->timeout = MAILBOX_TOV;
4317 rval = ql_mailbox_command(ha, mcp);
4318
4319 if (rval == QL_SUCCESS) {
4320 if (mr != NULL) {
4321 mr->mb[2] = mcp->mb[2];
4322 }
4323 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
4324 } else {
4325 EL(ha, "status=%xh, mbx2=%xh\n", rval, mcp->mb[2]);
4326 }
4327
4328 return (rval);
4329 }
4330
4331 /*
4332 * ql_idc_ack
4333 * Inter-Driver Communication Acknowledgement.
4334 *
4335 * Input:
4336 * ha: adapter state pointer.
4337 *
4338 * Returns:
4339 * ql local function return status code.
4340 *
4341 * Context:
4342 * Kernel context.
4343 */
4344 int
4345 ql_idc_ack(ql_adapter_state_t *ha)
4346 {
4347 int rval;
4348 mbx_cmd_t mc = {0};
4349 mbx_cmd_t *mcp = &mc;
4350
4351 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
4352
4353 mcp->mb[0] = MBC_IDC_ACK;
4354 mcp->mb[1] = ha->idc_mb[1];
4355 mcp->mb[2] = ha->idc_mb[2];
4356 mcp->mb[3] = ha->idc_mb[3];
4357 mcp->mb[4] = ha->idc_mb[4];
4358 mcp->mb[5] = ha->idc_mb[5];
4359 mcp->mb[6] = ha->idc_mb[6];
4360 mcp->mb[7] = ha->idc_mb[7];
4361 mcp->out_mb = MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
4362 mcp->in_mb = MBX_0;
4363 mcp->timeout = MAILBOX_TOV;
4364 rval = ql_mailbox_command(ha, mcp);
4365
4366 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
4367
4368 return (rval);
4369 }
4370
4371 /*
4372 * ql_idc_time_extend
4373 * Inter-Driver Communication Time Extend
4374 *
4375 * Input:
4376 * ha: adapter state pointer.
4377 * mr: pointer for mailbox data.
4378 *
4379 * Returns:
4380 * ql local function return status code.
4381 *
4382 * Context:
4383 * Kernel context.
4384 */
4385 int
4386 ql_idc_time_extend(ql_adapter_state_t *ha, ql_mbx_data_t *mr)
4387 {
4388 int rval;
4389 mbx_cmd_t mc = {0};
4390 mbx_cmd_t *mcp = &mc;
4391
4392 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
4393
4394 mcp->mb[0] = MBC_IDC_TIME_EXTEND;
4395 mcp->mb[1] = mr->mb[1];
4396 mcp->mb[2] = mr->mb[2];
4397 mcp->out_mb = MBX_2|MBX_1|MBX_0;
4398 mcp->in_mb = MBX_0;
4399 mcp->timeout = MAILBOX_TOV;
4400 rval = ql_mailbox_command(ha, mcp);
4401
4402 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
4403
4404 return (rval);
4405 }
4406
4407 /*
4408 * ql_port_reset
4409 * The Port Reset for the external 10G port associated with this function.
4410 *
4411 * Input:
4412 * ha: adapter state pointer.
4413 *
4414 * Returns:
4415 * ql local function return status code.
4416 *
4417 * Context:
4418 * Kernel context.
4419 */
4420 int
4421 ql_port_reset(ql_adapter_state_t *ha)
4422 {
4423 int rval;
4424 mbx_cmd_t mc = {0};
4425 mbx_cmd_t *mcp = &mc;
4426
4427 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
4428
4429 mcp->mb[0] = MBC_PORT_RESET;
4430 mcp->out_mb = MBX_0;
4431 mcp->in_mb = MBX_0;
4432 mcp->timeout = MAILBOX_TOV;
4433 rval = ql_mailbox_command(ha, mcp);
4434
4435 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
4436
4437 return (rval);
4438 }
4439
4440 /*
4441 * ql_set_port_config
4442 * The Set Port Configuration command sets the configuration for the
4443 * external 10G port associated with this function.
4444 *
4445 * Input:
4446 * ha: adapter state pointer.
4447 * mr: pointer for mailbox data.
4448 *
4449 * Returns:
4450 * ql local function return status code.
4451 *
4452 * Context:
4453 * Kernel context.
4454 */
4455 int
4456 ql_set_port_config(ql_adapter_state_t *ha, ql_mbx_data_t *mrp)
4457 {
4458 int rval;
4459 mbx_cmd_t mc = {0};
4460 mbx_cmd_t *mcp = &mc;
4461
4462 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
4463
4464 mcp->mb[0] = MBC_SET_PORT_CONFIG;
4465 mcp->mb[1] = mrp->mb[1];
4466 mcp->mb[2] = mrp->mb[2];
4467 mcp->mb[3] = mrp->mb[3];
4468 mcp->mb[4] = mrp->mb[4];
4469 mcp->out_mb = MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
4470 mcp->in_mb = MBX_0;
4471 mcp->timeout = MAILBOX_TOV;
4472 rval = ql_mailbox_command(ha, mcp);
4473
4474 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
4475
4476 return (rval);
4477 }
4478
4479 /*
4480 * ql_get_port_config
4481 * The Get Port Configuration command retrieves the current configuration
4482 * for the external 10G port associated with this function.
4483 *
4484 * Input:
4485 * ha: adapter state pointer.
4486 * mr: pointer for mailbox data.
4487 *
4488 * Returns:
4489 * ql local function return status code.
4490 *
4491 * Context:
4492 * Kernel context.
4493 */
4494 int
4495 ql_get_port_config(ql_adapter_state_t *ha, ql_mbx_data_t *mrp)
4496 {
4497 int rval;
4498 mbx_cmd_t mc = {0};
4499 mbx_cmd_t *mcp = &mc;
4500
4501 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
4502
4503 mcp->mb[0] = MBC_GET_PORT_CONFIG;
4504 mcp->out_mb = MBX_0;
4505 mcp->in_mb = MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
4506 mcp->timeout = MAILBOX_TOV;
4507 rval = ql_mailbox_command(ha, mcp);
4508
4509 if (rval == QL_SUCCESS) {
4510 if (mrp != NULL) {
4511 mrp->mb[1] = mcp->mb[1];
4512 mrp->mb[2] = mcp->mb[2];
4513 mrp->mb[3] = mcp->mb[3];
4514 mrp->mb[4] = mcp->mb[4];
4515 }
4516 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
4517 } else {
4518 EL(ha, "status=%xh, mbx1=%xh, mbx2=%xh, mbx3=%xh, mbx4=%xh\n",
4519 rval, mcp->mb[1], mcp->mb[2], mcp->mb[3], mcp->mb[4]);
4520 }
4521
4522 return (rval);
4523 }
4524
4525 /*
4526 * ql_flash_access
4527 * The Get Port Configuration command retrieves the current configuration
4528 * for the external 10G port associated with this function
4529 *
4530 * Input:
4531 * ha: adapter state pointer.
4532 * cmd: command.
4533 * start: 32bit word address.
4534 * end: 32bit word address.
4535 * dp: 32bit word pointer.
4536 *
4537 * Returns:
4538 * ql local function return status code.
4539 *
4540 * Context:
4541 * Kernel context.
4542 */
4543 int
4544 ql_flash_access(ql_adapter_state_t *ha, uint16_t cmd, uint32_t start,
4545 uint32_t end, uint32_t *dp)
4546 {
4547 int rval;
4548 mbx_cmd_t mc = {0};
4549 mbx_cmd_t *mcp = &mc;
4550
4551 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
4552
4553 mcp->mb[0] = MBC_FLASH_ACCESS;
4554 if (cmd > 0 && cmd < 4) {
4555 mcp->mb[1] = (uint16_t)(FAC_FORCE_SEMA_LOCK | cmd);
4556 } else {
4557 mcp->mb[1] = cmd;
4558 }
4559 mcp->mb[2] = LSW(start);
4560 mcp->mb[3] = MSW(start);
4561 mcp->mb[4] = LSW(end);
4562 mcp->mb[5] = MSW(end);
4563
4564 mcp->out_mb = MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
4565 mcp->in_mb = MBX_2|MBX_1|MBX_0;
4566 mcp->timeout = MAILBOX_TOV;
4567 rval = ql_mailbox_command(ha, mcp);
4568
4569 if (rval != QL_SUCCESS) {
4570 EL(ha, "status=%xh, mbx1=%xh, mbx2=%xh\n", rval, mcp->mb[1],
4571 mcp->mb[2]);
4572 } else {
4573 if (dp != NULL) {
4574 *dp = (uint32_t)mcp->mb[1];
4575 }
4576 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
4577 }
4578
4579 return (rval);
4580 }
4581
4582 /*
4583 * ql_get_xgmac_stats
4584 * Issue et XGMAC Statistics Mailbox command
4585 *
4586 * Input:
4587 * ha: adapter state pointer.
4588 * size: size of data buffer.
4589 * bufp: data pointer for DMA data.
4590 *
4591 * Returns:
4592 * ql local function return status code.
4593 *
4594 * Context:
4595 * Kernel context.
4596 */
4597 int
4598 ql_get_xgmac_stats(ql_adapter_state_t *ha, size_t size, caddr_t bufp)
4599 {
4600 int rval;
4601 dma_mem_t mem_desc;
4602 mbx_cmd_t mc = {0};
4603 mbx_cmd_t *mcp = &mc;
4604
4605 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
4606
4607 if ((rval = ql_setup_mbox_dma_resources(ha, &mem_desc,
4608 (uint32_t)size)) != QL_SUCCESS) {
4609 EL(ha, "setup_mbox_dma_resources failed: %xh\n", rval);
4610 return (QL_MEMORY_ALLOC_FAILED);
4611 }
4612
4613 mcp->mb[0] = MBC_GET_XGMAC_STATS;
4614 mcp->mb[2] = MSW(mem_desc.cookie.dmac_address);
4615 mcp->mb[3] = LSW(mem_desc.cookie.dmac_address);
4616 mcp->mb[6] = MSW(mem_desc.cookie.dmac_notused);
4617 mcp->mb[7] = LSW(mem_desc.cookie.dmac_notused);
4618 mcp->mb[8] = (uint16_t)(size >> 2);
4619 mcp->out_mb = MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_0;
4620 mcp->in_mb = MBX_2|MBX_1|MBX_0;
4621 mcp->timeout = MAILBOX_TOV;
4622 rval = ql_mailbox_command(ha, mcp);
4623
4624 if (rval == QL_SUCCESS) {
4625 ql_get_mbox_dma_data(&mem_desc, bufp);
4626 }
4627 ql_free_dma_resource(ha, &mem_desc);
4628
4629 if (rval != QL_SUCCESS) {
4630 EL(ha, "status=%xh, mbx1=%xh, mbx2=%xh\n", rval, mcp->mb[1],
4631 mcp->mb[2]);
4632 } else {
4633 /*EMPTY*/
4634 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
4635 }
4636
4637 return (rval);
4638 }
4639
4640 /*
4641 * ql_get_dcbx_params
4642 * Issue get DCBX parameters mailbox command.
4643 *
4644 * Input:
4645 * ha: adapter state pointer.
4646 * size: size of data buffer.
4647 * bufp: data pointer for DMA data.
4648 *
4649 * Returns:
4650 * ql local function return status code.
4651 *
4652 * Context:
4653 * Kernel context.
4654 */
4655 int
4656 ql_get_dcbx_params(ql_adapter_state_t *ha, uint32_t size, caddr_t bufp)
4657 {
4658 int rval;
4659 dma_mem_t mem_desc;
4660 mbx_cmd_t mc = {0};
4661 mbx_cmd_t *mcp = &mc;
4662
4663 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
4664
4665 if ((rval = ql_setup_mbox_dma_resources(ha, &mem_desc, size)) !=
4666 QL_SUCCESS) {
4667 EL(ha, "failed=%xh\n", QL_MEMORY_ALLOC_FAILED);
4668 return (QL_MEMORY_ALLOC_FAILED);
4669 }
4670
4671 mcp->mb[0] = MBC_GET_DCBX_PARAMS;
4672 mcp->mb[1] = 0; /* Return all DCBX paramters */
4673 mcp->mb[2] = MSW(LSD(mem_desc.cookie.dmac_laddress));
4674 mcp->mb[3] = LSW(LSD(mem_desc.cookie.dmac_laddress));
4675 mcp->mb[6] = MSW(MSD(mem_desc.cookie.dmac_laddress));
4676 mcp->mb[7] = LSW(MSD(mem_desc.cookie.dmac_laddress));
4677 mcp->mb[8] = (uint16_t)size;
4678 mcp->out_mb = MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
4679 mcp->in_mb = MBX_2|MBX_1|MBX_0;
4680 mcp->timeout = MAILBOX_TOV;
4681 rval = ql_mailbox_command(ha, mcp);
4682
4683 if (rval == QL_SUCCESS) {
4684 ql_get_mbox_dma_data(&mem_desc, bufp);
4685 }
4686
4687 ql_free_dma_resource(ha, &mem_desc);
4688
4689 if (rval != QL_SUCCESS) {
4690 EL(ha, "failed=%xh\n", rval);
4691 } else {
4692 /*EMPTY*/
4693 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
4694 }
4695
4696 return (rval);
4697 }
4698 /*
4699 * ql_get_fcf_list
4700 * Issue get FCF list mailbox command.
4701 *
4702 * Input:
4703 * ha: adapter state pointer.
4704 * fcf_list: pointer to ql_fcf_list_desc_t
4705 * bufp: data pointer for DMA data.
4706 *
4707 * Returns:
4708 * ql local function return status code.
4709 *
4710 * Context:
4711 * Kernel context.
4712 */
4713
4714 int
4715 ql_get_fcf_list_mbx(ql_adapter_state_t *ha, ql_fcf_list_desc_t *fcf_list,
4716 caddr_t bufp)
4717 {
4718 int rval;
4719 dma_mem_t mem_desc;
4720 mbx_cmd_t mc = {0};
4721 mbx_cmd_t *mcp = &mc;
4722
4723 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
4724
4725 if ((rval = ql_setup_mbox_dma_resources(ha, &mem_desc,
4726 fcf_list->buffer_size)) !=
4727 QL_SUCCESS) {
4728 EL(ha, "failed=%xh\n", QL_MEMORY_ALLOC_FAILED);
4729 return (QL_MEMORY_ALLOC_FAILED);
4730 }
4731
4732 mcp->mb[0] = MBC_GET_FCF_LIST;
4733 mcp->mb[1] = fcf_list->options;
4734 mcp->mb[2] = MSW(LSD(mem_desc.cookie.dmac_laddress));
4735 mcp->mb[3] = LSW(LSD(mem_desc.cookie.dmac_laddress));
4736 mcp->mb[6] = MSW(MSD(mem_desc.cookie.dmac_laddress));
4737 mcp->mb[7] = LSW(MSD(mem_desc.cookie.dmac_laddress));
4738 mcp->mb[8] = (uint16_t)fcf_list->buffer_size;
4739 mcp->mb[9] = fcf_list->fcf_index;
4740 mcp->out_mb = MBX_9|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
4741 mcp->in_mb = MBX_2|MBX_1|MBX_0;
4742 mcp->timeout = MAILBOX_TOV;
4743 rval = ql_mailbox_command(ha, mcp);
4744
4745 if (rval == QL_SUCCESS) {
4746 ql_get_mbox_dma_data(&mem_desc, bufp);
4747 fcf_list->buffer_size = (uint16_t)mcp->mb[1];
4748 }
4749
4750 ql_free_dma_resource(ha, &mem_desc);
4751
4752 if (rval != QL_SUCCESS) {
4753 EL(ha, "status=%xh, mbx1=%xh, mbx2=%xh\n", rval, mcp->mb[1],
4754 mcp->mb[2]);
4755 } else {
4756 /*EMPTY*/
4757 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
4758 }
4759
4760 return (rval);
4761 }
4762
4763 /*
4764 * ql_get_resource_cnts
4765 * Issue get Resourse Count mailbox command.
4766 *
4767 * Input:
4768 * ha: adapter state pointer.
4769 * mr: pointer for mailbox data.
4770 *
4771 * Returns:
4772 * ql local function return status code.
4773 *
4774 * Context:
4775 * Kernel context.
4776 */
4777
4778 int
4779 ql_get_resource_cnts(ql_adapter_state_t *ha, ql_mbx_data_t *mr)
4780 {
4781 int rval;
4782 mbx_cmd_t mc = {0};
4783 mbx_cmd_t *mcp = &mc;
4784
4785 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
4786
4787 mcp->mb[0] = MBC_GET_RESOURCE_COUNTS;
4788 mcp->out_mb = MBX_0;
4789 mcp->in_mb = MBX_12|MBX_11|MBX_10|MBX_7|MBX_6|
4790 MBX_3|MBX_2|MBX_1|MBX_0;
4791 mcp->timeout = MAILBOX_TOV;
4792 rval = ql_mailbox_command(ha, mcp);
4793
4794 /* Return mailbox data. */
4795 if (mr != NULL) {
4796 mr->mb[1] = mcp->mb[1];
4797 mr->mb[2] = mcp->mb[2];
4798 mr->mb[3] = mcp->mb[3];
4799 mr->mb[6] = mcp->mb[6];
4800 mr->mb[7] = mcp->mb[7];
4801 mr->mb[10] = mcp->mb[10];
4802 mr->mb[11] = mcp->mb[11];
4803 mr->mb[12] = mcp->mb[12];
4804 }
4805
4806 if (rval != QL_SUCCESS) {
4807 EL(ha, "failed=%xh\n", rval);
4808 } else {
4809 /*EMPTY*/
4810 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
4811 }
4812
4813 return (rval);
4814 }
4815
4816 /*
4817 * ql_toggle_interrupt
4818 * Issue Toggle Interrupt Mailbox Command.
4819 *
4820 * Input:
4821 * ha: adapter state pointer.
4822 * opt: 0 = disable, 1 = enable.
4823 *
4824 * Returns:
4825 * ql local function return status code.
4826 *
4827 * Context:
4828 * Kernel context.
4829 */
4830 int
4831 ql_toggle_interrupt(ql_adapter_state_t *ha, uint16_t opt)
4832 {
4833 int rval;
4834 mbx_cmd_t mc = {0};
4835 mbx_cmd_t *mcp = &mc;
4836
4837 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
4838
4839 mcp->mb[0] = MBC_TOGGLE_INTERRUPT;
4840 mcp->mb[1] = opt;
4841 mcp->out_mb = MBX_1|MBX_0;
4842 mcp->in_mb = MBX_0;
4843 mcp->timeout = 2;
4844 rval = ql_mailbox_command(ha, mcp);
4845
4846 if (rval != QL_SUCCESS) {
4847 EL(ha, "failed=%xh\n", rval);
4848 } else {
4849 /*EMPTY*/
4850 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
4851 }
4852
4853 return (rval);
4854 }