patch-2.0.26 linux/drivers/scsi/u14-34f.c
Next file: linux/drivers/scsi/u14-34f.h
Previous file: linux/drivers/scsi/scsi.c
Back to the patch index
Back to the overall index
- Lines: 432
- Date:
Tue Nov 19 16:21:07 1996
- Orig file:
v2.0.25/linux/drivers/scsi/u14-34f.c
- Orig date:
Wed Jul 10 08:05:27 1996
diff -u --recursive --new-file v2.0.25/linux/drivers/scsi/u14-34f.c linux/drivers/scsi/u14-34f.c
@@ -1,6 +1,13 @@
/*
* u14-34f.c - Low-level driver for UltraStor 14F/34F SCSI host adapters.
*
+ * 16 Nov 1996 rev. 2.20 for linux 2.1.10 and 2.0.25
+ * Added multichannel support.
+ *
+ * 27 Sep 1996 rev. 2.12 for linux 2.1.0
+ * Portability cleanups (virtual/bus addressing, little/big endian
+ * support).
+ *
* 09 Jul 1996 rev. 2.11 for linux 2.0.4
* "Data over/under-run" no longer implies a redo on all targets.
* Number of internal retries is now limited.
@@ -157,6 +164,7 @@
#include <linux/ioport.h>
#include <asm/io.h>
#include <asm/system.h>
+#include <asm/byteorder.h>
#include <linux/proc_fs.h>
#include <linux/blk.h>
#include "scsi.h"
@@ -197,6 +205,8 @@
#undef DEBUG_STATISTICS
#undef DEBUG_RESET
+#define MAX_CHANNEL 1
+#define MAX_LUN 8
#define MAX_TARGET 8
#define MAX_IRQ 16
#define MAX_BOARDS 4
@@ -248,9 +258,9 @@
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; /* target SCSI id */
- unsigned char ch_no: 2; /* SCSI channel (always 0 for 14f) */
- unsigned char lun: 3; /* logical unit number */
+ unsigned char target: 3; /* SCSI target id */
+ unsigned char channel: 2; /* SCSI channel number */
+ unsigned char lun: 3; /* SCSI logical unit number */
unsigned int data_address PACKED; /* transfer data pointer */
unsigned int data_len PACKED; /* length in bytes */
unsigned int command_link PACKED; /* for linking command chains */
@@ -266,8 +276,8 @@
Scsi_Cmnd *SCpnt;
struct sg_list {
- unsigned int address; /* Segment Address */
- unsigned int num_bytes; /* Segment Length */
+ unsigned int address; /* Segment Address */
+ unsigned int num_bytes; /* Segment Length */
} sglist[MAX_SGLIST];
unsigned int index; /* cp index */
@@ -283,8 +293,8 @@
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_time_out[MAX_TARGET]; /* N. of timeout errors on target */
- int target_reset[MAX_TARGET]; /* If TRUE redo operation on target */
+ 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 */
unsigned int retries; /* Number of internal retries */
unsigned long last_retried_pid; /* Pid of last retried command */
unsigned char subversion; /* Bus type, either ISA or ESA */
@@ -295,17 +305,31 @@
unsigned char slot;
};
-static struct Scsi_Host * sh[MAX_BOARDS + 1];
-static const char* driver_name = "Ux4F";
+static struct Scsi_Host *sh[MAX_BOARDS + 1];
+static const char *driver_name = "Ux4F";
static unsigned int irqlist[MAX_IRQ], calls[MAX_IRQ];
#define HD(board) ((struct hostdata *) &sh[board]->hostdata)
#define BN(board) (HD(board)->board_name)
+#if defined(__BIG_ENDIAN)
+#define H2DEV(x) ((unsigned long)( \
+ (((unsigned long)(x) & 0x000000ffU) << 24) | \
+ (((unsigned long)(x) & 0x0000ff00U) << 8) | \
+ (((unsigned long)(x) & 0x00ff0000U) >> 8) | \
+ (((unsigned long)(x) & 0xff000000U) >> 24)))
+#else
+#define H2DEV(x) (x)
+#endif
+
+#define DEV2H(x) H2DEV(x)
+#define V2DEV(addr) ((addr) ? H2DEV(virt_to_bus((void *)addr)) : 0)
+#define DEV2V(addr) ((addr) ? DEV2H(bus_to_virt((unsigned long)addr)) : 0)
+
static void u14_34f_interrupt_handler(int, void *, struct pt_regs *);
static int do_trace = FALSE;
-static inline unchar wait_on_busy(ushort iobase) {
+static inline int wait_on_busy(unsigned int iobase) {
unsigned int loop = MAXLOOP;
while (inb(iobase + REG_LCL_INTR) & BSY_ASSERTED)
@@ -322,8 +346,8 @@
memset(cpp, 0, sizeof(struct mscp));
cpp->opcode = OP_HOST_ADAPTER;
cpp->xdir = DTD_IN;
- cpp->data_address = (unsigned int) HD(j)->board_id;
- cpp->data_len = sizeof(HD(j)->board_id);
+ cpp->data_address = V2DEV(HD(j)->board_id);
+ cpp->data_len = H2DEV(sizeof(HD(j)->board_id));
cpp->scsi_cdbs_len = 6;
cpp->scsi_cdbs[0] = HA_CMD_INQUIRY;
@@ -338,7 +362,7 @@
outb(CMD_CLR_INTR, sh[j]->io_port + REG_SYS_INTR);
/* Store pointer in OGM address bytes */
- outl((unsigned int)cpp, sh[j]->io_port + REG_OGM);
+ outl(V2DEV(cpp), sh[j]->io_port + REG_OGM);
/* Issue OGM interrupt */
outb(CMD_OGM_INTR, sh[j]->io_port + REG_LCL_INTR);
@@ -357,9 +381,9 @@
return FALSE;
}
-static inline int port_detect(ushort *port_base, unsigned int j,
- Scsi_Host_Template * tpnt) {
- unsigned char irq, dma_channel, subversion;
+static inline int port_detect(unsigned int *port_base, unsigned int j,
+ Scsi_Host_Template *tpnt) {
+ unsigned char irq, dma_channel, subversion, c;
unsigned char in_byte;
/* Allowed BIOS base addresses (NULL indicates reserved) */
@@ -447,6 +471,7 @@
}
sh[j]->io_port = *port_base;
+ sh[j]->unique_id = *port_base;
sh[j]->n_io_port = REGION_SIZE;
sh[j]->base = bios_segment_table[config_1.bios_segment];
sh[j]->irq = irq;
@@ -505,6 +530,10 @@
enable_dma(dma_channel);
}
+ sh[j]->max_channel = MAX_CHANNEL - 1;
+ sh[j]->max_id = MAX_TARGET;
+ sh[j]->max_lun = MAX_LUN;
+
if (HD(j)->subversion == ISA && !board_inquiry(j)) {
HD(j)->board_id[40] = 0;
@@ -519,21 +548,29 @@
printk("%s: PORT 0x%03x, BIOS 0x%05x, IRQ %u, DMA %u, SG %d, "\
"Mbox %d, CmdLun %d, C%d.\n", BN(j), sh[j]->io_port,
- (int)sh[j]->base, sh[j]->irq,
- sh[j]->dma_channel, sh[j]->sg_tablesize,
- sh[j]->can_queue, sh[j]->cmd_per_lun,
+ (int)sh[j]->base, sh[j]->irq, sh[j]->dma_channel,
+ sh[j]->sg_tablesize, sh[j]->can_queue, sh[j]->cmd_per_lun,
sh[j]->hostt->use_clustering);
+
+ if (sh[j]->max_id > 8 || sh[j]->max_lun > 8)
+ printk("%s: wide SCSI support enabled, max_id %u, max_lun %u.\n",
+ BN(j), sh[j]->max_id, sh[j]->max_lun);
+
+ for (c = 0; c <= sh[j]->max_channel; c++)
+ printk("%s: SCSI channel %u enabled, host target ID %u.\n",
+ BN(j), c, sh[j]->this_id);
+
return TRUE;
}
-int u14_34f_detect (Scsi_Host_Template * tpnt) {
+int u14_34f_detect(Scsi_Host_Template *tpnt) {
unsigned int j = 0, k, flags;
- ushort io_port[] = {
+ unsigned int io_port[] = {
0x330, 0x340, 0x230, 0x240, 0x210, 0x130, 0x140, 0x0
};
- ushort *port_base = io_port;
+ unsigned int *port_base = io_port;
tpnt->proc_dir = &proc_scsi_u14_34f;
@@ -563,19 +600,19 @@
static inline void build_sg_list(struct mscp *cpp, Scsi_Cmnd *SCpnt) {
unsigned int k, data_len = 0;
- struct scatterlist * sgpnt;
+ struct scatterlist *sgpnt;
sgpnt = (struct scatterlist *) SCpnt->request_buffer;
for (k = 0; k < SCpnt->use_sg; k++) {
- cpp->sglist[k].address = (unsigned int) sgpnt[k].address;
- cpp->sglist[k].num_bytes = sgpnt[k].length;
+ cpp->sglist[k].address = V2DEV(sgpnt[k].address);
+ cpp->sglist[k].num_bytes = H2DEV(sgpnt[k].length);
data_len += sgpnt[k].length;
}
cpp->use_sg = SCpnt->use_sg;
- cpp->data_address = (unsigned int) cpp->sglist;
- cpp->data_len = data_len;
+ cpp->data_address = V2DEV(cpp->sglist);
+ cpp->data_len = H2DEV(data_len);
}
int u14_34f_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
@@ -634,8 +671,9 @@
cpp->index = i;
SCpnt->host_scribble = (unsigned char *) &cpp->index;
- if (do_trace) printk("%s: qcomm, mbox %d, target %d, pid %ld.\n",
- BN(j), i, SCpnt->target, SCpnt->pid);
+ if (do_trace) printk("%s: qcomm, mbox %d, target %d.%d:%d, pid %ld.\n",
+ BN(j), i, SCpnt->channel, SCpnt->target,
+ SCpnt->lun, SCpnt->pid);
cpp->xdir = DTD_IN;
@@ -646,10 +684,11 @@
}
cpp->opcode = OP_SCSI;
+ cpp->channel = SCpnt->channel;
cpp->target = SCpnt->target;
cpp->lun = SCpnt->lun;
cpp->SCpnt = SCpnt;
- cpp->sense_addr = (unsigned int) SCpnt->sense_buffer;
+ cpp->sense_addr = V2DEV(SCpnt->sense_buffer);
cpp->sense_len = sizeof SCpnt->sense_buffer;
if (SCpnt->use_sg) {
@@ -657,8 +696,8 @@
build_sg_list(cpp, SCpnt);
}
else {
- cpp->data_address = (unsigned int)SCpnt->request_buffer;
- cpp->data_len = SCpnt->request_bufflen;
+ cpp->data_address = V2DEV(SCpnt->request_buffer);
+ cpp->data_len = H2DEV(SCpnt->request_bufflen);
}
cpp->scsi_cdbs_len = SCpnt->cmd_len;
@@ -667,15 +706,16 @@
if (wait_on_busy(sh[j]->io_port)) {
SCpnt->result = DID_ERROR << 16;
SCpnt->host_scribble = NULL;
- printk("%s: qcomm, target %d, pid %ld, adapter busy, DID_ERROR, done.\n",
- BN(j), SCpnt->target, SCpnt->pid);
+ printk("%s: qcomm, target %d.%d:%d, pid %ld, adapter busy, DID_ERROR,"\
+ " done.\n", BN(j), SCpnt->channel, SCpnt->target, SCpnt->lun,
+ SCpnt->pid);
restore_flags(flags);
done(SCpnt);
return 0;
}
/* Store pointer in OGM address bytes */
- outl((unsigned int)cpp, sh[j]->io_port + REG_OGM);
+ outl(V2DEV(cpp), sh[j]->io_port + REG_OGM);
/* Issue OGM interrupt */
outb(CMD_OGM_INTR, sh[j]->io_port + REG_LCL_INTR);
@@ -693,15 +733,15 @@
j = ((struct hostdata *) SCarg->host->hostdata)->board_number;
if (SCarg->host_scribble == NULL) {
- printk("%s: abort, target %d, pid %ld inactive.\n",
- BN(j), SCarg->target, SCarg->pid);
+ printk("%s: abort, target %d.%d:%d, pid %ld inactive.\n",
+ BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid);
restore_flags(flags);
return SCSI_ABORT_NOT_RUNNING;
}
i = *(unsigned int *)SCarg->host_scribble;
- printk("%s: abort, mbox %d, target %d, pid %ld.\n",
- BN(j), i, SCarg->target, SCarg->pid);
+ printk("%s: abort, mbox %d, target %d.%d:%d, pid %ld.\n",
+ BN(j), i, SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid);
if (i >= sh[j]->can_queue)
panic("%s: abort, invalid SCarg->host_scribble.\n", BN(j));
@@ -744,16 +784,17 @@
panic("%s: abort, mbox %d, invalid cp_stat.\n", BN(j), i);
}
-int u14_34f_reset(Scsi_Cmnd * SCarg, unsigned int reset_flags) {
- unsigned int i, j, flags, time, k, limit = 0;
+int u14_34f_reset(Scsi_Cmnd *SCarg, unsigned int reset_flags) {
+ unsigned int i, j, flags, time, k, c, limit = 0;
int arg_done = FALSE;
Scsi_Cmnd *SCpnt;
save_flags(flags);
cli();
j = ((struct hostdata *) SCarg->host->hostdata)->board_number;
- printk("%s: reset, enter, target %d, pid %ld, reset_flags %u.\n",
- BN(j), SCarg->target, SCarg->pid, reset_flags);
+ printk("%s: reset, enter, target %d.%d:%d, pid %ld, reset_flags %u.\n",
+ BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid,
+ reset_flags);
if (SCarg->host_scribble == NULL)
printk("%s: reset, pid %ld inactive.\n", BN(j), SCarg->pid);
@@ -772,9 +813,11 @@
HD(j)->retries = 0;
- for (k = 0; k < MAX_TARGET; k++) HD(j)->target_reset[k] = TRUE;
-
- for (k = 0; k < MAX_TARGET; k++) HD(j)->target_time_out[k] = 0;
+ for (c = 0; c <= sh[j]->max_channel; c++)
+ for (k = 0; k < sh[j]->max_id; k++) {
+ HD(j)->target_redo[k][c] = TRUE;
+ HD(j)->target_to[k][c] = 0;
+ }
for (i = 0; i < sh[j]->can_queue; i++) {
@@ -859,7 +902,7 @@
}
}
-int u14_34f_biosparam(Disk * disk, kdev_t dev, int * dkinfo) {
+int u14_34f_biosparam(Disk *disk, kdev_t dev, int *dkinfo) {
unsigned int j = 0;
int size = disk->capacity;
@@ -869,9 +912,10 @@
return 0;
}
-static void u14_34f_interrupt_handler(int irq, void *dev_id, struct pt_regs * regs) {
+static void u14_34f_interrupt_handler(int irq, void *dev_id,
+ struct pt_regs *regs) {
Scsi_Cmnd *SCpnt;
- unsigned int i, j, k, flags, status, tstatus, loops, total_loops = 0;
+ unsigned int i, j, k, c, flags, status, tstatus, loops, total_loops = 0;
struct mscp *spp;
save_flags(flags);
@@ -901,7 +945,7 @@
if (do_trace) printk("%s: ihdlr, start service, count %d.\n",
BN(j), HD(j)->iocount);
- spp = (struct mscp *)inl(sh[j]->io_port + REG_ICM);
+ spp = (struct mscp *)DEV2V(inl(sh[j]->io_port + REG_ICM));
/* Clear interrupt pending flag */
outb(CMD_CLR_INTR, sh[j]->io_port + REG_SYS_INTR);
@@ -956,9 +1000,8 @@
status = DID_ERROR << 16;
/* If there was a bus reset, redo operation on each target */
- else if (tstatus != GOOD
- && SCpnt->device->type == TYPE_DISK
- && HD(j)->target_reset[SCpnt->target])
+ else if (tstatus != GOOD && SCpnt->device->type == TYPE_DISK
+ && HD(j)->target_redo[SCpnt->target][SCpnt->channel])
status = DID_BUS_BUSY << 16;
/* Works around a flaw in scsi.c */
@@ -971,26 +1014,27 @@
status = DID_OK << 16;
if (tstatus == GOOD)
- HD(j)->target_reset[SCpnt->target] = FALSE;
+ HD(j)->target_redo[SCpnt->target][SCpnt->channel] = FALSE;
if (spp->target_status && SCpnt->device->type == TYPE_DISK)
- printk("%s: ihdlr, target %d:%d, pid %ld, target_status "\
- "0x%x, sense key 0x%x.\n", BN(j),
- SCpnt->target, SCpnt->lun, SCpnt->pid,
- spp->target_status, SCpnt->sense_buffer[2]);
+ printk("%s: ihdlr, target %d.%d:%d, pid %ld, "\
+ "target_status 0x%x, sense key 0x%x.\n", BN(j),
+ SCpnt->channel, SCpnt->target, SCpnt->lun,
+ SCpnt->pid, spp->target_status,
+ SCpnt->sense_buffer[2]);
- HD(j)->target_time_out[SCpnt->target] = 0;
+ HD(j)->target_to[SCpnt->target][SCpnt->channel] = 0;
if (HD(j)->last_retried_pid == SCpnt->pid) HD(j)->retries = 0;
break;
case ASST: /* Selection Time Out */
- if (HD(j)->target_time_out[SCpnt->target] > 1)
+ if (HD(j)->target_to[SCpnt->target][SCpnt->channel] > 1)
status = DID_ERROR << 16;
else {
status = DID_TIME_OUT << 16;
- HD(j)->target_time_out[SCpnt->target]++;
+ HD(j)->target_to[SCpnt->target][SCpnt->channel]++;
}
break;
@@ -1001,8 +1045,10 @@
case 0x96: /* Illegal SCSI command */
case 0xa3: /* SCSI bus reset error */
- for (k = 0; k < MAX_TARGET; k++)
- HD(j)->target_reset[k] = TRUE;
+ for (c = 0; c <= sh[j]->max_channel; c++)
+ for (k = 0; k < sh[j]->max_id; k++)
+ HD(j)->target_redo[k][c] = TRUE;
+
case 0x92: /* Data over/under-run */
@@ -1042,9 +1088,10 @@
do_trace)
#endif
printk("%s: ihdlr, mbox %2d, err 0x%x:%x,"\
- " target %d:%d, pid %ld, count %d.\n",
+ " target %d.%d:%d, pid %ld, count %d.\n",
BN(j), i, spp->adapter_status, spp->target_status,
- SCpnt->target, SCpnt->lun, SCpnt->pid, HD(j)->iocount);
+ SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid,
+ HD(j)->iocount);
/* Set the command state to inactive */
SCpnt->host_scribble = NULL;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov