/*
* QLOGIC LINUX SOFTWARE
*
* QLogic ISP2x00 device driver for Linux 2.6.x
* Copyright (C) 2003-2004 QLogic Corporation
* (www.qlogic.com)
*
* 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, 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.
*
*/
#include "qla_def.h"
#include <linux/delay.h>
static int qla_uprintf(char **, char *, ...);
/**
* qla2300_fw_dump() - Dumps binary data from the 2300 firmware.
* @ha: HA context
* @hardware_locked: Called with the hardware_lock
*/
void
qla2300_fw_dump(scsi_qla_host_t *ha, int hardware_locked)
{
int rval;
uint32_t cnt, timer;
uint32_t risc_address;
uint16_t mb0, mb2;
uint32_t stat;
device_reg_t __iomem *reg = ha->iobase;
uint16_t __iomem *dmp_reg;
unsigned long flags;
struct qla2300_fw_dump *fw;
uint32_t dump_size, data_ram_cnt;
risc_address = data_ram_cnt = 0;
mb0 = mb2 = 0;
flags = 0;
if (!hardware_locked)
spin_lock_irqsave(&ha->hardware_lock, flags);
if (ha->fw_dump != NULL) {
qla_printk(KERN_WARNING, ha,
"Firmware has been previously dumped (%p) -- ignoring "
"request...\n", ha->fw_dump);
goto qla2300_fw_dump_failed;
}
/* Allocate (large) dump buffer. */
dump_size = sizeof(struct qla2300_fw_dump);
dump_size += (ha->fw_memory_size - 0x11000) * sizeof(uint16_t);
ha->fw_dump_order = get_order(dump_size);
ha->fw_dump = (struct qla2300_fw_dump *) __get_free_pages(GFP_ATOMIC,
ha->fw_dump_order);
if (ha->fw_dump == NULL) {
qla_printk(KERN_WARNING, ha,
"Unable to allocated memory for firmware dump (%d/%d).\n",
ha->fw_dump_order, dump_size);
goto qla2300_fw_dump_failed;
}
fw = ha->fw_dump;
rval = QLA_SUCCESS;
fw->hccr = RD_REG_WORD(®->hccr);
/* Pause RISC. */
WRT_REG_WORD(®->hccr, HCCR_PAUSE_RISC);
if (IS_QLA2300(ha)) {
for (cnt = 30000;
(RD_REG_WORD(®->hccr) & HCCR_RISC_PAUSE) == 0 &&
rval == QLA_SUCCESS; cnt--) {
if (cnt)
udelay(100);
else
rval = QLA_FUNCTION_TIMEOUT;
}
} else {
RD_REG_WORD(®->hccr); /* PCI Posting. */
udelay(10);
}
if (rval == QLA_SUCCESS) {
dmp_reg = (uint16_t __iomem *)(reg + 0);
for (cnt = 0; cnt < sizeof(fw->pbiu_reg) / 2; cnt++)
fw->pbiu_reg[cnt] = RD_REG_WORD(dmp_reg++);
dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x10);
for (cnt = 0; cnt < sizeof(fw->risc_host_reg) / 2; cnt++)
fw->risc_host_reg[cnt] =