cregit-Linux how code gets into the kernel

Release 4.11 drivers/scsi/qlogicpti.c

Directory: drivers/scsi
/* qlogicpti.c: Performance Technologies QlogicISP sbus card driver.
 *
 * Copyright (C) 1996, 2006, 2008 David S. Miller (davem@davemloft.net)
 *
 * A lot of this driver was directly stolen from Erik H. Moe's PCI
 * Qlogic ISP driver.  Mucho kudos to him for this code.
 *
 * An even bigger kudos to John Grana at Performance Technologies
 * for providing me with the hardware to write this driver, you rule
 * John you really do.
 *
 * May, 2, 1997: Added support for QLGC,isp --jj
 */

#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/types.h>
#include <linux/string.h>
#include <linux/gfp.h>
#include <linux/blkdev.h>
#include <linux/proc_fs.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/jiffies.h>
#include <linux/dma-mapping.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/firmware.h>

#include <asm/byteorder.h>

#include "qlogicpti.h"

#include <asm/dma.h>
#include <asm/ptrace.h>
#include <asm/pgtable.h>
#include <asm/oplib.h>
#include <asm/io.h>
#include <asm/irq.h>

#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_eh.h>
#include <scsi/scsi_tcq.h>
#include <scsi/scsi_host.h>


#define MAX_TARGETS	16

#define MAX_LUNS	8	
/* 32 for 1.31 F/W */


#define DEFAULT_LOOP_COUNT	10000


static struct qlogicpti *qptichain = NULL;
static DEFINE_SPINLOCK(qptichain_lock);


#define PACKB(a, b)			(((a)<<4)|(b))


static const u_char mbox_param[] = {
	PACKB(1, 1),	/* MBOX_NO_OP */
	PACKB(5, 5),	/* MBOX_LOAD_RAM */
	PACKB(2, 0),	/* MBOX_EXEC_FIRMWARE */
	PACKB(5, 5),	/* MBOX_DUMP_RAM */
	PACKB(3, 3),	/* MBOX_WRITE_RAM_WORD */
	PACKB(2, 3),	/* MBOX_READ_RAM_WORD */
	PACKB(6, 6),	/* MBOX_MAILBOX_REG_TEST */
	PACKB(2, 3),	/* MBOX_VERIFY_CHECKSUM */
	PACKB(1, 3),	/* MBOX_ABOUT_FIRMWARE */
	PACKB(0, 0),	/* 0x0009 */
	PACKB(0, 0),	/* 0x000a */
	PACKB(0, 0),	/* 0x000b */
	PACKB(0, 0),	/* 0x000c */
	PACKB(0, 0),	/* 0x000d */
	PACKB(1, 2),	/* MBOX_CHECK_FIRMWARE */
	PACKB(0, 0),	/* 0x000f */
	PACKB(5, 5),	/* MBOX_INIT_REQ_QUEUE */
	PACKB(6, 6),	/* MBOX_INIT_RES_QUEUE */
	PACKB(4, 4),	/* MBOX_EXECUTE_IOCB */
	PACKB(2, 2),	/* MBOX_WAKE_UP */
	PACKB(1, 6),	/* MBOX_STOP_FIRMWARE */
	PACKB(4, 4),	/* MBOX_ABORT */
	PACKB(2, 2),	/* MBOX_ABORT_DEVICE */
	PACKB(3, 3),	/* MBOX_ABORT_TARGET */
	PACKB(2, 2),	/* MBOX_BUS_RESET */
	PACKB(2, 3),	/* MBOX_STOP_QUEUE */
	PACKB(2, 3),	/* MBOX_START_QUEUE */
	PACKB(2, 3),	/* MBOX_SINGLE_STEP_QUEUE */
	PACKB(2, 3),	/* MBOX_ABORT_QUEUE */
	PACKB(2, 4),	/* MBOX_GET_DEV_QUEUE_STATUS */
	PACKB(0, 0),	/* 0x001e */
	PACKB(1, 3),	/* MBOX_GET_FIRMWARE_STATUS */
	PACKB(1, 2),	/* MBOX_GET_INIT_SCSI_ID */
	PACKB(1, 2),	/* MBOX_GET_SELECT_TIMEOUT */
	PACKB(1, 3),	/* MBOX_GET_RETRY_COUNT */
	PACKB(1, 2),	/* MBOX_GET_TAG_AGE_LIMIT */
	PACKB(1, 2),	/* MBOX_GET_CLOCK_RATE */
	PACKB(1, 2),	/* MBOX_GET_ACT_NEG_STATE */
	PACKB(1, 2),	/* MBOX_GET_ASYNC_DATA_SETUP_TIME */
	PACKB(1, 3),	/* MBOX_GET_SBUS_PARAMS */
	PACKB(2, 4),	/* MBOX_GET_TARGET_PARAMS */
	PACKB(2, 4),	/* MBOX_GET_DEV_QUEUE_PARAMS */
	PACKB(0, 0),	/* 0x002a */
	PACKB(0, 0),	/* 0x002b */
	PACKB(0, 0),	/* 0x002c */
	PACKB(0, 0),	/* 0x002d */
	PACKB(0, 0),	/* 0x002e */
	PACKB(0, 0),	/* 0x002f */
	PACKB(2, 2),	/* MBOX_SET_INIT_SCSI_ID */
	PACKB(2, 2),	/* MBOX_SET_SELECT_TIMEOUT */
	PACKB(3, 3),	/* MBOX_SET_RETRY_COUNT */
	PACKB(2, 2),	/* MBOX_SET_TAG_AGE_LIMIT */
	PACKB(2, 2),	/* MBOX_SET_CLOCK_RATE */
	PACKB(2, 2),	/* MBOX_SET_ACTIVE_NEG_STATE */
	PACKB(2, 2),	/* MBOX_SET_ASYNC_DATA_SETUP_TIME */
	PACKB(3, 3),	/* MBOX_SET_SBUS_CONTROL_PARAMS */
	PACKB(4, 4),	/* MBOX_SET_TARGET_PARAMS */
	PACKB(4, 4),	/* MBOX_SET_DEV_QUEUE_PARAMS */
	PACKB(0, 0),	/* 0x003a */
	PACKB(0, 0),	/* 0x003b */
	PACKB(0, 0),	/* 0x003c */
	PACKB(0, 0),	/* 0x003d */
	PACKB(0, 0),	/* 0x003e */
	PACKB(0, 0),	/* 0x003f */
	PACKB(0, 0),	/* 0x0040 */
	PACKB(0, 0),	/* 0x0041 */
	PACKB(0, 0)	/* 0x0042 */
};


