/*
- * QLOGIC LINUX SOFTWARE
- *
- * QLogic ISP2x00 device driver for Linux 2.6.x
- * Copyright (C) 2003-2005 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.
+ * QLogic Fibre Channel HBA Driver
+ * Copyright (c) 2003-2005 QLogic Corporation
*
+ * See LICENSE.qla2xxx for copyright and licensing details.
*/
#include "qla_def.h"
#include <linux/delay.h>
+#include <scsi/scsi_transport_fc.h>
static void
qla2x00_mbx_sem_timeout(unsigned long data)
/* Check for pending interrupts. */
qla2x00_poll(ha);
- udelay(10); /* v4.27 */
+ if (command != MBC_LOAD_RISC_RAM_EXTENDED &&
+ !ha->flags.mbox_int)
+ msleep(10);
} /* while */
}
mb0 = RD_REG_WORD(®->isp24.mailbox0);
ictrl = RD_REG_DWORD(®->isp24.ictrl);
} else {
- mb0 = RD_MAILBOX_REG(ha, reg->isp, 0);
+ mb0 = RD_MAILBOX_REG(ha, ®->isp, 0);
ictrl = RD_REG_WORD(®->isp.ictrl);
}
printk("%s(%ld): **** MB Command Timeout for cmd %x ****\n",
return rval;
}
-/*
- * qla2x00_load_ram
- * Load adapter RAM using DMA.
- *
- * Input:
- * ha = adapter block pointer.
- *
- * Returns:
- * qla2x00 local function return status code.
- *
- * Context:
- * Kernel context.
- */
int
-qla2x00_load_ram(scsi_qla_host_t *ha, dma_addr_t req_dma, uint16_t risc_addr,
- uint16_t risc_code_size)
+qla2x00_load_ram(scsi_qla_host_t *ha, dma_addr_t req_dma, uint32_t risc_addr,
+ uint32_t risc_code_size)
{
int rval;
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
- uint32_t req_len;
- dma_addr_t nml_dma;
- uint32_t nml_len;
- uint32_t normalized;
-
- DEBUG11(printk("qla2x00_load_ram(%ld): entered.\n",
- ha->host_no);)
-
- req_len = risc_code_size;
- nml_dma = 0;
- nml_len = 0;
- normalized = qla2x00_normalize_dma_addr(&req_dma, &req_len, &nml_dma,
- &nml_len);
-
- /* Load first segment */
- mcp->mb[0] = MBC_LOAD_RISC_RAM;
- mcp->mb[1] = risc_addr;
- mcp->mb[2] = MSW(req_dma);
- mcp->mb[3] = LSW(req_dma);
- mcp->mb[4] = (uint16_t)req_len;
- mcp->mb[6] = MSW(MSD(req_dma));
- mcp->mb[7] = LSW(MSD(req_dma));
- mcp->out_mb = MBX_7|MBX_6|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
- mcp->in_mb = MBX_0;
- mcp->tov = 30;
- mcp->flags = 0;
- rval = qla2x00_mailbox_command(ha, mcp);
-
- /* Load second segment - if necessary */
- if (normalized && (rval == QLA_SUCCESS)) {
- mcp->mb[0] = MBC_LOAD_RISC_RAM;
- mcp->mb[1] = risc_addr + (uint16_t)req_len;
- mcp->mb[2] = MSW(nml_dma);
- mcp->mb[3] = LSW(nml_dma);
- mcp->mb[4] = (uint16_t)nml_len;
- mcp->mb[6] = MSW(MSD(nml_dma));
- mcp->mb[7] = LSW(MSD(nml_dma));
- mcp->out_mb = MBX_7|MBX_6|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
- mcp->in_mb = MBX_0;
- mcp->tov = 30;
- mcp->flags = 0;
- rval = qla2x00_mailbox_command(ha, mcp);
- }
+ DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
- if (rval == QLA_SUCCESS) {
- /* Empty */
- DEBUG11(printk("qla2x00_load_ram(%ld): done.\n", ha->host_no);)
+ if (MSW(risc_addr) || IS_QLA24XX(ha) || IS_QLA25XX(ha)) {
+ mcp->mb[0] = MBC_LOAD_RISC_RAM_EXTENDED;
+ mcp->mb[8] = MSW(risc_addr);
+ mcp->out_mb = MBX_8|MBX_0;
} else {
- /* Empty */
- DEBUG2_3_11(printk("qla2x00_load_ram(%ld): failed. rval=%x "
- "mb[0]=%x.\n", ha->host_no, rval, mcp->mb[0]);)
+ mcp->mb[0] = MBC_LOAD_RISC_RAM;
+ mcp->out_mb = MBX_0;
}
- return rval;
-}
-
-/*
- * qla2x00_load_ram_ext
- * Load adapter extended RAM using DMA.
- *
- * Input:
- * ha = adapter block pointer.
- *
- * Returns:
- * qla2x00 local function return status code.
- *
- * Context:
- * Kernel context.
- */
-int
-qla2x00_load_ram_ext(scsi_qla_host_t *ha, dma_addr_t req_dma,
- uint32_t risc_addr, uint32_t risc_code_size)
-{
- int rval;
- mbx_cmd_t mc;
- mbx_cmd_t *mcp = &mc;
-
- DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
-
- mcp->mb[0] = MBC_LOAD_RISC_RAM_EXTENDED;
mcp->mb[1] = LSW(risc_addr);
mcp->mb[2] = MSW(req_dma);
mcp->mb[3] = LSW(req_dma);
mcp->mb[6] = MSW(MSD(req_dma));
mcp->mb[7] = LSW(MSD(req_dma));
- mcp->mb[8] = MSW(risc_addr);
- mcp->out_mb = MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
+ mcp->out_mb |= MBX_7|MBX_6|MBX_3|MBX_2|MBX_1;
if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) {
mcp->mb[4] = MSW(risc_code_size);
mcp->mb[5] = LSW(risc_code_size);
DEBUG11(printk("qla2x00_abort_command(%ld): entered.\n", ha->host_no);)
fcport = sp->fcport;
- if (atomic_read(&ha->loop_state) == LOOP_DOWN ||
- atomic_read(&fcport->state) == FCS_DEVICE_LOST) {
- return 1;
- }
spin_lock_irqsave(&ha->hardware_lock, flags);
for (handle = 1; handle < MAX_OUTSTANDING_COMMANDS; handle++) {
}
#endif
-/*
- * qla2x00_target_reset
- * Issue target reset mailbox command.
- *
- * Input:
- * ha = adapter block pointer.
- * TARGET_QUEUE_LOCK must be released.
- * ADAPTER_STATE_LOCK must be released.
- *
- * Returns:
- * qla2x00 local function return status code.
- *
- * Context:
- * Kernel context.
- */
-int
-qla2x00_target_reset(scsi_qla_host_t *ha, struct fc_port *fcport)
-{
- int rval;
- mbx_cmd_t mc;
- mbx_cmd_t *mcp = &mc;
-
- DEBUG11(printk("qla2x00_target_reset(%ld): entered.\n", ha->host_no);)
-
- if (atomic_read(&fcport->state) != FCS_ONLINE)
- return 0;
-
- mcp->mb[0] = MBC_TARGET_RESET;
- if (HAS_EXTENDED_IDS(ha))
- mcp->mb[1] = fcport->loop_id;
- else
- mcp->mb[1] = fcport->loop_id << 8;
- mcp->mb[2] = ha->loop_reset_delay;
- mcp->out_mb = MBX_2|MBX_1|MBX_0;
- mcp->in_mb = MBX_0;
- mcp->tov = 30;
- mcp->flags = 0;
- rval = qla2x00_mailbox_command(ha, mcp);
-
- if (rval != QLA_SUCCESS) {
- /*EMPTY*/
- DEBUG2_3_11(printk("qla2x00_target_reset(%ld): failed=%x.\n",
- ha->host_no, rval);)
- } else {
- /*EMPTY*/
- DEBUG11(printk("qla2x00_target_reset(%ld): done.\n",
- ha->host_no);)
- }
-
- return rval;
-}
-
/*
* qla2x00_get_adapter_id
* Get adapter ID and topology.
mcp->tov = 30;
mcp->flags = 0;
rval = qla2x00_mailbox_command(ha, mcp);
+ if (mcp->mb[0] == MBS_COMMAND_ERROR)
+ rval = QLA_COMMAND_ERROR;
/* Return data. */
*id = mcp->mb[1];
fcport->port_type = FCT_INITIATOR;
else
fcport->port_type = FCT_TARGET;
+
+ /* Passback COS information. */
+ fcport->supported_classes = (pd->options & BIT_4) ?
+ FC_COS_CLASS2: FC_COS_CLASS3;
}
gpd_error_out:
mb[1] |= BIT_1;
} else
mb[1] = BIT_0;
+
+ /* Passback COS information. */
+ mb[10] = 0;
+ if (lg->io_parameter[7] || lg->io_parameter[8])
+ mb[10] |= BIT_0; /* Class 2. */
+ if (lg->io_parameter[9] || lg->io_parameter[10])
+ mb[10] |= BIT_1; /* Class 3. */
}
dma_pool_free(ha->s_dma_pool, lg, lg_dma);
mb[2] = mcp->mb[2];
mb[6] = mcp->mb[6];
mb[7] = mcp->mb[7];
+ /* COS retrieved from Get-Port-Database mailbox command. */
+ mb[10] = 0;
}
if (rval != QLA_SUCCESS) {
DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no);)
fcport = sp->fcport;
- if (atomic_read(&ha->loop_state) == LOOP_DOWN ||
- atomic_read(&fcport->state) == FCS_DEVICE_LOST) {
- return QLA_FUNCTION_FAILED;
- }
spin_lock_irqsave(&ha->hardware_lock, flags);
for (handle = 1; handle < MAX_OUTSTANDING_COMMANDS; handle++) {
return rval;
}
+
+int
+qla2x00_stop_firmware(scsi_qla_host_t *ha)
+{
+ int rval;
+ mbx_cmd_t mc;
+ mbx_cmd_t *mcp = &mc;
+
+ if (!IS_QLA24XX(ha) && !IS_QLA25XX(ha))
+ return QLA_FUNCTION_FAILED;
+
+ DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
+
+ mcp->mb[0] = MBC_STOP_FIRMWARE;
+ mcp->out_mb = MBX_0;
+ mcp->in_mb = MBX_0;
+ mcp->tov = 5;
+ mcp->flags = 0;
+ rval = qla2x00_mailbox_command(ha, mcp);
+
+ if (rval != QLA_SUCCESS) {
+ DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__,
+ ha->host_no, rval));
+ } else {
+ DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no));
+ }
+
+ return rval;
+}