1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2009 QLogic Corporation. All rights reserved.
24  */
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, &reg_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 +=
326 				    mbx_cmd->timeout * drv_usectohz(1000000);
327 			} else {
328 				timer += 5 * drv_usectohz(1000000);
329 			}
330 			if (cv_timedwait(&qlge->cv_mbx_intr, &qlge->mbx_mutex,
331 			    timer) == -1) {
332 				/*
333 				 * The timeout time 'timer' was
334 				 * reached or expired without the condition
335 				 * being signaled.
336 				 */
337 				cmn_err(CE_WARN, "%s(%d) Wait for Mailbox cmd "
338 				    "complete timeout.",
339 				    __func__, qlge->instance);
340 				rtn_val = DDI_FAILURE;
341 				done = 1;
342 			} else {
343 				QL_PRINT(DBG_MBX,
344 				    ("%s(%d) mailbox completion signal received"
345 				    " \n", __func__, qlge->instance));
346 				for (i = 0; i < NUM_MAILBOX_REGS; i++) {
347 					mbx_cmd->mb[i] =
348 					    qlge->received_mbx_cmds.mb[i];
349 				}
350 				rtn_val = DDI_SUCCESS;
351 				done = 1;
352 			}
353 		}
354 	}
355 err:
356 	return (rtn_val);
357 }
358 
359 /*
360  * Inteprete incoming asynchronous events
361  */
362 static int
363 ql_async_event_parser(qlge_t *qlge, mbx_data_t *mbx_cmds)
364 {
365 	uint32_t link_status, cmd;
366 	uint8_t link_speed;
367 	uint8_t link_type;
368 	boolean_t proc_done = B_TRUE;
369 	mbx_cmd_t reply_cmd = {0};
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 		(void) ql_8xxx_binary_core_dump(qlge, &qlge->ql_mpi_coredump);
385 		break;
386 	case MBA_LINK_UP /* 8011h */:
387 		QL_PRINT(DBG_MBX, ("%s(%d): MBA_LINK_UP received\n",
388 		    __func__, qlge->instance));
389 		link_status = mbx_cmds->mb[1];
390 		QL_PRINT(DBG_MBX, ("%s(%d): Link Status %x \n",
391 		    __func__, qlge->instance, link_status));
392 		link_speed = (uint8_t)((link_status >> 3) & 0x07);
393 
394 		if (link_speed == 0) {
395 			qlge->speed = SPEED_100;
396 			QL_PRINT(DBG_MBX, ("%s(%d):Link speed 100M\n",
397 			    __func__, qlge->instance));
398 		} else if (link_speed == 1) {
399 			qlge->speed = SPEED_1000;
400 			QL_PRINT(DBG_MBX, ("%s(%d):Link speed 1G\n",
401 			    __func__, qlge->instance));
402 		} else if (link_speed == 2) {
403 			qlge->speed = SPEED_10G;
404 			QL_PRINT(DBG_MBX, ("%s(%d):Link speed 10G\n",
405 			    __func__, qlge->instance));
406 			}
407 
408 		qlge->link_type = link_type = (uint8_t)(link_status & 0x07);
409 
410 		if (link_type == XFI_NETWORK_INTERFACE) {
411 			/* EMPTY */
412 			QL_PRINT(DBG_MBX,
413 			    ("%s(%d):Link type XFI_NETWORK_INTERFACE\n",
414 			    __func__, qlge->instance));
415 		} else if (link_type == XAUI_NETWORK_INTERFACE) {
416 			/* EMPTY */
417 			QL_PRINT(DBG_MBX, ("%s(%d):Link type"
418 			    "XAUI_NETWORK_INTERFACE\n",
419 			    __func__, qlge->instance));
420 		} else if (link_type == XFI_BACKPLANE_INTERFACE) {
421 			/* EMPTY */
422 			QL_PRINT(DBG_MBX, ("%s(%d):Link type"
423 			    "XFI_BACKPLANE_INTERFACE\n",
424 			    __func__, qlge->instance));
425 		} else if (link_type == XAUI_BACKPLANE_INTERFACE) {
426 			/* EMPTY */
427 			QL_PRINT(DBG_MBX, ("%s(%d):Link type "
428 			    "XAUI_BACKPLANE_INTERFACE\n",
429 			    __func__, qlge->instance));
430 		} else if (link_type == EXT_10GBASE_T_PHY) {
431 			/* EMPTY */
432 			QL_PRINT(DBG_MBX,
433 			    ("%s(%d):Link type EXT_10GBASE_T_PHY\n",
434 			    __func__, qlge->instance));
435 		} else if (link_type == EXT_EXT_EDC_PHY) {
436 			/* EMPTY */
437 			QL_PRINT(DBG_MBX,
438 			    ("%s(%d):Link type EXT_EXT_EDC_PHY\n",
439 			    __func__, qlge->instance));
440 		} else {
441 			/* EMPTY */
442 			QL_PRINT(DBG_MBX,
443 			    ("%s(%d):unknown Link type \n",
444 			    __func__, qlge->instance));
445 		}
446 
447 		cmn_err(CE_NOTE, "mpi link up! link_status %x \n", link_status);
448 		/*
449 		 * start timer if not started to delay some time then
450 		 * check if link is really up or down
451 		 */
452 		ql_restart_timer(qlge);
453 
454 		break;
455 	case MBA_LINK_DOWN /* 8012h */:
456 		QL_PRINT(DBG_MBX,
457 		    ("%s(%d): MBA_LINK_DOWN received\n",
458 		    __func__, qlge->instance));
459 
460 		link_status = mbx_cmds->mb[1];
461 
462 		QL_PRINT(DBG_MBX, ("%s(%d): Link Status %x \n",
463 		    __func__, qlge->instance, link_status));
464 		if (link_status & 0x1) {
465 			/* EMPTY */
466 			QL_PRINT(DBG_MBX, ("%s(%d): Loss of signal \n",
467 			    __func__, qlge->instance));
468 		}
469 		if (link_status & 0x2) {
470 			/* EMPTY */
471 			QL_PRINT(DBG_MBX,
472 			    ("%s(%d): Auto-Negotiation Failed \n",
473 			    __func__, qlge->instance));
474 		}
475 		if (link_status & 0x4) {
476 			/* EMPTY */
477 			QL_PRINT(DBG_MBX,
478 			    ("%s(%d): XTI-Training Failed \n",
479 			    __func__, qlge->instance));
480 		}
481 
482 		cmn_err(CE_NOTE, "mpi link down! link_status %x \n",
483 		    link_status);
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 		break;
636 	default:
637 		if (mbx_cmds->mb[0] > 0x8000) {
638 			cmn_err(CE_WARN, "%s(%d): "
639 			    "Unknown Async event received: mbx[0] %x ,"
640 			    "mbx[1] %x; mbx[2] %x",
641 			    __func__, qlge->instance,
642 			    mbx_cmds->mb[0], mbx_cmds->mb[1],
643 			    mbx_cmds->mb[2]);
644 			proc_done = B_TRUE;
645 		} else {
646 			proc_done = B_FALSE;
647 		}
648 		break;
649 	}
650 	return (proc_done);
651 }
652 
653 
654 /*
655  * MPI Interrupt handler
656  * Caller must have MBX_LOCK
657  */
658 void
659 ql_do_mpi_intr(qlge_t *qlge)
660 {
661 	/*
662 	 * we just need to read first few mailboxes that this adapter's MPI
663 	 * will write response to.
664 	 */
665 	mutex_enter(&qlge->mbx_mutex);
666 
667 	(void) ql_read_mailbox_cmd(qlge, &qlge->received_mbx_cmds,
668 	    qlge->max_read_mbx);
669 
670 	/*
671 	 * process PI interrupt as async events, if not done,
672 	 * then pass to mailbox processing
673 	 */
674 	if (ql_async_event_parser(qlge, &qlge->received_mbx_cmds) == B_FALSE) {
675 		QL_PRINT(DBG_MBX, ("%s(%d) mailbox completion interrupt\n",
676 		    __func__, qlge->instance));
677 		/*
678 		 * If another thread is waiting for the mail box
679 		 * completion event to occur
680 		 */
681 		if (qlge->mbx_wait_completion == 1) {
682 			qlge->mbx_wait_completion = 0;
683 			cv_broadcast(&qlge->cv_mbx_intr);
684 			QL_PRINT(DBG_MBX,
685 			    ("%s(%d) mailbox completion signaled \n",
686 			    __func__, qlge->instance));
687 		}
688 	}
689 	/* inform MPI Firmware to clear the interrupt */
690 	ql_write_reg(qlge, REG_HOST_CMD_STATUS,
691 	    HOST_CMD_CLEAR_RISC_TO_HOST_INTR /* 0x0A */);
692 	mutex_exit(&qlge->mbx_mutex);
693 	ql_enable_completion_interrupt(qlge, 0); /* MPI is on irq 0 */
694 }
695 
696 /*
697  * Test if mailbox communication works
698  * This is used when Interrupt is not enabled
699  */
700 int
701 ql_mbx_test(qlge_t *qlge)
702 {
703 	mbx_cmd_t mbx_cmds;
704 	mbx_data_t mbx_results;
705 	int i, test_ok = 1;
706 	int rtn_val = DDI_FAILURE;
707 
708 	for (i = 0; i < NUM_MAILBOX_REGS; i++)
709 		mbx_cmds.mb[i] = i;
710 
711 	mbx_cmds.mb[0] = MBC_MAILBOX_REGISTER_TEST; /* 0x06 */
712 	if (ql_issue_mailbox_cmd(qlge, &mbx_cmds) != DDI_SUCCESS) {
713 		cmn_err(CE_WARN, "%s(%d) ql_issue_mailbox_cmd timeout.",
714 		    __func__, qlge->instance);
715 		goto out;
716 	}
717 
718 	/* delay for the processor interrupt is received */
719 	if (ql_poll_processor_intr(qlge, (uint8_t)mbx_cmds.timeout)
720 	    == DDI_SUCCESS) {
721 		QL_PRINT(DBG_MBX, ("%s(%d) PI Intr received",
722 		    __func__, qlge->instance));
723 		(void) ql_read_mailbox_cmd(qlge, &mbx_results, 0);
724 
725 		ql_write_reg(qlge, REG_HOST_CMD_STATUS,
726 		    HOST_CMD_CLEAR_RISC_TO_HOST_INTR);
727 
728 		if (mbx_results.mb[0] != MBS_COMMAND_COMPLETE /* 0x4000 */) {
729 			test_ok = 0;
730 		} else {
731 			for (i = 1; i < NUM_MAILBOX_REGS; i++) {
732 				if (mbx_results.mb[i] != i) {
733 					test_ok = 0;
734 					break;
735 				}
736 			}
737 		}
738 		if (test_ok) {
739 			rtn_val = DDI_SUCCESS;
740 		} else {
741 			cmn_err(CE_WARN, "%s(%d) mailbox test failed!",
742 			    __func__, qlge->instance);
743 		}
744 	} else {
745 		cmn_err(CE_WARN, "%s(%d) mailbox testing error: "
746 		    "PI Intr not received ", __func__, qlge->instance);
747 	}
748 out:
749 	return (rtn_val);
750 }
751 
752 /*
753  * ql_mbx_test2
754  * Test if mailbox communication works
755  * This is used when Interrupt is enabled
756  * mailbox cmd:0x06h
757  */
758 int
759 ql_mbx_test2(qlge_t *qlge)
760 {
761 	mbx_cmd_t mbx_cmds = {0};
762 	int i, test_ok = 1;
763 	int rtn_val = DDI_FAILURE;
764 
765 	for (i = 0; i < NUM_MAILBOX_REGS; i++)
766 		mbx_cmds.mb[i] = i;
767 
768 	mbx_cmds.mb[0] = MBC_MAILBOX_REGISTER_TEST; /* 0x06 */
769 	if (ql_issue_mailbox_cmd_and_wait_rsp(qlge, &mbx_cmds) != DDI_SUCCESS) {
770 		cmn_err(CE_WARN,
771 		    "%s(%d) ql_issue_mailbox_cmd_and_wait_rsp failed.",
772 		    __func__, qlge->instance);
773 		goto out;
774 	}
775 
776 	/* verify if the incoming outbound mailbox value is what we just sent */
777 	if (mbx_cmds.mb[0] != MBS_COMMAND_COMPLETE /* 0x4000 */) {
778 		test_ok = 0;
779 	} else {
780 		for (i = 1; i < qlge->max_read_mbx; i++) {
781 			if (mbx_cmds.mb[i] != i) {
782 				test_ok = 0;
783 				break;
784 			}
785 		}
786 	}
787 	if (test_ok) {
788 		rtn_val = DDI_SUCCESS;
789 	} else {
790 		cmn_err(CE_WARN, "%s(%d) mailbox test failed!",
791 		    __func__, qlge->instance);
792 	}
793 out:
794 	return (rtn_val);
795 }
796 
797 /*
798  * ql_get_fw_state
799  * Get fw state.
800  * mailbox cmd:0x69h
801  */
802 int
803 ql_get_fw_state(qlge_t *qlge, uint32_t *fw_state_ptr)
804 {
805 	int rtn_val = DDI_FAILURE;
806 	mbx_cmd_t mbx_cmds = {0};
807 
808 	mbx_cmds.mb[0] = MBC_GET_FIRMWARE_STATE;
809 
810 	if (ql_issue_mailbox_cmd_and_wait_rsp(qlge, &mbx_cmds)
811 	    != DDI_SUCCESS) {
812 		cmn_err(CE_WARN, "%s(%d) ql_issue_mailbox_cmd_and_wait_rsp"
813 		    " failed.", __func__, qlge->instance);
814 		goto out;
815 	}
816 	/* verify if the transaction is completed successful */
817 	if (mbx_cmds.mb[0] != MBS_COMMAND_COMPLETE /* 0x4000 */) {
818 		cmn_err(CE_WARN, "%s(%d) failed, 0x%x",
819 		    __func__, qlge->instance, mbx_cmds.mb[0]);
820 	} else {
821 		/* EMPTY */
822 		QL_PRINT(DBG_MBX, ("firmware state: 0x%x\n", mbx_cmds.mb[1]));
823 	}
824 	if (fw_state_ptr != NULL)
825 		*fw_state_ptr = mbx_cmds.mb[1];
826 	rtn_val = DDI_SUCCESS;
827 out:
828 	return (rtn_val);
829 }
830 
831 /*
832  * ql_set_IDC_Req
833  * Send a IDC Request to firmware to notify all functions
834  * or any specific functions on the same port
835  * mailbox cmd:0x100h
836  */
837 int
838 ql_set_IDC_Req(qlge_t *qlge, uint8_t dest_functions, uint8_t timeout)
839 {
840 	int rtn_val = DDI_FAILURE;
841 	mbx_cmd_t mbx_cmds = {0};
842 
843 	mbx_cmds.mb[0] = MBC_IDC_REQUEST /* 0x100 */;
844 	mbx_cmds.mb[1] = (timeout<<8) | qlge->func_number;
845 
846 	switch (dest_functions) {
847 	case IDC_REQ_DEST_FUNC_ALL:
848 		mbx_cmds.mb[1] |= IDC_REQ_ALL_DEST_FUNC_MASK;
849 		mbx_cmds.mb[2] = 0;
850 		break;
851 	case IDC_REQ_DEST_FUNC_0:
852 		mbx_cmds.mb[2] = IDC_REQ_DEST_FUNC_0_MASK;
853 		break;
854 	case IDC_REQ_DEST_FUNC_1:
855 		mbx_cmds.mb[2] = IDC_REQ_DEST_FUNC_1_MASK;
856 		break;
857 	case IDC_REQ_DEST_FUNC_2:
858 		mbx_cmds.mb[2] = IDC_REQ_DEST_FUNC_2_MASK;
859 		break;
860 	case IDC_REQ_DEST_FUNC_3:
861 		mbx_cmds.mb[2] = IDC_REQ_DEST_FUNC_3_MASK;
862 		break;
863 	default:
864 		cmn_err(CE_WARN, "Wrong dest functions %x",
865 		    dest_functions);
866 	}
867 
868 	if (ql_issue_mailbox_cmd_and_wait_rsp(qlge, &mbx_cmds) != DDI_SUCCESS) {
869 		cmn_err(CE_WARN,
870 		    "%s(%d) ql_issue_mailbox_cmd_and_wait_rsp failed.",
871 		    __func__, qlge->instance);
872 		goto out;
873 	}
874 	/* verify if the transaction is completed successful */
875 	if (mbx_cmds.mb[0] == MBA_IDC_INTERMEDIATE_COMPLETE /* 0x1000 */) {
876 		QL_PRINT(DBG_MBX, ("%s(%d) mbx1: 0x%x, mbx2: 0x%x\n",
877 		    __func__, qlge->instance, mbx_cmds.mb[1], mbx_cmds.mb[2]));
878 		rtn_val = DDI_SUCCESS;
879 	} else if (mbx_cmds.mb[0] == MBS_COMMAND_COMPLETE /* 0x4000 */) {
880 		QL_PRINT(DBG_MBX, ("%s(%d) cmd sent succesfully 0x%x\n",
881 		    __func__, qlge->instance));
882 		rtn_val = DDI_SUCCESS;
883 	} else if (mbx_cmds.mb[0] == MBS_COMMAND_ERROR /* 0x4005 */) {
884 		cmn_err(CE_WARN, "%s(%d) failed: COMMAND_ERROR",
885 		    __func__, qlge->instance);
886 	} else if (mbx_cmds.mb[0] == MBS_COMMAND_PARAMETER_ERROR /* 0x4006 */) {
887 		cmn_err(CE_WARN, "%s(%d) failed: COMMAND_PARAMETER_ERROR",
888 		    __func__, qlge->instance);
889 	} else {
890 		cmn_err(CE_WARN, "%s(%d) unknow result: mbx[0]: 0x%x; mbx[1]:"
891 		    " 0x%x; mbx[2]: 0x%x", __func__, qlge->instance,
892 		    mbx_cmds.mb[0], mbx_cmds.mb[1], mbx_cmds.mb[2]);
893 	}
894 
895 out:
896 	return (rtn_val);
897 }
898 
899 /*
900  * ql_set_mpi_port_config
901  * Send new port configuration.to mpi
902  * mailbox cmd:0x122h
903  */
904 static int
905 ql_set_mpi_port_config(qlge_t *qlge, port_cfg_info_t new_cfg)
906 {
907 	int rtn_val = DDI_FAILURE;
908 	mbx_cmd_t mbx_cmds = {0};
909 
910 	mbx_cmds.mb[0] = MBC_SET_PORT_CONFIG /* 0x122 */;
911 	mbx_cmds.mb[1] = new_cfg.link_cfg;
912 	mbx_cmds.mb[2] = new_cfg.max_frame_size;
913 
914 	if (ql_issue_mailbox_cmd_and_wait_rsp(qlge, &mbx_cmds) != DDI_SUCCESS) {
915 		cmn_err(CE_WARN, "%s(%d) ql_issue_mailbox_cmd_and_wait_rsp"
916 		    " failed.", __func__, qlge->instance);
917 		goto out;
918 	}
919 	/* verify if the transaction is completed successful */
920 	if ((mbx_cmds.mb[0] != MBS_COMMAND_COMPLETE /* 0x4000 */) &&
921 	    (mbx_cmds.mb[0] != MBA_IDC_COMPLETE /* 0x8100 */)) {
922 		cmn_err(CE_WARN, "%s(%d) failed, 0x%x",
923 		    __func__, qlge->instance, mbx_cmds.mb[0]);
924 	} else
925 		rtn_val = DDI_SUCCESS;
926 out:
927 	return (rtn_val);
928 }
929 
930 /*
931  * ql_set_port_cfg
932  * Set new port configuration
933  */
934 int
935 ql_set_port_cfg(qlge_t *qlge)
936 {
937 	uint32_t loop_back_bit_mask = 0x0e; /* bit 1-3 */
938 	uint32_t pause_bit_mask = 0x60;	/* bit 5-6 */
939 
940 	/* clear pause bits */
941 	qlge->port_cfg_info.link_cfg &= ~pause_bit_mask;
942 	/* clear loop back bits */
943 	qlge->port_cfg_info.link_cfg &= ~loop_back_bit_mask;
944 	/* set new pause mode */
945 	if (qlge->pause == PAUSE_MODE_STANDARD)
946 		qlge->port_cfg_info.link_cfg |= STD_PAUSE;
947 	else if (qlge->pause == PAUSE_MODE_PER_PRIORITY)
948 		qlge->port_cfg_info.link_cfg |= PP_PAUSE;
949 
950 	/* loop back cfg: bit1-3 */
951 	if (qlge->loop_back_mode == QLGE_LOOP_INTERNAL_PARALLEL)
952 		qlge->port_cfg_info.link_cfg |= LOOP_INTERNAL_PARALLEL;
953 	else if (qlge->loop_back_mode == QLGE_LOOP_INTERNAL_SERIAL)
954 		qlge->port_cfg_info.link_cfg |= LOOP_INTERNAL_SERIAL;
955 
956 	/* max frame size */
957 	if (qlge->mtu == ETHERMTU) {
958 		qlge->port_cfg_info.link_cfg &= ~ENABLE_JUMBO;
959 		qlge->port_cfg_info.max_frame_size = NORMAL_FRAME_SIZE;
960 	} else {
961 		qlge->port_cfg_info.link_cfg |= ENABLE_JUMBO;
962 		qlge->port_cfg_info.max_frame_size = JUMBO_FRAME_SIZE;
963 	}
964 
965 	return (ql_set_mpi_port_config(qlge, qlge->port_cfg_info));
966 
967 }
968 
969 /*
970  * ql_get_port_cfg
971  * Get port configuration.
972  * mailbox cmd:0x123h
973  */
974 int
975 ql_get_port_cfg(qlge_t *qlge)
976 {
977 	int rtn_val = DDI_FAILURE;
978 	mbx_cmd_t mbx_cmds = {0};
979 
980 	mbx_cmds.mb[0] = MBC_GET_PORT_CONFIG /* 0x123 */;
981 	if (ql_issue_mailbox_cmd_and_wait_rsp(qlge, &mbx_cmds) != DDI_SUCCESS) {
982 		cmn_err(CE_WARN, "%s(%d) ql_issue_mailbox_cmd_and_wait_rsp"
983 		    " failed.", __func__, qlge->instance);
984 		goto out;
985 	}
986 	/* verify if the transaction is completed successfully */
987 	if (mbx_cmds.mb[0] != MBS_COMMAND_COMPLETE /* 0x4000 */) {
988 		cmn_err(CE_WARN, "%s(%d) failed, 0x%x",
989 		    __func__, qlge->instance, mbx_cmds.mb[0]);
990 	} else { /* verify frame size */
991 		if ((mbx_cmds.mb[2] == NORMAL_FRAME_SIZE) ||
992 		    (mbx_cmds.mb[2] == JUMBO_FRAME_SIZE)) {
993 			qlge->port_cfg_info.link_cfg = mbx_cmds.mb[1];
994 			qlge->port_cfg_info.max_frame_size = mbx_cmds.mb[2];
995 			QL_PRINT(DBG_MBX, ("link_cfg: 0x%x, max_frame_size:"
996 			    " %d bytes\n", mbx_cmds.mb[1], mbx_cmds.mb[2]));
997 			rtn_val = DDI_SUCCESS;
998 		} else {
999 			cmn_err(CE_WARN, "bad link_cfg: 0x%x, max_frame_size:"
1000 			    " %d bytes", mbx_cmds.mb[1], mbx_cmds.mb[2]);
1001 		}
1002 	}
1003 out:
1004 	return (rtn_val);
1005 }
1006 
1007 /*
1008  * qlge_get_link_status
1009  * Get link status.
1010  * mailbox cmd:0x124h
1011  */
1012 int
1013 qlge_get_link_status(qlge_t *qlge,
1014     struct qlnic_link_status_info *link_status_ptr)
1015 {
1016 	int rtn_val = DDI_FAILURE;
1017 	mbx_cmd_t mbx_cmds = {0};
1018 
1019 	mbx_cmds.mb[0] = MBC_GET_LINK_STATUS /* 0x124 */;
1020 
1021 	if (ql_issue_mailbox_cmd_and_wait_rsp(qlge, &mbx_cmds)
1022 	    != DDI_SUCCESS) {
1023 		cmn_err(CE_WARN,
1024 		    "%s(%d) ql_issue_mailbox_cmd_and_wait_rsp failed.",
1025 		    __func__, qlge->instance);
1026 		goto out;
1027 	}
1028 	/* verify if the transaction is completed successful */
1029 	if (mbx_cmds.mb[0] != MBS_COMMAND_COMPLETE /* 0x4000 */) {
1030 		cmn_err(CE_WARN, "%s(%d) failed, 0x%x", __func__,
1031 		    qlge->instance, mbx_cmds.mb[0]);
1032 	} else {
1033 		/* EMPTY */
1034 		QL_PRINT(DBG_MBX,
1035 		    ("link status: status1 : 0x%x, status2 : 0x%x, "
1036 		    "status3 : 0x%x\n",
1037 		    mbx_cmds.mb[1], mbx_cmds.mb[2], mbx_cmds.mb[3]));
1038 	}
1039 	if (link_status_ptr != NULL) {
1040 		link_status_ptr->link_status_info = mbx_cmds.mb[1];
1041 		link_status_ptr->additional_info = mbx_cmds.mb[2];
1042 		link_status_ptr->network_hw_info = mbx_cmds.mb[3];
1043 		link_status_ptr->dcbx_frame_counters_info = mbx_cmds.mb[4];
1044 		link_status_ptr->change_counters_info = mbx_cmds.mb[5];
1045 	}
1046 	rtn_val = DDI_SUCCESS;
1047 out:
1048 
1049 	return (rtn_val);
1050 }
1051 
1052 /*
1053  * ql_get_firmware_version
1054  * Get firmware version.
1055  */
1056 int
1057 ql_get_firmware_version(qlge_t *qlge,
1058     struct qlnic_mpi_version_info *mpi_version_ptr)
1059 {
1060 	int rtn_val = DDI_FAILURE;
1061 	mbx_cmd_t mbx_cmds = {0};
1062 
1063 	mbx_cmds.mb[0] = MBC_ABOUT_FIRMWARE /* 0x08 */;
1064 
1065 	if (ql_issue_mailbox_cmd_and_wait_rsp(qlge, &mbx_cmds)
1066 	    != DDI_SUCCESS) {
1067 		cmn_err(CE_WARN,
1068 		    "%s(%d) ql_issue_mailbox_cmd_and_wait_rsp failed.",
1069 		    __func__, qlge->instance);
1070 		goto out;
1071 	}
1072 
1073 	/* verify if the transaction is completed successful */
1074 	if (mbx_cmds.mb[0] != MBS_COMMAND_COMPLETE /* 0x4000 */) {
1075 		cmn_err(CE_WARN, "%s(%d) failed, 0x%x", __func__,
1076 		    qlge->instance, mbx_cmds.mb[0]);
1077 	} else {
1078 		qlge->fw_version_info.major_version =
1079 		    LSB(MSW(mbx_cmds.mb[1]));
1080 		qlge->fw_version_info.minor_version =
1081 		    MSB(LSW(mbx_cmds.mb[1]));
1082 		qlge->fw_version_info.sub_minor_version =
1083 		    LSB(LSW(mbx_cmds.mb[1]));
1084 		qlge->phy_version_info.major_version =
1085 		    LSB(MSW(mbx_cmds.mb[2]));
1086 		qlge->phy_version_info.minor_version =
1087 		    MSB(LSW(mbx_cmds.mb[2]));
1088 		qlge->phy_version_info.sub_minor_version =
1089 		    LSB(LSW(mbx_cmds.mb[2]));
1090 #ifdef QLGE_LOAD_UNLOAD
1091 		cmn_err(CE_NOTE, "firmware version: %d.%d.%d\n",
1092 		    qlge->fw_version_info.major_version,
1093 		    qlge->fw_version_info.minor_version,
1094 		    qlge->fw_version_info.sub_minor_version);
1095 #endif
1096 		if (mpi_version_ptr != NULL) {
1097 			mpi_version_ptr->fw_version =
1098 			    (qlge->fw_version_info.major_version<<16)
1099 			    |(qlge->fw_version_info.minor_version<<8)
1100 			    |(qlge->fw_version_info.sub_minor_version);
1101 			mpi_version_ptr->phy_version =
1102 			    (qlge->phy_version_info.major_version<<16)
1103 			    |(qlge->phy_version_info.minor_version<<8)
1104 			    |(qlge->phy_version_info.sub_minor_version);
1105 		}
1106 	}
1107 	rtn_val = DDI_SUCCESS;
1108 out:
1109 	return (rtn_val);
1110 }
1111 
1112 /*
1113  * Trigger a system error event
1114  */
1115 int
1116 ql_trigger_system_error_event(qlge_t *qlge)
1117 {
1118 	mbx_cmd_t mbx_cmds = {0};
1119 	int rtn_val = DDI_FAILURE;
1120 
1121 	mbx_cmds.mb[0] = MBC_GENERATE_SYS_ERROR; /* 0x2A */
1122 	if (ql_issue_mailbox_cmd(qlge, &mbx_cmds) != DDI_SUCCESS) {
1123 		cmn_err(CE_WARN, "%s(%d) ql_issue_mailbox_cmd timeout.",
1124 		    __func__, qlge->instance);
1125 		goto out;
1126 	}
1127 	rtn_val = DDI_SUCCESS;
1128 out:
1129 	return (rtn_val);
1130 }
1131 
1132 /*
1133  * Reset the MPI RISC Processor
1134  */
1135 int
1136 ql_reset_mpi_risc(qlge_t *qlge)
1137 {
1138 	int rtn_val = DDI_FAILURE;
1139 
1140 	/* Reset the MPI Processor */
1141 	ql_write_reg(qlge, REG_HOST_CMD_STATUS, HOST_CMD_SET_RISC_RESET);
1142 	if (ql_wait_reg_bit(qlge, REG_HOST_CMD_STATUS, RISC_RESET,
1143 	    BIT_SET, 0) != DDI_SUCCESS) {
1144 		(void) ql_read_reg(qlge, REG_HOST_CMD_STATUS);
1145 		goto out;
1146 	}
1147 	ql_write_reg(qlge, REG_HOST_CMD_STATUS, HOST_CMD_CLEAR_RISC_RESET);
1148 	rtn_val = DDI_SUCCESS;
1149 out:
1150 	return (rtn_val);
1151 }
1152 
1153 int
1154 ql_read_risc_ram(qlge_t *qlge, uint32_t risc_address, uint64_t bp,
1155     uint32_t word_count)
1156 {
1157 	int rval = DDI_FAILURE;
1158 	mbx_cmd_t mc = {0};
1159 	mbx_cmd_t *mcp = &mc;
1160 	mbx_data_t mbx_results;
1161 
1162 	QL_PRINT(DBG_MBX, ("%s(%d): read risc addr:0x%x,"
1163 	    "phys_addr %x,%x words\n", __func__, qlge->instance,
1164 	    risc_address, bp, word_count));
1165 	if (CFG_IST(qlge, CFG_CHIP_8100)) {
1166 		mcp->mb[0] = MBC_DUMP_RISC_RAM /* 0x0C */;
1167 		mcp->mb[1] = LSW(risc_address);
1168 		mcp->mb[2] = MSW(LSD(bp));
1169 		mcp->mb[3] = LSW(LSD(bp));
1170 		mcp->mb[4] = MSW(word_count);
1171 		mcp->mb[5] = LSW(word_count);
1172 		mcp->mb[6] = MSW(MSD(bp));
1173 		mcp->mb[7] = LSW(MSD(bp));
1174 		mcp->mb[8] = MSW(risc_address);
1175 	}
1176 	mcp->timeout = 10 /* MAILBOX_TOV */;
1177 
1178 	if (ql_issue_mailbox_cmd_and_poll_rsp(qlge, mcp, &mbx_results)
1179 	    != DDI_SUCCESS) {
1180 		goto out;
1181 	} else {
1182 		QL_PRINT(DBG_MBX, ("%s(%d) PI Intr received",
1183 		    __func__, qlge->instance));
1184 		if (mbx_results.mb[0] == MBS_COMMAND_COMPLETE /* 0x4000 */) {
1185 			QL_PRINT(DBG_MBX, ("%s(%d): success\n",
1186 			    __func__, qlge->instance));
1187 			rval = DDI_SUCCESS;
1188 		} else {
1189 			cmn_err(CE_WARN, "%s(%d): failed , status %x",
1190 			    __func__, qlge->instance, mbx_results.mb[0]);
1191 		}
1192 	}
1193 out:
1194 	return (rval);
1195 }
1196