1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2010 QLogic Corporation. All rights reserved.
24 */
25
26 #include <qlge.h>
27
28 static int ql_async_event_parser(qlge_t *, mbx_data_t *);
29
30 /*
31 * Wait upto timeout seconds for Processor Interrupt
32 * if timeout is 0, then wait for default waittime
33 */
34 static int
35 ql_poll_processor_intr(qlge_t *qlge, uint8_t timeout)
36 {
37 int rtn_val = DDI_SUCCESS;
38
39 if (ql_wait_reg_bit(qlge, REG_STATUS, STS_PI, BIT_SET, timeout)
40 != DDI_SUCCESS) {
41 cmn_err(CE_WARN, "Polling for processor interrupt failed.");
42 rtn_val = DDI_FAILURE;
43 }
44 return (rtn_val);
45 }
46
47 /*
48 * Wait for mailbox Processor Register Ready
49 */
50 static int
51 ql_wait_processor_addr_reg_ready(qlge_t *qlge)
52 {
53 int rtn_val = DDI_SUCCESS;
54
55 if (ql_wait_reg_bit(qlge, REG_PROCESSOR_ADDR,
56 PROCESSOR_ADDRESS_RDY, BIT_SET, 0) != DDI_SUCCESS) {
57 cmn_err(CE_WARN,
58 "Wait for processor address register ready timeout.");
59 rtn_val = DDI_FAILURE;
60 }
61 return (rtn_val);
62 }
63
64 /*
65 * Read and write MPI registers using the indirect register interface
66 * Assume all the locks&semaphore have been acquired
67 */
68 int
69 ql_write_processor_data(qlge_t *qlge, uint32_t addr, uint32_t data)
70 {
71 int rtn_val = DDI_FAILURE;
72
73 /* wait for processor address register ready */
74 if (ql_wait_processor_addr_reg_ready(qlge) == DDI_FAILURE)
75 goto out;
76 /* write the data to the data reg */
77 ql_write_reg(qlge, REG_PROCESSOR_DATA, data);
78 /* trigger the write */
79 ql_write_reg(qlge, REG_PROCESSOR_ADDR, addr);
80 /* wait for register to come ready */
81 if (ql_wait_processor_addr_reg_ready(qlge) == DDI_FAILURE)
82 goto out;
83
84 rtn_val = DDI_SUCCESS;
85
86 out:
87 return (rtn_val);
88
89 }
90
91 /*
92 * Read from processor register
93 */
94 int
95 ql_read_processor_data(qlge_t *qlge, uint32_t addr, uint32_t *data)
96 {
97 int rtn_val = DDI_FAILURE;
98
99 /* enable read operation */
100 addr |= PROCESSOR_ADDRESS_READ;
101 /* wait for processor address register ready */
102 if (ql_wait_processor_addr_reg_ready(qlge) == DDI_FAILURE)
103 goto out;
104
105 /* Write read address, wait for data ready in Data register */
106 ql_write_reg(qlge, REG_PROCESSOR_ADDR, addr);
107 /* wait for data ready */
108 if (ql_wait_processor_addr_reg_ready(qlge) == DDI_FAILURE)
109 goto out;
110 /* read data */
111 *data = ql_read_reg(qlge, REG_PROCESSOR_DATA);
112
113 rtn_val = DDI_SUCCESS;
114
115 out:
116 return (rtn_val);
117
118 }
119
120 /*
121 * Read "count" number of outgoing Mailbox register starting
122 * from mailbox #0 if count is 0 then read all mailboxes
123 */
124 static int
125 ql_read_mailbox_cmd(qlge_t *qlge, mbx_data_t *mbx_buf, uint32_t count)
126 {
127 int rtn_val = DDI_FAILURE;
128 uint32_t reg_status;
129 uint32_t addr;
130 int i;
131
132 if (ql_sem_spinlock(qlge, QL_PROCESSOR_SEM_MASK) != DDI_SUCCESS) {
133 cmn_err(CE_WARN,
134 "%s(%d) get QL_PROCESSOR_SEM_MASK time out error",
135 __func__, qlge->instance);
136 return (DDI_FAILURE);
137 }
138
139 if (qlge->func_number == qlge->fn0_net)
140 addr = FUNC_0_OUT_MAILBOX_0_REG_OFFSET;
141 else
142 addr = FUNC_1_OUT_MAILBOX_0_REG_OFFSET;
143
144 if (count == 0)
145 count = NUM_MAILBOX_REGS;
146 for (i = 0; i < count; i++) {
147 if (ql_read_processor_data(qlge, addr, ®_status)
148 == DDI_FAILURE)
149 goto out;
150 QL_PRINT(DBG_MBX, ("%s(%d) mailbox %d value 0x%x\n",
151 __func__, qlge->instance, i, reg_status));
152 mbx_buf->mb[i] = reg_status;
153 addr ++;
154 }
155
156 rtn_val = DDI_SUCCESS;
157
158 out:
159 ql_sem_unlock(qlge, QL_PROCESSOR_SEM_MASK);
160
161 return (rtn_val);
162
163 }
164
165 /*
166 * Write mail box command (upto 16) to MPI Firmware
167 */
168 int
169 ql_issue_mailbox_cmd(qlge_t *qlge, mbx_cmd_t *mbx_cmd)
170 {
171 int rtn_val = DDI_FAILURE;
172 uint32_t addr;
173 int i;
174 /*
175 * Get semaphore to access Processor Address and
176 * Processor Data Registers
177 */
178 if (ql_sem_spinlock(qlge, QL_PROCESSOR_SEM_MASK) != DDI_SUCCESS) {
179 return (DDI_FAILURE);
180 }
181 /* ensure no overwriting current command */
182 if (ql_wait_reg_bit(qlge, REG_HOST_CMD_STATUS,
183 HOST_TO_MPI_INTR_NOT_DONE, BIT_RESET, 0) != DDI_SUCCESS) {
184 goto out;
185 }
186
187 if (qlge->func_number == qlge->fn0_net)
188 addr = FUNC_0_IN_MAILBOX_0_REG_OFFSET;
189 else
190 addr = FUNC_1_IN_MAILBOX_0_REG_OFFSET;
191
192 /* wait for mailbox registers to be ready to access */
193 if (ql_wait_processor_addr_reg_ready(qlge) == DDI_FAILURE)
194 goto out;
195
196 /* issue mailbox command one by one */
197 for (i = 0; i < NUM_MAILBOX_REGS; i++) {
198 /* write sending cmd to mailbox data register */
199 ql_write_reg(qlge, REG_PROCESSOR_DATA, mbx_cmd->mb[i]);
200 /* write mailbox address to address register */
201 ql_write_reg(qlge, REG_PROCESSOR_ADDR, addr);
202 QL_PRINT(DBG_MBX, ("%s(%d) write %x to mailbox(%x) addr %x \n",
203 __func__, qlge->instance, mbx_cmd->mb[i], i, addr));
204 addr++;
205 /*
206 * wait for mailbox cmd to be written before
207 * next write can start
208 */
209 if (ql_wait_processor_addr_reg_ready(qlge) == DDI_FAILURE)
210 goto out;
211 }
212 /* inform MPI that new mailbox commands are available */
213 ql_write_reg(qlge, REG_HOST_CMD_STATUS, HOST_CMD_SET_RISC_INTR);
214 rtn_val = DDI_SUCCESS;
215 out:
216 ql_sem_unlock(qlge, QL_PROCESSOR_SEM_MASK);
217 return (rtn_val);
218 }
219
220 /*
221 * Send mail box command (upto 16) to MPI Firmware
222 * and polling for MPI mailbox completion response when
223 * interrupt is not enabled.
224 * The MBX_LOCK mutexe should have been held and released
225 * externally
226 */
227 int
228 ql_issue_mailbox_cmd_and_poll_rsp(qlge_t *qlge, mbx_cmd_t *mbx_cmd,
229 mbx_data_t *p_results)
230 {
231 int rtn_val = DDI_FAILURE;
232 boolean_t done;
233 int max_wait;
234
235 if (mbx_cmd == NULL)
236 goto err;
237
238 rtn_val = ql_issue_mailbox_cmd(qlge, mbx_cmd);
239 if (rtn_val != DDI_SUCCESS) {
240 cmn_err(CE_WARN, "%s(%d) ql_issue_mailbox_cmd failed",
241 __func__, qlge->instance);
242 goto err;
243 }
244 done = B_FALSE;
245 max_wait = 5; /* wait upto 5 PI interrupt */
246 /* delay for the processor interrupt is received */
247 while ((done != B_TRUE) && (max_wait--)) {
248 /* wait up to 5s for PI interrupt */
249 if (ql_poll_processor_intr(qlge, (uint8_t)mbx_cmd->timeout)
250 == DDI_SUCCESS) {
251 QL_PRINT(DBG_MBX, ("%s(%d) PI Intr received",
252 __func__, qlge->instance));
253 (void) ql_read_mailbox_cmd(qlge, p_results, 0);
254 /*
255 * Sometimes, the incoming messages is not what we are
256 * waiting for, ie. async events, then, continue to
257 * wait. If it is the result * of previous mailbox
258 * command, then Done. No matter what, send
259 * HOST_CMD_CLEAR_RISC_TO_HOST_INTR to clear each
260 * PI interrupt
261 */
262 if (ql_async_event_parser(qlge, p_results) == B_FALSE) {
263 /*
264 * we get what we are waiting for,
265 * clear the interrupt
266 */
267 rtn_val = DDI_SUCCESS;
268 done = B_TRUE;
269 } else {
270 /*EMPTY*/
271 QL_PRINT(DBG_MBX,
272 ("%s(%d) result ignored, not we wait for\n",
273 __func__, qlge->instance));
274 }
275 ql_write_reg(qlge, REG_HOST_CMD_STATUS,
276 HOST_CMD_CLEAR_RISC_TO_HOST_INTR);
277 } else { /* timeout */
278 done = B_TRUE;
279 }
280 rtn_val = DDI_SUCCESS;
281 }
282 err:
283 return (rtn_val);
284 }
285 /*
286 * Send mail box command (upto 16) to MPI Firmware
287 * and wait for MPI mailbox completion response which
288 * is saved in interrupt. Thus, this function can only
289 * be used after interrupt is enabled.
290 * Must hold MBX mutex before calling this function
291 */
292 static int
293 ql_issue_mailbox_cmd_and_wait_rsp(qlge_t *qlge, mbx_cmd_t *mbx_cmd)
294 {
295 int rtn_val = DDI_FAILURE;
296 clock_t timer;
297 int i;
298 int done = 0;
299
300 if (mbx_cmd == NULL)
301 goto err;
302
303 ASSERT(mutex_owned(&qlge->mbx_mutex));
304
305 /* if interrupts are not enabled, poll when results are available */
306 if (!(qlge->flags & INTERRUPTS_ENABLED)) {
307 rtn_val = ql_issue_mailbox_cmd_and_poll_rsp(qlge, mbx_cmd,
308 &qlge->received_mbx_cmds);
309 if (rtn_val == DDI_SUCCESS) {
310 for (i = 0; i < NUM_MAILBOX_REGS; i++)
311 mbx_cmd->mb[i] = qlge->received_mbx_cmds.mb[i];
312 }
313 } else {
314 rtn_val = ql_issue_mailbox_cmd(qlge, mbx_cmd);
315 if (rtn_val != DDI_SUCCESS) {
316 cmn_err(CE_WARN, "%s(%d) ql_issue_mailbox_cmd failed",
317 __func__, qlge->instance);
318 goto err;
319 }
320 qlge->mbx_wait_completion = 1;
321 while (!done && qlge->mbx_wait_completion && !ddi_in_panic()) {
322 /* default 5 seconds from now to timeout */
323 timer = ddi_get_lbolt();
324 if (mbx_cmd->timeout) {
325 timer += drv_sectohz(mbx_cmd->timeout);
326 } else {
327 timer += drv_sectohz(5);
328 }
329 if (cv_timedwait(&qlge->cv_mbx_intr, &qlge->mbx_mutex,
330 timer) == -1) {
331 /*
332 * The timeout time 'timer' was
333 * reached or expired without the condition
334 * being signaled.
335 */
336 cmn_err(CE_WARN, "%s(%d) Wait for Mailbox cmd "
337 "complete timeout.",
338 __func__, qlge->instance);
339 rtn_val = DDI_FAILURE;
340 done = 1;
341 } else {
342 QL_PRINT(DBG_MBX,
343 ("%s(%d) mailbox completion signal received"
344 " \n", __func__, qlge->instance));
345 for (i = 0; i < NUM_MAILBOX_REGS; i++) {
346 mbx_cmd->mb[i] =
347 qlge->received_mbx_cmds.mb[i];
348 }
349 rtn_val = DDI_SUCCESS;
350 done = 1;
351 }
352 }
353 }
354 err:
355 return (rtn_val);
356 }
357
358 /*
359 * Inteprete incoming asynchronous events
360 */
361 static int
362 ql_async_event_parser(qlge_t *qlge, mbx_data_t *mbx_cmds)
363 {
364 uint32_t link_status, cmd;
365 uint8_t link_speed;
366 uint8_t link_type;
367 boolean_t proc_done = B_TRUE;
368 mbx_cmd_t reply_cmd = {0};
369 boolean_t fatal_error = B_FALSE;
370
371 switch (mbx_cmds->mb[0]) {
372 case MBA_IDC_INTERMEDIATE_COMPLETE /* 1000h */:
373 QL_PRINT(DBG_MBX, ("%s(%d):"
374 "MBA_IDC_INTERMEDIATE_COMPLETE received\n",
375 __func__, qlge->instance));
376 break;
377 case MBA_SYSTEM_ERR /* 8002h */:
378 cmn_err(CE_WARN, "%s(%d): MBA_SYSTEM_ERR received",
379 __func__, qlge->instance);
380 cmn_err(CE_WARN, "%s(%d): File id %x, Line # %x,"
381 "Firmware Ver# %x",
382 __func__, qlge->instance, mbx_cmds->mb[1],
383 mbx_cmds->mb[2], mbx_cmds->mb[3]);
384 fatal_error = B_TRUE;
385 (void) ql_8xxx_binary_core_dump(qlge, &qlge->ql_mpi_coredump);
386 break;
387 case MBA_LINK_UP /* 8011h */:
388 QL_PRINT(DBG_MBX, ("%s(%d): MBA_LINK_UP received\n",
389 __func__, qlge->instance));
390 link_status = mbx_cmds->mb[1];
391 QL_PRINT(DBG_MBX, ("%s(%d): Link Status %x \n",
392 __func__, qlge->instance, link_status));
393 link_speed = (uint8_t)((link_status >> 3) & 0x07);
394
395 if (link_speed == 0) {
396 qlge->speed = SPEED_100;
397 QL_PRINT(DBG_MBX, ("%s(%d):Link speed 100M\n",
398 __func__, qlge->instance));
399 } else if (link_speed == 1) {
400 qlge->speed = SPEED_1000;
401 QL_PRINT(DBG_MBX, ("%s(%d):Link speed 1G\n",
402 __func__, qlge->instance));
403 } else if (link_speed == 2) {
404 qlge->speed = SPEED_10G;
405 QL_PRINT(DBG_MBX, ("%s(%d):Link speed 10G\n",
406 __func__, qlge->instance));
407 }
408
409 qlge->link_type = link_type = (uint8_t)(link_status & 0x07);
410
411 if (link_type == XFI_NETWORK_INTERFACE) {
412 /* EMPTY */
413 QL_PRINT(DBG_MBX,
414 ("%s(%d):Link type XFI_NETWORK_INTERFACE\n",
415 __func__, qlge->instance));
416 } else if (link_type == XAUI_NETWORK_INTERFACE) {
417 /* EMPTY */
418 QL_PRINT(DBG_MBX, ("%s(%d):Link type"
419 "XAUI_NETWORK_INTERFACE\n",
420 __func__, qlge->instance));
421 } else if (link_type == XFI_BACKPLANE_INTERFACE) {
422 /* EMPTY */
423 QL_PRINT(DBG_MBX, ("%s(%d):Link type"
424 "XFI_BACKPLANE_INTERFACE\n",
425 __func__, qlge->instance));
426 } else if (link_type == XAUI_BACKPLANE_INTERFACE) {
427 /* EMPTY */
428 QL_PRINT(DBG_MBX, ("%s(%d):Link type "
429 "XAUI_BACKPLANE_INTERFACE\n",
430 __func__, qlge->instance));
431 } else if (link_type == EXT_10GBASE_T_PHY) {
432 /* EMPTY */
433 QL_PRINT(DBG_MBX,
434 ("%s(%d):Link type EXT_10GBASE_T_PHY\n",
435 __func__, qlge->instance));
436 } else if (link_type == EXT_EXT_EDC_PHY) {
437 /* EMPTY */
438 QL_PRINT(DBG_MBX,
439 ("%s(%d):Link type EXT_EXT_EDC_PHY\n",
440 __func__, qlge->instance));
441 } else {
442 /* EMPTY */
443 QL_PRINT(DBG_MBX,
444 ("%s(%d):unknown Link type \n",
445 __func__, qlge->instance));
446 }
447 cmn_err(CE_NOTE, "qlge(%d) mpi link up! speed %dMbps\n",
448 qlge->instance, qlge->speed);
449 /*
450 * start timer if not started to delay some time then
451 * check if link is really up or down
452 */
453 ql_restart_timer(qlge);
454
455 break;
456 case MBA_LINK_DOWN /* 8012h */:
457 QL_PRINT(DBG_MBX,
458 ("%s(%d): MBA_LINK_DOWN received\n",
459 __func__, qlge->instance));
460
461 link_status = mbx_cmds->mb[1];
462
463 QL_PRINT(DBG_MBX, ("%s(%d): Link Status %x \n",
464 __func__, qlge->instance, link_status));
465 if (link_status & 0x1) {
466 /* EMPTY */
467 QL_PRINT(DBG_MBX, ("%s(%d): Loss of signal \n",
468 __func__, qlge->instance));
469 }
470 if (link_status & 0x2) {
471 /* EMPTY */
472 QL_PRINT(DBG_MBX,
473 ("%s(%d): Auto-Negotiation Failed \n",
474 __func__, qlge->instance));
475 }
476 if (link_status & 0x4) {
477 /* EMPTY */
478 QL_PRINT(DBG_MBX,
479 ("%s(%d): XTI-Training Failed \n",
480 __func__, qlge->instance));
481 }
482
483 cmn_err(CE_NOTE, "qlge(%d) mpi link down!\n", qlge->instance);
484 ql_restart_timer(qlge);
485 break;
486 case MBA_IDC_COMPLETE /* 8100h */:
487
488 QL_PRINT(DBG_MBX,
489 ("%s(%d): MBA_IDC_COMPLETE received\n",
490 __func__, qlge->instance));
491 cmd = mbx_cmds->mb[1];
492 if (cmd == MBC_STOP_FIRMWARE) {
493 /* EMPTY */
494 QL_PRINT(DBG_MBX,
495 ("%s(%d): STOP_FIRMWARE event completed\n",
496 __func__, qlge->instance));
497 } else if (cmd == MBC_IDC_REQUEST) {
498 /* EMPTY */
499 QL_PRINT(DBG_MBX,
500 ("%s(%d): IDC_REQUEST event completed\n",
501 __func__, qlge->instance));
502 } else if (cmd == MBC_PORT_RESET) {
503 /* EMPTY */
504 QL_PRINT(DBG_MBX,
505 ("%s(%d): PORT_RESET event completed\n",
506 __func__, qlge->instance));
507 } else if (cmd == MBC_SET_PORT_CONFIG) {
508 /* EMPTY */
509 QL_PRINT(DBG_MBX,
510 ("%s(%d): SET_PORT_CONFIG event "
511 "completed\n", __func__, qlge->instance));
512 } else {
513 /* EMPTY */
514 QL_PRINT(DBG_MBX,
515 ("%s(%d): unknown IDC completion request"
516 " event %x %x\n", __func__, qlge->instance,
517 mbx_cmds->mb[1], mbx_cmds->mb[2]));
518 }
519 proc_done = B_FALSE;
520 break;
521
522 case MBA_IDC_REQUEST_NOTIFICATION /* 8101h */:
523 QL_PRINT(DBG_MBX,
524 ("%s(%d): MBA_IDC_REQUEST_NOTIFICATION "
525 "received\n", __func__, qlge->instance));
526 cmd = mbx_cmds->mb[1];
527 if (cmd == MBC_STOP_FIRMWARE) {
528 /* EMPTY */
529 QL_PRINT(DBG_MBX,
530 ("%s(%d): STOP_FIRMWARE notification"
531 " received\n", __func__, qlge->instance));
532 } else if (cmd == MBC_IDC_REQUEST) {
533 /* EMPTY */
534 QL_PRINT(DBG_MBX,
535 ("%s(%d): IDC_REQUEST notification "
536 "received\n", __func__, qlge->instance));
537 } else if (cmd == MBC_PORT_RESET) {
538 /* EMPTY */
539 QL_PRINT(DBG_MBX, ("%s(%d): PORT_RESET "
540 "notification received\n",
541 __func__, qlge->instance));
542 } else if (cmd == MBC_SET_PORT_CONFIG) {
543 /* EMPTY */
544 QL_PRINT(DBG_MBX,
545 ("%s(%d): SET_PORT_CONFIG notification "
546 "received\n", __func__, qlge->instance));
547 } else {
548 /* EMPTY */
549 QL_PRINT(DBG_MBX, ("%s(%d): "
550 "unknown request received %x %x\n",
551 __func__, qlge->instance, mbx_cmds->mb[1],
552 mbx_cmds->mb[2]));
553 }
554 reply_cmd.mb[0] = MBC_IDC_ACK;
555 reply_cmd.mb[1] = mbx_cmds->mb[1];
556 reply_cmd.mb[2] = mbx_cmds->mb[2];
557 reply_cmd.mb[3] = mbx_cmds->mb[3];
558 reply_cmd.mb[4] = mbx_cmds->mb[4];
559 if (ql_issue_mailbox_cmd(qlge, &reply_cmd)
560 != DDI_SUCCESS) {
561 cmn_err(CE_WARN,
562 "%s(%d) send IDC Ack failed.",
563 __func__, qlge->instance);
564 }
565 /*
566 * verify if the incoming outbound mailbox value is what
567 * we just sent
568 */
569 if (mbx_cmds->mb[0] == MBS_COMMAND_COMPLETE) {
570 /* 0x4000 */
571 /* EMPTY */
572 QL_PRINT(DBG_MBX,
573 ("%s(%d): IDC Ack sent success.\n",
574 __func__, qlge->instance));
575 } else {
576 /* EMPTY */
577 QL_PRINT(DBG_MBX,
578 ("%s(%d): IDC Ack reply error %x %x %x.\n",
579 __func__, qlge->instance, mbx_cmds->mb[0],
580 mbx_cmds->mb[1], mbx_cmds->mb[2]));
581 }
582 break;
583 case MBA_IDC_TIME_EXTENDED /* 8102 */:
584 QL_PRINT(DBG_MBX,
585 ("%s(%d): MBA_IDC_TIME_EXTENDED received\n",
586 __func__, qlge->instance));
587 break;
588 case MBA_DCBX_CONFIG_CHANGE /* 8110 */:
589 QL_PRINT(DBG_MBX,
590 ("%s(%d): MBA_DCBX_CONFIG_CHANGE received\n",
591 __func__, qlge->instance));
592 break;
593 case MBA_NOTIFICATION_LOST /* 8120 */:
594 QL_PRINT(DBG_MBX,
595 ("%s(%d): MBA_NOTIFICATION_LOST received\n",
596 __func__, qlge->instance));
597 break;
598 case MBA_SFT_TRANSCEIVER_INSERTION /* 8130 */:
599 QL_PRINT(DBG_MBX,
600 ("%s(%d): MBA_SFT_TRANSCEIVER_INSERTION "
601 "received\n", __func__, qlge->instance));
602 break;
603 case MBA_SFT_TRANSCEIVER_REMOVAL /* 8140 */:
604 QL_PRINT(DBG_MBX,
605 ("%s(%d): MBA_SFT_TRANSCEIVER_REMOVAL "
606 "received\n", __func__, qlge->instance));
607 break;
608 case MBA_FIRMWARE_INIT_COMPLETE /* 8400 */:
609 QL_PRINT(DBG_MBX,
610 ("%s(%d): MBA_FIRMWARE_INIT_COMPLETE "
611 "received\n", __func__, qlge->instance));
612 QL_PRINT(DBG_MBX,
613 ("%s(%d): mbx[1] %x, mbx[2] %x\n", __func__,
614 qlge->instance, mbx_cmds->mb[1], mbx_cmds->mb[2]));
615 qlge->fw_init_complete = B_TRUE;
616 qlge->fw_version_info.major_version =
617 LSB(MSW(mbx_cmds->mb[1]));
618 qlge->fw_version_info.minor_version =
619 MSB(LSW(mbx_cmds->mb[1]));
620 qlge->fw_version_info.sub_minor_version =
621 LSB(LSW(mbx_cmds->mb[1]));
622 qlge->phy_version_info.major_version =
623 LSB(MSW(mbx_cmds->mb[2]));
624 qlge->phy_version_info.minor_version =
625 MSB(LSW(mbx_cmds->mb[2]));
626 qlge->phy_version_info.sub_minor_version =
627 LSB(LSW(mbx_cmds->mb[2]));
628 break;
629 case MBA_FIRMWARE_INIT_FAILED /* 8401 */:
630 cmn_err(CE_WARN, "%s(%d):"
631 "ASYNC_EVENT_FIRMWARE_INIT_FAILURE "
632 "received: mbx[1] %x, mbx[2] %x",
633 __func__, qlge->instance,
634 mbx_cmds->mb[1], mbx_cmds->mb[2]);
635 fatal_error = B_TRUE;
636 break;
637 default:
638 if (mbx_cmds->mb[0] > 0x8000) {
639 cmn_err(CE_WARN, "%s(%d): "
640 "Unknown Async event received: mbx[0] %x ,"
641 "mbx[1] %x; mbx[2] %x",
642 __func__, qlge->instance,
643 mbx_cmds->mb[0], mbx_cmds->mb[1],
644 mbx_cmds->mb[2]);
645 proc_done = B_TRUE;
646 } else {
647 proc_done = B_FALSE;
648 }
649 break;
650 }
651 if (fatal_error) {
652 if (qlge->fm_enable) {
653 ql_fm_ereport(qlge, DDI_FM_DEVICE_NO_RESPONSE);
654 ddi_fm_service_impact(qlge->dip, DDI_SERVICE_LOST);
655 atomic_or_32(&qlge->flags, ADAPTER_ERROR);
656 }
657 }
658 return (proc_done);
659 }
660
661
662 /*
663 * MPI Interrupt handler
664 * Caller must have MBX_LOCK
665 */
666 void
667 ql_do_mpi_intr(qlge_t *qlge)
668 {
669 /*
670 * we just need to read first few mailboxes that this adapter's MPI
671 * will write response to.
672 */
673 mutex_enter(&qlge->mbx_mutex);
674
675 (void) ql_read_mailbox_cmd(qlge, &qlge->received_mbx_cmds,
676 qlge->max_read_mbx);
677
678 /*
679 * process PI interrupt as async events, if not done,
680 * then pass to mailbox processing
681 */
682 if (ql_async_event_parser(qlge, &qlge->received_mbx_cmds) == B_FALSE) {
683 QL_PRINT(DBG_MBX, ("%s(%d) mailbox completion interrupt\n",
684 __func__, qlge->instance));
685 /*
686 * If another thread is waiting for the mail box
687 * completion event to occur
688 */
689 if (qlge->mbx_wait_completion == 1) {
690 qlge->mbx_wait_completion = 0;
691 cv_broadcast(&qlge->cv_mbx_intr);
692 QL_PRINT(DBG_MBX,
693 ("%s(%d) mailbox completion signaled \n",
694 __func__, qlge->instance));
695 }
696 }
697 /* inform MPI Firmware to clear the interrupt */
698 ql_write_reg(qlge, REG_HOST_CMD_STATUS,
699 HOST_CMD_CLEAR_RISC_TO_HOST_INTR /* 0x0A */);
700 mutex_exit(&qlge->mbx_mutex);
701 ql_enable_completion_interrupt(qlge, 0); /* MPI is on irq 0 */
702 }
703
704 /*
705 * Test if mailbox communication works
706 * This is used when Interrupt is not enabled
707 */
708 int
709 ql_mbx_test(qlge_t *qlge)
710 {
711 mbx_cmd_t mbx_cmds;
712 mbx_data_t mbx_results;
713 int i, test_ok = 1;
714 int rtn_val = DDI_FAILURE;
715
716 for (i = 0; i < NUM_MAILBOX_REGS; i++)
717 mbx_cmds.mb[i] = i;
718
719 mbx_cmds.mb[0] = MBC_MAILBOX_REGISTER_TEST; /* 0x06 */
720 if (ql_issue_mailbox_cmd(qlge, &mbx_cmds) != DDI_SUCCESS) {
721 cmn_err(CE_WARN, "%s(%d) ql_issue_mailbox_cmd timeout.",
722 __func__, qlge->instance);
723 goto out;
724 }
725
726 /* delay for the processor interrupt is received */
727 if (ql_poll_processor_intr(qlge, (uint8_t)mbx_cmds.timeout)
728 == DDI_SUCCESS) {
729 QL_PRINT(DBG_MBX, ("%s(%d) PI Intr received",
730 __func__, qlge->instance));
731 (void) ql_read_mailbox_cmd(qlge, &mbx_results, 0);
732
733 ql_write_reg(qlge, REG_HOST_CMD_STATUS,
734 HOST_CMD_CLEAR_RISC_TO_HOST_INTR);
735
736 if (mbx_results.mb[0] != MBS_COMMAND_COMPLETE /* 0x4000 */) {
737 test_ok = 0;
738 } else {
739 for (i = 1; i < NUM_MAILBOX_REGS; i++) {
740 if (mbx_results.mb[i] != i) {
741 test_ok = 0;
742 break;
743 }
744 }
745 }
746 if (test_ok) {
747 rtn_val = DDI_SUCCESS;
748 } else {
749 cmn_err(CE_WARN, "%s(%d) mailbox test failed!",
750 __func__, qlge->instance);
751 }
752 } else {
753 cmn_err(CE_WARN, "%s(%d) mailbox testing error: "
754 "PI Intr not received ", __func__, qlge->instance);
755 }
756 out:
757 return (rtn_val);
758 }
759
760 /*
761 * ql_mbx_test2
762 * Test if mailbox communication works
763 * This is used when Interrupt is enabled
764 * mailbox cmd:0x06h
765 */
766 int
767 ql_mbx_test2(qlge_t *qlge)
768 {
769 mbx_cmd_t mbx_cmds = {0};
770 int i, test_ok = 1;
771 int rtn_val = DDI_FAILURE;
772
773 for (i = 0; i < NUM_MAILBOX_REGS; i++)
774 mbx_cmds.mb[i] = i;
775
776 mbx_cmds.mb[0] = MBC_MAILBOX_REGISTER_TEST; /* 0x06 */
777 if (ql_issue_mailbox_cmd_and_wait_rsp(qlge, &mbx_cmds) != DDI_SUCCESS) {
778 cmn_err(CE_WARN,
779 "%s(%d) ql_issue_mailbox_cmd_and_wait_rsp failed.",
780 __func__, qlge->instance);
781 goto out;
782 }
783
784 /* verify if the incoming outbound mailbox value is what we just sent */
785 if (mbx_cmds.mb[0] != MBS_COMMAND_COMPLETE /* 0x4000 */) {
786 test_ok = 0;
787 } else {
788 for (i = 1; i < qlge->max_read_mbx; i++) {
789 if (mbx_cmds.mb[i] != i) {
790 test_ok = 0;
791 break;
792 }
793 }
794 }
795 if (test_ok) {
796 rtn_val = DDI_SUCCESS;
797 } else {
798 cmn_err(CE_WARN, "%s(%d) mailbox test failed!",
799 __func__, qlge->instance);
800 }
801 out:
802 if ((rtn_val != DDI_SUCCESS) && qlge->fm_enable) {
803 ql_fm_ereport(qlge, DDI_FM_DEVICE_NO_RESPONSE);
804 ddi_fm_service_impact(qlge->dip, DDI_SERVICE_DEGRADED);
805 }
806 return (rtn_val);
807 }
808
809 /*
810 * ql_get_fw_state
811 * Get fw state.
812 * mailbox cmd:0x69h
813 */
814 int
815 ql_get_fw_state(qlge_t *qlge, uint32_t *fw_state_ptr)
816 {
817 int rtn_val = DDI_FAILURE;
818 mbx_cmd_t mbx_cmds = {0};
819
820 mbx_cmds.mb[0] = MBC_GET_FIRMWARE_STATE;
821
822 if (ql_issue_mailbox_cmd_and_wait_rsp(qlge, &mbx_cmds)
823 != DDI_SUCCESS) {
824 cmn_err(CE_WARN, "%s(%d) ql_issue_mailbox_cmd_and_wait_rsp"
825 " failed.", __func__, qlge->instance);
826 goto out;
827 }
828 /* verify if the transaction is completed successful */
829 if (mbx_cmds.mb[0] != MBS_COMMAND_COMPLETE /* 0x4000 */) {
830 cmn_err(CE_WARN, "%s(%d) failed, 0x%x",
831 __func__, qlge->instance, mbx_cmds.mb[0]);
832 } else {
833 /* EMPTY */
834 QL_PRINT(DBG_MBX, ("firmware state: 0x%x\n", mbx_cmds.mb[1]));
835 }
836 if (fw_state_ptr != NULL)
837 *fw_state_ptr = mbx_cmds.mb[1];
838 rtn_val = DDI_SUCCESS;
839 out:
840 if ((rtn_val != DDI_SUCCESS) && qlge->fm_enable) {
841 ql_fm_ereport(qlge, DDI_FM_DEVICE_NO_RESPONSE);
842 ddi_fm_service_impact(qlge->dip, DDI_SERVICE_DEGRADED);
843 }
844 return (rtn_val);
845 }
846
847 /*
848 * ql_set_IDC_Req
849 * Send a IDC Request to firmware to notify all functions
850 * or any specific functions on the same port
851 * mailbox cmd:0x100h
852 */
853 int
854 ql_set_IDC_Req(qlge_t *qlge, uint8_t dest_functions, uint8_t timeout)
855 {
856 int rtn_val = DDI_FAILURE;
857 mbx_cmd_t mbx_cmds = {0};
858
859 mbx_cmds.mb[0] = MBC_IDC_REQUEST /* 0x100 */;
860 mbx_cmds.mb[1] = (timeout<<8) | qlge->func_number;
861
862 switch (dest_functions) {
863 case IDC_REQ_DEST_FUNC_ALL:
864 mbx_cmds.mb[1] |= IDC_REQ_ALL_DEST_FUNC_MASK;
865 mbx_cmds.mb[2] = 0;
866 break;
867 case IDC_REQ_DEST_FUNC_0:
868 mbx_cmds.mb[2] = IDC_REQ_DEST_FUNC_0_MASK;
869 break;
870 case IDC_REQ_DEST_FUNC_1:
871 mbx_cmds.mb[2] = IDC_REQ_DEST_FUNC_1_MASK;
872 break;
873 case IDC_REQ_DEST_FUNC_2:
874 mbx_cmds.mb[2] = IDC_REQ_DEST_FUNC_2_MASK;
875 break;
876 case IDC_REQ_DEST_FUNC_3:
877 mbx_cmds.mb[2] = IDC_REQ_DEST_FUNC_3_MASK;
878 break;
879 default:
880 cmn_err(CE_WARN, "Wrong dest functions %x",
881 dest_functions);
882 }
883
884 if (ql_issue_mailbox_cmd_and_wait_rsp(qlge, &mbx_cmds) != DDI_SUCCESS) {
885 cmn_err(CE_WARN,
886 "%s(%d) ql_issue_mailbox_cmd_and_wait_rsp failed.",
887 __func__, qlge->instance);
888 goto out;
889 }
890 /* verify if the transaction is completed successful */
891 if (mbx_cmds.mb[0] == MBA_IDC_INTERMEDIATE_COMPLETE /* 0x1000 */) {
892 QL_PRINT(DBG_MBX, ("%s(%d) mbx1: 0x%x, mbx2: 0x%x\n",
893 __func__, qlge->instance, mbx_cmds.mb[1], mbx_cmds.mb[2]));
894 rtn_val = DDI_SUCCESS;
895 } else if (mbx_cmds.mb[0] == MBS_COMMAND_COMPLETE /* 0x4000 */) {
896 QL_PRINT(DBG_MBX, ("%s(%d) cmd sent succesfully 0x%x\n",
897 __func__, qlge->instance));
898 rtn_val = DDI_SUCCESS;
899 } else if (mbx_cmds.mb[0] == MBS_COMMAND_ERROR /* 0x4005 */) {
900 cmn_err(CE_WARN, "%s(%d) failed: COMMAND_ERROR",
901 __func__, qlge->instance);
902 } else if (mbx_cmds.mb[0] == MBS_COMMAND_PARAMETER_ERROR /* 0x4006 */) {
903 cmn_err(CE_WARN, "%s(%d) failed: COMMAND_PARAMETER_ERROR",
904 __func__, qlge->instance);
905 } else {
906 cmn_err(CE_WARN, "%s(%d) unknow result: mbx[0]: 0x%x; mbx[1]:"
907 " 0x%x; mbx[2]: 0x%x", __func__, qlge->instance,
908 mbx_cmds.mb[0], mbx_cmds.mb[1], mbx_cmds.mb[2]);
909 }
910
911 out:
912 if ((rtn_val != DDI_SUCCESS) && qlge->fm_enable) {
913 ql_fm_ereport(qlge, DDI_FM_DEVICE_NO_RESPONSE);
914 ddi_fm_service_impact(qlge->dip, DDI_SERVICE_DEGRADED);
915 }
916 return (rtn_val);
917 }
918
919 /*
920 * ql_set_mpi_port_config
921 * Send new port configuration.to mpi
922 * mailbox cmd:0x122h
923 */
924 int
925 ql_set_mpi_port_config(qlge_t *qlge, port_cfg_info_t new_cfg)
926 {
927 int rtn_val = DDI_FAILURE;
928 mbx_cmd_t mbx_cmds = {0};
929
930 mbx_cmds.mb[0] = MBC_SET_PORT_CONFIG /* 0x122 */;
931 mbx_cmds.mb[1] = new_cfg.link_cfg;
932 mbx_cmds.mb[2] = new_cfg.max_frame_size;
933
934 if (ql_issue_mailbox_cmd_and_wait_rsp(qlge, &mbx_cmds) != DDI_SUCCESS) {
935 cmn_err(CE_WARN, "%s(%d) ql_issue_mailbox_cmd_and_wait_rsp"
936 " failed.", __func__, qlge->instance);
937 goto out;
938 }
939 /* verify if the transaction is completed successful */
940 if ((mbx_cmds.mb[0] != MBS_COMMAND_COMPLETE /* 0x4000 */) &&
941 (mbx_cmds.mb[0] != MBA_IDC_COMPLETE /* 0x8100 */)) {
942 cmn_err(CE_WARN, "set port config (%d) failed, 0x%x",
943 qlge->instance, mbx_cmds.mb[0]);
944 } else
945 rtn_val = DDI_SUCCESS;
946 out:
947 if ((rtn_val != DDI_SUCCESS) && qlge->fm_enable) {
948 ql_fm_ereport(qlge, DDI_FM_DEVICE_NO_RESPONSE);
949 ddi_fm_service_impact(qlge->dip, DDI_SERVICE_DEGRADED);
950 }
951 return (rtn_val);
952 }
953
954 int
955 ql_set_pause_mode(qlge_t *qlge)
956 {
957 uint32_t pause_bit_mask = 0x60; /* bit 5-6 */
958
959 /* clear pause bits */
960 qlge->port_cfg_info.link_cfg &= ~pause_bit_mask;
961
962 /* set new pause mode */
963 if (qlge->pause == PAUSE_MODE_STANDARD)
964 qlge->port_cfg_info.link_cfg |= STD_PAUSE;
965 else if (qlge->pause == PAUSE_MODE_PER_PRIORITY)
966 qlge->port_cfg_info.link_cfg |= PP_PAUSE;
967
968 return (ql_set_mpi_port_config(qlge, qlge->port_cfg_info));
969 }
970
971 int
972 ql_set_loop_back_mode(qlge_t *qlge)
973 {
974 uint32_t loop_back_bit_mask = 0x0e; /* bit 1-3 */
975
976 /* clear loop back bits */
977 qlge->port_cfg_info.link_cfg &= ~loop_back_bit_mask;
978 /* loop back cfg: bit1-3 */
979 if (qlge->loop_back_mode == QLGE_LOOP_INTERNAL_PARALLEL)
980 qlge->port_cfg_info.link_cfg |= LOOP_INTERNAL_PARALLEL;
981 else if (qlge->loop_back_mode == QLGE_LOOP_INTERNAL_SERIAL)
982 qlge->port_cfg_info.link_cfg |= LOOP_INTERNAL_SERIAL;
983 else if (qlge->loop_back_mode == QLGE_LOOP_EXTERNAL_PHY)
984 qlge->port_cfg_info.link_cfg |= LOOP_EXTERNAL_PHY;
985
986 return (ql_set_mpi_port_config(qlge, qlge->port_cfg_info));
987
988 }
989 /*
990 * ql_get_port_cfg
991 * Get port configuration.
992 * mailbox cmd:0x123h
993 */
994 int
995 ql_get_port_cfg(qlge_t *qlge)
996 {
997 int rtn_val = DDI_FAILURE;
998 mbx_cmd_t mbx_cmds = {0};
999
1000 mbx_cmds.mb[0] = MBC_GET_PORT_CONFIG /* 0x123 */;
1001 if (ql_issue_mailbox_cmd_and_wait_rsp(qlge, &mbx_cmds) != DDI_SUCCESS) {
1002 cmn_err(CE_WARN, "%s(%d) ql_issue_mailbox_cmd_and_wait_rsp"
1003 " failed.", __func__, qlge->instance);
1004 goto out;
1005 }
1006 /* verify if the transaction is completed successfully */
1007 if (mbx_cmds.mb[0] != MBS_COMMAND_COMPLETE /* 0x4000 */) {
1008 cmn_err(CE_WARN, "get port config (%d) failed, 0x%x",
1009 qlge->instance, mbx_cmds.mb[0]);
1010 } else { /* verify frame size */
1011 if ((mbx_cmds.mb[2] == NORMAL_FRAME_SIZE) ||
1012 (mbx_cmds.mb[2] == JUMBO_FRAME_SIZE)) {
1013 qlge->port_cfg_info.link_cfg = mbx_cmds.mb[1];
1014 qlge->port_cfg_info.max_frame_size = mbx_cmds.mb[2];
1015 QL_PRINT(DBG_MBX, ("link_cfg: 0x%x, max_frame_size:"
1016 " %d bytes\n", mbx_cmds.mb[1], mbx_cmds.mb[2]));
1017 rtn_val = DDI_SUCCESS;
1018 } else {
1019 cmn_err(CE_WARN, "bad link_cfg: 0x%x, max_frame_size:"
1020 " %d bytes", mbx_cmds.mb[1], mbx_cmds.mb[2]);
1021 }
1022 }
1023 out:
1024 if ((rtn_val != DDI_SUCCESS) && qlge->fm_enable) {
1025 ql_fm_ereport(qlge, DDI_FM_DEVICE_NO_RESPONSE);
1026 ddi_fm_service_impact(qlge->dip, DDI_SERVICE_DEGRADED);
1027 }
1028 return (rtn_val);
1029 }
1030
1031 /*
1032 * qlge_get_link_status
1033 * Get link status.
1034 * mailbox cmd:0x124h
1035 */
1036 int
1037 qlge_get_link_status(qlge_t *qlge,
1038 struct qlnic_link_status_info *link_status_ptr)
1039 {
1040 int rtn_val = DDI_FAILURE;
1041 mbx_cmd_t mbx_cmds = {0};
1042
1043 mbx_cmds.mb[0] = MBC_GET_LINK_STATUS /* 0x124 */;
1044
1045 if (ql_issue_mailbox_cmd_and_wait_rsp(qlge, &mbx_cmds)
1046 != DDI_SUCCESS) {
1047 cmn_err(CE_WARN,
1048 "%s(%d) ql_issue_mailbox_cmd_and_wait_rsp failed.",
1049 __func__, qlge->instance);
1050 goto out;
1051 }
1052 /* verify if the transaction is completed successful */
1053 if (mbx_cmds.mb[0] != MBS_COMMAND_COMPLETE /* 0x4000 */) {
1054 cmn_err(CE_WARN, "get link status(%d) failed, 0x%x",
1055 qlge->instance, mbx_cmds.mb[0]);
1056 } else {
1057 /* EMPTY */
1058 QL_PRINT(DBG_MBX,
1059 ("link status: status1 : 0x%x, status2 : 0x%x, "
1060 "status3 : 0x%x\n",
1061 mbx_cmds.mb[1], mbx_cmds.mb[2], mbx_cmds.mb[3]));
1062 }
1063 if (link_status_ptr != NULL) {
1064 link_status_ptr->link_status_info = mbx_cmds.mb[1];
1065 link_status_ptr->additional_info = mbx_cmds.mb[2];
1066 link_status_ptr->network_hw_info = mbx_cmds.mb[3];
1067 link_status_ptr->dcbx_frame_counters_info = mbx_cmds.mb[4];
1068 link_status_ptr->change_counters_info = mbx_cmds.mb[5];
1069 }
1070 rtn_val = DDI_SUCCESS;
1071 out:
1072 if ((rtn_val != DDI_SUCCESS) && qlge->fm_enable) {
1073 ql_fm_ereport(qlge, DDI_FM_DEVICE_NO_RESPONSE);
1074 ddi_fm_service_impact(qlge->dip, DDI_SERVICE_DEGRADED);
1075 }
1076 return (rtn_val);
1077 }
1078
1079 /*
1080 * ql_get_firmware_version
1081 * Get firmware version.
1082 */
1083 int
1084 ql_get_firmware_version(qlge_t *qlge,
1085 struct qlnic_mpi_version_info *mpi_version_ptr)
1086 {
1087 int rtn_val = DDI_FAILURE;
1088 mbx_cmd_t mbx_cmds = {0};
1089
1090 mbx_cmds.mb[0] = MBC_ABOUT_FIRMWARE /* 0x08 */;
1091
1092 if (ql_issue_mailbox_cmd_and_wait_rsp(qlge, &mbx_cmds)
1093 != DDI_SUCCESS) {
1094 cmn_err(CE_WARN,
1095 "%s(%d) ql_issue_mailbox_cmd_and_wait_rsp failed.",
1096 __func__, qlge->instance);
1097 goto out;
1098 }
1099
1100 /* verify if the transaction is completed successful */
1101 if (mbx_cmds.mb[0] != MBS_COMMAND_COMPLETE /* 0x4000 */) {
1102 cmn_err(CE_WARN, "get firmware version(%d) failed, 0x%x",
1103 qlge->instance, mbx_cmds.mb[0]);
1104 } else {
1105 qlge->fw_version_info.major_version =
1106 LSB(MSW(mbx_cmds.mb[1]));
1107 qlge->fw_version_info.minor_version =
1108 MSB(LSW(mbx_cmds.mb[1]));
1109 qlge->fw_version_info.sub_minor_version =
1110 LSB(LSW(mbx_cmds.mb[1]));
1111 qlge->phy_version_info.major_version =
1112 LSB(MSW(mbx_cmds.mb[2]));
1113 qlge->phy_version_info.minor_version =
1114 MSB(LSW(mbx_cmds.mb[2]));
1115 qlge->phy_version_info.sub_minor_version =
1116 LSB(LSW(mbx_cmds.mb[2]));
1117 #ifdef QLGE_LOAD_UNLOAD
1118 cmn_err(CE_NOTE, "firmware version: %d.%d.%d\n",
1119 qlge->fw_version_info.major_version,
1120 qlge->fw_version_info.minor_version,
1121 qlge->fw_version_info.sub_minor_version);
1122 #endif
1123 if (mpi_version_ptr != NULL) {
1124 mpi_version_ptr->fw_version =
1125 (qlge->fw_version_info.major_version<<16)
1126 |(qlge->fw_version_info.minor_version<<8)
1127 |(qlge->fw_version_info.sub_minor_version);
1128 mpi_version_ptr->phy_version =
1129 (qlge->phy_version_info.major_version<<16)
1130 |(qlge->phy_version_info.minor_version<<8)
1131 |(qlge->phy_version_info.sub_minor_version);
1132 }
1133 }
1134 rtn_val = DDI_SUCCESS;
1135 out:
1136 if ((rtn_val != DDI_SUCCESS) && qlge->fm_enable) {
1137 ql_fm_ereport(qlge, DDI_FM_DEVICE_NO_RESPONSE);
1138 ddi_fm_service_impact(qlge->dip, DDI_SERVICE_DEGRADED);
1139 }
1140 return (rtn_val);
1141 }
1142
1143 /*
1144 * Trigger a system error event
1145 */
1146 int
1147 ql_trigger_system_error_event(qlge_t *qlge)
1148 {
1149 mbx_cmd_t mbx_cmds = {0};
1150 int rtn_val = DDI_FAILURE;
1151
1152 mbx_cmds.mb[0] = MBC_GENERATE_SYS_ERROR; /* 0x2A */
1153 if (ql_issue_mailbox_cmd(qlge, &mbx_cmds) != DDI_SUCCESS) {
1154 cmn_err(CE_WARN, "%s(%d) ql_issue_mailbox_cmd timeout.",
1155 __func__, qlge->instance);
1156 goto out;
1157 }
1158 rtn_val = DDI_SUCCESS;
1159 out:
1160 return (rtn_val);
1161 }
1162
1163 /*
1164 * Reset the MPI RISC Processor
1165 */
1166 int
1167 ql_reset_mpi_risc(qlge_t *qlge)
1168 {
1169 int rtn_val = DDI_FAILURE;
1170
1171 /* Reset the MPI Processor */
1172 ql_write_reg(qlge, REG_HOST_CMD_STATUS, HOST_CMD_SET_RISC_RESET);
1173 if (ql_wait_reg_bit(qlge, REG_HOST_CMD_STATUS, RISC_RESET,
1174 BIT_SET, 0) != DDI_SUCCESS) {
1175 (void) ql_read_reg(qlge, REG_HOST_CMD_STATUS);
1176 goto out;
1177 }
1178 ql_write_reg(qlge, REG_HOST_CMD_STATUS, HOST_CMD_CLEAR_RISC_RESET);
1179 rtn_val = DDI_SUCCESS;
1180 out:
1181 return (rtn_val);
1182 }
1183
1184 int
1185 ql_read_risc_ram(qlge_t *qlge, uint32_t risc_address, uint64_t bp,
1186 uint32_t word_count)
1187 {
1188 int rval = DDI_FAILURE;
1189 mbx_cmd_t mc = {0};
1190 mbx_cmd_t *mcp = &mc;
1191 mbx_data_t mbx_results;
1192
1193 QL_PRINT(DBG_MBX, ("%s(%d): read risc addr:0x%x,"
1194 "phys_addr %x,%x words\n", __func__, qlge->instance,
1195 risc_address, bp, word_count));
1196 if (CFG_IST(qlge, CFG_CHIP_8100)) {
1197 mcp->mb[0] = MBC_DUMP_RISC_RAM /* 0x0C */;
1198 mcp->mb[1] = LSW(risc_address);
1199 mcp->mb[2] = MSW(LSD(bp));
1200 mcp->mb[3] = LSW(LSD(bp));
1201 mcp->mb[4] = MSW(word_count);
1202 mcp->mb[5] = LSW(word_count);
1203 mcp->mb[6] = MSW(MSD(bp));
1204 mcp->mb[7] = LSW(MSD(bp));
1205 mcp->mb[8] = MSW(risc_address);
1206 }
1207 mcp->timeout = 10 /* MAILBOX_TOV */;
1208
1209 if (ql_issue_mailbox_cmd_and_poll_rsp(qlge, mcp, &mbx_results)
1210 != DDI_SUCCESS) {
1211 goto out;
1212 } else {
1213 QL_PRINT(DBG_MBX, ("%s(%d) PI Intr received",
1214 __func__, qlge->instance));
1215 if (mbx_results.mb[0] == MBS_COMMAND_COMPLETE /* 0x4000 */) {
1216 QL_PRINT(DBG_MBX, ("%s(%d): success\n",
1217 __func__, qlge->instance));
1218 rval = DDI_SUCCESS;
1219 } else {
1220 cmn_err(CE_WARN, "read_risc_ram(%d): failed, status %x",
1221 qlge->instance, mbx_results.mb[0]);
1222 }
1223 }
1224 out:
1225 return (rval);
1226 }