/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2010 QLogic Corporation. All rights reserved.
*/
#include <qlge.h>
/*
* Wait upto timeout seconds for Processor Interrupt
* if timeout is 0, then wait for default waittime
*/
static int
{
!= DDI_SUCCESS) {
}
return (rtn_val);
}
/*
* Wait for mailbox Processor Register Ready
*/
static int
{
"Wait for processor address register ready timeout.");
}
return (rtn_val);
}
/*
* Read and write MPI registers using the indirect register interface
* Assume all the locks&semaphore have been acquired
*/
int
{
/* wait for processor address register ready */
goto out;
/* write the data to the data reg */
/* trigger the write */
/* wait for register to come ready */
goto out;
out:
return (rtn_val);
}
/*
* Read from processor register
*/
int
{
/* enable read operation */
/* wait for processor address register ready */
goto out;
/* Write read address, wait for data ready in Data register */
/* wait for data ready */
goto out;
/* read data */
out:
return (rtn_val);
}
/*
* Read "count" number of outgoing Mailbox register starting
* from mailbox #0 if count is 0 then read all mailboxes
*/
static int
{
int i;
"%s(%d) get QL_PROCESSOR_SEM_MASK time out error",
return (DDI_FAILURE);
}
else
if (count == 0)
for (i = 0; i < count; i++) {
== DDI_FAILURE)
goto out;
addr ++;
}
out:
return (rtn_val);
}
/*
* Write mail box command (upto 16) to MPI Firmware
*/
int
{
int i;
/*
* Get semaphore to access Processor Address and
* Processor Data Registers
*/
return (DDI_FAILURE);
}
/* ensure no overwriting current command */
goto out;
}
else
/* wait for mailbox registers to be ready to access */
goto out;
/* issue mailbox command one by one */
for (i = 0; i < NUM_MAILBOX_REGS; i++) {
/* write sending cmd to mailbox data register */
/* write mailbox address to address register */
addr++;
/*
* wait for mailbox cmd to be written before
* next write can start
*/
goto out;
}
/* inform MPI that new mailbox commands are available */
out:
return (rtn_val);
}
/*
* Send mail box command (upto 16) to MPI Firmware
* and polling for MPI mailbox completion response when
* interrupt is not enabled.
* The MBX_LOCK mutexe should have been held and released
* externally
*/
int
{
int max_wait;
goto err;
if (rtn_val != DDI_SUCCESS) {
goto err;
}
/* delay for the processor interrupt is received */
/* wait up to 5s for PI interrupt */
== DDI_SUCCESS) {
/*
* Sometimes, the incoming messages is not what we are
* waiting for, ie. async events, then, continue to
* wait. If it is the result * of previous mailbox
* command, then Done. No matter what, send
* HOST_CMD_CLEAR_RISC_TO_HOST_INTR to clear each
* PI interrupt
*/
/*
* we get what we are waiting for,
* clear the interrupt
*/
} else {
/*EMPTY*/
("%s(%d) result ignored, not we wait for\n",
}
} else { /* timeout */
}
}
err:
return (rtn_val);
}
/*
* Send mail box command (upto 16) to MPI Firmware
* and wait for MPI mailbox completion response which
* is saved in interrupt. Thus, this function can only
* be used after interrupt is enabled.
* Must hold MBX mutex before calling this function
*/
static int
{
int i;
int done = 0;
goto err;
/* if interrupts are not enabled, poll when results are available */
if (rtn_val == DDI_SUCCESS) {
for (i = 0; i < NUM_MAILBOX_REGS; i++)
}
} else {
if (rtn_val != DDI_SUCCESS) {
goto err;
}
/* default 5 seconds from now to timeout */
timer = ddi_get_lbolt();
timer +=
} else {
}
timer) == -1) {
/*
* The timeout time 'timer' was
* reached or expired without the condition
* being signaled.
*/
"complete timeout.",
done = 1;
} else {
("%s(%d) mailbox completion signal received"
for (i = 0; i < NUM_MAILBOX_REGS; i++) {
}
done = 1;
}
}
}
err:
return (rtn_val);
}
/*
* Inteprete incoming asynchronous events
*/
static int
{
case MBA_IDC_INTERMEDIATE_COMPLETE /* 1000h */:
"MBA_IDC_INTERMEDIATE_COMPLETE received\n",
break;
case MBA_SYSTEM_ERR /* 8002h */:
"Firmware Ver# %x",
break;
case MBA_LINK_UP /* 8011h */:
if (link_speed == 0) {
} else if (link_speed == 1) {
} else if (link_speed == 2) {
}
if (link_type == XFI_NETWORK_INTERFACE) {
/* EMPTY */
("%s(%d):Link type XFI_NETWORK_INTERFACE\n",
} else if (link_type == XAUI_NETWORK_INTERFACE) {
/* EMPTY */
"XAUI_NETWORK_INTERFACE\n",
} else if (link_type == XFI_BACKPLANE_INTERFACE) {
/* EMPTY */
"XFI_BACKPLANE_INTERFACE\n",
} else if (link_type == XAUI_BACKPLANE_INTERFACE) {
/* EMPTY */
"XAUI_BACKPLANE_INTERFACE\n",
} else if (link_type == EXT_10GBASE_T_PHY) {
/* EMPTY */
("%s(%d):Link type EXT_10GBASE_T_PHY\n",
} else if (link_type == EXT_EXT_EDC_PHY) {
/* EMPTY */
("%s(%d):Link type EXT_EXT_EDC_PHY\n",
} else {
/* EMPTY */
("%s(%d):unknown Link type \n",
}
/*
* start timer if not started to delay some time then
* check if link is really up or down
*/
break;
case MBA_LINK_DOWN /* 8012h */:
("%s(%d): MBA_LINK_DOWN received\n",
if (link_status & 0x1) {
/* EMPTY */
}
if (link_status & 0x2) {
/* EMPTY */
("%s(%d): Auto-Negotiation Failed \n",
}
if (link_status & 0x4) {
/* EMPTY */
("%s(%d): XTI-Training Failed \n",
}
break;
case MBA_IDC_COMPLETE /* 8100h */:
("%s(%d): MBA_IDC_COMPLETE received\n",
if (cmd == MBC_STOP_FIRMWARE) {
/* EMPTY */
("%s(%d): STOP_FIRMWARE event completed\n",
} else if (cmd == MBC_IDC_REQUEST) {
/* EMPTY */
("%s(%d): IDC_REQUEST event completed\n",
} else if (cmd == MBC_PORT_RESET) {
/* EMPTY */
("%s(%d): PORT_RESET event completed\n",
} else if (cmd == MBC_SET_PORT_CONFIG) {
/* EMPTY */
("%s(%d): SET_PORT_CONFIG event "
} else {
/* EMPTY */
("%s(%d): unknown IDC completion request"
}
break;
case MBA_IDC_REQUEST_NOTIFICATION /* 8101h */:
("%s(%d): MBA_IDC_REQUEST_NOTIFICATION "
if (cmd == MBC_STOP_FIRMWARE) {
/* EMPTY */
("%s(%d): STOP_FIRMWARE notification"
} else if (cmd == MBC_IDC_REQUEST) {
/* EMPTY */
("%s(%d): IDC_REQUEST notification "
} else if (cmd == MBC_PORT_RESET) {
/* EMPTY */
"notification received\n",
} else if (cmd == MBC_SET_PORT_CONFIG) {
/* EMPTY */
("%s(%d): SET_PORT_CONFIG notification "
} else {
/* EMPTY */
"unknown request received %x %x\n",
}
!= DDI_SUCCESS) {
"%s(%d) send IDC Ack failed.",
}
/*
* verify if the incoming outbound mailbox value is what
* we just sent
*/
/* 0x4000 */
/* EMPTY */
("%s(%d): IDC Ack sent success.\n",
} else {
/* EMPTY */
("%s(%d): IDC Ack reply error %x %x %x.\n",
}
break;
case MBA_IDC_TIME_EXTENDED /* 8102 */:
("%s(%d): MBA_IDC_TIME_EXTENDED received\n",
break;
case MBA_DCBX_CONFIG_CHANGE /* 8110 */:
("%s(%d): MBA_DCBX_CONFIG_CHANGE received\n",
break;
case MBA_NOTIFICATION_LOST /* 8120 */:
("%s(%d): MBA_NOTIFICATION_LOST received\n",
break;
case MBA_SFT_TRANSCEIVER_INSERTION /* 8130 */:
("%s(%d): MBA_SFT_TRANSCEIVER_INSERTION "
break;
case MBA_SFT_TRANSCEIVER_REMOVAL /* 8140 */:
("%s(%d): MBA_SFT_TRANSCEIVER_REMOVAL "
break;
case MBA_FIRMWARE_INIT_COMPLETE /* 8400 */:
("%s(%d): MBA_FIRMWARE_INIT_COMPLETE "
("%s(%d): mbx[1] %x, mbx[2] %x\n", __func__,
break;
case MBA_FIRMWARE_INIT_FAILED /* 8401 */:
"ASYNC_EVENT_FIRMWARE_INIT_FAILURE "
"received: mbx[1] %x, mbx[2] %x",
break;
default:
"Unknown Async event received: mbx[0] %x ,"
"mbx[1] %x; mbx[2] %x",
} else {
}
break;
}
if (fatal_error) {
}
}
return (proc_done);
}
/*
* MPI Interrupt handler
* Caller must have MBX_LOCK
*/
void
{
/*
* we just need to read first few mailboxes that this adapter's MPI
* will write response to.
*/
qlge->max_read_mbx);
/*
* process PI interrupt as async events, if not done,
* then pass to mailbox processing
*/
/*
* If another thread is waiting for the mail box
* completion event to occur
*/
qlge->mbx_wait_completion = 0;
("%s(%d) mailbox completion signaled \n",
}
}
/* inform MPI Firmware to clear the interrupt */
HOST_CMD_CLEAR_RISC_TO_HOST_INTR /* 0x0A */);
}
/*
* Test if mailbox communication works
* This is used when Interrupt is not enabled
*/
int
{
for (i = 0; i < NUM_MAILBOX_REGS; i++)
goto out;
}
/* delay for the processor interrupt is received */
== DDI_SUCCESS) {
test_ok = 0;
} else {
for (i = 1; i < NUM_MAILBOX_REGS; i++) {
if (mbx_results.mb[i] != i) {
test_ok = 0;
break;
}
}
}
if (test_ok) {
} else {
}
} else {
}
out:
return (rtn_val);
}
/*
* ql_mbx_test2
* Test if mailbox communication works
* This is used when Interrupt is enabled
* mailbox cmd:0x06h
*/
int
{
for (i = 0; i < NUM_MAILBOX_REGS; i++)
"%s(%d) ql_issue_mailbox_cmd_and_wait_rsp failed.",
goto out;
}
/* verify if the incoming outbound mailbox value is what we just sent */
test_ok = 0;
} else {
test_ok = 0;
break;
}
}
}
if (test_ok) {
} else {
}
out:
}
return (rtn_val);
}
/*
* ql_get_fw_state
* Get fw state.
* mailbox cmd:0x69h
*/
int
{
!= DDI_SUCCESS) {
goto out;
}
/* verify if the transaction is completed successful */
} else {
/* EMPTY */
}
if (fw_state_ptr != NULL)
out:
}
return (rtn_val);
}
/*
* ql_set_IDC_Req
* Send a IDC Request to firmware to notify all functions
* or any specific functions on the same port
* mailbox cmd:0x100h
*/
int
{
switch (dest_functions) {
case IDC_REQ_DEST_FUNC_ALL:
break;
case IDC_REQ_DEST_FUNC_0:
break;
case IDC_REQ_DEST_FUNC_1:
break;
case IDC_REQ_DEST_FUNC_2:
break;
case IDC_REQ_DEST_FUNC_3:
break;
default:
}
"%s(%d) ql_issue_mailbox_cmd_and_wait_rsp failed.",
goto out;
}
/* verify if the transaction is completed successful */
} else {
}
out:
}
return (rtn_val);
}
/*
* ql_set_mpi_port_config
* Send new port configuration.to mpi
* mailbox cmd:0x122h
*/
int
{
goto out;
}
/* verify if the transaction is completed successful */
} else
out:
}
return (rtn_val);
}
int
{
/* clear pause bits */
/* set new pause mode */
}
int
{
/* clear loop back bits */
/* loop back cfg: bit1-3 */
}
/*
* ql_get_port_cfg
* Get port configuration.
* mailbox cmd:0x123h
*/
int
{
goto out;
}
/* verify if the transaction is completed successfully */
} else { /* verify frame size */
} else {
}
}
out:
}
return (rtn_val);
}
/*
* qlge_get_link_status
* Get link status.
* mailbox cmd:0x124h
*/
int
struct qlnic_link_status_info *link_status_ptr)
{
!= DDI_SUCCESS) {
"%s(%d) ql_issue_mailbox_cmd_and_wait_rsp failed.",
goto out;
}
/* verify if the transaction is completed successful */
} else {
/* EMPTY */
("link status: status1 : 0x%x, status2 : 0x%x, "
"status3 : 0x%x\n",
}
if (link_status_ptr != NULL) {
}
out:
}
return (rtn_val);
}
/*
* ql_get_firmware_version
* Get firmware version.
*/
int
struct qlnic_mpi_version_info *mpi_version_ptr)
{
!= DDI_SUCCESS) {
"%s(%d) ql_issue_mailbox_cmd_and_wait_rsp failed.",
goto out;
}
/* verify if the transaction is completed successful */
} else {
#ifdef QLGE_LOAD_UNLOAD
#endif
if (mpi_version_ptr != NULL) {
}
}
out:
}
return (rtn_val);
}
/*
* Trigger a system error event
*/
int
{
goto out;
}
out:
return (rtn_val);
}
/*
* Reset the MPI RISC Processor
*/
int
{
/* Reset the MPI Processor */
BIT_SET, 0) != DDI_SUCCESS) {
goto out;
}
out:
return (rtn_val);
}
int
{
}
!= DDI_SUCCESS) {
goto out;
} else {
rval = DDI_SUCCESS;
} else {
}
}
out:
return (rval);
}