/*
* Copyright (C) 2003 - 2009 NetXen, Inc.
* Copyright (C) 2009 - QLogic Corporation.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston,
* MA 02111-1307, USA.
*
* The full GNU General Public License is included in this distribution
* in the file called "COPYING".
*
*/
#include "netxen_nic_hw.h"
#include "netxen_nic.h"
#define NXHAL_VERSION 1
static u32
netxen_poll_rsp(struct netxen_adapter *adapter)
{
u32 rsp = NX_CDRP_RSP_OK;
int timeout = 0;
do {
/* give atleast 1ms for firmware to respond */
msleep(1);
if (++timeout > NX_OS_CRB_RETRY_COUNT)
return NX_CDRP_RSP_TIMEOUT;
rsp = NXRD32(adapter, NX_CDRP_CRB_OFFSET);
} while (!NX_CDRP_IS_RSP(rsp));
return rsp;
}
static u32
netxen_issue_cmd(struct netxen_adapter *adapter, struct netxen_cmd_args *cmd)
{
u32 rsp;
u32 signature = 0;
u32 rcode = NX_RCODE_SUCCESS;
signature = NX_CDRP_SIGNATURE_MAKE(adapter->ahw.pci_func,
NXHAL_VERSION);
/* Acquire semaphore before accessing CRB */
if (netxen_api_lock(adapter))
return NX_RCODE_TIMEOUT;
NXWR32(adapter, NX_SIGN_CRB_OFFSET, signature);
NXWR32(adapter, NX_ARG1_CRB_OFFSET, cmd->req.arg1);
NXWR32(adapter, NX_ARG2_CRB_OFFSET, cmd->req.arg2);
NXWR32(adapter, NX_ARG3_CRB_OFFSET, cmd->req.arg3);
NXWR32(adapter, NX_CDRP_CRB_OFFSET, NX_CDRP_FORM_CMD(cmd->req.cmd));
rsp = netxen_poll_rsp(adapter);
if (rsp == NX_CDRP_RSP_TIMEOUT) {
printk(KERN_ERR "%s: card response timeout.\n",
netxen_nic_driver_name);
rcode = NX_RCODE_TIMEOUT;
} else if (rsp == NX_CDRP_RSP_FAIL) {
rcode = NXRD32(adapter, NX_ARG1_CRB_OFFSET);
printk(KERN_ERR "%s: failed card response code:0x%x\n",
netxen_nic_driver_name, rcode);
} else if (rsp == NX_CDRP_RSP_OK) {
cmd->rsp.cmd = NX_RCODE_SUCCESS;
if (cmd->rsp.arg2)
cmd->rsp.arg2 = NXRD32(adapter, NX_ARG2_CRB_OFFSET);
if (cmd->rsp.arg3)
cmd->rsp.arg3 = NXRD32(adapter, NX_ARG3_CRB_OFFSET);
}
if (cmd->rsp.arg1)
cmd->rsp.arg1 = NXRD32(adapter, NX_ARG1_CRB_OFFSET);
/* Release semaphore */
netxen_api_unlock(adapter);
return rcode;
}
static int
netxen_get_minidump_template_size(struct netxen_adapter *adapter)
{
struct netxen_cmd_args cmd;
memset(&cmd, 0, sizeof(cmd));
cmd.req.cmd = NX_CDRP_CMD_TEMP_SIZE;
memset(&cmd.rsp, 1, sizeof(struct _cdrp_cmd));
netxen_issue_cmd(adapter, &cmd);
if (cmd.rsp.cmd != NX_RCODE_SUCCESS) {
dev_info(&adapter->pdev->dev,
"Can't get template size %d\n", cmd.rsp.cmd);
return -EIO;
}
adapter->mdump.md_template_size = cmd.rsp.arg2;
adapter->mdump.md_template_ver = cmd.rsp.arg3;
return 0;
}
static int
netxen_get_minidump_template(struct netxen_adapter *adapter)
{
dma_addr_t md_template_addr;
void *addr;
u32 size;
struct netxen_cmd_args cmd;
size = adapter->mdump.md_template_size;
if (size == 0) {
dev_err(&adapter->pdev->dev, "Can not capture Minidump "
"template. Invalid template size.\n");
return NX_RCODE_INVALID_ARGS;
}
addr = pci_alloc_consistent(adapter->pdev, size, &md_template_addr);
if (!addr) {
dev_err(&adapter->pdev->dev, "Unable to allocate dmable memory for template.\n");
return -ENOMEM;
}
memset(addr, 0, size);
memset(&cmd, 0, sizeof(cmd));
memset(&cmd.rsp, 1, sizeof(struct _cdrp_cmd));
cmd.req.cmd = NX_CDRP_CMD_GET_TEMP_HDR;
cmd.req.arg1 = LSD(md_template_addr);
cmd.req.arg2 = MSD(md_template_addr);
cmd.req.arg3 |= size;
netxen_issue_cmd(adapter, &cmd);
if ((cmd.rsp.cmd == NX_RCODE_SUCCESS) && (size == cmd.rsp.