summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qlogicfc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/qlogicfc.c')
-rw-r--r--drivers/scsi/qlogicfc.c355
1 files changed, 194 insertions, 161 deletions
diff --git a/drivers/scsi/qlogicfc.c b/drivers/scsi/qlogicfc.c
index 283fe9c3d..df9ba38d4 100644
--- a/drivers/scsi/qlogicfc.c
+++ b/drivers/scsi/qlogicfc.c
@@ -18,6 +18,9 @@
/* This is a version of the isp1020 driver which was modified by
* Chris Loveland <cwl@iol.unh.edu> to support the isp2100 and isp2200
+ *
+ * Big endian support and dynamic DMA mapping added
+ * by Jakub Jelinek <jakub@redhat.com>.
*/
/*
@@ -59,6 +62,24 @@
#include "sd.h"
#include "hosts.h"
+
+#if 1
+/* Once pci64_ DMA mapping interface is in, kill this. */
+typedef dma_addr_t dma64_addr_t;
+#define pci64_alloc_consistent(d,s,p) pci_alloc_consistent((d),(s),(p))
+#define pci64_free_consistent(d,s,c,a) pci_free_consistent((d),(s),(c),(a))
+#define pci64_map_single(d,c,s,dir) pci_map_single((d),(c),(s),(dir))
+#define pci64_map_sg(d,s,n,dir) pci_map_sg((d),(s),(n),(dir))
+#define pci64_unmap_single(d,a,s,dir) pci_unmap_single((d),(a),(s),(dir))
+#define pci64_unmap_sg(d,s,n,dir) pci_unmap_sg((d),(s),(n),(dir))
+#define pci64_dma_hi32(a) 0
+#define pci64_dma_lo32(a) (a)
+#define pci64_dma_build(hi,lo) (lo)
+#define sg_dma64_address(s) sg_dma_address(s)
+#define sg_dma64_len(s) sg_dma_len(s)
+#define PCI64_DMA_BITS 32
+#endif
+
#include "qlogicfc.h"
/* Configuration section **************************************************** */
@@ -157,18 +178,6 @@ struct {
#endif /* DEBUG ISP2x00_INTR */
-#if BITS_PER_LONG > 32
-#define virt_to_bus_low32(x) ((u32) (0xffffffff & virt_to_bus(x)))
-#define virt_to_bus_high32(x) ((u32) (0xffffffff & (virt_to_bus(x)>>32)))
-#define bus_to_virt_low32(x) ((u32) (0xffffffff & bus_to_virt(x)))
-#define bus_to_virt_high32(x) ((u32) (0xffffffff & (bus_to_virt(x)>>32)))
-#else
-#define virt_to_bus_low32(x) virt_to_bus(x)
-#define virt_to_bus_high32(x) 0x0
-#define bus_to_virt_low32(x) bus_to_virt(x)
-#define bus_to_virt_high32(x) 0x0
-#endif
-
#define ISP2100_REV_ID1 1
#define ISP2100_REV_ID3 3
#define ISP2200_REV_ID5 5
@@ -230,7 +239,7 @@ struct Entry_header {
};
/* entry header type commands */
-#if BITS_PER_LONG > 32
+#if PCI64_DMA_BITS > 32
#define ENTRY_COMMAND 0x19
#define ENTRY_CONTINUATION 0x0a
#else
@@ -247,34 +256,23 @@ struct Entry_header {
#define EFLAG_BAD_HEADER 4
#define EFLAG_BAD_PAYLOAD 8
-#if BITS_PER_LONG > 32
+#if PCI64_DMA_BITS > 32
+
struct dataseg {
u_int d_base;
u_int d_base_hi;
u_int d_count;
};
-struct Command_Entry {
- struct Entry_header hdr;
- u_int handle;
- u_char target_lun;
- u_char target_id;
- u_short expanded_lun;
- u_short control_flags;
- u_short rsvd2;
- u_short time_out;
- u_short segment_cnt;
- u_char cdb[16];
- u_int total_byte_cnt;
- struct dataseg dataseg[DATASEGS_PER_COMMAND];
-};
-
#else
+
struct dataseg {
u_int d_base;
u_int d_count;
};
+#endif
+
struct Command_Entry {
struct Entry_header hdr;
u_int handle;
@@ -290,9 +288,6 @@ struct Command_Entry {
struct dataseg dataseg[DATASEGS_PER_COMMAND];
};
-#endif
-
-
/* command entry control flag definitions */
#define CFLAG_NODISC 0x01
#define CFLAG_HEAD_TAG 0x02
@@ -302,7 +297,7 @@ struct Command_Entry {
#define CFLAG_READ 0x20
#define CFLAG_WRITE 0x40
-#if BITS_PER_LONG > 32
+#if PCI64_DMA_BITS > 32
struct Continuation_Entry {
struct Entry_header hdr;
struct dataseg dataseg[DATASEGS_PER_CONT];
@@ -650,6 +645,9 @@ struct init_cb {
#define AS_REDO_FABRIC_PORTDB 2
#define AS_REDO_LOOP_PORTDB 4
+#define RES_SIZE ((RES_QUEUE_LEN + 1)*QUEUE_ENTRY_LEN)
+#define REQ_SIZE ((QLOGICFC_REQ_QUEUE_LEN + 1)*QUEUE_ENTRY_LEN)
+
struct isp2x00_hostdata {
u_char revision;
struct pci_dev *pci_dev;
@@ -730,6 +728,7 @@ int isp2x00_detect(Scsi_Host_Template * tmpt)
struct isp2x00_hostdata *hostdata;
struct pci_dev *pdev = NULL;
unsigned short device_ids[2];
+ dma64_addr_t busaddr;
int i;
@@ -756,50 +755,43 @@ int isp2x00_detect(Scsi_Host_Template * tmpt)
memset(hostdata, 0, sizeof(struct isp2x00_hostdata));
hostdata->pci_dev = pdev;
- hostdata->res = (char *) kmalloc((RES_QUEUE_LEN + 1)*QUEUE_ENTRY_LEN, GFP_KERNEL);
+ hostdata->res = pci64_alloc_consistent(pdev, RES_SIZE + REQ_SIZE, &busaddr);
+
if (!hostdata->res){
- printk("qlogicfc%d : could not allocate memory for response queue.\n", hostdata->host_id);
- scsi_unregister(host);
- continue;
- }
- hostdata->req = (char *) kmalloc((QLOGICFC_REQ_QUEUE_LEN + 1)*QUEUE_ENTRY_LEN, GFP_KERNEL);
- if (!hostdata->req){
- printk("qlogicfc%d : could not allocate memory for request queue.\n", hostdata->host_id);
- kfree(hostdata->res);
+ printk("qlogicfc%d : could not allocate memory for request and response queue.\n", hostdata->host_id);
scsi_unregister(host);
continue;
}
-
+ hostdata->req = hostdata->res + (RES_QUEUE_LEN + 1)*QUEUE_ENTRY_LEN;
hostdata->queued = 0;
/* set up the control block */
hostdata->control_block.version = 0x1;
- hostdata->control_block.firm_opts = 0x800e;
- hostdata->control_block.max_frame_len = 2048;
- hostdata->control_block.max_iocb = QLOGICFC_REQ_QUEUE_LEN;
- hostdata->control_block.exec_throttle = QLOGICFC_CMD_PER_LUN;
+ hostdata->control_block.firm_opts = cpu_to_le16(0x800e);
+ hostdata->control_block.max_frame_len = cpu_to_le16(2048);
+ hostdata->control_block.max_iocb = cpu_to_le16(QLOGICFC_REQ_QUEUE_LEN);
+ hostdata->control_block.exec_throttle = cpu_to_le16(QLOGICFC_CMD_PER_LUN);
hostdata->control_block.retry_delay = 5;
hostdata->control_block.retry_cnt = 1;
- hostdata->control_block.node_name[0] = 0x0020;
- hostdata->control_block.node_name[1] = 0xE000;
- hostdata->control_block.node_name[2] = 0x008B;
- hostdata->control_block.node_name[3] = 0x0000;
- hostdata->control_block.hard_addr = 0x0003;
- hostdata->control_block.req_queue_len = QLOGICFC_REQ_QUEUE_LEN + 1;
- hostdata->control_block.res_queue_len = RES_QUEUE_LEN + 1;
- hostdata->control_block.res_queue_addr_lo = virt_to_bus_low32(hostdata->res);
- hostdata->control_block.res_queue_addr_high = virt_to_bus_high32(hostdata->res);
- hostdata->control_block.req_queue_addr_lo = virt_to_bus_low32(hostdata->req);
- hostdata->control_block.req_queue_addr_high = virt_to_bus_high32(hostdata->req);
-
-
- hostdata->control_block.add_firm_opts |= CONNECTION_PREFERENCE<<4;
+ hostdata->control_block.node_name[0] = cpu_to_le16(0x0020);
+ hostdata->control_block.node_name[1] = cpu_to_le16(0xE000);
+ hostdata->control_block.node_name[2] = cpu_to_le16(0x008B);
+ hostdata->control_block.node_name[3] = cpu_to_le16(0x0000);
+ hostdata->control_block.hard_addr = cpu_to_le16(0x0003);
+ hostdata->control_block.req_queue_len = cpu_to_le16(QLOGICFC_REQ_QUEUE_LEN + 1);
+ hostdata->control_block.res_queue_len = cpu_to_le16(RES_QUEUE_LEN + 1);
+ hostdata->control_block.res_queue_addr_lo = cpu_to_le32(pci64_dma_lo32(busaddr));
+ hostdata->control_block.res_queue_addr_high = cpu_to_le32(pci64_dma_hi32(busaddr));
+ hostdata->control_block.req_queue_addr_lo = cpu_to_le32(pci64_dma_lo32(busaddr + RES_SIZE));
+ hostdata->control_block.req_queue_addr_high = cpu_to_le32(pci64_dma_hi32(busaddr + RES_SIZE));
+
+
+ hostdata->control_block.add_firm_opts |= cpu_to_le16(CONNECTION_PREFERENCE<<4);
hostdata->adapter_state = AS_LOOP_DOWN;
hostdata->explore_timer.data = 1;
hostdata->host_id = hosts;
if (isp2x00_init(host) || isp2x00_reset_hardware(host)) {
- kfree(hostdata->res);
- kfree(hostdata->req);
+ pci64_free_consistent (pdev, RES_SIZE + REQ_SIZE, hostdata->res, busaddr);
scsi_unregister(host);
continue;
}
@@ -808,8 +800,7 @@ int isp2x00_detect(Scsi_Host_Template * tmpt)
if (request_irq(host->irq, do_isp2x00_intr_handler, SA_INTERRUPT | SA_SHIRQ, "qlogicfc", host)) {
printk("qlogicfc%d : interrupt %d already in use\n",
hostdata->host_id, host->irq);
- kfree(hostdata->res);
- kfree(hostdata->req);
+ pci64_free_consistent (pdev, RES_SIZE + REQ_SIZE, hostdata->res, busaddr);
scsi_unregister(host);
continue;
}
@@ -818,8 +809,7 @@ int isp2x00_detect(Scsi_Host_Template * tmpt)
"in use\n",
hostdata->host_id, host->io_port, host->io_port + 0xff);
free_irq(host->irq, host);
- kfree(hostdata->res);
- kfree(hostdata->req);
+ pci64_free_consistent (pdev, RES_SIZE + REQ_SIZE, hostdata->res, busaddr);
scsi_unregister(host);
continue;
}
@@ -977,12 +967,13 @@ int isp2x00_init_fabric(struct Scsi_Host *host, struct id_name_map *port_db, int
u_short loop_id = 0x81;
u_short scsi_id = cur_scsi_id;
u_int port_id;
- struct sns_cb req;
- u_char sns_response[608];
+ struct sns_cb *req;
+ u_char *sns_response;
+ dma64_addr_t busaddr;
struct isp2x00_hostdata *hostdata;
hostdata = (struct isp2x00_hostdata *) host->hostdata;
-
+
DEBUG_FABRIC(printk("qlogicfc%d : Checking for a fabric.\n", hostdata->host_id));
param[0] = MBOX_GET_PORT_NAME;
param[1] = (u16)FABRIC_PORT << 8;
@@ -995,52 +986,60 @@ int isp2x00_init_fabric(struct Scsi_Host *host, struct id_name_map *port_db, int
}
printk("qlogicfc%d : Fabric found.\n", hostdata->host_id);
+ req = (struct sns_cb *)pci64_alloc_consistent(hostdata->pci_dev, sizeof(*req) + 608, &busaddr);
+
+ if (!req){
+ printk("qlogicfc%d : Could not allocate DMA resources for fabric initialization\n", hostdata->host_id);
+ return 0;
+ }
+ sns_response = (u_char *)(req + 1);
+
if (hostdata->adapter_state & AS_REDO_LOOP_PORTDB){
- memset(&req, 0, sizeof(req));
+ memset(req, 0, sizeof(*req));
- req.len = 8;
- req.response_low = virt_to_bus_low32(sns_response);
- req.response_high = virt_to_bus_high32(sns_response);
- req.sub_len = 22;
- req.data[0] = 0x17;
- req.data[1] = 0x02;
- req.data[8] = (u_char) (hostdata->port_id & 0xff);
- req.data[9] = (u_char) (hostdata->port_id >> 8 & 0xff);
- req.data[10] = (u_char) (hostdata->port_id >> 16 & 0xff);
- req.data[13] = 0x01;
+ req->len = cpu_to_le16(8);
+ req->response_low = cpu_to_le32(pci64_dma_lo32(busaddr + sizeof(*req)));
+ req->response_high = cpu_to_le32(pci64_dma_hi32(busaddr + sizeof(*req)));
+ req->sub_len = cpu_to_le16(22);
+ req->data[0] = 0x17;
+ req->data[1] = 0x02;
+ req->data[8] = (u_char) (hostdata->port_id & 0xff);
+ req->data[9] = (u_char) (hostdata->port_id >> 8 & 0xff);
+ req->data[10] = (u_char) (hostdata->port_id >> 16 & 0xff);
+ req->data[13] = 0x01;
param[0] = MBOX_SEND_SNS;
param[1] = 30;
- param[2] = virt_to_bus_low32(&req) >> 16;
- param[3] = virt_to_bus_low32(&req);
- param[6] = virt_to_bus_high32(&req) >> 16;
- param[7] = virt_to_bus_high32(&req);
-
+ param[2] = pci64_dma_lo32(busaddr) >> 16;
+ param[3] = pci64_dma_lo32(busaddr);
+ param[6] = pci64_dma_hi32(busaddr) >> 16;
+ param[7] = pci64_dma_hi32(busaddr);
+
isp2x00_mbox_command(host, param);
if (param[0] != MBOX_COMMAND_COMPLETE)
- printk("qlogicfc%d : error sending RFC-4\n", hostdata->host_id);
+ printk("qlogicfc%d : error sending RFC-4\n", hostdata->host_id);
}
port_id = hostdata->port_id;
while (!done) {
- memset(&req, 0, sizeof(req));
-
- req.len = 304;
- req.response_low = virt_to_bus_low32(sns_response);
- req.response_high = virt_to_bus_high32(sns_response);
- req.sub_len = 6;
- req.data[0] = 0x00;
- req.data[1] = 0x01;
- req.data[8] = (u_char) (port_id & 0xff);
- req.data[9] = (u_char) (port_id >> 8 & 0xff);
- req.data[10] = (u_char) (port_id >> 16 & 0xff);
+ memset(req, 0, sizeof(*req));
+
+ req->len = cpu_to_le16(304);
+ req->response_low = cpu_to_le32(pci64_dma_lo32(busaddr + sizeof(*req)));
+ req->response_high = cpu_to_le32(pci64_dma_hi32(busaddr + sizeof(*req)));
+ req->sub_len = cpu_to_le16(6);
+ req->data[0] = 0x00;
+ req->data[1] = 0x01;
+ req->data[8] = (u_char) (port_id & 0xff);
+ req->data[9] = (u_char) (port_id >> 8 & 0xff);
+ req->data[10] = (u_char) (port_id >> 16 & 0xff);
param[0] = MBOX_SEND_SNS;
param[1] = 14;
- param[2] = virt_to_bus_low32(&req) >> 16;
- param[3] = virt_to_bus_low32(&req);
- param[6] = virt_to_bus_high32(&req) >> 16;
- param[7] = virt_to_bus_high32(&req);
+ param[2] = pci64_dma_lo32(busaddr) >> 16;
+ param[3] = pci64_dma_lo32(busaddr);
+ param[6] = pci64_dma_hi32(busaddr) >> 16;
+ param[7] = pci64_dma_hi32(busaddr);
isp2x00_mbox_command(host, param);
@@ -1089,10 +1088,12 @@ int isp2x00_init_fabric(struct Scsi_Host *host, struct id_name_map *port_db, int
done = 1;
} else {
printk("qlogicfc%d : Get All Next failed %x.\n", hostdata->host_id, param[0]);
+ pci64_free_consistent(hostdata->pci_dev, sizeof(*req) + 608, req, busaddr);
return 0;
}
}
+ pci64_free_consistent(hostdata->pci_dev, sizeof(*req) + 608, req, busaddr);
return 1;
}
@@ -1102,6 +1103,7 @@ int isp2x00_init_fabric(struct Scsi_Host *host, struct id_name_map *port_db, int
int isp2x00_release(struct Scsi_Host *host)
{
struct isp2x00_hostdata *hostdata;
+ dma64_addr_t busaddr;
ENTER("isp2x00_release");
@@ -1112,8 +1114,9 @@ int isp2x00_release(struct Scsi_Host *host)
release_region(host->io_port, 0xff);
- kfree(hostdata->res);
- kfree(hostdata->req);
+ busaddr = pci64_dma_build(le32_to_cpu(hostdata->control_block.res_queue_addr_high),
+ le32_to_cpu(hostdata->control_block.res_queue_addr_lo));
+ pci64_free_consistent(hostdata->pci_dev, RES_SIZE + REQ_SIZE, hostdata->res, busaddr);
LEAVE("isp2x00_release");
@@ -1245,19 +1248,20 @@ int isp2x00_queuecommand(Scsi_Cmnd * Cmnd, void (*done) (Scsi_Cmnd *))
cmd->hdr.entry_type = ENTRY_COMMAND;
cmd->hdr.entry_cnt = 1;
cmd->target_lun = Cmnd->lun;
- cmd->expanded_lun = Cmnd->lun;
+ cmd->expanded_lun = cpu_to_le16(Cmnd->lun);
#if ISP2x00_PORTDB
cmd->target_id = hostdata->port_db[Cmnd->target].loop_id;
#else
cmd->target_id = Cmnd->target;
#endif
- cmd->total_byte_cnt = (u_int) Cmnd->request_bufflen;
+ cmd->total_byte_cnt = cpu_to_le32(Cmnd->request_bufflen);
cmd->time_out = 0;
memcpy(cmd->cdb, Cmnd->cmnd, Cmnd->cmd_len);
if (Cmnd->use_sg) {
- cmd->segment_cnt = sg_count = Cmnd->use_sg;
sg = (struct scatterlist *) Cmnd->request_buffer;
+ sg_count = pci64_map_sg(hostdata->pci_dev, sg, Cmnd->use_sg, scsi_to_pci_dma_dir(Cmnd->sc_data_direction));
+ cmd->segment_cnt = cpu_to_le16(sg_count);
ds = cmd->dataseg;
/* fill in first two sg entries: */
n = sg_count;
@@ -1265,11 +1269,11 @@ int isp2x00_queuecommand(Scsi_Cmnd * Cmnd, void (*done) (Scsi_Cmnd *))
n = DATASEGS_PER_COMMAND;
for (i = 0; i < n; i++) {
- ds[i].d_base = virt_to_bus_low32(sg->address);
-#if BITS_PER_LONG > 32
- ds[i].d_base_hi = virt_to_bus_high32(sg->address);
+ ds[i].d_base = cpu_to_le32(pci64_dma_lo32(sg_dma64_address(sg)));
+#if PCI64_DMA_BITS > 32
+ ds[i].d_base_hi = cpu_to_le32(pci64_dma_hi32(sg_dma64_address(sg)));
#endif
- ds[i].d_count = sg->length;
+ ds[i].d_count = cpu_to_le32(sg_dma64_len(sg));
++sg;
}
sg_count -= DATASEGS_PER_COMMAND;
@@ -1291,22 +1295,32 @@ int isp2x00_queuecommand(Scsi_Cmnd * Cmnd, void (*done) (Scsi_Cmnd *))
if (n > DATASEGS_PER_CONT)
n = DATASEGS_PER_CONT;
for (i = 0; i < n; ++i) {
- ds[i].d_base = virt_to_bus_low32(sg->address);
-#if BITS_PER_LONG > 32
- ds[i].d_base_hi = virt_to_bus_high32(sg->address);
+ ds[i].d_base = cpu_to_le32(pci64_dma_lo32(sg_dma64_address(sg)));
+#if PCI64_DMA_BITS > 32
+ ds[i].d_base_hi = cpu_to_le32(pci64_dma_hi32(sg_dma64_address(sg)));
#endif
- ds[i].d_count = sg->length;
+ ds[i].d_count = cpu_to_le32(sg_dma64_len(sg));
++sg;
}
sg_count -= n;
}
+ } else if (Cmnd->request_bufflen) {
+ dma64_addr_t busaddr = pci64_map_single(hostdata->pci_dev, Cmnd->request_buffer, Cmnd->request_bufflen,
+ scsi_to_pci_dma_dir(Cmnd->sc_data_direction));
+
+ *(dma64_addr_t *)&Cmnd->SCp = busaddr;
+ cmd->dataseg[0].d_base = cpu_to_le32(pci64_dma_lo32(busaddr));
+#if PCI64_DMA_BITS > 32
+ cmd->dataseg[0].d_base_hi = cpu_to_le32(pci64_dma_hi32(busaddr));
+#endif
+ cmd->dataseg[0].d_count = cpu_to_le32(Cmnd->request_bufflen);
+ cmd->segment_cnt = cpu_to_le16(1);
} else {
- cmd->dataseg[0].d_base = virt_to_bus_low32(Cmnd->request_buffer);
-#if BITS_PER_LONG > 32
- cmd->dataseg[0].d_base_hi = virt_to_bus_high32(Cmnd->request_buffer);
+ cmd->dataseg[0].d_base = 0;
+#if PCI64_DMA_BITS > 32
+ cmd->dataseg[0].d_base_hi = 0;
#endif
- cmd->dataseg[0].d_count = (u_int) Cmnd->request_bufflen;
- cmd->segment_cnt = 1;
+ cmd->segment_cnt = cpu_to_le16(1); /* Shouldn't this be 0? */
}
switch (Cmnd->cmnd[0]) {
@@ -1317,38 +1331,28 @@ int isp2x00_queuecommand(Scsi_Cmnd * Cmnd, void (*done) (Scsi_Cmnd *))
case WRITE_6:
case WRITE_BUFFER:
case MODE_SELECT:
- cmd->control_flags = CFLAG_WRITE;
- break;
- case REQUEST_SENSE:
- /* scsi.c expects sense info in a different buffer */
- cmd->dataseg[0].d_base = virt_to_bus_low32(Cmnd->sense_buffer);
-#if BITS_PER_LONG > 32
- cmd->dataseg[0].d_base_hi = virt_to_bus_high32(Cmnd->sense_buffer);
-#endif
- cmd->dataseg[0].d_count = sizeof(Cmnd->sense_buffer);
- cmd->segment_cnt = 1;
- cmd->control_flags = CFLAG_READ;
+ cmd->control_flags = cpu_to_le16(CFLAG_WRITE);
break;
default:
- cmd->control_flags = CFLAG_READ;
+ cmd->control_flags = cpu_to_le16(CFLAG_READ);
break;
}
if (Cmnd->device->tagged_supported) {
if ((jiffies - hostdata->tag_ages[Cmnd->target]) > (2 * SCSI_TIMEOUT)) {
- cmd->control_flags |= CFLAG_ORDERED_TAG;
+ cmd->control_flags |= cpu_to_le16(CFLAG_ORDERED_TAG);
hostdata->tag_ages[Cmnd->target] = jiffies;
} else
switch (Cmnd->tag) {
case HEAD_OF_QUEUE_TAG:
- cmd->control_flags |= CFLAG_HEAD_TAG;
+ cmd->control_flags |= cpu_to_le16(CFLAG_HEAD_TAG);
break;
case ORDERED_QUEUE_TAG:
- cmd->control_flags |= CFLAG_ORDERED_TAG;
+ cmd->control_flags |= cpu_to_le16(CFLAG_ORDERED_TAG);
break;
default:
- cmd->control_flags |= CFLAG_SIMPLE_TAG;
+ cmd->control_flags |= cpu_to_le16(CFLAG_SIMPLE_TAG);
break;
}
}
@@ -1543,6 +1547,16 @@ void isp2x00_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
if (sts->hdr.entry_type == ENTRY_STATUS && (Cmnd = hostdata->handle_ptrs[sts->handle])) {
Cmnd->result = isp2x00_return_status(Cmnd, sts);
hostdata->queued--;
+
+ if (Cmnd->use_sg)
+ pci64_unmap_sg(hostdata->pci_dev,
+ (struct scatterlist *)Cmnd->buffer, Cmnd->use_sg,
+ scsi_to_pci_dma_dir(Cmnd->sc_data_direction));
+ else if (Cmnd->request_bufflen)
+ pci64_unmap_single(hostdata->pci_dev, *(dma64_addr_t *)&Cmnd->SCp,
+ Cmnd->request_bufflen,
+ scsi_to_pci_dma_dir(Cmnd->sc_data_direction));
+
/*
* if any of the following are true we do not
* call scsi_done. if the status is CS_ABORTED
@@ -1550,7 +1564,7 @@ void isp2x00_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
* level should already know its aborted.
*/
if (hostdata->handle_serials[sts->handle] != Cmnd->serial_number
- || sts->completion_status == CS_ABORTED){
+ || le16_to_cpu(sts->completion_status) == CS_ABORTED){
hostdata->handle_serials[sts->handle] = 0;
hostdata->handle_ptrs[sts->handle] = NULL;
outw(out_ptr, host->io_port + MBOX5);
@@ -1564,7 +1578,7 @@ void isp2x00_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
* the device may well be back in a couple of
* seconds.
*/
- if ((hostdata->adapter_state == AS_LOOP_DOWN || sts->completion_status == CS_PORT_UNAVAILABLE || sts->completion_status == CS_PORT_LOGGED_OUT || sts->completion_status == CS_PORT_CONFIG_CHANGED) && hostdata->port_db[Cmnd->target].wwn){
+ if ((hostdata->adapter_state == AS_LOOP_DOWN || sts->completion_status == cpu_to_le16(CS_PORT_UNAVAILABLE) || sts->completion_status == cpu_to_le16(CS_PORT_LOGGED_OUT) || sts->completion_status == cpu_to_le16(CS_PORT_CONFIG_CHANGED)) && hostdata->port_db[Cmnd->target].wwn){
outw(out_ptr, host->io_port + MBOX5);
continue;
}
@@ -1575,12 +1589,11 @@ void isp2x00_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
hostdata->handle_ptrs[sts->handle] = NULL;
- if (sts->completion_status == CS_RESET_OCCURRED
- || (sts->status_flags & STF_BUS_RESET))
+ if (sts->completion_status == cpu_to_le16(CS_RESET_OCCURRED)
+ || (sts->status_flags & cpu_to_le16(STF_BUS_RESET)))
hostdata->send_marker = 1;
- memset(Cmnd->sense_buffer, 0, sizeof(Cmnd->sense_buffer));
- if (sts->scsi_status & 0x0200)
+ if (le16_to_cpu(sts->scsi_status) & 0x0200)
memcpy(Cmnd->sense_buffer, sts->req_sense_data,
sizeof(Cmnd->sense_buffer));
@@ -1638,9 +1651,9 @@ static int isp2x00_return_status(Scsi_Cmnd *Cmnd, struct Status_Entry *sts)
ENTER("isp2x00_return_status");
DEBUG(printk("qlogicfc : completion status = 0x%04x\n",
- sts->completion_status));
+ le16_to_cpu(sts->completion_status)));
- switch (sts->completion_status) {
+ switch (le16_to_cpu(sts->completion_status)) {
case CS_COMPLETE:
host_status = DID_OK;
break;
@@ -1660,7 +1673,7 @@ static int isp2x00_return_status(Scsi_Cmnd *Cmnd, struct Status_Entry *sts)
host_status = DID_ERROR;
break;
case CS_DATA_UNDERRUN:
- if (Cmnd->underflow <= (Cmnd->request_bufflen - sts->residual))
+ if (Cmnd->underflow <= (Cmnd->request_bufflen - le32_to_cpu(sts->residual)))
host_status = DID_OK;
else
host_status = DID_ERROR;
@@ -1675,17 +1688,17 @@ static int isp2x00_return_status(Scsi_Cmnd *Cmnd, struct Status_Entry *sts)
break;
default:
printk("qlogicfc : unknown completion status 0x%04x\n",
- sts->completion_status);
+ le16_to_cpu(sts->completion_status));
host_status = DID_ERROR;
break;
}
DEBUG_INTR(printk("qlogicfc : host status (%s) scsi status %x\n",
- reason[host_status], sts->scsi_status));
+ reason[host_status], le16_to_cpu(sts->scsi_status)));
LEAVE("isp2x00_return_status");
- return (sts->scsi_status & STATUS_MASK) | (host_status << 16);
+ return (le16_to_cpu(sts->scsi_status) & STATUS_MASK) | (host_status << 16);
}
@@ -1802,6 +1815,7 @@ static int isp2x00_reset_hardware(struct Scsi_Host *host)
u_short param[8];
struct isp2x00_hostdata *hostdata;
int loop_count;
+ dma64_addr_t busaddr;
ENTER("isp2x00_reset_hardware");
@@ -1896,6 +1910,14 @@ static int isp2x00_reset_hardware(struct Scsi_Host *host)
}
#endif
+#ifdef __BIG_ENDIAN
+ {
+ u64 val;
+ memcpy(&val, &hostdata->control_block.node_name, sizeof(u64));
+ hostdata->wwn = ((val & 0xff00ff00ff00ff00ULL) >> 8)
+ | ((val & 0x00ff00ff00ff00ffULL) << 8);
+ }
+#else
hostdata->wwn = (u64) (hostdata->control_block.node_name[0]) << 56;
hostdata->wwn |= (u64) (hostdata->control_block.node_name[0] & 0xff00) << 48;
hostdata->wwn |= (u64) (hostdata->control_block.node_name[1] & 0xff00) << 24;
@@ -1904,26 +1926,37 @@ static int isp2x00_reset_hardware(struct Scsi_Host *host)
hostdata->wwn |= (u64) (hostdata->control_block.node_name[2] & 0xff00) << 8;
hostdata->wwn |= (u64) (hostdata->control_block.node_name[3] & 0x00ff) << 8;
hostdata->wwn |= (u64) (hostdata->control_block.node_name[3] & 0xff00) >> 8;
+#endif
+
+ /* FIXME: If the DMA transfer goes one way only, this should use PCI_DMA_TODEVICE and below as well. */
+ busaddr = pci64_map_single(hostdata->pci_dev, &hostdata->control_block, sizeof(hostdata->control_block),
+ PCI_DMA_BIDIRECTIONAL);
param[0] = MBOX_INIT_FIRMWARE;
- param[2] = (u_short) (virt_to_bus_low32(&hostdata->control_block) >> 16);
- param[3] = (u_short) (virt_to_bus_low32(&hostdata->control_block) & 0xffff);
+ param[2] = (u_short) (pci64_dma_lo32(busaddr) >> 16);
+ param[3] = (u_short) (pci64_dma_lo32(busaddr) & 0xffff);
param[4] = 0;
param[5] = 0;
- param[6] = (u_short) (virt_to_bus_high32(&hostdata->control_block) >> 16);
- param[7] = (u_short) (virt_to_bus_high32(&hostdata->control_block) & 0xffff);
+ param[6] = (u_short) (pci64_dma_hi32(busaddr) >> 16);
+ param[7] = (u_short) (pci64_dma_hi32(busaddr) & 0xffff);
isp2x00_mbox_command(host, param);
if (param[0] != MBOX_COMMAND_COMPLETE) {
printk("qlogicfc%d.c: Ouch 0x%04x\n", hostdata->host_id, param[0]);
+ pci64_unmap_single(hostdata->pci_dev, busaddr, sizeof(hostdata->control_block),
+ PCI_DMA_BIDIRECTIONAL);
return 1;
}
param[0] = MBOX_GET_FIRMWARE_STATE;
isp2x00_mbox_command(host, param);
if (param[0] != MBOX_COMMAND_COMPLETE) {
printk("qlogicfc%d.c: 0x%04x\n", hostdata->host_id, param[0]);
+ pci64_unmap_single(hostdata->pci_dev, busaddr, sizeof(hostdata->control_block),
+ PCI_DMA_BIDIRECTIONAL);
return 1;
}
+ pci64_unmap_single(hostdata->pci_dev, busaddr, sizeof(hostdata->control_block),
+ PCI_DMA_BIDIRECTIONAL);
LEAVE("isp2x00_reset_hardware");
return 0;
@@ -1939,11 +1972,11 @@ static int isp2x00_get_nvram_defaults(struct Scsi_Host *host, struct init_cb *co
return 1;
value = isp2x00_read_nvram_word(host, 8);
- control_block->node_name[0] = isp2x00_read_nvram_word(host, 9);
- control_block->node_name[1] = isp2x00_read_nvram_word(host, 10);
- control_block->node_name[2] = isp2x00_read_nvram_word(host, 11);
- control_block->node_name[3] = isp2x00_read_nvram_word(host, 12);
- control_block->hard_addr = isp2x00_read_nvram_word(host, 13);
+ control_block->node_name[0] = cpu_to_le16(isp2x00_read_nvram_word(host, 9));
+ control_block->node_name[1] = cpu_to_le16(isp2x00_read_nvram_word(host, 10));
+ control_block->node_name[2] = cpu_to_le16(isp2x00_read_nvram_word(host, 11));
+ control_block->node_name[3] = cpu_to_le16(isp2x00_read_nvram_word(host, 12));
+ control_block->hard_addr = cpu_to_le16(isp2x00_read_nvram_word(host, 13));
return 0;
@@ -2156,12 +2189,12 @@ void isp2x00_print_status_entry(struct Status_Entry *status)
printk("qlogicfc : entry count = 0x%02x, type = 0x%02x, flags = 0x%02x\n",
status->hdr.entry_cnt, status->hdr.entry_type, status->hdr.flags);
printk("qlogicfc : scsi status = 0x%04x, completion status = 0x%04x\n",
- status->scsi_status, status->completion_status);
+ le16_to_cpu(status->scsi_status), le16_to_cpu(status->completion_status));
printk("qlogicfc : state flags = 0x%04x, status flags = 0x%04x\n",
- status->state_flags, status->status_flags);
+ le16_to_cpu(status->state_flags), le16_to_cpu(status->status_flags));
printk("qlogicfc : response info length = 0x%04x, request sense length = 0x%04x\n",
- status->res_info_len, status->req_sense_len);
- printk("qlogicfc : residual transfer length = 0x%08x, response = 0x%02x\n", status->residual, status->res_info[3]);
+ le16_to_cpu(status->res_info_len), le16_to_cpu(status->req_sense_len));
+ printk("qlogicfc : residual transfer length = 0x%08x, response = 0x%02x\n", le32_to_cpu(status->residual), status->res_info[3]);
}