Release 4.11 drivers/scsi/qlogicpti.c
/* 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
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 25 | 100.00% | 2 | 100.00% |
Total | 25 | 100.00% | 2 | 100.00% |
static inline void qlogicpti_disable_irqs(struct qlogicpti *qpti)
{
sbus_writew(0, qpti->qregs + SBUS_CTRL);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 23 | 100.00% | 2 | 100.00% |
Total | 23 | 100.00% | 2 | 100.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
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 97 | 98.98% | 2 | 66.67% |
David S. Miller | 1 | 1.02% | 1 | 33.33% |
Total | 98 | 100.00% | 3 | 100.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
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 610 | 96.06% | 2 | 50.00% |
Mark Fortescue | 20 | 3.15% | 1 | 25.00% |
Linus Torvalds | 5 | 0.79% | 1 | 25.00% |
Total | 635 | 100.00% | 4 | 100.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
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 217 | 100.00% | 3 | 100.00% |
Total | 217 | 100.00% | 3 | 100.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
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 850 | 96.05% | 4 | 57.14% |
David S. Miller | 30 | 3.39% | 2 | 28.57% |
Mark Fortescue | 5 | 0.56% | 1 | 14.29% |
Total | 885 | 100.00% | 7 | 100.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