#define MAX_MBOX_COMMAND	ARRAY_SIZE(mbox_param)

/* queue length's _must_ be power of two: */

#define QUEUE_DEPTH(in, out, ql)	((in - out) & (ql))

#define REQ_QUEUE_DEPTH(in, out)	QUEUE_DEPTH(in, out,                 \
                                                    QLOGICPTI_REQ_QUEUE_LEN)

#define RES_QUEUE_DEPTH(in, out)	QUEUE_DEPTH(in, out, RES_QUEUE_LEN)


static inline void qlogicpti_enable_irqs(struct qlogicpti *qpti) { sbus_writew(SBUS_CTRL_ERIRQ | SBUS_CTRL_GENAB, qpti->qregs + SBUS_CTRL); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)25100.00%2100.00%
Total25100.00%2100.00%


static inline void qlogicpti_disable_irqs(struct qlogicpti *qpti) { sbus_writew(0, qpti->qregs + SBUS_CTRL); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)23100.00%2100.00%
Total23100.00%2100.00%


static inline void set_sbus_cfg1(struct qlogicpti *qpti) { u16 val; u8 bursts = qpti->bursts; #if 0 /* It appears that at least PTI cards do not support * 64-byte bursts and that setting the B64 bit actually * is a nop and the chip ends up using the smallest burst * size. -DaveM */ if (sbus_can_burst64() && (bursts & DMA_BURST64)) { val = (SBUS_CFG1_BENAB | SBUS_CFG1_B64); } else #endif if (bursts & DMA_BURST32) { val = (SBUS_CFG1_BENAB | SBUS_CFG1_B32); } else if (bursts & DMA_BURST16) { val = (SBUS_CFG1_BENAB | SBUS_CFG1_B16); } else if (bursts & DMA_BURST8) { val = (SBUS_CFG1_BENAB | SBUS_CFG1_B8); } else { val = 0; /* No sbus bursts for you... */ } sbus_writew(val, qpti->qregs + SBUS_CFG1); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)9798.98%266.67%
David S. Miller11.02%133.33%
Total98100.00%3100.00%


static int qlogicpti_mbox_command(struct qlogicpti *qpti, u_short param[], int force) { int loop_count; u16 tmp; if (mbox_param[param[0]] == 0) return 1; /* Set SBUS semaphore. */ tmp = sbus_readw(qpti->qregs + SBUS_SEMAPHORE); tmp |= SBUS_SEMAPHORE_LCK; sbus_writew(tmp, qpti->qregs + SBUS_SEMAPHORE); /* Wait for host IRQ bit to clear. */ loop_count = DEFAULT_LOOP_COUNT; while (--loop_count && (sbus_readw(qpti->qregs + HCCTRL) & HCCTRL_HIRQ)) { barrier(); cpu_relax(); } if (!loop_count) printk(KERN_EMERG "qlogicpti%d: mbox_command loop timeout #1\n", qpti->qpti_id); /* Write mailbox command registers. */ switch (mbox_param[param[0]] >> 4) { case 6: sbus_writew(param[5], qpti->qregs + MBOX5); case 5: sbus_writew(param[4], qpti->qregs + MBOX4); case 4: sbus_writew(param[3], qpti->qregs + MBOX3); case 3: sbus_writew(param[2], qpti->qregs + MBOX2); case 2: sbus_writew(param[1], qpti->qregs + MBOX1); case 1: sbus_writew(param[0], qpti->qregs + MBOX0); } /* Clear RISC interrupt. */ tmp = sbus_readw(qpti->qregs + HCCTRL); tmp |= HCCTRL_CRIRQ; sbus_writew(tmp, qpti->qregs + HCCTRL); /* Clear SBUS semaphore. */ sbus_writew(0, qpti->qregs + SBUS_SEMAPHORE); /* Set HOST interrupt. */ tmp = sbus_readw(qpti->qregs + HCCTRL); tmp |= HCCTRL_SHIRQ; sbus_writew(tmp, qpti->qregs + HCCTRL); /* Wait for HOST interrupt clears. */ loop_count = DEFAULT_LOOP_COUNT; while (--loop_count && (sbus_readw(qpti->qregs + HCCTRL) & HCCTRL_CRIRQ)) udelay(20); if (!loop_count) printk(KERN_EMERG "qlogicpti%d: mbox_command[%04x] loop timeout #2\n", qpti->qpti_id, param[0]); /* Wait for SBUS semaphore to get set. */ loop_count = DEFAULT_LOOP_COUNT; while (--loop_count && !(sbus_readw(qpti->qregs + SBUS_SEMAPHORE) & SBUS_SEMAPHORE_LCK)) { udelay(20); /* Workaround for some buggy chips. */ if (sbus_readw(qpti->qregs + MBOX0) & 0x4000) break; } if (!loop_count) printk(KERN_EMERG "qlogicpti%d: mbox_command[%04x] loop timeout #3\n", qpti->qpti_id, param[0]); /* Wait for MBOX busy condition to go away. */ loop_count = DEFAULT_LOOP_COUNT; while (--loop_count && (sbus_readw(qpti->qregs + MBOX0) == 0x04)) udelay(20); if (!loop_count) printk(KERN_EMERG "qlogicpti%d: mbox_command[%04x] loop timeout #4\n", qpti->qpti_id, param[0]); /* Read back output parameters. */ switch (mbox_param[param[0]] & 0xf) { case 6: param[5] = sbus_readw(qpti->qregs + MBOX5); case 5: param[4] = sbus_readw(qpti->qregs + MBOX4); case 4: param[3] = sbus_readw(qpti->qregs + MBOX3); case 3: param[2] = sbus_readw(qpti->qregs + MBOX2); case 2: param[1] = sbus_readw(qpti->qregs + MBOX1); case 1: param[0] = sbus_readw(qpti->qregs + MBOX0); } /* Clear RISC interrupt. */ tmp = sbus_readw(qpti->qregs + HCCTRL); tmp |= HCCTRL_CRIRQ; sbus_writew(tmp, qpti->qregs + HCCTRL); /* Release SBUS semaphore. */ tmp = sbus_readw(qpti->qregs + SBUS_SEMAPHORE); tmp &= ~(SBUS_SEMAPHORE_LCK); sbus_writew(tmp, qpti->qregs + SBUS_SEMAPHORE); /* We're done. */ return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)61096.06%250.00%
Mark Fortescue203.15%125.00%
Linus Torvalds50.79%125.00%
Total635100.00%4100.00%


static inline void qlogicpti_set_hostdev_defaults(struct qlogicpti *qpti) { int i; qpti->host_param.initiator_scsi_id = qpti->scsi_id; qpti->host_param.bus_reset_delay = 3; qpti->host_param.retry_count = 0; qpti->host_param.retry_delay = 5; qpti->host_param.async_data_setup_time = 3; qpti->host_param.req_ack_active_negation = 1; qpti->host_param.data_line_active_negation = 1; qpti->host_param.data_dma_burst_enable = 1; qpti->host_param.command_dma_burst_enable = 1; qpti->host_param.tag_aging = 8; qpti->host_param.selection_timeout = 250; qpti->host_param.max_queue_depth = 256; for(i = 0; i < MAX_TARGETS; i++) { /* * disconnect, parity, arq, reneg on reset, and, oddly enough * tags...the midlayer's notion of tagged support has to match * our device settings, and since we base whether we enable a * tag on a per-cmnd basis upon what the midlayer sez, we * actually enable the capability here. */ qpti->dev_param[i].device_flags = 0xcd; qpti->dev_param[i].execution_throttle = 16; if (qpti->ultra) { qpti->dev_param[i].synchronous_period = 12; qpti->dev_param[i].synchronous_offset = 8; } else { qpti->dev_param[i].synchronous_period = 25; qpti->dev_param[i].synchronous_offset = 12; } qpti->dev_param[i].device_enable = 1; } }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)217100.00%3100.00%
Total217100.00%3100.00%


