* General Public License for more details.
*
******************************************************************************/
-#define QLA1280_VERSION "3.24.1"
+#define QLA1280_VERSION "3.24.3"
/*****************************************************************************
Revision History:
+ Rev 3.24.3 January 19, 2004, Jes Sorensen
+ - Handle PCI DMA mask settings correctly
+ - Correct order of error handling in probe_one, free_irq should not
+ be called if request_irq failed
+ Rev 3.24.2 January 19, 2004, James Bottomley & Andrew Vasquez
+ - Big endian fixes (James)
+ - Remove bogus IOCB content on zero data transfer commands (Andrew)
Rev 3.24.1 January 5, 2004, Jes Sorensen
- Initialize completion queue to avoid OOPS on probe
- Handle interrupts during mailbox testing
static int qla1280_abort_device(struct scsi_qla_host *, int, int, int);
static int qla1280_abort_command(struct scsi_qla_host *, struct srb *, int);
static int qla1280_abort_isp(struct scsi_qla_host *);
+#ifdef QLA_64BIT_PTR
static int qla1280_64bit_start_scsi(struct scsi_qla_host *, struct srb *);
+#else
static int qla1280_32bit_start_scsi(struct scsi_qla_host *, struct srb *);
+#endif
static void qla1280_nv_write(struct scsi_qla_host *, uint16_t);
static void qla1280_poll(struct scsi_qla_host *);
static void qla1280_reset_adapter(struct scsi_qla_host *);
{
uint16_t *wptr;
uint8_t chksum;
- int cnt;
+ int cnt, i;
struct nvram *nv;
ENTER("qla1280_read_nvram");
} else
ha->nvram_valid = 1;
+ /* The firmware interface is, um, interesting, in that the
+ * actual firmware image on the chip is little endian, thus,
+ * the process of taking that image to the CPU would end up
+ * little endian. However, the firmare interface requires it
+ * to be read a word (two bytes) at a time.
+ *
+ * The net result of this would be that the word (and
+ * doubleword) quantites in the firmware would be correct, but
+ * the bytes would be pairwise reversed. Since most of the
+ * firmware quantites are, in fact, bytes, we do an extra
+ * le16_to_cpu() in the firmware read routine.
+ *
+ * The upshot of all this is that the bytes in the firmware
+ * are in the correct places, but the 16 and 32 bit quantites
+ * are still in little endian format. We fix that up below by
+ * doing extra reverses on them */
+ nv->isp_parameter = cpu_to_le16(nv->isp_parameter);
+ nv->firmware_feature.w = cpu_to_le16(nv->firmware_feature.w);
+ for(i = 0; i < MAX_BUSES; i++) {
+ nv->bus[i].selection_timeout = cpu_to_le16(nv->bus[i].selection_timeout);
+ nv->bus[i].max_queue_depth = cpu_to_le16(nv->bus[i].max_queue_depth);
+ }
dprintk(1, "qla1280_read_nvram: Completed Reading NVRAM\n");
LEAVE("qla1280_read_nvram");
struct Scsi_Host *host = cmd->device->host;
struct scsi_qla_host *ha = (struct scsi_qla_host *)host->hostdata;
struct srb *sp = (struct srb *)&cmd->SCp;
+ int status;
cmd->scsi_done = fn;
sp->cmd = cmd;
qla1280_print_scsi_cmd(5, cmd);
- if (ha->flags.enable_64bit_addressing)
- return qla1280_64bit_start_scsi(ha, sp);
- return qla1280_32bit_start_scsi(ha, sp);
+#ifdef QLA_64BIT_PTR
+ /*
+ * Using 64 bit commands if the PCI bridge doesn't support it is a
+ * bit wasteful, however this should really only happen if one's
+ * PCI controller is completely broken, like the BCM1250. For
+ * sane hardware this is not an issue.
+ */
+ status = qla1280_64bit_start_scsi(ha, sp);
+#else
+ status = qla1280_32bit_start_scsi(ha, sp);
+#endif
+ return status;
}
enum action {
qla1280_return_status(struct response * sts, struct scsi_cmnd *cp)
{
int host_status = DID_ERROR;
+ uint16_t comp_status = le16_to_cpu(sts->comp_status);
+ uint16_t state_flags = le16_to_cpu(sts->state_flags);
+ uint16_t residual_length = le16_to_cpu(sts->residual_length);
+ uint16_t scsi_status = le16_to_cpu(sts->scsi_status);
#if DEBUG_QLA1280_INTR
static char *reason[] = {
"DID_OK",
#if DEBUG_QLA1280_INTR
/*
dprintk(1, "qla1280_return_status: compl status = 0x%04x\n",
- sts->comp_status);
+ comp_status);
*/
#endif
- switch (sts->comp_status) {
+
+ switch (comp_status) {
case CS_COMPLETE:
host_status = DID_OK;
break;
case CS_INCOMPLETE:
- if (!(sts->state_flags & SF_GOT_BUS))
+ if (!(state_flags & SF_GOT_BUS))
host_status = DID_NO_CONNECT;
- else if (!(sts->state_flags & SF_GOT_TARGET))
+ else if (!(state_flags & SF_GOT_TARGET))
host_status = DID_BAD_TARGET;
- else if (!(sts->state_flags & SF_SENT_CDB))
+ else if (!(state_flags & SF_SENT_CDB))
host_status = DID_ERROR;
- else if (!(sts->state_flags & SF_TRANSFERRED_DATA))
+ else if (!(state_flags & SF_TRANSFERRED_DATA))
host_status = DID_ERROR;
- else if (!(sts->state_flags & SF_GOT_STATUS))
+ else if (!(state_flags & SF_GOT_STATUS))
host_status = DID_ERROR;
- else if (!(sts->state_flags & SF_GOT_SENSE))
+ else if (!(state_flags & SF_GOT_SENSE))
host_status = DID_ERROR;
break;
break;
case CS_DATA_OVERRUN:
- dprintk(2, "Data overrun 0x%x\n", sts->residual_length);
+ dprintk(2, "Data overrun 0x%x\n", residual_length);
dprintk(2, "qla1280_isr: response packet data\n");
qla1280_dump_buffer(2, (char *)sts, RESPONSE_ENTRY_SIZE);
host_status = DID_ERROR;
break;
case CS_DATA_UNDERRUN:
- if ((cp->request_bufflen - sts->residual_length) <
+ if ((cp->request_bufflen - residual_length) <
cp->underflow) {
printk(KERN_WARNING
"scsi: Underflow detected - retrying "
#if DEBUG_QLA1280_INTR
dprintk(1, "qla1280 ISP status: host status (%s) scsi status %x\n",
- reason[host_status], sts->scsi_status);
+ reason[host_status], scsi_status);
#endif
LEAVE("qla1280_return_status");
- return (sts->scsi_status & 0xff) | (host_status << 16);
+ return (scsi_status & 0xff) | (host_status << 16);
}
/****************************************************************************/
ha->flags.disable_risc_code_load =
nv->cntr_flags_1.disable_loading_risc_code;
-#ifdef QLA_64BIT_PTR
- /* Enable 64bit addressing for OS/System combination supporting it */
- /* actual NVRAM bit is: nv->cntr_flags_1.enable_64bit_addressing */
- /* but we will ignore it and use BITS_PER_LONG macro to setup for */
- /* 64 or 32 bit access of host memory in all x86/ia-64/Alpha systems */
- ha->flags.enable_64bit_addressing = 1;
-#else
- ha->flags.enable_64bit_addressing = 0;
-#endif
-
- if (ha->flags.enable_64bit_addressing) {
- dprintk(2, "scsi(%li): 64 Bit PCI Addressing Enabled\n",
- ha->host_no);
-
- pci_set_dma_mask(ha->pdev, (dma_addr_t) ~ 0ULL);
- }
-
/* Set ISP hardware DMA burst */
mb[0] = nv->isp_config.c;
/* Enable DMA arbitration on dual channel controllers */
#endif
*dword_ptr++ = cpu_to_le32(pci_dma_lo32(dma_handle));
*dword_ptr++ = cpu_to_le32(pci_dma_hi32(dma_handle));
- *dword_ptr = (uint32_t)cmd->request_bufflen;
+ *dword_ptr = cpu_to_le32(cmd->request_bufflen);
dprintk(5, "qla1280_64bit_start_scsi: No scatter/"
"gather command packet data - b %i, t %i, "
REQUEST_ENTRY_SIZE);
}
} else { /* No data transfer */
- dword_ptr = (uint32_t *)(pkt + 1);
- *dword_ptr++ = 0;
- *dword_ptr++ = 0;
- *dword_ptr = 0;
dprintk(5, "qla1280_64bit_start_scsi: No data, command "
"packet data - b %i, t %i, l %i \n",
SCSI_BUS_32(cmd), SCSI_TCN_32(cmd), SCSI_LUN_32(cmd));
}
+#ifndef QLA_64BIT_PTR
/*
* qla1280_32bit_start_scsi
* The start SCSI is responsible for building request packets on
*dword_ptr = cpu_to_le32(cmd->request_bufflen);
}
} else { /* No data transfer at all */
- dword_ptr = (uint32_t *)(pkt + 1);
- *dword_ptr++ = 0;
- *dword_ptr = 0;
dprintk(5, "qla1280_32bit_start_scsi: No data, command "
"packet data - \n");
qla1280_dump_buffer(5, (char *)pkt, REQUEST_ENTRY_SIZE);
return status;
}
+#endif
/*
* qla1280_req_pkt
ha->pdev = pdev;
ha->devnum = devnum; /* specifies microcode load address */
+#ifdef QLA_64BIT_PTR
+ if (pci_set_dma_mask(ha->pdev, (dma_addr_t) ~ 0ULL)) {
+ if (pci_set_dma_mask(ha->pdev, 0xffffffff)) {
+ printk(KERN_WARNING "scsi(%li): Unable to set a "
+ " suitable DMA mask - aboring\n", ha->host_no);
+ error = -ENODEV;
+ goto error_free_irq;
+ }
+ } else
+ dprintk(2, "scsi(%li): 64 Bit PCI Addressing Enabled\n",
+ ha->host_no);
+#else
+ if (pci_set_dma_mask(ha->pdev, 0xffffffff)) {
+ printk(KERN_WARNING "scsi(%li): Unable to set a "
+ " suitable DMA mask - aboring\n", ha->host_no);
+ error = -ENODEV;
+ goto error_free_irq;
+ }
+#endif
+
ha->request_ring = pci_alloc_consistent(ha->pdev,
((REQUEST_ENTRY_CNT + 1) * (sizeof(request_t))),
&ha->request_dma);
error_disable_adapter:
WRT_REG_WORD(&ha->iobase->ictrl, 0);
#endif
+ error_free_irq:
+ free_irq(pdev->irq, ha);
error_release_region:
#if MEMORY_MAPPED_IO
iounmap(ha->mmpbase);
#else
release_region(host->io_port, 0xff);
#endif
- error_free_irq:
- free_irq(pdev->irq, ha);
error_free_response_ring:
pci_free_consistent(ha->pdev,
((RESPONSE_ENTRY_CNT + 1) * (sizeof(struct response))),