patch-2.2.14 linux/drivers/scsi/ips.c
Next file: linux/drivers/scsi/ips.h
Previous file: linux/drivers/scsi/in2000.h
Back to the patch index
Back to the overall index
- Lines: 238
- Date:
Tue Jan 4 10:12:20 2000
- Orig file:
v2.2.13/linux/drivers/scsi/ips.c
- Orig date:
Tue Jan 4 11:10:38 2000
diff -u --recursive --new-file v2.2.13/linux/drivers/scsi/ips.c linux/drivers/scsi/ips.c
@@ -60,6 +60,12 @@
/* 0.99.05 - Fix an oops when we get certain passthru commands */
/* 1.00.00 - Initial Public Release */
/* Functionally equivalent to 0.99.05 */
+/* 3.60.00 - Bump max commands to 128 for use with ServeRAID firmware 3.60 */
+/* - Change version to 3.60 to coincide with ServeRAID release */
+/* numbering. */
+/* 3.60.01 - Remove bogus error check in passthru routine */
+/* 3.60.02 - Make DCDB direction based on lookup table */
+/* - Only allow one DCDB command to a SCSI ID at a time */
/* */
/*****************************************************************************/
@@ -111,8 +117,8 @@
/*
* DRIVER_VER
*/
-#define IPS_VERSION_HIGH "1.00" /* MUST be 4 chars */
-#define IPS_VERSION_LOW ".00 " /* MUST be 4 chars */
+#define IPS_VERSION_HIGH "3.60" /* MUST be 4 chars */
+#define IPS_VERSION_LOW ".02 " /* MUST be 4 chars */
struct proc_dir_entry proc_scsi_ips = {
#if !defined(PROC_SCSI_IPS)
@@ -170,6 +176,63 @@
};
/*
+ * Direction table
+ */
+static char ips_command_direction[] = {
+IPS_DATA_NONE, IPS_DATA_NONE, IPS_DATA_IN, IPS_DATA_IN, IPS_DATA_OUT,
+IPS_DATA_IN, IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_IN, IPS_DATA_UNK,
+IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_IN, IPS_DATA_NONE, IPS_DATA_IN, IPS_DATA_IN, IPS_DATA_OUT,
+IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_NONE, IPS_DATA_NONE, IPS_DATA_OUT,
+IPS_DATA_NONE, IPS_DATA_IN, IPS_DATA_NONE, IPS_DATA_IN, IPS_DATA_OUT,
+IPS_DATA_NONE, IPS_DATA_UNK, IPS_DATA_IN, IPS_DATA_UNK, IPS_DATA_IN,
+IPS_DATA_UNK, IPS_DATA_OUT, IPS_DATA_IN, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_IN, IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_NONE, IPS_DATA_UNK,
+IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_OUT,
+IPS_DATA_OUT, IPS_DATA_NONE, IPS_DATA_IN, IPS_DATA_NONE, IPS_DATA_NONE,
+IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_OUT,
+IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_OUT,
+IPS_DATA_OUT, IPS_DATA_IN, IPS_DATA_IN, IPS_DATA_IN, IPS_DATA_NONE,
+IPS_DATA_UNK, IPS_DATA_NONE, IPS_DATA_NONE, IPS_DATA_NONE, IPS_DATA_UNK,
+IPS_DATA_NONE, IPS_DATA_OUT, IPS_DATA_IN, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_OUT, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_IN, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_NONE, IPS_DATA_NONE, IPS_DATA_UNK, IPS_DATA_IN, IPS_DATA_NONE,
+IPS_DATA_OUT, IPS_DATA_UNK, IPS_DATA_NONE, IPS_DATA_UNK, IPS_DATA_OUT,
+IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_OUT, IPS_DATA_NONE,
+IPS_DATA_UNK, IPS_DATA_IN, IPS_DATA_OUT, IPS_DATA_IN, IPS_DATA_IN,
+IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_OUT,
+IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK,
+IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK
+};
+
+/*
* Function prototypes
*/
int ips_detect(Scsi_Host_Template *);
@@ -1351,7 +1414,7 @@
(scb->cmd.basic_io.op_code == DIRECT_CDB_SCATTER_GATHER))
return (0);
- if (pt->CmdBSize && pt->CmdBuffer) {
+ if (pt->CmdBSize) {
scb->data_busaddr = VIRT_TO_BUS(scb->scsi_cmd->request_buffer + sizeof(ips_passthru_t));
} else {
scb->data_busaddr = 0L;
@@ -1675,8 +1738,10 @@
/* set controller IDs */
ha->ha_id[0] = IPS_ADAPTER_ID;
- for (i = 1; i < ha->nbus; i++)
+ for (i = 1; i < ha->nbus; i++) {
ha->ha_id[i] = ha->conf->init_id[i-1] & 0x1f;
+ ha->dcdb_active[i-1] = 0;
+ }
return (1);
}
@@ -1696,6 +1761,7 @@
ips_next(ips_ha_t *ha) {
ips_scb_t *scb;
Scsi_Cmnd *SC;
+ Scsi_Cmnd *p;
int ret;
DBG("ips_next");
@@ -1768,9 +1834,15 @@
/*
* Send "Normal" I/O commands
*/
- while ((ha->scb_waitlist.head) &&
- (scb = ips_getscb(ha))) {
- SC = ips_removeq_wait_head(&ha->scb_waitlist);
+ p = ha->scb_waitlist.head;
+ while ((p) && (scb = ips_getscb(ha))) {
+ if ((p->channel > 0) && (ha->dcdb_active[p->channel-1] & (1 << p->target))) {
+ ips_freescb(ha, scb);
+ p = (Scsi_Cmnd *) p->host_scribble;
+ continue;
+ }
+
+ SC = ips_removeq_wait(&ha->scb_waitlist, p);
SC->result = DID_OK;
SC->host_scribble = NULL;
@@ -1785,7 +1857,7 @@
scb->data_len = 0;
scb->callback = ipsintr_done;
scb->timeout = ips_cmd_timeout;
- memset(&scb->cmd, 0, 4);
+ memset(&scb->cmd, 0, 16);
/* copy in the CDB */
memcpy(scb->cdb, SC->cmnd, SC->cmd_len);
@@ -1843,11 +1915,11 @@
}
- if ((scb->scsi_cmd->request.cmd == READ) && (SC->request_bufflen))
- scb->dcdb.cmd_attribute |= DATA_IN;
+ scb->dcdb.cmd_attribute |=
+ ips_command_direction[scb->scsi_cmd->cmnd[0]];
- if ((scb->scsi_cmd->request.cmd == WRITE) && (SC->request_bufflen))
- scb->dcdb.cmd_attribute |= DATA_OUT;
+ if (!scb->dcdb.cmd_attribute & 0x3)
+ scb->dcdb.transfer_length = 0;
if (scb->data_len >= IPS_MAX_XFER) {
scb->dcdb.cmd_attribute |= TRANSFER_64K;
@@ -1866,16 +1938,25 @@
scb->scsi_cmd->scsi_done(scb->scsi_cmd);
}
+ if (scb->bus)
+ ha->dcdb_active[scb->bus-1] &= ~(1 << scb->target_id);
+
ips_freescb(ha, scb);
break;
case IPS_SUCCESS_IMM:
if (scb->scsi_cmd)
scb->scsi_cmd->scsi_done(scb->scsi_cmd);
+
+ if (scb->bus)
+ ha->dcdb_active[scb->bus-1] &= ~(1 << scb->target_id);
+
ips_freescb(ha, scb);
break;
default:
break;
} /* end case */
+
+ p = (Scsi_Cmnd *) p->host_scribble;
} /* end while */
}
@@ -2277,11 +2358,11 @@
scb->sg_len = 0;
}
- if ((scb->scsi_cmd->request.cmd == READ) && (scb->data_len))
- scb->dcdb.cmd_attribute |= DATA_IN;
+ scb->dcdb.cmd_attribute |=
+ ips_command_direction[scb->scsi_cmd->cmnd[0]];
- if ((scb->scsi_cmd->request.cmd == WRITE) && (scb->data_len))
- scb->dcdb.cmd_attribute |= DATA_OUT;
+ if (!scb->dcdb.cmd_attribute & 0x3)
+ scb->dcdb.transfer_length = 0;
if (scb->data_len >= IPS_MAX_XFER) {
scb->dcdb.cmd_attribute |= TRANSFER_64K;
@@ -2317,6 +2398,9 @@
} /* end if passthru */
#endif
+ if (scb->bus)
+ ha->dcdb_active[scb->bus-1] &= ~(1 << scb->target_id);
+
/* call back to SCSI layer */
scb->scsi_cmd->scsi_done(scb->scsi_cmd);
ips_freescb(ha, scb);
@@ -2341,6 +2425,16 @@
DBG("ips_map_status");
if (scb->bus) {
+#if IPS_DEBUG >= 10
+ printk(KERN_NOTICE "(%s) Physical device error: %x %x, Sense Key: %x, ASC: %x, ASCQ: %x\n",
+ ips_name,
+ scb->basic_status,
+ scb->extended_status,
+ scb->dcdb.sense_info[2] & 0xf,
+ scb->dcdb.sense_info[12],
+ scb->dcdb.sense_info[13]);
+#endif
+
/* copy SCSI status and sense data for DCDB commands */
memcpy(scb->scsi_cmd->sense_buffer, scb->dcdb.sense_info,
sizeof(scb->scsi_cmd->sense_buffer));
@@ -2687,6 +2781,7 @@
else
scb->cmd.dcdb.op_code = DIRECT_CDB_SCATTER_GATHER;
+ ha->dcdb_active[scb->bus-1] |= (1 << scb->target_id);
scb->cmd.dcdb.command_id = IPS_COMMAND_ID(ha, scb);
scb->cmd.dcdb.dcdb_address = VIRT_TO_BUS(&scb->dcdb);
scb->cmd.dcdb.reserved = 0;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)