static int qlogicpti_reset_hardware(struct Scsi_Host *host) { struct qlogicpti *qpti = (struct qlogicpti *) host->hostdata; u_short param[6]; unsigned short risc_code_addr; int loop_count, i; unsigned long flags; risc_code_addr = 0x1000; /* all load addresses are at 0x1000 */ spin_lock_irqsave(host->host_lock, flags); sbus_writew(HCCTRL_PAUSE, qpti->qregs + HCCTRL); /* Only reset the scsi bus if it is not free. */ if (sbus_readw(qpti->qregs + CPU_PCTRL) & CPU_PCTRL_BSY) { sbus_writew(CPU_ORIDE_RMOD, qpti->qregs + CPU_ORIDE); sbus_writew(CPU_CMD_BRESET, qpti->qregs + CPU_CMD); udelay(400); } sbus_writew(SBUS_CTRL_RESET, qpti->qregs + SBUS_CTRL); sbus_writew((DMA_CTRL_CCLEAR | DMA_CTRL_CIRQ), qpti->qregs + CMD_DMA_CTRL); sbus_writew((DMA_CTRL_CCLEAR | DMA_CTRL_CIRQ), qpti->qregs + DATA_DMA_CTRL); loop_count = DEFAULT_LOOP_COUNT; while (--loop_count && ((sbus_readw(qpti->qregs + MBOX0) & 0xff) == 0x04)) udelay(20); if (!loop_count) printk(KERN_EMERG "qlogicpti%d: reset_hardware loop timeout\n", qpti->qpti_id); sbus_writew(HCCTRL_PAUSE, qpti->qregs + HCCTRL); set_sbus_cfg1(qpti); qlogicpti_enable_irqs(qpti); if (sbus_readw(qpti->qregs + RISC_PSR) & RISC_PSR_ULTRA) { qpti->ultra = 1; sbus_writew((RISC_MTREG_P0ULTRA | RISC_MTREG_P1ULTRA), qpti->qregs + RISC_MTREG); } else { qpti->ultra = 0; sbus_writew((RISC_MTREG_P0DFLT | RISC_MTREG_P1DFLT), qpti->qregs + RISC_MTREG); } /* reset adapter and per-device default values. */ /* do it after finding out whether we're ultra mode capable */ qlogicpti_set_hostdev_defaults(qpti); /* Release the RISC processor. */ sbus_writew(HCCTRL_REL, qpti->qregs + HCCTRL); /* Get RISC to start executing the firmware code. */ param[0] = MBOX_EXEC_FIRMWARE; param[1] = risc_code_addr; if (qlogicpti_mbox_command(qpti, param, 1)) { printk(KERN_EMERG "qlogicpti%d: Cannot execute ISP firmware.\n", qpti->qpti_id); spin_unlock_irqrestore(host->host_lock, flags); return 1; } /* Set initiator scsi ID. */ param[0] = MBOX_SET_INIT_SCSI_ID; param[1] = qpti->host_param.initiator_scsi_id; if (qlogicpti_mbox_command(qpti, param, 1) || (param[0] != MBOX_COMMAND_COMPLETE)) { printk(KERN_EMERG "qlogicpti%d: Cannot set initiator SCSI ID.\n", qpti->qpti_id); spin_unlock_irqrestore(host->host_lock, flags); return 1; } /* Initialize state of the queues, both hw and sw. */ qpti->req_in_ptr = qpti->res_out_ptr = 0; param[0] = MBOX_INIT_RES_QUEUE; param[1] = RES_QUEUE_LEN + 1; param[2] = (u_short) (qpti->res_dvma >> 16); param[3] = (u_short) (qpti->res_dvma & 0xffff); param[4] = param[5] = 0; if (qlogicpti_mbox_command(qpti, param, 1)) { printk(KERN_EMERG "qlogicpti%d: Cannot init response queue.\n", qpti->qpti_id); spin_unlock_irqrestore(host->host_lock, flags); return 1; } param[0] = MBOX_INIT_REQ_QUEUE; param[1] = QLOGICPTI_REQ_QUEUE_LEN + 1; param[2] = (u_short) (qpti->req_dvma >> 16); param[3] = (u_short) (qpti->req_dvma & 0xffff); param[4] = param[5] = 0; if (qlogicpti_mbox_command(qpti, param, 1)) { printk(KERN_EMERG "qlogicpti%d: Cannot init request queue.\n", qpti->qpti_id); spin_unlock_irqrestore(host->host_lock, flags); return 1; } param[0] = MBOX_SET_RETRY_COUNT; param[1] = qpti->host_param.retry_count; param[2] = qpti->host_param.retry_delay; qlogicpti_mbox_command(qpti, param, 0); param[0] = MBOX_SET_TAG_AGE_LIMIT; param[1] = qpti->host_param.tag_aging; qlogicpti_mbox_command(qpti, param, 0); for (i = 0; i < MAX_TARGETS; i++) { param[0] = MBOX_GET_DEV_QUEUE_PARAMS; param[1] = (i << 8); qlogicpti_mbox_command(qpti, param, 0); } param[0] = MBOX_GET_FIRMWARE_STATUS; qlogicpti_mbox_command(qpti, param, 0); param[0] = MBOX_SET_SELECT_TIMEOUT; param[1] = qpti->host_param.selection_timeout; qlogicpti_mbox_command(qpti, param, 0); for (i = 0; i < MAX_TARGETS; i++) { param[0] = MBOX_SET_TARGET_PARAMS; param[1] = (i << 8); param[2] = (qpti->dev_param[i].device_flags << 8); /* * Since we're now loading 1.31 f/w, force narrow/async. */ param[2] |= 0xc0; param[3] = 0; /* no offset, we do not have sync mode yet */ qlogicpti_mbox_command(qpti, param, 0); } /* * Always (sigh) do an initial bus reset (kicks f/w). */ param[0] = MBOX_BUS_RESET; param[1] = qpti->host_param.bus_reset_delay; qlogicpti_mbox_command(qpti, param, 0); qpti->send_marker = 1; spin_unlock_irqrestore(host->host_lock, flags); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)85096.05%457.14%
David S. Miller303.39%228.57%
Mark Fortescue50.56%114.29%
Total885100.00%7100.00%

