Commit b1b0a996 authored by Justin T. Gibbs's avatar Justin T. Gibbs

Enable highmem_io.

parent b83302d7
......@@ -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_host.h#10 $
* $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_host.h#11 $
*/
#ifndef _AIC79XX_LINUX_HOST_H_
......@@ -68,6 +68,13 @@ int ahd_linux_abort(Scsi_Cmnd *);
# define AIC79XX_BIOSPARAM NULL
#endif
#if defined BLK_BOUNCE_HIGH
#define AIC79XX_TEMPLATE_HIGHMEM_IO \
highmem_io: 1,
#else
#define AIC79XX_TEMPLATE_HIGHMEM_IO
#endif
/*
* Scsi_Host_Template (see hosts.h) for AIC-79xx - some fields
* to do with card config are filled in after the card is detected.
......@@ -88,6 +95,7 @@ int ahd_linux_abort(Scsi_Cmnd *);
cmd_per_lun: 2, /* cmds per lun */\
present: 0, /* number of 7xxx's present */\
unchecked_isa_dma: 0, /* no memory DMA restrictions*/\
AIC79XX_TEMPLATE_HIGHMEM_IO \
use_clustering: ENABLE_CLUSTERING
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
......
/*
* Adaptec AIC79xx device driver for Linux.
*
* $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm.c#90 $
* $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm.c#91 $
*
* --------------------------------------------------------------------------
* Copyright (c) 1994-2000 Justin T. Gibbs.
......@@ -3005,11 +3005,11 @@ ahd_linux_fallback(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
fallback_speed = ahd_linux_calc_speed(width, period+1, offset);
#ifdef AHD_DEBUG
if (ahd_debug & AHD_SHOW_DV) {
#endif
printf("cur_speed= %d, wide_speed= %d, narrow_speed= %d, "
"fallback_speed= %d\n", cur_speed, wide_speed,
narrow_speed, fallback_speed);
}
#endif
if (cur_speed > 160000) {
/*
......
......@@ -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/aic7xxx_host.h#12 $
* $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_host.h#13 $
*/
#ifndef _AIC7XXX_HOST_H_
......@@ -68,6 +68,13 @@ int ahc_linux_abort(Scsi_Cmnd *);
# define AIC7XXX_BIOSPARAM NULL
#endif
#if defined BLK_BOUNCE_HIGH
#define AIC7XXX_TEMPLATE_HIGHMEM_IO \
highmem_io: 1,
#else
#define AIC7XXX_TEMPLATE_HIGHMEM_IO
#endif
/*
* Scsi_Host_Template (see hosts.h) for AIC-7xxx - some fields
* to do with card config are filled in after the card is detected.
......@@ -88,6 +95,7 @@ int ahc_linux_abort(Scsi_Cmnd *);
cmd_per_lun: 2, /* cmds per lun */\
present: 0, /* number of 7xxx's present */\
unchecked_isa_dma: 0, /* no memory DMA restrictions*/\
AIC7XXX_TEMPLATE_HIGHMEM_IO \
use_clustering: ENABLE_CLUSTERING
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
......
/*
* Adaptec AIC7xxx device driver for Linux.
*
* $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm.c#158 $
* $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm.c#159 $
*
* Copyright (c) 1994 John Aycock
* The University of Calgary Department of Computer Science.
......@@ -2592,592 +2592,6 @@ ahc_linux_dv_transition(struct ahc_softc *ahc, struct scsi_cmnd *cmd,
}
}
#if 0
static void
ahc_linux_dv_target(struct ahc_softc *ahc, u_int target_offset)
{
struct ahc_devinfo devinfo;
struct ahc_linux_target *targ;
struct scsi_cmnd *cmd;
struct scsi_sense_data *sense;
uint8_t *buffer;
u_long s;
u_int timeout;
int echo_size;
sense = NULL;
buffer = NULL;
echo_size = 0;
ahc_lock(ahc, &s);
targ = ahc->platform_data->targets[target_offset];
if (targ == NULL || (targ->flags & AHC_DV_REQUIRED) == 0) {
ahc_unlock(ahc, &s);
return;
}
ahc_compile_devinfo(&devinfo,
targ->channel == 0 ? ahc->our_id : ahc->our_id_b,
targ->target, /*lun*/0, targ->channel + 'A',
ROLE_INITIATOR);
#ifdef AHC_DEBUG
if (ahc_debug & AHC_SHOW_DV) {
ahc_print_devinfo(ahc, &devinfo);
printf("Performing DV\n");
}
#endif
ahc_unlock(ahc, &s);
cmd = malloc(sizeof(struct scsi_cmnd), M_DEVBUF, M_WAITOK);
AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_INQ_ASYNC);
while (targ->dv_state != AHC_DV_STATE_EXIT) {
timeout = AHC_LINUX_DV_TIMEOUT;
switch (targ->dv_state) {
case AHC_DV_STATE_INQ_ASYNC:
case AHC_DV_STATE_INQ_ASYNC_VERIFY:
/*
* Set things to async narrow to reduce the
* chance that the INQ will fail.
*/
ahc_lock(ahc, &s);
ahc_set_syncrate(ahc, &devinfo, NULL, 0, 0, 0,
AHC_TRANS_GOAL, /*paused*/FALSE);
ahc_set_width(ahc, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,
AHC_TRANS_GOAL, /*paused*/FALSE);
ahc_unlock(ahc, &s);
timeout = 10 * HZ;
/* FALLTHROUGH */
case AHC_DV_STATE_INQ_VERIFY:
ahc_linux_dv_inq(ahc, cmd, &devinfo, targ);
break;
case AHC_DV_STATE_TUR:
case AHC_DV_STATE_BUSY:
ahc_linux_dv_tur(ahc, cmd, &devinfo);
break;
case AHC_DV_STATE_REBD:
ahc_linux_dv_rebd(ahc, cmd, &devinfo, targ);
break;
case AHC_DV_STATE_WEB:
ahc_linux_dv_web(ahc, cmd, &devinfo, targ);
break;
case AHC_DV_STATE_REB:
ahc_linux_dv_reb(ahc, cmd, &devinfo, targ);
break;
case AHC_DV_STATE_SU:
ahc_linux_dv_su(ahc, cmd, &devinfo, targ);
timeout = 50 * HZ;
break;
default:
ahc_print_devinfo(ahc, &devinfo);
printf("Unknown DV state %d\n", targ->dv_state);
goto out;
}
/* Queue the command and wait for it to complete */
/* Abuse eh_timeout in the scsi_cmnd struct for our purposes */
init_timer(&cmd->eh_timeout);
#ifdef AHC_DEBUG
if ((ahc_debug & AHC_SHOW_MESSAGES) != 0)
/*
* All of the printfs during negotiation
* really slow down the negotiation.
* Add a bit of time just to be safe.
*/
timeout += HZ;
#endif
scsi_add_timer(cmd, timeout, ahc_linux_dv_timeout);
/*
* In 2.5.X, it is assumed that all calls from the
* "midlayer" (which we are emulating) will have the
* ahc host lock held.
*/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
ahc_lock(ahc, &s);
#endif
ahc_linux_queue(cmd, ahc_linux_dv_complete);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
ahc_unlock(ahc, &s);
#endif
down(&ahc->platform_data->dv_cmd_sem);
/*
* Wait for the SIMQ to be released so that DV is the
* only reason the queue is frozen.
*/
ahc_lock(ahc, &s);
while (AHC_DV_SIMQ_FROZEN(ahc) == 0) {
ahc->platform_data->flags |= AHC_DV_WAIT_SIMQ_RELEASE;
ahc_unlock(ahc, &s);
down(&ahc->platform_data->dv_sem);
ahc_lock(ahc, &s);
}
ahc_unlock(ahc, &s);
ahc_linux_dv_transition(ahc, cmd, &devinfo, targ);
}
out:
if (cmd != NULL)
free(cmd, M_DEVBUF);
ahc_lock(ahc, &s);
if (targ->dv_buffer != NULL)
free(targ->dv_buffer, M_DEVBUF);
if (targ->dv_buffer1 != NULL)
free(targ->dv_buffer1, M_DEVBUF);
targ->flags &= ~AHC_DV_REQUIRED;
if (targ->refcount == 0)
ahc_linux_free_target(ahc, targ);
ahc_unlock(ahc, &s);
}
static void
ahc_linux_dv_transition(struct ahc_softc *ahc, struct scsi_cmnd *cmd,
struct ahc_devinfo *devinfo,
struct ahc_linux_target *targ)
{
u_int32_t status;
status = aic_dv_error_action(cmd, targ->inq_data);
#ifdef AHC_DEBUG
if (ahc_debug & AHC_SHOW_DV) {
ahc_print_devinfo(ahc, devinfo);
printf("Entering ahc_linux_dv_transition, state= %d, "
"status= 0x%x, cmd->result= 0x%x\n", targ->dv_state,
status, cmd->result);
}
#endif
switch (targ->dv_state) {
case AHC_DV_STATE_INQ_ASYNC:
switch (status & SS_MASK) {
case SS_NOP:
{
AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_TUR);
break;
}
case SS_INQ_REFRESH:
AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_INQ_ASYNC);
break;
case SS_TUR:
case SS_RETRY:
AHC_SET_DV_STATE(ahc, targ, targ->dv_state);
if (ahc_cmd_get_transaction_status(cmd)
== CAM_REQUEUE_REQ)
targ->dv_state_retry--;
if ((status & SS_ERRMASK) == EBUSY)
AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_BUSY);
if (targ->dv_state_retry < 10)
break;
/* FALLTHROUGH */
default:
AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT);
#ifdef AHC_DEBUG
if (ahc_debug & AHC_SHOW_DV) {
ahc_print_devinfo(ahc, devinfo);
printf("Failed DV inquiry, skipping\n");
}
#endif
break;
}
break;
case AHC_DV_STATE_INQ_ASYNC_VERIFY:
switch (status & SS_MASK) {
case SS_NOP:
{
u_int spi3data;
if (memcmp(targ->inq_data, targ->dv_buffer,
AHC_LINUX_DV_INQ_LEN) != 0) {
/*
* Inquiry data must have changed.
* Try from the top again.
*/
AHC_SET_DV_STATE(ahc, targ,
AHC_DV_STATE_INQ_ASYNC);
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);
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);
break;
case SID_SPI_CLOCK_DT:
case SID_SPI_CLOCK_DT_ST:
AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_REBD);
break;
}
break;
}
case SS_INQ_REFRESH:
AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_INQ_ASYNC);
break;
case SS_TUR:
case SS_RETRY:
AHC_SET_DV_STATE(ahc, targ, targ->dv_state);
if (ahc_cmd_get_transaction_status(cmd)
== CAM_REQUEUE_REQ)
targ->dv_state_retry--;
if ((status & SS_ERRMASK) == EBUSY)
AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_BUSY);
if (targ->dv_state_retry < 10)
break;
/* FALLTHROUGH */
default:
AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT);
#ifdef AHC_DEBUG
if (ahc_debug & AHC_SHOW_DV) {
ahc_print_devinfo(ahc, devinfo);
printf("Failed DV inquiry, skipping\n");
}
#endif
break;
}
break;
case AHC_DV_STATE_INQ_VERIFY:
switch (status & SS_MASK) {
case SS_NOP:
{
if (memcmp(targ->inq_data, targ->dv_buffer,
AHC_LINUX_DV_INQ_LEN) == 0) {
AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT);
break;
}
if (ahc_linux_fallback(ahc, devinfo) != 0) {
AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT);
break;
}
/*
* Do not count "falling back"
* against our retries.
*/
targ->dv_state_retry = 0;
AHC_SET_DV_STATE(ahc, targ, targ->dv_state);
break;
}
case SS_INQ_REFRESH:
AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_INQ_ASYNC);
break;
case SS_TUR:
case SS_RETRY:
AHC_SET_DV_STATE(ahc, targ, targ->dv_state);
if (ahc_cmd_get_transaction_status(cmd)
== CAM_REQUEUE_REQ) {
targ->dv_state_retry--;
} else if ((status & SSQ_FALLBACK) != 0) {
if (ahc_linux_fallback(ahc, devinfo) != 0) {
AHC_SET_DV_STATE(ahc, targ,
AHC_DV_STATE_EXIT);
break;
}
/*
* Do not count "falling back"
* against our retries.
*/
targ->dv_state_retry = 0;
} else if ((status & SS_ERRMASK) == EBUSY)
AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_BUSY);
if (targ->dv_state_retry < 10)
break;
/* FALLTHROUGH */
default:
AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT);
#ifdef AHC_DEBUG
if (ahc_debug & AHC_SHOW_DV) {
ahc_print_devinfo(ahc, devinfo);
printf("Failed DV inquiry, skipping\n");
}
#endif
break;
}
break;
case AHC_DV_STATE_TUR:
switch (status & SS_MASK) {
case SS_NOP:
AHC_SET_DV_STATE(ahc, targ,
AHC_DV_STATE_INQ_ASYNC_VERIFY);
break;
case SS_RETRY:
case SS_TUR:
if ((status & SS_ERRMASK) == EBUSY) {
AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_BUSY);
break;
}
AHC_SET_DV_STATE(ahc, targ, targ->dv_state);
if (ahc_cmd_get_transaction_status(cmd)
== CAM_REQUEUE_REQ) {
targ->dv_state_retry--;
} else if ((status & SSQ_FALLBACK) != 0) {
if (ahc_linux_fallback(ahc, devinfo) != 0) {
AHC_SET_DV_STATE(ahc, targ,
AHC_DV_STATE_EXIT);
break;
}
/*
* Do not count "falling back"
* against our retries.
*/
targ->dv_state_retry = 0;
}
if (targ->dv_state_retry >= 10) {
#ifdef AHC_DEBUG
if (ahc_debug & AHC_SHOW_DV) {
ahc_print_devinfo(ahc, devinfo);
printf("DV TUR reties exhausted\n");
}
#endif
AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT);
break;
}
if (status & SSQ_DELAY)
scsi_sleep(1 * HZ);
break;
case SS_START:
AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_SU);
break;
case SS_INQ_REFRESH:
AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_INQ_ASYNC);
break;
default:
AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT);
break;
}
break;
case AHC_DV_STATE_REBD:
switch (status & SS_MASK) {
case SS_NOP:
{
uint32_t echo_size;
AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_WEB);
echo_size = scsi_3btoul(&targ->dv_buffer[1]);
echo_size &= 0x1FFF;
#ifdef AHC_DEBUG
if (ahc_debug & AHC_SHOW_DV) {
ahc_print_devinfo(ahc, devinfo);
printf("Echo buffer size= %d\n", echo_size);
}
#endif
if (echo_size == 0) {
AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT);
break;
}
/* Generate the buffer pattern */
targ->dv_echo_size = echo_size;
ahc_linux_generate_dv_pattern(targ);
/*
* Setup initial negotiation values.
*/
ahc_linux_filter_inquiry(ahc, devinfo);
break;
}
case SS_INQ_REFRESH:
AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_INQ_ASYNC);
break;
case SS_RETRY:
AHC_SET_DV_STATE(ahc, targ, targ->dv_state);
if (ahc_cmd_get_transaction_status(cmd)
== CAM_REQUEUE_REQ)
targ->dv_state_retry--;
if (targ->dv_state_retry <= 10)
break;
#ifdef AHC_DEBUG
if (ahc_debug & AHC_SHOW_DV) {
ahc_print_devinfo(ahc, devinfo);
printf("DV REBD reties exhausted\n");
}
#endif
/* FALLTHROUGH */
case SS_FATAL:
default:
/*
* Setup initial negotiation values
* and try level 1 DV.
*/
ahc_linux_filter_inquiry(ahc, devinfo);
AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_INQ_VERIFY);
targ->dv_echo_size = 0;
break;
}
break;
case AHC_DV_STATE_WEB:
switch (status & SS_MASK) {
case SS_NOP:
AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_REB);
break;
case SS_INQ_REFRESH:
AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_INQ_ASYNC);
break;
case SS_RETRY:
AHC_SET_DV_STATE(ahc, targ, targ->dv_state);
if (ahc_cmd_get_transaction_status(cmd)
== CAM_REQUEUE_REQ) {
targ->dv_state_retry--;
} else if ((status & SSQ_FALLBACK) != 0) {
if (ahc_linux_fallback(ahc, devinfo) != 0) {
AHC_SET_DV_STATE(ahc, targ,
AHC_DV_STATE_EXIT);
break;
}
/*
* Do not count "falling back"
* against our retries.
*/
targ->dv_state_retry = 0;
}
if (targ->dv_state_retry <= 10)
break;
/* FALLTHROUGH */
#ifdef AHC_DEBUG
if (ahc_debug & AHC_SHOW_DV) {
ahc_print_devinfo(ahc, devinfo);
printf("DV WEB reties exhausted\n");
}
#endif
default:
AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT);
break;
}
break;
case AHC_DV_STATE_REB:
switch (status & SS_MASK) {
case SS_NOP:
if (memcmp(targ->dv_buffer, targ->dv_buffer1,
targ->dv_echo_size) != 0) {
if (ahc_linux_fallback(ahc, devinfo) != 0)
AHC_SET_DV_STATE(ahc, targ,
AHC_DV_STATE_EXIT);
else
AHC_SET_DV_STATE(ahc, targ,
AHC_DV_STATE_WEB);
break;
}
if (targ->dv_buffer != NULL) {
free(targ->dv_buffer, M_DEVBUF);
targ->dv_buffer = NULL;
}
if (targ->dv_buffer1 != NULL) {
free(targ->dv_buffer1, M_DEVBUF);
targ->dv_buffer1 = NULL;
}
AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT);
break;
case SS_INQ_REFRESH:
AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_INQ_ASYNC);
break;
case SS_RETRY:
AHC_SET_DV_STATE(ahc, targ, targ->dv_state);
if (ahc_cmd_get_transaction_status(cmd)
== CAM_REQUEUE_REQ) {
targ->dv_state_retry--;
} else if ((status & SSQ_FALLBACK) != 0) {
if (ahc_linux_fallback(ahc, devinfo) != 0) {
AHC_SET_DV_STATE(ahc, targ,
AHC_DV_STATE_EXIT);
break;
}
/*
* Do not count "falling back"
* against our retries.
*/
targ->dv_state_retry = 0;
}
if (targ->dv_state_retry <= 10) {
if ((status & (SSQ_DELAY_RANDOM|SSQ_DELAY))!= 0)
scsi_sleep(devinfo->our_scsiid*HZ/10);
break;
}
#ifdef AHC_DEBUG
if (ahc_debug & AHC_SHOW_DV) {
ahc_print_devinfo(ahc, devinfo);
printf("DV REB reties exhausted\n");
}
#endif
/* FALLTHROUGH */
default:
AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT);
break;
}
break;
case AHC_DV_STATE_SU:
switch (status & SS_MASK) {
case SS_NOP:
case SS_INQ_REFRESH:
AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_INQ_ASYNC);
break;
default:
AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT);
break;
}
break;
case AHC_DV_STATE_BUSY:
switch (status & SS_MASK) {
case SS_NOP:
case SS_INQ_REFRESH:
AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_INQ_ASYNC);
break;
case SS_TUR:
case SS_RETRY:
AHC_SET_DV_STATE(ahc, targ, targ->dv_state);
if (ahc_cmd_get_transaction_status(cmd)
== CAM_REQUEUE_REQ) {
targ->dv_state_retry--;
} else if (targ->dv_state_retry < 60) {
if ((status & SSQ_DELAY) != 0)
scsi_sleep(1 * HZ);
} else {
#ifdef AHC_DEBUG
if (ahc_debug & AHC_SHOW_DV) {
ahc_print_devinfo(ahc, devinfo);
printf("DV BUSY reties exhausted\n");
}
#endif
AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT);
}
break;
default:
AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT);
break;
}
break;
default:
printf("%s: Invalid DV completion state %d\n", ahc_name(ahc),
targ->dv_state);
AHC_SET_DV_STATE(ahc, targ, AHC_DV_STATE_EXIT);
break;
}
}
#endif
static uint32_t
aic_dv_error_action(struct scsi_cmnd *cmd, struct scsi_inquiry_data *inq_data)
{
......@@ -3317,46 +2731,6 @@ ahc_linux_dv_inq(struct ahc_softc *ahc, struct scsi_cmnd *cmd,
memset(cmd->request_buffer, 0, AHC_LINUX_DV_INQ_LEN);
}
#if 0
/*
* Synthesize an inquiry command. On the return trip, it'll be
* sniffed and the device transfer settings set for us.
*/
static void
ahc_linux_dv_inq(struct ahc_softc *ahc, struct scsi_cmnd *cmd,
struct ahc_devinfo *devinfo, struct ahc_linux_target *targ)
{
#ifdef AHC_DEBUG
if (ahc_debug & AHC_SHOW_DV) {
ahc_print_devinfo(ahc, devinfo);
printf("Sending INQ\n");
}
#endif
if (targ->inq_data == NULL)
targ->inq_data = malloc(AHC_LINUX_DV_INQ_LEN,
M_DEVBUF, M_WAITOK);
if (targ->dv_state != AHC_DV_STATE_INQ_ASYNC) {
if (targ->dv_buffer != NULL)
free(targ->dv_buffer, M_DEVBUF);
targ->dv_buffer = malloc(AHC_LINUX_DV_INQ_LEN,
M_DEVBUF, M_WAITOK);
}
ahc_linux_dv_fill_cmd(ahc, cmd, devinfo);
cmd->sc_data_direction = SCSI_DATA_READ;
cmd->cmd_len = 6;
cmd->cmnd[0] = INQUIRY;
cmd->cmnd[4] = AHC_LINUX_DV_INQ_LEN;
cmd->request_bufflen = AHC_LINUX_DV_INQ_LEN;
if (targ->dv_state != AHC_DV_STATE_INQ_ASYNC)
cmd->request_buffer = targ->dv_buffer;
else
cmd->request_buffer = targ->inq_data;
memset(cmd->request_buffer, 0, AHC_LINUX_DV_INQ_LEN);
}
#endif
static void
ahc_linux_dv_tur(struct ahc_softc *ahc, struct scsi_cmnd *cmd,
struct ahc_devinfo *devinfo)
......@@ -3540,11 +2914,11 @@ ahc_linux_fallback(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
fallback_speed = ahc_linux_calc_speed(width, period+1, offset);
#ifdef AHC_DEBUG
if (ahc_debug & AHC_SHOW_DV) {
#endif
printf("cur_speed= %d, wide_speed= %d, narrow_speed= %d, "
"fallback_speed= %d\n", cur_speed, wide_speed,
narrow_speed, fallback_speed);
}
#endif
if (cur_speed > 160000) {
/*
......@@ -3662,179 +3036,6 @@ ahc_linux_fallback(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
return (0);
}
#if 0
static int
ahc_linux_fallback(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
{
struct ahc_linux_target *targ;
struct ahc_initiator_tinfo *tinfo;
struct ahc_transinfo *goal;
struct ahc_tmode_tstate *tstate;
struct ahc_syncrate *syncrate;
u_long s;
u_int width;
u_int period;
u_int offset;
u_int ppr_options;
u_int cur_speed;
u_int wide_speed;
u_int narrow_speed;
u_int fallback_speed;
#ifdef AHC_DEBUG
if (ahc_debug & AHC_SHOW_DV) {
ahc_print_devinfo(ahc, devinfo);
printf("Trying to fallback\n");
}
#endif
ahc_lock(ahc, &s);
targ = ahc->platform_data->targets[devinfo->target_offset];
tinfo = ahc_fetch_transinfo(ahc, devinfo->channel,
devinfo->our_scsiid,
devinfo->target, &tstate);
goal = &tinfo->goal;
width = goal->width;
period = goal->period;
offset = goal->offset;
ppr_options = goal->ppr_options;
if (offset == 0)
period = AHC_ASYNC_XFER_PERIOD;
if (targ->dv_next_narrow_period == 0)
targ->dv_next_narrow_period = MAX(period, AHC_SYNCRATE_ULTRA2);
if (targ->dv_next_wide_period == 0)
targ->dv_next_wide_period = period;
if (targ->dv_max_ppr_options == 0)
targ->dv_max_ppr_options = ppr_options;
if (targ->dv_last_ppr_options == 0)
targ->dv_last_ppr_options = ppr_options;
cur_speed = ahc_linux_calc_speed(width, period, offset);
wide_speed = ahc_linux_calc_speed(MSG_EXT_WDTR_BUS_16_BIT,
targ->dv_next_wide_period,
MAX_OFFSET);
narrow_speed = ahc_linux_calc_speed(MSG_EXT_WDTR_BUS_8_BIT,
targ->dv_next_narrow_period,
MAX_OFFSET);
fallback_speed = ahc_linux_calc_speed(width, period+1, offset);
#ifdef AHC_DEBUG
if (ahc_debug & AHC_SHOW_DV) {
printf("cur_speed= %d, wide_speed= %d, narrow_speed= %d, "
"fallback_speed= %d\n", cur_speed, wide_speed,
narrow_speed, fallback_speed);
}
#endif
if (cur_speed > 160000) {
/*
* Paced/DT/IU_REQ only transfer speeds. All we
* can do is fallback in terms of syncrate.
*/
period++;
} else if (cur_speed > 80000) {
if ((ppr_options & MSG_EXT_PPR_IU_REQ) != 0) {
/*
* Try without IU_REQ as it may be confusing
* an expander.
*/
ppr_options &= ~MSG_EXT_PPR_IU_REQ;
} else {
/*
* Paced/DT only transfer speeds. All we
* can do is fallback in terms of syncrate.
*/
period++;
ppr_options = targ->dv_max_ppr_options;
}
} else if (cur_speed > 3300) {
/*
* In this range we the following
* options ordered from highest to
* lowest desireability:
*
* o Wide/DT
* o Wide/non-DT
* o Narrow at a potentally higher sync rate.
*
* All modes are tested with and without IU_REQ
* set since using IUs may confuse an expander.
*/
if ((ppr_options & MSG_EXT_PPR_IU_REQ) != 0) {
ppr_options &= ~MSG_EXT_PPR_IU_REQ;
} else if ((ppr_options & MSG_EXT_PPR_DT_REQ) != 0) {
/*
* Try going non-DT. We also disable QAS
* since we may need a non-PPR message to
* work with an expander.
*/
ppr_options = targ->dv_max_ppr_options;
ppr_options &=
~(MSG_EXT_PPR_DT_REQ|MSG_EXT_PPR_QAS_REQ);
} else if (width == MSG_EXT_WDTR_BUS_16_BIT) {
/*
* If the next narrow speed is greater than
* the next wide speed, fallback to narrow.
* Otherwise fallback to the next DT/Wide setting.
* The narrow async speed will always be smaller
* than the wide async speed, so handle this case
* specifically.
*/
ppr_options = targ->dv_max_ppr_options;
if (narrow_speed > fallback_speed
|| period >= AHC_ASYNC_XFER_PERIOD) {
targ->dv_next_wide_period = period+1;
width = MSG_EXT_WDTR_BUS_8_BIT;
period = targ->dv_next_narrow_period;
} else {
period++;
}
} else if ((ahc->features & AHC_WIDE) != 0
&& tinfo->user.width != 0
&& wide_speed >= fallback_speed
&& (targ->dv_next_wide_period <= AHC_ASYNC_XFER_PERIOD
|| period >= AHC_ASYNC_XFER_PERIOD)) {
/*
* We are narrow. Try falling back
* to the next wide speed with
* all supported ppr options set.
*/
targ->dv_next_narrow_period = period+1;
width = MSG_EXT_WDTR_BUS_16_BIT;
period = targ->dv_next_wide_period;
ppr_options = targ->dv_max_ppr_options;
} else {
/* Only narrow fallback is allowed. */
period++;
ppr_options = targ->dv_max_ppr_options;
}
} else {
ahc_unlock(ahc, &s);
return (-1);
}
offset = MAX_OFFSET;
syncrate = ahc_find_syncrate(ahc, &period, &ppr_options,
AHC_SYNCRATE_DT);
ahc_set_width(ahc, devinfo, width, AHC_TRANS_GOAL, FALSE);
if (period == 0) {
period = 0;
offset = 0;
ppr_options = 0;
if (width == MSG_EXT_WDTR_BUS_8_BIT)
targ->dv_next_narrow_period = AHC_ASYNC_XFER_PERIOD;
else
targ->dv_next_wide_period = AHC_ASYNC_XFER_PERIOD;
} else
period = syncrate->period;
ahc_set_syncrate(ahc, devinfo, syncrate, period, offset,
ppr_options, AHC_TRANS_GOAL, FALSE);
ahc_unlock(ahc, &s);
return (0);
}
#endif
static void
ahc_linux_dv_timeout(struct scsi_cmnd *cmd)
{
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment