diff options
| -rw-r--r-- | drivers/scsi/aic7xxx/aic79xx_osm.c | 46 | ||||
| -rw-r--r-- | drivers/scsi/aic7xxx/aic79xx_osm.h | 9 | ||||
| -rw-r--r-- | drivers/scsi/aic7xxx/aic7xxx_osm.c | 46 | ||||
| -rw-r--r-- | drivers/scsi/aic7xxx/aic7xxx_osm.h | 9 |
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, |