#define PTI_RESET_LIMIT 400
static int qlogicpti_load_firmware(struct qlogicpti *qpti) { const struct firmware *fw; const char fwname[] = "qlogic/isp1000.bin"; const __le16 *fw_data; struct Scsi_Host *host = qpti->qhost; unsigned short csum = 0; unsigned short param[6]; unsigned short risc_code_addr, risc_code_length; int err; unsigned long flags; int i, timeout; err = request_firmware(&fw, fwname, &qpti->op->dev); if (err) { printk(KERN_ERR "Failed to load image \"%s\" err %d\n", fwname, err); return err; } if (fw->size % 2) { printk(KERN_ERR "Bogus length %zu in image \"%s\"\n", fw->size, fwname); err = -EINVAL; goto outfirm; } fw_data = (const __le16 *)&fw->data[0]; risc_code_addr = 0x1000; /* all f/w modules load at 0x1000 */ risc_code_length = fw->size / 2; spin_lock_irqsave(host->host_lock, flags); /* Verify the checksum twice, one before loading it, and once * afterwards via the mailbox commands. */ for (i = 0; i < risc_code_length; i++) csum += __le16_to_cpu(fw_data[i]); if (csum) { printk(KERN_EMERG "qlogicpti%d: Aieee, firmware checksum failed!", qpti->qpti_id); err = 1; goto out; } sbus_writew(SBUS_CTRL_RESET, qpti->qregs + SBUS_CTRL); sbus_writew((DMA_CTRL_CCLEAR | DMA_CTRL_CIRQ), qpti->qregs + CMD_DMA_CTRL); sbus_writew((DMA_CTRL_CCLEAR | DMA_CTRL_CIRQ), qpti->qregs + DATA_DMA_CTRL); timeout = PTI_RESET_LIMIT; while (--timeout && (sbus_readw(qpti->qregs + SBUS_CTRL) & SBUS_CTRL_RESET)) udelay(20); if (!timeout) { printk(KERN_EMERG "qlogicpti%d: Cannot reset the ISP.", qpti->qpti_id); err = 1; goto out; } sbus_writew(HCCTRL_RESET, qpti->qregs + HCCTRL); mdelay(1); sbus_writew((SBUS_CTRL_GENAB | SBUS_CTRL_ERIRQ), qpti->qregs + SBUS_CTRL); set_sbus_cfg1(qpti); sbus_writew(0, qpti->qregs + SBUS_SEMAPHORE); if (sbus_readw(qpti->qregs + RISC_PSR) & RISC_PSR_ULTRA) { qpti->ultra = 1; sbus_writew((RISC_MTREG_P0ULTRA | RISC_MTREG_P1ULTRA), qpti->qregs + RISC_MTREG); } else { qpti->ultra = 0; sbus_writew((RISC_MTREG_P0DFLT | RISC_MTREG_P1DFLT), qpti->qregs + RISC_MTREG); } sbus_writew(HCCTRL_REL, qpti->qregs + HCCTRL); /* Pin lines are only stable while RISC is paused. */ sbus_writew(HCCTRL_PAUSE, qpti->qregs + HCCTRL); if (sbus_readw(qpti->qregs + CPU_PDIFF) & CPU_PDIFF_MODE) qpti->differential = 1; else qpti->differential = 0; sbus_writew(HCCTRL_REL, qpti->qregs + HCCTRL); /* This shouldn't be necessary- we've reset things so we should be running from the ROM now.. */ param[0] = MBOX_STOP_FIRMWARE; param[1] = param[2] = param[3] = param[4] = param[5] = 0; if (qlogicpti_mbox_command(qpti, param, 1)) { printk(KERN_EMERG "qlogicpti%d: Cannot stop firmware for reload.\n", qpti->qpti_id); err = 1; goto out; } /* Load it up.. */ for (i = 0; i < risc_code_length; i++) { param[0] = MBOX_WRITE_RAM_WORD; param[1] = risc_code_addr + i; param[2] = __le16_to_cpu(fw_data[i]); if (qlogicpti_mbox_command(qpti, param, 1) || param[0] != MBOX_COMMAND_COMPLETE) { printk("qlogicpti%d: Firmware dload failed, I'm bolixed!\n", qpti->qpti_id); err = 1; goto out; } } /* Reset the ISP again. */ sbus_writew(HCCTRL_RESET, qpti-&g