xref: /titanic_50/usr/src/uts/common/io/fibre-channel/fca/qlge/qlge_mpi.c (revision 803376f094adaaf2e4d9aa1c1d0efd56b642d838)
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
ql_poll_processor_intr(qlge_t * qlge,uint8_t timeout)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
ql_wait_processor_addr_reg_ready(qlge_t * qlge)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
ql_write_processor_data(qlge_t * qlge,uint32_t addr,uint32_t data)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
ql_read_processor_data(qlge_t * qlge,uint32_t addr,uint32_t * data)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
ql_read_mailbox_cmd(qlge_t * qlge,mbx_data_t * mbx_buf,uint32_t count)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
ql_issue_mailbox_cmd(qlge_t * qlge,mbx_cmd_t * mbx_cmd)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
ql_issue_mailbox_cmd_and_poll_rsp(qlge_t * qlge,mbx_cmd_t * mbx_cmd,mbx_data_t * p_results)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
ql_issue_mailbox_cmd_and_wait_rsp(qlge_t * qlge,mbx_cmd_t * mbx_cmd)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
ql_async_event_parser(qlge_t * qlge,mbx_data_t * mbx_cmds)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 	boolean_t fatal_error = B_FALSE;
371 
372 	switch (mbx_cmds->mb[0]) {
373 	case MBA_IDC_INTERMEDIATE_COMPLETE /* 1000h */:
374 		QL_PRINT(DBG_MBX, ("%s(%d):"
375 		    "MBA_IDC_INTERMEDIATE_COMPLETE received\n",
376 		    __func__, qlge->instance));
377 		break;
378 	case MBA_SYSTEM_ERR /* 8002h */:
379 		cmn_err(CE_WARN, "%s(%d): MBA_SYSTEM_ERR received",
380 		    __func__, qlge->instance);
381 		cmn_err(CE_WARN, "%s(%d): File id %x, Line # %x,"
382 		    "Firmware Ver# %x",
383 		    __func__, qlge->instance, mbx_cmds->mb[1],
384 		    mbx_cmds->mb[2], mbx_cmds->mb[3]);
385 		fatal_error = B_TRUE;
386 		(void) ql_8xxx_binary_core_dump(qlge, &qlge->ql_mpi_coredump);
387 		break;
388 	case MBA_LINK_UP /* 8011h */:
389 		QL_PRINT(DBG_MBX, ("%s(%d): MBA_LINK_UP received\n",
390 		    __func__, qlge->instance));
391 		link_status = mbx_cmds->mb[1];
392 		QL_PRINT(DBG_MBX, ("%s(%d): Link Status %x \n",
393 		    __func__, qlge->instance, link_status));
394 		link_speed = (uint8_t)((link_status >> 3) & 0x07);
395 
396 		if (link_speed == 0) {
397 			qlge->speed = SPEED_100;
398 			QL_PRINT(DBG_MBX, ("%s(%d):Link speed 100M\n",
399 			    __func__, qlge->instance));
400 		} else if (link_speed == 1) {
401 			qlge->speed = SPEED_1000;
402 			QL_PRINT(DBG_MBX, ("%s(%d):Link speed 1G\n",
403 			    __func__, qlge->instance));
404 		} else if (link_speed == 2) {
405 			qlge->speed = SPEED_10G;
406 			QL_PRINT(DBG_MBX, ("%s(%d):Link speed 10G\n",
407 			    __func__, qlge->instance));
408 			}
409 
410 		qlge->link_type = link_type = (uint8_t)(link_status & 0x07);
411 
412 		if (link_type == XFI_NETWORK_INTERFACE) {
413 			/* EMPTY */
414 			QL_PRINT(DBG_MBX,
415 			    ("%s(%d):Link type XFI_NETWORK_INTERFACE\n",
416 			    __func__, qlge->instance));
417 		} else if (link_type == XAUI_NETWORK_INTERFACE) {
418 			/* EMPTY */
419 			QL_PRINT(DBG_MBX, ("%s(%d):Link type"
420 			    "XAUI_NETWORK_INTERFACE\n",
421 			    __func__, qlge->instance));
422 		} else if (link_type == XFI_BACKPLANE_INTERFACE) {
423 			/* EMPTY */
424 			QL_PRINT(DBG_MBX, ("%s(%d):Link type"
425 			    "XFI_BACKPLANE_INTERFACE\n",
426 			    __func__, qlge->instance));
427 		} else if (link_type == XAUI_BACKPLANE_INTERFACE) {
428 			/* EMPTY */
429 			QL_PRINT(DBG_MBX, ("%s(%d):Link type "
430 			    "XAUI_BACKPLANE_INTERFACE\n",
431 			    __func__, qlge->instance));
432 		} else if (link_type == EXT_10GBASE_T_PHY) {
433 			/* EMPTY */
434 			QL_PRINT(DBG_MBX,
435 			    ("%s(%d):Link type EXT_10GBASE_T_PHY\n",
436 			    __func__, qlge->instance));
437 		} else if (link_type == EXT_EXT_EDC_PHY) {
438 			/* EMPTY */
439 			QL_PRINT(DBG_MBX,
440 			    ("%s(%d):Link type EXT_EXT_EDC_PHY\n",
441 			    __func__, qlge->instance));
442 		} else {
443 			/* EMPTY */
444 			QL_PRINT(DBG_MBX,
445 			    ("%s(%d):unknown Link type \n",
446 			    __func__, qlge->instance));
447 		}
448 		cmn_err(CE_NOTE, "qlge(%d) mpi link up! speed %dMbps\n",
449 		    qlge->instance, qlge->speed);
450 		/*
451 		 * start timer if not started to delay some time then
452 		 * check if link is really up or down
453 		 */
454 		ql_restart_timer(qlge);
455 
456 		break;
457 	case MBA_LINK_DOWN /* 8012h */:
458 		QL_PRINT(DBG_MBX,
459 		    ("%s(%d): MBA_LINK_DOWN received\n",
460 		    __func__, qlge->instance));
461 
462 		link_status = mbx_cmds->mb[1];
463 
464 		QL_PRINT(DBG_MBX, ("%s(%d): Link Status %x \n",
465 		    __func__, qlge->instance, link_status));
466 		if (link_status & 0x1) {
467 			/* EMPTY */
468 			QL_PRINT(DBG_MBX, ("%s(%d): Loss of signal \n",
469 			    __func__, qlge->instance));
470 		}
471 		if (link_status & 0x2) {
472 			/* EMPTY */
473 			QL_PRINT(DBG_MBX,
474 			    ("%s(%d): Auto-Negotiation Failed \n",
475 			    __func__, qlge->instance));
476 		}
477 		if (link_status & 0x4) {
478 			/* EMPTY */
479 			QL_PRINT(DBG_MBX,
480 			    ("%s(%d): XTI-Training Failed \n",
481 			    __func__, qlge->instance));
482 		}
483 
484 		cmn_err(CE_NOTE, "qlge(%d) mpi link down!\n", qlge->instance);
485 		ql_restart_timer(qlge);
486 		break;
487 	case MBA_IDC_COMPLETE /* 8100h */:
488 
489 		QL_PRINT(DBG_MBX,
490 		    ("%s(%d): MBA_IDC_COMPLETE received\n",
491 		    __func__, qlge->instance));
492 		cmd = mbx_cmds->mb[1];
493 		if (cmd == MBC_STOP_FIRMWARE) {
494 			/* EMPTY */
495 			QL_PRINT(DBG_MBX,
496 			    ("%s(%d): STOP_FIRMWARE event completed\n",
497 			    __func__, qlge->instance));
498 		} else if (cmd == MBC_IDC_REQUEST) {
499 			/* EMPTY */
500 			QL_PRINT(DBG_MBX,
501 			    ("%s(%d): IDC_REQUEST event completed\n",
502 			    __func__, qlge->instance));
503 		} else if (cmd == MBC_PORT_RESET) {
504 			/* EMPTY */
505 			QL_PRINT(DBG_MBX,
506 			    ("%s(%d): PORT_RESET event completed\n",
507 			    __func__, qlge->instance));
508 		} else if (cmd == MBC_SET_PORT_CONFIG) {
509 			/* EMPTY */
510 			QL_PRINT(DBG_MBX,
511 			    ("%s(%d): SET_PORT_CONFIG event "
512 			    "completed\n", __func__, qlge->instance));
513 		} else {
514 			/* EMPTY */
515 			QL_PRINT(DBG_MBX,
516 			    ("%s(%d): unknown IDC completion request"
517 			    " event %x %x\n", __func__, qlge->instance,
518 			    mbx_cmds->mb[1], mbx_cmds->mb[2]));
519 		}
520 		proc_done = B_FALSE;
521 		break;
522 
523 	case MBA_IDC_REQUEST_NOTIFICATION /* 8101h */:
524 		QL_PRINT(DBG_MBX,
525 		    ("%s(%d): MBA_IDC_REQUEST_NOTIFICATION "
526 		    "received\n", __func__, qlge->instance));
527 		cmd = mbx_cmds->mb[1];
528 		if (cmd == MBC_STOP_FIRMWARE) {
529 			/* EMPTY */
530 			QL_PRINT(DBG_MBX,
531 			    ("%s(%d): STOP_FIRMWARE notification"
532 			    " received\n", __func__, qlge->instance));
533 		} else if (cmd == MBC_IDC_REQUEST) {
534 			/* EMPTY */
535 			QL_PRINT(DBG_MBX,
536 			    ("%s(%d): IDC_REQUEST notification "
537 			    "received\n", __func__, qlge->instance));
538 		} else if (cmd == MBC_PORT_RESET) {
539 			/* EMPTY */
540 			QL_PRINT(DBG_MBX, ("%s(%d): PORT_RESET "
541 			    "notification received\n",
542 			    __func__, qlge->instance));
543 		} else if (cmd == MBC_SET_PORT_CONFIG) {
544 			/* EMPTY */
545 			QL_PRINT(DBG_MBX,
546 			    ("%s(%d): SET_PORT_CONFIG notification "
547 			    "received\n", __func__, qlge->instance));
548 		} else {
549 			/* EMPTY */
550 			QL_PRINT(DBG_MBX, ("%s(%d): "
551 			    "unknown request received %x %x\n",
552 			    __func__, qlge->instance, mbx_cmds->mb[1],
553 			    mbx_cmds->mb[2]));
554 		}
555 		reply_cmd.mb[0] = MBC_IDC_ACK;
556 		reply_cmd.mb[1] = mbx_cmds->mb[1];
557 		reply_cmd.mb[2] = mbx_cmds->mb[2];
558 		reply_cmd.mb[3] = mbx_cmds->mb[3];
559 		reply_cmd.mb[4] = mbx_cmds->mb[4];
560 		if (ql_issue_mailbox_cmd(qlge, &reply_cmd)
561 		    != DDI_SUCCESS) {
562 			cmn_err(CE_WARN,
563 			    "%s(%d) send IDC Ack failed.",
564 			    __func__, qlge->instance);
565 		}
566 		/*
567 		 * verify if the incoming outbound mailbox value is what
568 		 * we just sent
569 		 */
570 		if (mbx_cmds->mb[0] == MBS_COMMAND_COMPLETE) {
571 			/* 0x4000 */
572 			/* EMPTY */
573 			QL_PRINT(DBG_MBX,
574 			    ("%s(%d): IDC Ack sent success.\n",
575 			    __func__, qlge->instance));
576 			} else {
577 			/* EMPTY */
578 			QL_PRINT(DBG_MBX,
579 			    ("%s(%d): IDC Ack reply error %x %x %x.\n",
580 			    __func__, qlge->instance, mbx_cmds->mb[0],
581 			    mbx_cmds->mb[1], mbx_cmds->mb[2]));
582 			}
583 		break;
584 	case MBA_IDC_TIME_EXTENDED /* 8102 */:
585 		QL_PRINT(DBG_MBX,
586 		    ("%s(%d): MBA_IDC_TIME_EXTENDED received\n",
587 		    __func__, qlge->instance));
588 		break;
589 	case MBA_DCBX_CONFIG_CHANGE /* 8110 */:
590 		QL_PRINT(DBG_MBX,
591 		    ("%s(%d): MBA_DCBX_CONFIG_CHANGE received\n",
592 		    __func__, qlge->instance));
593 		break;
594 	case MBA_NOTIFICATION_LOST /* 8120 */:
595 		QL_PRINT(DBG_MBX,
596 		    ("%s(%d): MBA_NOTIFICATION_LOST received\n",
597 		    __func__, qlge->instance));
598 		break;
599 	case MBA_SFT_TRANSCEIVER_INSERTION /* 8130 */:
600 		QL_PRINT(DBG_MBX,
601 		    ("%s(%d): MBA_SFT_TRANSCEIVER_INSERTION "
602 		    "received\n", __func__, qlge->instance));
603 		break;
604 	case MBA_SFT_TRANSCEIVER_REMOVAL /* 8140 */:
605 		QL_PRINT(DBG_MBX,
606 		    ("%s(%d): MBA_SFT_TRANSCEIVER_REMOVAL "
607 		    "received\n", __func__, qlge->instance));
608 		break;
609 	case MBA_FIRMWARE_INIT_COMPLETE /* 8400 */:
610 		QL_PRINT(DBG_MBX,
611 		    ("%s(%d): MBA_FIRMWARE_INIT_COMPLETE "
612 		    "received\n", __func__, qlge->instance));
613 		QL_PRINT(DBG_MBX,
614 		    ("%s(%d): mbx[1] %x, mbx[2] %x\n", __func__,
615 		    qlge->instance, mbx_cmds->mb[1], mbx_cmds->mb[2]));
616 		qlge->fw_init_complete = B_TRUE;
617 		qlge->fw_version_info.major_version =
618 		    LSB(MSW(mbx_cmds->mb[1]));
619 		qlge->fw_version_info.minor_version =
620 		    MSB(LSW(mbx_cmds->mb[1]));
621 		qlge->fw_version_info.sub_minor_version =
622 		    LSB(LSW(mbx_cmds->mb[1]));
623 		qlge->phy_version_info.major_version =
624 		    LSB(MSW(mbx_cmds->mb[2]));
625 		qlge->phy_version_info.minor_version =
626 		    MSB(LSW(mbx_cmds->mb[2]));
627 		qlge->phy_version_info.sub_minor_version =
628 		    LSB(LSW(mbx_cmds->mb[2]));
629 		break;
630 	case MBA_FIRMWARE_INIT_FAILED /* 8401 */:
631 		cmn_err(CE_WARN, "%s(%d):"
632 		    "ASYNC_EVENT_FIRMWARE_INIT_FAILURE "
633 		    "received:  mbx[1] %x, mbx[2] %x",
634 		    __func__, qlge->instance,
635 		    mbx_cmds->mb[1], mbx_cmds->mb[2]);
636 		fatal_error = B_TRUE;
637 		break;
638 	default:
639 		if (mbx_cmds->mb[0] > 0x8000) {
640 			cmn_err(CE_WARN, "%s(%d): "
641 			    "Unknown Async event received: mbx[0] %x ,"
642 			    "mbx[1] %x; mbx[2] %x",
643 			    __func__, qlge->instance,
644 			    mbx_cmds->mb[0], mbx_cmds->mb[1],
645 			    mbx_cmds->mb[2]);
646 			proc_done = B_TRUE;
647 		} else {
648 			proc_done = B_FALSE;
649 		}
650 		break;
651 	}
652 	if (fatal_error) {
653 		if (qlge->fm_enable) {
654 			ql_fm_ereport(qlge, DDI_FM_DEVICE_NO_RESPONSE);
655 			ddi_fm_service_impact(qlge->dip, DDI_SERVICE_LOST);
656 			atomic_or_32(&qlge->flags, ADAPTER_ERROR);
657 		}
658 	}
659 	return (proc_done);
660 }
661 
662 
663 /*
664  * MPI Interrupt handler
665  * Caller must have MBX_LOCK
666  */
667 void
ql_do_mpi_intr(qlge_t * qlge)668 ql_do_mpi_intr(qlge_t *qlge)
669 {
670 	/*
671 	 * we just need to read first few mailboxes that this adapter's MPI
672 	 * will write response to.
673 	 */
674 	mutex_enter(&qlge->mbx_mutex);
675 
676 	(void) ql_read_mailbox_cmd(qlge, &qlge->received_mbx_cmds,
677 	    qlge->max_read_mbx);
678 
679 	/*
680 	 * process PI interrupt as async events, if not done,
681 	 * then pass to mailbox processing
682 	 */
683 	if (ql_async_event_parser(qlge, &qlge->received_mbx_cmds) == B_FALSE) {
684 		QL_PRINT(DBG_MBX, ("%s(%d) mailbox completion interrupt\n",
685 		    __func__, qlge->instance));
686 		/*
687 		 * If another thread is waiting for the mail box
688 		 * completion event to occur
689 		 */
690 		if (qlge->mbx_wait_completion == 1) {
691 			qlge->mbx_wait_completion = 0;
692 			cv_broadcast(&qlge->cv_mbx_intr);
693 			QL_PRINT(DBG_MBX,
694 			    ("%s(%d) mailbox completion signaled \n",
695 			    __func__, qlge->instance));
696 		}
697 	}
698 	/* inform MPI Firmware to clear the interrupt */
699 	ql_write_reg(qlge, REG_HOST_CMD_STATUS,
700 	    HOST_CMD_CLEAR_RISC_TO_HOST_INTR /* 0x0A */);
701 	mutex_exit(&qlge->mbx_mutex);
702 	ql_enable_completion_interrupt(qlge, 0); /* MPI is on irq 0 */
703 }
704 
705 /*
706  * Test if mailbox communication works
707  * This is used when Interrupt is not enabled
708  */
709 int
ql_mbx_test(qlge_t * qlge)710 ql_mbx_test(qlge_t *qlge)
711 {
712 	mbx_cmd_t mbx_cmds;
713 	mbx_data_t mbx_results;
714 	int i, test_ok = 1;
715 	int rtn_val = DDI_FAILURE;
716 
717 	for (i = 0; i < NUM_MAILBOX_REGS; i++)
718 		mbx_cmds.mb[i] = i;
719 
720 	mbx_cmds.mb[0] = MBC_MAILBOX_REGISTER_TEST; /* 0x06 */
721 	if (ql_issue_mailbox_cmd(qlge, &mbx_cmds) != DDI_SUCCESS) {
722 		cmn_err(CE_WARN, "%s(%d) ql_issue_mailbox_cmd timeout.",
723 		    __func__, qlge->instance);
724 		goto out;
725 	}
726 
727 	/* delay for the processor interrupt is received */
728 	if (ql_poll_processor_intr(qlge, (uint8_t)mbx_cmds.timeout)
729 	    == DDI_SUCCESS) {
730 		QL_PRINT(DBG_MBX, ("%s(%d) PI Intr received",
731 		    __func__, qlge->instance));
732 		(void) ql_read_mailbox_cmd(qlge, &mbx_results, 0);
733 
734 		ql_write_reg(qlge, REG_HOST_CMD_STATUS,
735 		    HOST_CMD_CLEAR_RISC_TO_HOST_INTR);
736 
737 		if (mbx_results.mb[0] != MBS_COMMAND_COMPLETE /* 0x4000 */) {
738 			test_ok = 0;
739 		} else {
740 			for (i = 1; i < NUM_MAILBOX_REGS; i++) {
741 				if (mbx_results.mb[i] != i) {
742 					test_ok = 0;
743 					break;
744 				}
745 			}
746 		}
747 		if (test_ok) {
748 			rtn_val = DDI_SUCCESS;
749 		} else {
750 			cmn_err(CE_WARN, "%s(%d) mailbox test failed!",
751 			    __func__, qlge->instance);
752 		}
753 	} else {
754 		cmn_err(CE_WARN, "%s(%d) mailbox testing error: "
755 		    "PI Intr not received ", __func__, qlge->instance);
756 	}
757 out:
758 	return (rtn_val);
759 }
760 
761 /*
762  * ql_mbx_test2
763  * Test if mailbox communication works
764  * This is used when Interrupt is enabled
765  * mailbox cmd:0x06h
766  */
767 int
ql_mbx_test2(qlge_t * qlge)768 ql_mbx_test2(qlge_t *qlge)
769 {
770 	mbx_cmd_t mbx_cmds = {0};
771 	int i, test_ok = 1;
772 	int rtn_val = DDI_FAILURE;
773 
774 	for (i = 0; i < NUM_MAILBOX_REGS; i++)
775 		mbx_cmds.mb[i] = i;
776 
777 	mbx_cmds.mb[0] = MBC_MAILBOX_REGISTER_TEST; /* 0x06 */
778 	if (ql_issue_mailbox_cmd_and_wait_rsp(qlge, &mbx_cmds) != DDI_SUCCESS) {
779 		cmn_err(CE_WARN,
780 		    "%s(%d) ql_issue_mailbox_cmd_and_wait_rsp failed.",
781 		    __func__, qlge->instance);
782 		goto out;
783 	}
784 
785 	/* verify if the incoming outbound mailbox value is what we just sent */
786 	if (mbx_cmds.mb[0] != MBS_COMMAND_COMPLETE /* 0x4000 */) {
787 		test_ok = 0;
788 	} else {
789 		for (i = 1; i < qlge->max_read_mbx; i++) {
790 			if (mbx_cmds.mb[i] != i) {
791 				test_ok = 0;
792 				break;
793 			}
794 		}
795 	}
796 	if (test_ok) {
797 		rtn_val = DDI_SUCCESS;
798 	} else {
799 		cmn_err(CE_WARN, "%s(%d) mailbox test failed!",
800 		    __func__, qlge->instance);
801 	}
802 out:
803 	if ((rtn_val != DDI_SUCCESS) && qlge->fm_enable) {
804 		ql_fm_ereport(qlge, DDI_FM_DEVICE_NO_RESPONSE);
805 		ddi_fm_service_impact(qlge->dip, DDI_SERVICE_DEGRADED);
806 	}
807 	return (rtn_val);
808 }
809 
810 /*
811  * ql_get_fw_state
812  * Get fw state.
813  * mailbox cmd:0x69h
814  */
815 int
ql_get_fw_state(qlge_t * qlge,uint32_t * fw_state_ptr)816 ql_get_fw_state(qlge_t *qlge, uint32_t *fw_state_ptr)
817 {
818 	int rtn_val = DDI_FAILURE;
819 	mbx_cmd_t mbx_cmds = {0};
820 
821 	mbx_cmds.mb[0] = MBC_GET_FIRMWARE_STATE;
822 
823 	if (ql_issue_mailbox_cmd_and_wait_rsp(qlge, &mbx_cmds)
824 	    != DDI_SUCCESS) {
825 		cmn_err(CE_WARN, "%s(%d) ql_issue_mailbox_cmd_and_wait_rsp"
826 		    " failed.", __func__, qlge->instance);
827 		goto out;
828 	}
829 	/* verify if the transaction is completed successful */
830 	if (mbx_cmds.mb[0] != MBS_COMMAND_COMPLETE /* 0x4000 */) {
831 		cmn_err(CE_WARN, "%s(%d) failed, 0x%x",
832 		    __func__, qlge->instance, mbx_cmds.mb[0]);
833 	} else {
834 		/* EMPTY */
835 		QL_PRINT(DBG_MBX, ("firmware state: 0x%x\n", mbx_cmds.mb[1]));
836 	}
837 	if (fw_state_ptr != NULL)
838 		*fw_state_ptr = mbx_cmds.mb[1];
839 	rtn_val = DDI_SUCCESS;
840 out:
841 	if ((rtn_val != DDI_SUCCESS) && qlge->fm_enable) {
842 		ql_fm_ereport(qlge, DDI_FM_DEVICE_NO_RESPONSE);
843 		ddi_fm_service_impact(qlge->dip, DDI_SERVICE_DEGRADED);
844 	}
845 	return (rtn_val);
846 }
847 
848 /*
849  * ql_set_IDC_Req
850  * Send a IDC Request to firmware to notify all functions
851  * or any specific functions on the same port
852  * mailbox cmd:0x100h
853  */
854 int
ql_set_IDC_Req(qlge_t * qlge,uint8_t dest_functions,uint8_t timeout)855 ql_set_IDC_Req(qlge_t *qlge, uint8_t dest_functions, uint8_t timeout)
856 {
857 	int rtn_val = DDI_FAILURE;
858 	mbx_cmd_t mbx_cmds = {0};
859 
860 	mbx_cmds.mb[0] = MBC_IDC_REQUEST /* 0x100 */;
861 	mbx_cmds.mb[1] = (timeout<<8) | qlge->func_number;
862 
863 	switch (dest_functions) {
864 	case IDC_REQ_DEST_FUNC_ALL:
865 		mbx_cmds.mb[1] |= IDC_REQ_ALL_DEST_FUNC_MASK;
866 		mbx_cmds.mb[2] = 0;
867 		break;
868 	case IDC_REQ_DEST_FUNC_0:
869 		mbx_cmds.mb[2] = IDC_REQ_DEST_FUNC_0_MASK;
870 		break;
871 	case IDC_REQ_DEST_FUNC_1:
872 		mbx_cmds.mb[2] = IDC_REQ_DEST_FUNC_1_MASK;
873 		break;
874 	case IDC_REQ_DEST_FUNC_2:
875 		mbx_cmds.mb[2] = IDC_REQ_DEST_FUNC_2_MASK;
876 		break;
877 	case IDC_REQ_DEST_FUNC_3:
878 		mbx_cmds.mb[2] = IDC_REQ_DEST_FUNC_3_MASK;
879 		break;
880 	default:
881 		cmn_err(CE_WARN, "Wrong dest functions %x",
882 		    dest_functions);
883 	}
884 
885 	if (ql_issue_mailbox_cmd_and_wait_rsp(qlge, &mbx_cmds) != DDI_SUCCESS) {
886 		cmn_err(CE_WARN,
887 		    "%s(%d) ql_issue_mailbox_cmd_and_wait_rsp failed.",
888 		    __func__, qlge->instance);
889 		goto out;
890 	}
891 	/* verify if the transaction is completed successful */
892 	if (mbx_cmds.mb[0] == MBA_IDC_INTERMEDIATE_COMPLETE /* 0x1000 */) {
893 		QL_PRINT(DBG_MBX, ("%s(%d) mbx1: 0x%x, mbx2: 0x%x\n",
894 		    __func__, qlge->instance, mbx_cmds.mb[1], mbx_cmds.mb[2]));
895 		rtn_val = DDI_SUCCESS;
896 	} else if (mbx_cmds.mb[0] == MBS_COMMAND_COMPLETE /* 0x4000 */) {
897 		QL_PRINT(DBG_MBX, ("%s(%d) cmd sent succesfully 0x%x\n",
898 		    __func__, qlge->instance));
899 		rtn_val = DDI_SUCCESS;
900 	} else if (mbx_cmds.mb[0] == MBS_COMMAND_ERROR /* 0x4005 */) {
901 		cmn_err(CE_WARN, "%s(%d) failed: COMMAND_ERROR",
902 		    __func__, qlge->instance);
903 	} else if (mbx_cmds.mb[0] == MBS_COMMAND_PARAMETER_ERROR /* 0x4006 */) {
904 		cmn_err(CE_WARN, "%s(%d) failed: COMMAND_PARAMETER_ERROR",
905 		    __func__, qlge->instance);
906 	} else {
907 		cmn_err(CE_WARN, "%s(%d) unknow result: mbx[0]: 0x%x; mbx[1]:"
908 		    " 0x%x; mbx[2]: 0x%x", __func__, qlge->instance,
909 		    mbx_cmds.mb[0], mbx_cmds.mb[1], mbx_cmds.mb[2]);
910 	}
911 
912 out:
913 	if ((rtn_val != DDI_SUCCESS) && qlge->fm_enable) {
914 		ql_fm_ereport(qlge, DDI_FM_DEVICE_NO_RESPONSE);
915 		ddi_fm_service_impact(qlge->dip, DDI_SERVICE_DEGRADED);
916 	}
917 return (rtn_val);
918 }
919 
920 /*
921  * ql_set_mpi_port_config
922  * Send new port configuration.to mpi
923  * mailbox cmd:0x122h
924  */
925 int
ql_set_mpi_port_config(qlge_t * qlge,port_cfg_info_t new_cfg)926 ql_set_mpi_port_config(qlge_t *qlge, port_cfg_info_t new_cfg)
927 {
928 	int rtn_val = DDI_FAILURE;
929 	mbx_cmd_t mbx_cmds = {0};
930 
931 	mbx_cmds.mb[0] = MBC_SET_PORT_CONFIG /* 0x122 */;
932 	mbx_cmds.mb[1] = new_cfg.link_cfg;
933 	mbx_cmds.mb[2] = new_cfg.max_frame_size;
934 
935 	if (ql_issue_mailbox_cmd_and_wait_rsp(qlge, &mbx_cmds) != DDI_SUCCESS) {
936 		cmn_err(CE_WARN, "%s(%d) ql_issue_mailbox_cmd_and_wait_rsp"
937 		    " failed.", __func__, qlge->instance);
938 		goto out;
939 	}
940 	/* verify if the transaction is completed successful */
941 	if ((mbx_cmds.mb[0] != MBS_COMMAND_COMPLETE /* 0x4000 */) &&
942 	    (mbx_cmds.mb[0] != MBA_IDC_COMPLETE /* 0x8100 */)) {
943 		cmn_err(CE_WARN, "set port config (%d) failed, 0x%x",
944 		    qlge->instance, mbx_cmds.mb[0]);
945 	} else
946 		rtn_val = DDI_SUCCESS;
947 out:
948 	if ((rtn_val != DDI_SUCCESS) && qlge->fm_enable) {
949 		ql_fm_ereport(qlge, DDI_FM_DEVICE_NO_RESPONSE);
950 		ddi_fm_service_impact(qlge->dip, DDI_SERVICE_DEGRADED);
951 	}
952 	return (rtn_val);
953 }
954 
955 int
ql_set_pause_mode(qlge_t * qlge)956 ql_set_pause_mode(qlge_t *qlge)
957 {
958 	uint32_t pause_bit_mask = 0x60;	/* bit 5-6 */
959 
960 	/* clear pause bits */
961 	qlge->port_cfg_info.link_cfg &= ~pause_bit_mask;
962 
963 	/* set new pause mode */
964 	if (qlge->pause == PAUSE_MODE_STANDARD)
965 		qlge->port_cfg_info.link_cfg |= STD_PAUSE;
966 	else if (qlge->pause == PAUSE_MODE_PER_PRIORITY)
967 		qlge->port_cfg_info.link_cfg |= PP_PAUSE;
968 
969 	return (ql_set_mpi_port_config(qlge, qlge->port_cfg_info));
970 }
971 
972 int
ql_set_loop_back_mode(qlge_t * qlge)973 ql_set_loop_back_mode(qlge_t *qlge)
974 {
975 	uint32_t loop_back_bit_mask = 0x0e; /* bit 1-3 */
976 
977 	/* clear loop back bits */
978 	qlge->port_cfg_info.link_cfg &= ~loop_back_bit_mask;
979 	/* loop back cfg: bit1-3 */
980 	if (qlge->loop_back_mode == QLGE_LOOP_INTERNAL_PARALLEL)
981 		qlge->port_cfg_info.link_cfg |= LOOP_INTERNAL_PARALLEL;
982 	else if (qlge->loop_back_mode == QLGE_LOOP_INTERNAL_SERIAL)
983 		qlge->port_cfg_info.link_cfg |= LOOP_INTERNAL_SERIAL;
984 	else if (qlge->loop_back_mode == QLGE_LOOP_EXTERNAL_PHY)
985 		qlge->port_cfg_info.link_cfg |= LOOP_EXTERNAL_PHY;
986 
987 	return (ql_set_mpi_port_config(qlge, qlge->port_cfg_info));
988 
989 }
990 /*
991  * ql_get_port_cfg
992  * Get port configuration.
993  * mailbox cmd:0x123h
994  */
995 int
ql_get_port_cfg(qlge_t * qlge)996 ql_get_port_cfg(qlge_t *qlge)
997 {
998 	int rtn_val = DDI_FAILURE;
999 	mbx_cmd_t mbx_cmds = {0};
1000 
1001 	mbx_cmds.mb[0] = MBC_GET_PORT_CONFIG /* 0x123 */;
1002 	if (ql_issue_mailbox_cmd_and_wait_rsp(qlge, &mbx_cmds) != DDI_SUCCESS) {
1003 		cmn_err(CE_WARN, "%s(%d) ql_issue_mailbox_cmd_and_wait_rsp"
1004 		    " failed.", __func__, qlge->instance);
1005 		goto out;
1006 	}
1007 	/* verify if the transaction is completed successfully */
1008 	if (mbx_cmds.mb[0] != MBS_COMMAND_COMPLETE /* 0x4000 */) {
1009 		cmn_err(CE_WARN, "get port config (%d) failed, 0x%x",
1010 		    qlge->instance, mbx_cmds.mb[0]);
1011 	} else { /* verify frame size */
1012 		if ((mbx_cmds.mb[2] == NORMAL_FRAME_SIZE) ||
1013 		    (mbx_cmds.mb[2] == JUMBO_FRAME_SIZE)) {
1014 			qlge->port_cfg_info.link_cfg = mbx_cmds.mb[1];
1015 			qlge->port_cfg_info.max_frame_size = mbx_cmds.mb[2];
1016 			QL_PRINT(DBG_MBX, ("link_cfg: 0x%x, max_frame_size:"
1017 			    " %d bytes\n", mbx_cmds.mb[1], mbx_cmds.mb[2]));
1018 			rtn_val = DDI_SUCCESS;
1019 		} else {
1020 			cmn_err(CE_WARN, "bad link_cfg: 0x%x, max_frame_size:"
1021 			    " %d bytes", mbx_cmds.mb[1], mbx_cmds.mb[2]);
1022 		}
1023 	}
1024 out:
1025 	if ((rtn_val != DDI_SUCCESS) && qlge->fm_enable) {
1026 		ql_fm_ereport(qlge, DDI_FM_DEVICE_NO_RESPONSE);
1027 		ddi_fm_service_impact(qlge->dip, DDI_SERVICE_DEGRADED);
1028 	}
1029 	return (rtn_val);
1030 }
1031 
1032 /*
1033  * qlge_get_link_status
1034  * Get link status.
1035  * mailbox cmd:0x124h
1036  */
1037 int
qlge_get_link_status(qlge_t * qlge,struct qlnic_link_status_info * link_status_ptr)1038 qlge_get_link_status(qlge_t *qlge,
1039     struct qlnic_link_status_info *link_status_ptr)
1040 {
1041 	int rtn_val = DDI_FAILURE;
1042 	mbx_cmd_t mbx_cmds = {0};
1043 
1044 	mbx_cmds.mb[0] = MBC_GET_LINK_STATUS /* 0x124 */;
1045 
1046 	if (ql_issue_mailbox_cmd_and_wait_rsp(qlge, &mbx_cmds)
1047 	    != DDI_SUCCESS) {
1048 		cmn_err(CE_WARN,
1049 		    "%s(%d) ql_issue_mailbox_cmd_and_wait_rsp failed.",
1050 		    __func__, qlge->instance);
1051 		goto out;
1052 	}
1053 	/* verify if the transaction is completed successful */
1054 	if (mbx_cmds.mb[0] != MBS_COMMAND_COMPLETE /* 0x4000 */) {
1055 		cmn_err(CE_WARN, "get link status(%d) failed, 0x%x",
1056 		    qlge->instance, mbx_cmds.mb[0]);
1057 	} else {
1058 		/* EMPTY */
1059 		QL_PRINT(DBG_MBX,
1060 		    ("link status: status1 : 0x%x, status2 : 0x%x, "
1061 		    "status3 : 0x%x\n",
1062 		    mbx_cmds.mb[1], mbx_cmds.mb[2], mbx_cmds.mb[3]));
1063 	}
1064 	if (link_status_ptr != NULL) {
1065 		link_status_ptr->link_status_info = mbx_cmds.mb[1];
1066 		link_status_ptr->additional_info = mbx_cmds.mb[2];
1067 		link_status_ptr->network_hw_info = mbx_cmds.mb[3];
1068 		link_status_ptr->dcbx_frame_counters_info = mbx_cmds.mb[4];
1069 		link_status_ptr->change_counters_info = mbx_cmds.mb[5];
1070 	}
1071 	rtn_val = DDI_SUCCESS;
1072 out:
1073 	if ((rtn_val != DDI_SUCCESS) && qlge->fm_enable) {
1074 		ql_fm_ereport(qlge, DDI_FM_DEVICE_NO_RESPONSE);
1075 		ddi_fm_service_impact(qlge->dip, DDI_SERVICE_DEGRADED);
1076 	}
1077 	return (rtn_val);
1078 }
1079 
1080 /*
1081  * ql_get_firmware_version
1082  * Get firmware version.
1083  */
1084 int
ql_get_firmware_version(qlge_t * qlge,struct qlnic_mpi_version_info * mpi_version_ptr)1085 ql_get_firmware_version(qlge_t *qlge,
1086     struct qlnic_mpi_version_info *mpi_version_ptr)
1087 {
1088 	int rtn_val = DDI_FAILURE;
1089 	mbx_cmd_t mbx_cmds = {0};
1090 
1091 	mbx_cmds.mb[0] = MBC_ABOUT_FIRMWARE /* 0x08 */;
1092 
1093 	if (ql_issue_mailbox_cmd_and_wait_rsp(qlge, &mbx_cmds)
1094 	    != DDI_SUCCESS) {
1095 		cmn_err(CE_WARN,
1096 		    "%s(%d) ql_issue_mailbox_cmd_and_wait_rsp failed.",
1097 		    __func__, qlge->instance);
1098 		goto out;
1099 	}
1100 
1101 	/* verify if the transaction is completed successful */
1102 	if (mbx_cmds.mb[0] != MBS_COMMAND_COMPLETE /* 0x4000 */) {
1103 		cmn_err(CE_WARN, "get firmware version(%d) failed, 0x%x",
1104 		    qlge->instance, mbx_cmds.mb[0]);
1105 	} else {
1106 		qlge->fw_version_info.major_version =
1107 		    LSB(MSW(mbx_cmds.mb[1]));
1108 		qlge->fw_version_info.minor_version =
1109 		    MSB(LSW(mbx_cmds.mb[1]));
1110 		qlge->fw_version_info.sub_minor_version =
1111 		    LSB(LSW(mbx_cmds.mb[1]));
1112 		qlge->phy_version_info.major_version =
1113 		    LSB(MSW(mbx_cmds.mb[2]));
1114 		qlge->phy_version_info.minor_version =
1115 		    MSB(LSW(mbx_cmds.mb[2]));
1116 		qlge->phy_version_info.sub_minor_version =
1117 		    LSB(LSW(mbx_cmds.mb[2]));
1118 #ifdef QLGE_LOAD_UNLOAD
1119 		cmn_err(CE_NOTE, "firmware version: %d.%d.%d\n",
1120 		    qlge->fw_version_info.major_version,
1121 		    qlge->fw_version_info.minor_version,
1122 		    qlge->fw_version_info.sub_minor_version);
1123 #endif
1124 		if (mpi_version_ptr != NULL) {
1125 			mpi_version_ptr->fw_version =
1126 			    (qlge->fw_version_info.major_version<<16)
1127 			    |(qlge->fw_version_info.minor_version<<8)
1128 			    |(qlge->fw_version_info.sub_minor_version);
1129 			mpi_version_ptr->phy_version =
1130 			    (qlge->phy_version_info.major_version<<16)
1131 			    |(qlge->phy_version_info.minor_version<<8)
1132 			    |(qlge->phy_version_info.sub_minor_version);
1133 		}
1134 	}
1135 	rtn_val = DDI_SUCCESS;
1136 out:
1137 	if ((rtn_val != DDI_SUCCESS) && qlge->fm_enable) {
1138 		ql_fm_ereport(qlge, DDI_FM_DEVICE_NO_RESPONSE);
1139 		ddi_fm_service_impact(qlge->dip, DDI_SERVICE_DEGRADED);
1140 	}
1141 	return (rtn_val);
1142 }
1143 
1144 /*
1145  * Trigger a system error event
1146  */
1147 int
ql_trigger_system_error_event(qlge_t * qlge)1148 ql_trigger_system_error_event(qlge_t *qlge)
1149 {
1150 	mbx_cmd_t mbx_cmds = {0};
1151 	int rtn_val = DDI_FAILURE;
1152 
1153 	mbx_cmds.mb[0] = MBC_GENERATE_SYS_ERROR; /* 0x2A */
1154 	if (ql_issue_mailbox_cmd(qlge, &mbx_cmds) != DDI_SUCCESS) {
1155 		cmn_err(CE_WARN, "%s(%d) ql_issue_mailbox_cmd timeout.",
1156 		    __func__, qlge->instance);
1157 		goto out;
1158 	}
1159 	rtn_val = DDI_SUCCESS;
1160 out:
1161 	return (rtn_val);
1162 }
1163 
1164 /*
1165  * Reset the MPI RISC Processor
1166  */
1167 int
ql_reset_mpi_risc(qlge_t * qlge)1168 ql_reset_mpi_risc(qlge_t *qlge)
1169 {
1170 	int rtn_val = DDI_FAILURE;
1171 
1172 	/* Reset the MPI Processor */
1173 	ql_write_reg(qlge, REG_HOST_CMD_STATUS, HOST_CMD_SET_RISC_RESET);
1174 	if (ql_wait_reg_bit(qlge, REG_HOST_CMD_STATUS, RISC_RESET,
1175 	    BIT_SET, 0) != DDI_SUCCESS) {
1176 		(void) ql_read_reg(qlge, REG_HOST_CMD_STATUS);
1177 		goto out;
1178 	}
1179 	ql_write_reg(qlge, REG_HOST_CMD_STATUS, HOST_CMD_CLEAR_RISC_RESET);
1180 	rtn_val = DDI_SUCCESS;
1181 out:
1182 	return (rtn_val);
1183 }
1184 
1185 int
ql_read_risc_ram(qlge_t * qlge,uint32_t risc_address,uint64_t bp,uint32_t word_count)1186 ql_read_risc_ram(qlge_t *qlge, uint32_t risc_address, uint64_t bp,
1187     uint32_t word_count)
1188 {
1189 	int rval = DDI_FAILURE;
1190 	mbx_cmd_t mc = {0};
1191 	mbx_cmd_t *mcp = &mc;
1192 	mbx_data_t mbx_results;
1193 
1194 	QL_PRINT(DBG_MBX, ("%s(%d): read risc addr:0x%x,"
1195 	    "phys_addr %x,%x words\n", __func__, qlge->instance,
1196 	    risc_address, bp, word_count));
1197 	if (CFG_IST(qlge, CFG_CHIP_8100)) {
1198 		mcp->mb[0] = MBC_DUMP_RISC_RAM /* 0x0C */;
1199 		mcp->mb[1] = LSW(risc_address);
1200 		mcp->mb[2] = MSW(LSD(bp));
1201 		mcp->mb[3] = LSW(LSD(bp));
1202 		mcp->mb[4] = MSW(word_count);
1203 		mcp->mb[5] = LSW(word_count);
1204 		mcp->mb[6] = MSW(MSD(bp));
1205 		mcp->mb[7] = LSW(MSD(bp));
1206 		mcp->mb[8] = MSW(risc_address);
1207 	}
1208 	mcp->timeout = 10 /* MAILBOX_TOV */;
1209 
1210 	if (ql_issue_mailbox_cmd_and_poll_rsp(qlge, mcp, &mbx_results)
1211 	    != DDI_SUCCESS) {
1212 		goto out;
1213 	} else {
1214 		QL_PRINT(DBG_MBX, ("%s(%d) PI Intr received",
1215 		    __func__, qlge->instance));
1216 		if (mbx_results.mb[0] == MBS_COMMAND_COMPLETE /* 0x4000 */) {
1217 			QL_PRINT(DBG_MBX, ("%s(%d): success\n",
1218 			    __func__, qlge->instance));
1219 			rval = DDI_SUCCESS;
1220 		} else {
1221 			cmn_err(CE_WARN, "read_risc_ram(%d): failed, status %x",
1222 			    qlge->instance, mbx_results.mb[0]);
1223 		}
1224 	}
1225 out:
1226 	return (rval);
1227 }
1228