summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm.c46
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm.h9
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm.c46
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm.h9
4 files changed, 82 insertions, 28 deletions
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c
index 636de9ab9c32..02a7612a7efd 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.c
@@ -1,7 +1,7 @@
/*
* Adaptec AIC79xx device driver for Linux.
*
- * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm.c#102 $
+ * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm.c#103 $
*
* --------------------------------------------------------------------------
* Copyright (c) 1994-2000 Justin T. Gibbs.
@@ -2640,6 +2640,7 @@ ahd_linux_dv_target(struct ahd_softc *ahd, u_int target_offset)
AHD_TRANS_GOAL, /*paused*/FALSE);
ahd_unlock(ahd, &s);
timeout = 10 * HZ;
+ targ->flags &= ~AHD_INQ_VALID;
/* FALLTHROUGH */
case AHD_DV_STATE_INQ_VERIFY:
{
@@ -2721,6 +2722,25 @@ ahd_linux_dv_target(struct ahd_softc *ahd, u_int target_offset)
}
out:
+ if ((targ->flags & AHD_INQ_VALID) != 0
+ && ahd_linux_get_device(ahd, devinfo.channel - 'A',
+ devinfo.target, devinfo.lun,
+ /*alloc*/FALSE) == NULL) {
+ /*
+ * The DV state machine failed to configure this device.
+ * This is normal if DV is disabled. Since we have inquiry
+ * data, filter it and use the "optimistic" negotiation
+ * parameters found in the inquiry string.
+ */
+ ahd_linux_filter_inquiry(ahd, &devinfo);
+ if ((targ->flags & (AHD_BASIC_DV|AHD_ENHANCED_DV)) != 0) {
+ ahd_print_devinfo(ahd, &devinfo);
+ printf("DV failed to configure device. "
+ "Please file a bug report against "
+ "this driver.\n");
+ }
+ }
+
if (cmd != NULL)
free(cmd, M_DEVBUF);
@@ -2806,24 +2826,21 @@ ahd_linux_dv_transition(struct ahd_softc *ahd, struct scsi_cmnd *cmd,
break;
}
- if (ahd_linux_user_dv_setting(ahd) == 0) {
- ahd_linux_filter_inquiry(ahd, devinfo);
- AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
+ AHD_SET_DV_STATE(ahd, targ, targ->dv_state+1);
+ targ->flags |= AHD_INQ_VALID;
+ if (ahd_linux_user_dv_setting(ahd) == 0)
break;
- }
spi3data = targ->inq_data->spi3data;
switch (spi3data & SID_SPI_CLOCK_DT_ST) {
default:
case SID_SPI_CLOCK_ST:
/* Assume only basic DV is supported. */
- ahd_linux_filter_inquiry(ahd, devinfo);
- AHD_SET_DV_STATE(ahd, targ,
- AHD_DV_STATE_INQ_VERIFY);
+ targ->flags |= AHD_BASIC_DV;
break;
case SID_SPI_CLOCK_DT:
case SID_SPI_CLOCK_DT_ST:
- AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_REBD);
+ targ->flags |= AHD_ENHANCED_DV;
break;
}
break;
@@ -2919,8 +2936,15 @@ ahd_linux_dv_transition(struct ahd_softc *ahd, struct scsi_cmnd *cmd,
case AHD_DV_STATE_TUR:
switch (status & SS_MASK) {
case SS_NOP:
- AHD_SET_DV_STATE(ahd, targ,
- AHD_DV_STATE_INQ_ASYNC);
+ if ((targ->flags & AHD_BASIC_DV) != 0) {
+ ahd_linux_filter_inquiry(ahd, devinfo);
+ AHD_SET_DV_STATE(ahd, targ,
+ AHD_DV_STATE_INQ_VERIFY);
+ } else if ((targ->flags & AHD_ENHANCED_DV) != 0) {
+ AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_REBD);
+ } else {
+ AHD_SET_DV_STATE(ahd, targ, AHD_DV_STATE_EXIT);
+ }
break;
case SS_RETRY:
case SS_TUR:
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.h b/drivers/scsi/aic7xxx/aic79xx_osm.h
index 2aed30d80a24..5b632e68dd38 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.h
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.h
@@ -36,7 +36,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
- * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm.h#97 $
+ * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm.h#98 $
*
*/
#ifndef _AIC79XX_LINUX_H_
@@ -425,16 +425,19 @@ struct ahd_linux_device {
};
typedef enum {
- AHD_DV_REQUIRED = 0x01
+ AHD_DV_REQUIRED = 0x01,
+ AHD_INQ_VALID = 0x02,
+ AHD_BASIC_DV = 0x04,
+ AHD_ENHANCED_DV = 0x08
} ahd_linux_targ_flags;
/* DV States */
typedef enum {
AHD_DV_STATE_EXIT = 0,
AHD_DV_STATE_INQ_SHORT_ASYNC,
- AHD_DV_STATE_TUR,
AHD_DV_STATE_INQ_ASYNC,
AHD_DV_STATE_INQ_ASYNC_VERIFY,
+ AHD_DV_STATE_TUR,
AHD_DV_STATE_REBD,
AHD_DV_STATE_INQ_VERIFY,
AHD_DV_STATE_WEB,
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c
index 11a830ea8cc6..bc59c7c76123 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c
@@ -1,7 +1,7 @@
/*
* Adaptec AIC7xxx device driver for Linux.
*
- * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm.c#165 $
+ * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm.c#166 $
*
* Copyright (c) 1994 John Aycock
* The University of Calgary Department of Computer Science.
@@ -2492,6 +2492,7 @@ ahc_linux_dv_target(struct ahc_softc *ahc, u_int target_offset)
AHC_TRANS_GOAL, /*paused*/FALSE);
ahc_unlock(ahc, &s);
timeout = 10 * HZ;
+ targ->flags &= ~AHC_INQ_VALID;
/* FALLTHROUGH */
case AHC_DV_STATE_INQ_VERIFY:
{
@@ -2573,6 +2574,25 @@ ahc_linux_dv_target(struct ahc_softc *ahc, u_int target_offset)
}
out:
+ if ((targ->flags & AHC_INQ_VALID) != 0
+ && ahc_linux_get_device(ahc, devinfo.channel - 'A',
+ devinfo.target, devinfo.lun,
+ /*alloc*/FALSE) == NULL) {
+ /*
+ * The DV state machine failed to configure this device.
+ * This is normal if DV is disabled. Since we have inquiry
+ * data, filter it and use the "optimistic" negotiation
+ * parameters found in the inquiry string.
+ */
+ ahc_linux_filter_inquiry(ahc, &devinfo);
+ if ((targ->flags & (AHC_BASIC_DV|AHC_ENHANCED_DV)) != 0) {
+ ahc_print_devinfo(ahc, &devinfo);
+ printf("DV failed to configure device. "
+ "Please file a bug report against "
+ "this driver.\n");
+ }
+ }
+
if (cmd != NULL)
free(cmd, M_DEVBUF);
@@ -2658,24 +2678,21 @@ ahc_linux_dv_transition(struct ahc_softc *ahc, struct scsi_cmnd *cmd,
break;
}
- if (ahc_linux_user_dv_setting(ahc) == 0) {
- ahc_linux_filter_inquiry(ahc, devinfo);
- AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT);
+ AHC_SET_DV_STATE(ahc, targ, targ->dv_state+1);
+ targ->flags |= AHC_INQ_VALID;
+ if (ahc_linux_user_dv_setting(ahc) == 0)
break;
- }
spi3data = targ->inq_data->spi3data;
switch (spi3data & SID_SPI_CLOCK_DT_ST) {
default:
case SID_SPI_CLOCK_ST:
/* Assume only basic DV is supported. */
- ahc_linux_filter_inquiry(ahc, devinfo);
- AHC_SET_DV_STATE(ahc, targ,
- AHC_DV_STATE_INQ_VERIFY);
+ targ->flags |= AHC_BASIC_DV;
break;
case SID_SPI_CLOCK_DT:
case SID_SPI_CLOCK_DT_ST:
- AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_REBD);
+ targ->flags |= AHC_ENHANCED_DV;
break;
}
break;
@@ -2771,8 +2788,15 @@ ahc_linux_dv_transition(struct ahc_softc *ahc, struct scsi_cmnd *cmd,
case AHC_DV_STATE_TUR:
switch (status & SS_MASK) {
case SS_NOP:
- AHC_SET_DV_STATE(ahc, targ,
- AHC_DV_STATE_INQ_ASYNC);
+ if ((targ->flags & AHC_BASIC_DV) != 0) {
+ ahc_linux_filter_inquiry(ahc, devinfo);
+ AHC_SET_DV_STATE(ahc, targ,
+ AHC_DV_STATE_INQ_VERIFY);
+ } else if ((targ->flags & AHC_ENHANCED_DV) != 0) {
+ AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_REBD);
+ } else {
+ AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT);
+ }
break;
case SS_RETRY:
case SS_TUR:
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.h b/drivers/scsi/aic7xxx/aic7xxx_osm.h
index 7c549176292d..5edbdda8bfee 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.h
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.h
@@ -53,7 +53,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
- * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm.h#112 $
+ * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm.h#113 $
*
*/
#ifndef _AIC7XXX_LINUX_H_
@@ -438,16 +438,19 @@ struct ahc_linux_device {
};
typedef enum {
- AHC_DV_REQUIRED = 0x01
+ AHC_DV_REQUIRED = 0x01,
+ AHC_INQ_VALID = 0x02,
+ AHC_BASIC_DV = 0x04,
+ AHC_ENHANCED_DV = 0x08
} ahc_linux_targ_flags;
/* DV States */
typedef enum {
AHC_DV_STATE_EXIT = 0,
AHC_DV_STATE_INQ_SHORT_ASYNC,
- AHC_DV_STATE_TUR,
AHC_DV_STATE_INQ_ASYNC,
AHC_DV_STATE_INQ_ASYNC_VERIFY,
+ AHC_DV_STATE_TUR,
AHC_DV_STATE_REBD,
AHC_DV_STATE_INQ_VERIFY,
AHC_DV_STATE_WEB,