patch-2.4.20 linux-2.4.20/drivers/scsi/u14-34f.c
Next file: linux-2.4.20/drivers/scsi/u14-34f.h
Previous file: linux-2.4.20/drivers/scsi/sym53c8xx_comm.h
Back to the patch index
Back to the overall index
- Lines: 367
- Date:
Thu Nov 28 15:53:14 2002
- Orig file:
linux-2.4.19/drivers/scsi/u14-34f.c
- Orig date:
Fri Aug 2 17:39:44 2002
diff -urN linux-2.4.19/drivers/scsi/u14-34f.c linux-2.4.20/drivers/scsi/u14-34f.c
@@ -1,9 +1,26 @@
/*
* u14-34f.c - Low-level driver for UltraStor 14F/34F SCSI host adapters.
*
- * 01 Jan 2002 Rev. 6.50 for linux 2.4.16
+ * 25 Jun 2002 Rev. 6.70 for linux 2.4.19
+ * + Fixed endian-ness problem due to bitfields.
+ *
+ * 21 Feb 2002 Rev. 6.52 for linux 2.4.18
+ * + Backport from rev. 7.22 (use io_request_lock).
+ *
+ * 20 Feb 2002 Rev. 7.22 for linux 2.5.5
+ * + Remove any reference to virt_to_bus().
+ * + Fix pio hang while detecting multiple HBAs.
+ *
+ * 01 Jan 2002 Rev. 7.20 for linux 2.5.1
* + Use the dynamic DMA mapping API.
*
+ * 19 Dec 2001 Rev. 7.02 for linux 2.5.1
+ * + Use SCpnt->sc_data_direction if set.
+ * + Use sglist.page instead of sglist.address.
+ *
+ * 11 Dec 2001 Rev. 7.00 for linux 2.5.1
+ * + Use host->host_lock instead of io_request_lock.
+ *
* 1 May 2001 Rev. 6.05 for linux 2.4.4
* + Fix data transfer direction for opcode SEND_CUE_SHEET (0x5d)
*
@@ -23,7 +40,7 @@
* + When loaded as a module, accepts the new parameter boot_options
* which value is a string with the same format of the kernel boot
* command line options. A valid example is:
- * modprobe u14-34f boot_options=\"0x230,0x340,lc:y,mq:4\"
+ * modprobe u14-34f 'boot_options="0x230,0x340,lc:y,mq:4"'
*
* 22 Jul 1999 Rev. 5.00 for linux 2.2.10 and 2.3.11
* + Removed pre-2.2 source code compatibility.
@@ -382,6 +399,10 @@
#include <linux/ctype.h>
#include <linux/spinlock.h>
+#if !defined(__BIG_ENDIAN_BITFIELD) && !defined(__LITTLE_ENDIAN_BITFIELD)
+#error "Adjust your <asm/byteorder.h> defines"
+#endif
+
/* Values for the PRODUCT_ID ports for the 14/34F */
#define PRODUCT_ID1 0x56
#define PRODUCT_ID2 0x40 /* NOTE: Only upper nibble is used */
@@ -448,7 +469,7 @@
#define REG_CONFIG2 7
#define REG_OGM 8
#define REG_ICM 12
-#define REGION_SIZE 13
+#define REGION_SIZE 13UL
#define BSY_ASSERTED 0x01
#define IRQ_ASSERTED 0x01
#define CMD_RESET 0xc0
@@ -470,14 +491,21 @@
/* MailBox SCSI Command Packet */
struct mscp {
- unsigned char opcode: 3; /* type of command */
- unsigned char xdir: 2; /* data transfer direction */
- unsigned char dcn: 1; /* disable disconnect */
- unsigned char ca: 1; /* use cache (if available) */
- unsigned char sg: 1; /* scatter/gather operation */
- unsigned char target: 3; /* SCSI target id */
- unsigned char channel: 2; /* SCSI channel number */
- unsigned char lun: 3; /* SCSI logical unit number */
+
+#if defined(__BIG_ENDIAN_BITFIELD)
+ unsigned char sg:1, ca:1, dcn:1, xdir:2, opcode:3;
+ unsigned char lun: 3, channel:2, target:3;
+#else
+ unsigned char opcode: 3, /* type of command */
+ xdir: 2, /* data transfer direction */
+ dcn: 1, /* disable disconnect */
+ ca: 1, /* use cache (if available) */
+ sg: 1; /* scatter/gather operation */
+ unsigned char target: 3, /* SCSI target id */
+ channel: 2, /* SCSI channel number */
+ lun: 3; /* SCSI logical unit number */
+#endif
+
unsigned int data_address PACKED; /* transfer data pointer */
unsigned int data_len PACKED; /* length in bytes */
unsigned int link_address PACKED; /* for linking command chains */
@@ -489,11 +517,19 @@
unsigned char adapter_status; /* non-zero indicates HA error */
unsigned char target_status; /* non-zero indicates target error */
unsigned int sense_addr PACKED;
+
+ /* Additional fields begin here. */
Scsi_Cmnd *SCpnt;
unsigned int cpp_index; /* cp index */
- struct sg_list *sglist;
+
+ /* All the cp structure is zero filled by queuecommand except the
+ following CP_TAIL_SIZE bytes, initialized by detect */
+ dma_addr_t cp_dma_addr; /* dma handle for this cp structure */
+ struct sg_list *sglist; /* pointer to the allocated SG list */
};
+#define CP_TAIL_SIZE (sizeof(struct sglist *) + sizeof(dma_addr_t))
+
struct hostdata {
struct mscp cp[MAX_MAILBOXES]; /* Mailboxes for this board */
unsigned int cp_stat[MAX_MAILBOXES]; /* FREE, IN_USE, LOCKED, IN_RESET */
@@ -501,7 +537,6 @@
unsigned int iocount; /* Total i/o done for this board */
int board_number; /* Number of this board */
char board_name[16]; /* Name of this board */
- char board_id[256]; /* data from INQUIRY on this board */
int in_reset; /* True if board is doing a reset */
int target_to[MAX_TARGET][MAX_CHANNEL]; /* N. of timeout errors on target */
int target_redo[MAX_TARGET][MAX_CHANNEL]; /* If TRUE redo i/o on target */
@@ -511,9 +546,7 @@
struct pci_dev *pdev; /* Always NULL */
unsigned char heads;
unsigned char sectors;
-
- /* slot != 0 for the U24F, slot == 0 for both the U14F and U34F */
- unsigned char slot;
+ char board_id[256]; /* data from INQUIRY on this board */
};
static struct Scsi_Host *sh[MAX_BOARDS + 1];
@@ -543,8 +576,6 @@
#define H2DEV(x) cpu_to_le32(x)
#define DEV2H(x) le32_to_cpu(x)
-#define V2DEV(addr) ((addr) ? H2DEV(virt_to_bus((void *)addr)) : 0)
-
static void do_interrupt_handler(int, void *, struct pt_regs *);
static void flush_dev(Scsi_Device *, unsigned long, unsigned int, unsigned int);
static int do_trace = FALSE;
@@ -637,13 +668,18 @@
static int board_inquiry(unsigned int j) {
struct mscp *cpp;
+ dma_addr_t id_dma_addr;
unsigned int time, limit = 0;
+ id_dma_addr = pci_map_single(HD(j)->pdev, HD(j)->board_id,
+ sizeof(HD(j)->board_id), PCI_DMA_BIDIRECTIONAL);
cpp = &HD(j)->cp[0];
- memset(cpp, 0, sizeof(struct mscp));
+ cpp->cp_dma_addr = pci_map_single(HD(j)->pdev, cpp, sizeof(struct mscp),
+ PCI_DMA_BIDIRECTIONAL);
+ memset(cpp, 0, sizeof(struct mscp) - CP_TAIL_SIZE);
cpp->opcode = OP_HOST_ADAPTER;
cpp->xdir = DTD_IN;
- cpp->data_address = V2DEV(HD(j)->board_id);
+ cpp->data_address = H2DEV(id_dma_addr);
cpp->data_len = H2DEV(sizeof(HD(j)->board_id));
cpp->cdb_len = 6;
cpp->cdb[0] = HA_CMD_INQUIRY;
@@ -659,7 +695,7 @@
outb(CMD_CLR_INTR, sh[j]->io_port + REG_SYS_INTR);
/* Store pointer in OGM address bytes */
- outl(V2DEV(cpp), sh[j]->io_port + REG_OGM);
+ outl(H2DEV(cpp->cp_dma_addr), sh[j]->io_port + REG_OGM);
/* Issue OGM interrupt */
outb(CMD_OGM_INTR, sh[j]->io_port + REG_LCL_INTR);
@@ -675,6 +711,10 @@
return TRUE;
}
+ pci_unmap_single(HD(j)->pdev, cpp->cp_dma_addr, sizeof(struct mscp),
+ PCI_DMA_BIDIRECTIONAL);
+ pci_unmap_single(HD(j)->pdev, id_dma_addr, sizeof(HD(j)->board_id),
+ PCI_DMA_BIDIRECTIONAL);
return FALSE;
}
@@ -706,17 +746,27 @@
};
struct config_1 {
- unsigned char bios_segment: 3;
- unsigned char removable_disks_as_fixed: 1;
- unsigned char interrupt: 2;
- unsigned char dma_channel: 2;
+
+#if defined(__BIG_ENDIAN_BITFIELD)
+ unsigned char dma_channel: 2, interrupt:2,
+ removable_disks_as_fixed:1, bios_segment: 3;
+#else
+ unsigned char bios_segment: 3, removable_disks_as_fixed: 1,
+ interrupt: 2, dma_channel: 2;
+#endif
+
} config_1;
struct config_2 {
- unsigned char ha_scsi_id: 3;
- unsigned char mapping_mode: 2;
- unsigned char bios_drive_number: 1;
- unsigned char tfr_port: 2;
+
+#if defined(__BIG_ENDIAN_BITFIELD)
+ unsigned char tfr_port: 2, bios_drive_number: 1,
+ mapping_mode: 2, ha_scsi_id: 3;
+#else
+ unsigned char ha_scsi_id: 3, mapping_mode: 2,
+ bios_drive_number: 1, tfr_port: 2;
+#endif
+
} config_2;
char name[16];
@@ -812,6 +862,7 @@
HD(j)->heads = mapping_table[config_2.mapping_mode].heads;
HD(j)->sectors = mapping_table[config_2.mapping_mode].sectors;
HD(j)->subversion = subversion;
+ HD(j)->pdev = NULL;
HD(j)->board_number = j;
if (have_old_firmware) sh[j]->sg_tablesize = MAX_SAFE_SGLIST;
@@ -859,6 +910,10 @@
else sprintf(dma_name, "DMA %u", dma_channel);
for (i = 0; i < sh[j]->can_queue; i++)
+ HD(j)->cp[i].cp_dma_addr = pci_map_single(HD(j)->pdev,
+ &HD(j)->cp[i], sizeof(struct mscp), PCI_DMA_BIDIRECTIONAL);
+
+ for (i = 0; i < sh[j]->can_queue; i++)
if (! ((&HD(j)->cp[i])->sglist = kmalloc(
sh[j]->sg_tablesize * sizeof(struct sg_list),
(sh[j]->unchecked_isa_dma ? GFP_DMA : 0) | GFP_ATOMIC))) {
@@ -972,7 +1027,8 @@
}
static inline void map_dma(unsigned int i, unsigned int j) {
- unsigned int k, count, data_len = 0, pci_dir;
+ unsigned int data_len = 0;
+ unsigned int k, count, pci_dir;
struct scatterlist *sgpnt;
struct mscp *cpp;
Scsi_Cmnd *SCpnt;
@@ -988,10 +1044,10 @@
if (!SCpnt->use_sg) {
- if (!SCpnt->request_bufflen)
- cpp->data_address = V2DEV(SCpnt->request_buffer);
+ /* If we get here with PCI_DMA_NONE, pci_map_single triggers a BUG() */
+ if (!SCpnt->request_bufflen) pci_dir = PCI_DMA_BIDIRECTIONAL;
- else if (SCpnt->request_buffer)
+ if (SCpnt->request_buffer)
cpp->data_address = H2DEV(pci_map_single(HD(j)->pdev,
SCpnt->request_buffer, SCpnt->request_bufflen, pci_dir));
@@ -1010,7 +1066,8 @@
cpp->sg = TRUE;
cpp->use_sg = SCpnt->use_sg;
- cpp->data_address = V2DEV(cpp->sglist);
+ cpp->data_address = H2DEV(pci_map_single(HD(j)->pdev, cpp->sglist,
+ SCpnt->use_sg * sizeof(struct sg_list), pci_dir));
cpp->data_len = H2DEV(data_len);
}
@@ -1026,13 +1083,14 @@
pci_unmap_single(HD(j)->pdev, DEV2H(cpp->sense_addr),
DEV2H(cpp->sense_len), PCI_DMA_FROMDEVICE);
- if (SCpnt->use_sg)
+ if (SCpnt->use_sg)
pci_unmap_sg(HD(j)->pdev, SCpnt->request_buffer, SCpnt->use_sg, pci_dir);
- else if (DEV2H(cpp->data_address) && DEV2H(cpp->data_len))
- pci_unmap_single(HD(j)->pdev, DEV2H(cpp->data_address),
- DEV2H(cpp->data_len), pci_dir);
+ if (!DEV2H(cpp->data_len)) pci_dir = PCI_DMA_BIDIRECTIONAL;
+ if (DEV2H(cpp->data_address))
+ pci_unmap_single(HD(j)->pdev, DEV2H(cpp->data_address),
+ DEV2H(cpp->data_len), pci_dir);
}
static void sync_dma(unsigned int i, unsigned int j) {
@@ -1047,14 +1105,15 @@
pci_dma_sync_single(HD(j)->pdev, DEV2H(cpp->sense_addr),
DEV2H(cpp->sense_len), PCI_DMA_FROMDEVICE);
- if (SCpnt->use_sg)
- pci_dma_sync_sg(HD(j)->pdev, SCpnt->request_buffer,
+ if (SCpnt->use_sg)
+ pci_dma_sync_sg(HD(j)->pdev, SCpnt->request_buffer,
SCpnt->use_sg, pci_dir);
- else if (DEV2H(cpp->data_address) && DEV2H(cpp->data_len))
- pci_dma_sync_single(HD(j)->pdev, DEV2H(cpp->data_address),
- DEV2H(cpp->data_len), pci_dir);
+ if (!DEV2H(cpp->data_len)) pci_dir = PCI_DMA_BIDIRECTIONAL;
+ if (DEV2H(cpp->data_address))
+ pci_dma_sync_single(HD(j)->pdev, DEV2H(cpp->data_address),
+ DEV2H(cpp->data_len), pci_dir);
}
static inline void scsi_to_dev_dir(unsigned int i, unsigned int j) {
@@ -1090,7 +1149,7 @@
return;
}
- if (SCpnt->sc_data_direction != SCSI_DATA_UNKNOWN)
+ if (SCpnt->sc_data_direction != SCSI_DATA_UNKNOWN)
panic("%s: qcomm, invalid SCpnt->sc_data_direction.\n", BN(j));
cpp->xdir = DTD_IN;
@@ -1143,7 +1202,7 @@
/* Set pointer to control packet structure */
cpp = &HD(j)->cp[i];
- memset(cpp, 0, sizeof(struct mscp) - sizeof(struct sg_list *));
+ memset(cpp, 0, sizeof(struct mscp) - CP_TAIL_SIZE);
SCpnt->scsi_done = done;
cpp->cpp_index = i;
SCpnt->host_scribble = (unsigned char *) &cpp->cpp_index;
@@ -1182,7 +1241,7 @@
}
/* Store pointer in OGM address bytes */
- outl(V2DEV(cpp), sh[j]->io_port + REG_OGM);
+ outl(H2DEV(cpp->cp_dma_addr), sh[j]->io_port + REG_OGM);
/* Issue OGM interrupt */
outb(CMD_OGM_INTR, sh[j]->io_port + REG_LCL_INTR);
@@ -1592,7 +1651,7 @@
continue;
}
- outl(V2DEV(cpp), sh[j]->io_port + REG_OGM);
+ outl(H2DEV(cpp->cp_dma_addr), sh[j]->io_port + REG_OGM);
outb(CMD_OGM_INTR, sh[j]->io_port + REG_LCL_INTR);
HD(j)->cp_stat[k] = IN_USE;
}
@@ -1630,11 +1689,11 @@
/* Find the mailbox to be serviced on this board */
for (i = 0; i < sh[j]->can_queue; i++)
- if (V2DEV(&(HD(j)->cp[i])) == ret) break;
+ if (H2DEV(HD(j)->cp[i].cp_dma_addr) == ret) break;
if (i >= sh[j]->can_queue)
panic("%s: ihdlr, invalid mscp bus address %p, cp0 %p.\n", BN(j),
- (void *)ret, (void *)V2DEV(HD(j)->cp));
+ (void *)ret, (void *)H2DEV(HD(j)->cp[0].cp_dma_addr));
cpp = &(HD(j)->cp[i]);
spp = cpp;
@@ -1834,6 +1893,10 @@
for (i = 0; i < sh[j]->can_queue; i++)
if ((&HD(j)->cp[i])->sglist) kfree((&HD(j)->cp[i])->sglist);
+ for (i = 0; i < sh[j]->can_queue; i++)
+ pci_unmap_single(HD(j)->pdev, HD(j)->cp[i].cp_dma_addr,
+ sizeof(struct mscp), PCI_DMA_BIDIRECTIONAL);
+
free_irq(sh[j]->irq, &sha[j]);
if (sh[j]->dma_channel != NO_DMA) free_dma(sh[j]->dma_channel);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)