Commit 11668bb6 authored by Hannes Reinecke's avatar Hannes Reinecke Committed by James Bottomley

[SCSI] aic79xx: Sequencer update

Update sequencer code to Adaptec version 2.0.12-6.3.9.
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent ba62cd2d
...@@ -75,8 +75,7 @@ struct scb_platform_data; ...@@ -75,8 +75,7 @@ struct scb_platform_data;
#define INITIATOR_WILDCARD (~0) #define INITIATOR_WILDCARD (~0)
#define SCB_LIST_NULL 0xFF00 #define SCB_LIST_NULL 0xFF00
#define SCB_LIST_NULL_LE (ahd_htole16(SCB_LIST_NULL)) #define SCB_LIST_NULL_LE (ahd_htole16(SCB_LIST_NULL))
#define QOUTFIFO_ENTRY_VALID 0x8000 #define QOUTFIFO_ENTRY_VALID 0x80
#define QOUTFIFO_ENTRY_VALID_LE (ahd_htole16(0x8000))
#define SCBID_IS_NULL(scbid) (((scbid) & 0xFF00 ) == SCB_LIST_NULL) #define SCBID_IS_NULL(scbid) (((scbid) & 0xFF00 ) == SCB_LIST_NULL)
#define SCSIID_TARGET(ahd, scsiid) \ #define SCSIID_TARGET(ahd, scsiid) \
...@@ -1053,6 +1052,13 @@ typedef uint8_t ahd_mode_state; ...@@ -1053,6 +1052,13 @@ typedef uint8_t ahd_mode_state;
typedef void ahd_callback_t (void *); typedef void ahd_callback_t (void *);
struct ahd_completion
{
uint16_t tag;
uint8_t sg_status;
uint8_t valid_tag;
};
struct ahd_softc { struct ahd_softc {
bus_space_tag_t tags[2]; bus_space_tag_t tags[2];
bus_space_handle_t bshs[2]; bus_space_handle_t bshs[2];
...@@ -1142,11 +1148,11 @@ struct ahd_softc { ...@@ -1142,11 +1148,11 @@ struct ahd_softc {
struct seeprom_config *seep_config; struct seeprom_config *seep_config;
/* Command Queues */ /* Command Queues */
struct ahd_completion *qoutfifo;
uint16_t qoutfifonext; uint16_t qoutfifonext;
uint16_t qoutfifonext_valid_tag; uint16_t qoutfifonext_valid_tag;
uint16_t qinfifonext; uint16_t qinfifonext;
uint16_t qinfifo[AHD_SCB_MAX]; uint16_t qinfifo[AHD_SCB_MAX];
uint16_t *qoutfifo;
/* /*
* Our qfreeze count. The sequencer compares * Our qfreeze count. The sequencer compares
......
...@@ -39,7 +39,7 @@ ...@@ -39,7 +39,7 @@
* *
* $FreeBSD$ * $FreeBSD$
*/ */
VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#70 $" VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#76 $"
/* /*
* This file is processed by the aic7xxx_asm utility for use in assembling * This file is processed by the aic7xxx_asm utility for use in assembling
...@@ -65,13 +65,6 @@ VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#70 $" ...@@ -65,13 +65,6 @@ VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#70 $"
mvi MODE_PTR, MK_MODE(src, dst); \ mvi MODE_PTR, MK_MODE(src, dst); \
} }
#define TOGGLE_DFF_MODE \
if ((ahd->bugs & AHD_SET_MODE_BUG) != 0) { \
call toggle_dff_mode_work_around; \
} else { \
xor MODE_PTR, MK_MODE(M_DFF1, M_DFF1); \
}
#define RESTORE_MODE(mode) \ #define RESTORE_MODE(mode) \
if ((ahd->bugs & AHD_SET_MODE_BUG) != 0) { \ if ((ahd->bugs & AHD_SET_MODE_BUG) != 0) { \
mov mode call set_mode_work_around; \ mov mode call set_mode_work_around; \
...@@ -1199,7 +1192,7 @@ register TARGPCISTAT { ...@@ -1199,7 +1192,7 @@ register TARGPCISTAT {
/* /*
* LQ Packet In * LQ Packet In
* The last LQ Packet received * The last LQ Packet recieved
*/ */
register LQIN { register LQIN {
address 0x020 address 0x020
...@@ -3542,10 +3535,34 @@ scratch_ram { ...@@ -3542,10 +3535,34 @@ scratch_ram {
COMPLETE_DMA_SCB_HEAD { COMPLETE_DMA_SCB_HEAD {
size 2 size 2
} }
/* Counting semaphore to prevent new select-outs */ /*
* tail of list of SCBs that have
* completed but need to be uploaded
* to the host prior to being completed.
*/
COMPLETE_DMA_SCB_TAIL {
size 2
}
/*
* head of list of SCBs that have
* been uploaded to the host, but cannot
* be completed until the QFREEZE is in
* full effect (i.e. no selections pending).
*/
COMPLETE_ON_QFREEZE_HEAD {
size 2
}
/*
* Counting semaphore to prevent new select-outs
* The queue is frozen so long as the sequencer
* and kernel freeze counts differ.
*/
QFREEZE_COUNT { QFREEZE_COUNT {
size 2 size 2
} }
KERNEL_QFREEZE_COUNT {
size 2
}
/* /*
* Mode to restore on legacy idle loop exit. * Mode to restore on legacy idle loop exit.
*/ */
...@@ -3624,6 +3641,17 @@ scratch_ram { ...@@ -3624,6 +3641,17 @@ scratch_ram {
QOUTFIFO_ENTRY_VALID_TAG { QOUTFIFO_ENTRY_VALID_TAG {
size 1 size 1
} }
/*
* Kernel and sequencer offsets into the queue of
* incoming target mode command descriptors. The
* queue is full when the KERNEL_TQINPOS == TQINPOS.
*/
KERNEL_TQINPOS {
size 1
}
TQINPOS {
size 1
}
/* /*
* Base address of our shared data with the kernel driver in host * Base address of our shared data with the kernel driver in host
* memory. This includes the qoutfifo and target mode * memory. This includes the qoutfifo and target mode
...@@ -3639,17 +3667,6 @@ scratch_ram { ...@@ -3639,17 +3667,6 @@ scratch_ram {
QOUTFIFO_NEXT_ADDR { QOUTFIFO_NEXT_ADDR {
size 4 size 4
} }
/*
* Kernel and sequencer offsets into the queue of
* incoming target mode command descriptors. The
* queue is full when the KERNEL_TQINPOS == TQINPOS.
*/
KERNEL_TQINPOS {
size 1
}
TQINPOS {
size 1
}
ARG_1 { ARG_1 {
size 1 size 1
mask SEND_MSG 0x80 mask SEND_MSG 0x80
...@@ -3951,6 +3968,7 @@ const SG_PREFETCH_ADDR_MASK download ...@@ -3951,6 +3968,7 @@ const SG_PREFETCH_ADDR_MASK download
const SG_SIZEOF download const SG_SIZEOF download
const PKT_OVERRUN_BUFOFFSET download const PKT_OVERRUN_BUFOFFSET download
const SCB_TRANSFER_SIZE download const SCB_TRANSFER_SIZE download
const CACHELINE_MASK download
/* /*
* BIOS SCB offsets * BIOS SCB offsets
......
This diff is collapsed.
This diff is collapsed.
...@@ -839,7 +839,7 @@ ahd_sync_qoutfifo(struct ahd_softc *ahd, int op) ...@@ -839,7 +839,7 @@ ahd_sync_qoutfifo(struct ahd_softc *ahd, int op)
{ {
ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap, ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap,
/*offset*/0, /*offset*/0,
/*len*/AHD_SCB_MAX * sizeof(uint16_t), op); /*len*/AHD_SCB_MAX * sizeof(struct ahd_completion), op);
} }
static __inline void static __inline void
...@@ -871,8 +871,8 @@ ahd_check_cmdcmpltqueues(struct ahd_softc *ahd) ...@@ -871,8 +871,8 @@ ahd_check_cmdcmpltqueues(struct ahd_softc *ahd)
ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap, ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap,
/*offset*/ahd->qoutfifonext * sizeof(*ahd->qoutfifo), /*offset*/ahd->qoutfifonext * sizeof(*ahd->qoutfifo),
/*len*/sizeof(*ahd->qoutfifo), BUS_DMASYNC_POSTREAD); /*len*/sizeof(*ahd->qoutfifo), BUS_DMASYNC_POSTREAD);
if ((ahd->qoutfifo[ahd->qoutfifonext] if (ahd->qoutfifo[ahd->qoutfifonext].valid_tag
& QOUTFIFO_ENTRY_VALID_LE) == ahd->qoutfifonext_valid_tag) == ahd->qoutfifonext_valid_tag)
retval |= AHD_RUN_QOUTFIFO; retval |= AHD_RUN_QOUTFIFO;
#ifdef AHD_TARGET_MODE #ifdef AHD_TARGET_MODE
if ((ahd->flags & AHD_TARGETROLE) != 0 if ((ahd->flags & AHD_TARGETROLE) != 0
......
...@@ -1468,6 +1468,30 @@ ahd_linux_run_command(struct ahd_softc *ahd, struct ahd_linux_device *dev, ...@@ -1468,6 +1468,30 @@ ahd_linux_run_command(struct ahd_softc *ahd, struct ahd_linux_device *dev,
if ((tstate->auto_negotiate & mask) != 0) { if ((tstate->auto_negotiate & mask) != 0) {
scb->flags |= SCB_AUTO_NEGOTIATE; scb->flags |= SCB_AUTO_NEGOTIATE;
scb->hscb->control |= MK_MESSAGE; scb->hscb->control |= MK_MESSAGE;
} else if (cmd->cmnd[0] == INQUIRY
&& (tinfo->curr.offset != 0
|| tinfo->curr.width != MSG_EXT_WDTR_BUS_8_BIT
|| tinfo->curr.ppr_options != 0)
&& (tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ)==0) {
/*
* The SCSI spec requires inquiry
* commands to complete without
* reporting unit attention conditions.
* Because of this, an inquiry command
* that occurs just after a device is
* reset will result in a data phase
* with mismatched negotiated rates.
* The core already forces a renegotiation
* for reset events that are visible to
* our controller or that we initiate,
* but a third party device reset or a
* hot-plug insertion can still cause this
* issue. Therefore, we force a re-negotiation
* for every inquiry command unless we
* are async.
*/
scb->flags |= SCB_NEGOTIATE;
scb->hscb->control |= MK_MESSAGE;
} }
if ((dev->flags & (AHD_DEV_Q_TAGGED|AHD_DEV_Q_BASIC)) != 0) { if ((dev->flags & (AHD_DEV_Q_TAGGED|AHD_DEV_Q_BASIC)) != 0) {
...@@ -2058,6 +2082,7 @@ ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag) ...@@ -2058,6 +2082,7 @@ ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
int paused; int paused;
int wait; int wait;
int disconnected; int disconnected;
int found;
ahd_mode_state saved_modes; ahd_mode_state saved_modes;
unsigned long flags; unsigned long flags;
...@@ -2176,7 +2201,8 @@ ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag) ...@@ -2176,7 +2201,8 @@ ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
last_phase = ahd_inb(ahd, LASTPHASE); last_phase = ahd_inb(ahd, LASTPHASE);
saved_scbptr = ahd_get_scbptr(ahd); saved_scbptr = ahd_get_scbptr(ahd);
active_scbptr = saved_scbptr; active_scbptr = saved_scbptr;
if (disconnected && (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) == 0) { if (disconnected && ((last_phase != P_BUSFREE) ||
(ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) == 0)) {
struct scb *bus_scb; struct scb *bus_scb;
bus_scb = ahd_lookup_scb(ahd, active_scbptr); bus_scb = ahd_lookup_scb(ahd, active_scbptr);
...@@ -2194,28 +2220,41 @@ ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag) ...@@ -2194,28 +2220,41 @@ ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
* bus or is in the disconnected state. * bus or is in the disconnected state.
*/ */
saved_scsiid = ahd_inb(ahd, SAVED_SCSIID); saved_scsiid = ahd_inb(ahd, SAVED_SCSIID);
if (last_phase != P_BUSFREE if (SCB_GET_TAG(pending_scb) == active_scbptr
&& (SCB_GET_TAG(pending_scb) == active_scbptr
|| (flag == SCB_DEVICE_RESET || (flag == SCB_DEVICE_RESET
&& SCSIID_TARGET(ahd, saved_scsiid) == scmd_id(cmd)))) { && SCSIID_TARGET(ahd, saved_scsiid) == scmd_id(cmd))) {
/* /*
* We're active on the bus, so assert ATN * We're active on the bus, so assert ATN
* and hope that the target responds. * and hope that the target responds.
*/ */
pending_scb = ahd_lookup_scb(ahd, active_scbptr); pending_scb = ahd_lookup_scb(ahd, active_scbptr);
pending_scb->flags |= SCB_RECOVERY_SCB|flag; pending_scb->flags |= SCB_RECOVERY_SCB|SCB_DEVICE_RESET;
ahd_outb(ahd, MSG_OUT, HOST_MSG); ahd_outb(ahd, MSG_OUT, HOST_MSG);
ahd_outb(ahd, SCSISIGO, last_phase|ATNO); ahd_outb(ahd, SCSISIGO, last_phase|ATNO);
scmd_printk(KERN_INFO, cmd, "Device is active, asserting ATN\n"); scmd_printk(KERN_INFO, cmd, "BDR message in message buffer\n");
wait = TRUE; wait = TRUE;
} else if (last_phase != P_BUSFREE
&& ahd_inb(ahd, SCSIPHASE) == 0) {
/*
* SCB is not identified, there
* is no pending REQ, and the sequencer
* has not seen a busfree. Looks like
* a stuck connection waiting to
* go busfree. Reset the bus.
*/
found = ahd_reset_channel(ahd, cmd->device->channel + 'A',
/*Initiate Reset*/TRUE);
printf("%s: Issued Channel %c Bus Reset. "
"%d SCBs aborted\n", ahd_name(ahd),
cmd->device->channel + 'A', found);
} else if (disconnected) { } else if (disconnected) {
/* /*
* Actually re-queue this SCB in an attempt * Actually re-queue this SCB in an attempt
* to select the device before it reconnects. * to select the device before it reconnects.
*/ */
pending_scb->flags |= SCB_RECOVERY_SCB|SCB_ABORT; pending_scb->flags |= SCB_RECOVERY_SCB|flag;
ahd_set_scbptr(ahd, SCB_GET_TAG(pending_scb)); ahd_set_scbptr(ahd, SCB_GET_TAG(pending_scb));
pending_scb->hscb->cdb_len = 0; pending_scb->hscb->cdb_len = 0;
pending_scb->hscb->task_attribute = 0; pending_scb->hscb->task_attribute = 0;
...@@ -2296,16 +2335,17 @@ done: ...@@ -2296,16 +2335,17 @@ done:
timer.expires = jiffies + (5 * HZ); timer.expires = jiffies + (5 * HZ);
timer.function = ahd_linux_sem_timeout; timer.function = ahd_linux_sem_timeout;
add_timer(&timer); add_timer(&timer);
printf("Recovery code sleeping\n"); printf("%s: Recovery code sleeping\n", ahd_name(ahd));
down(&ahd->platform_data->eh_sem); down(&ahd->platform_data->eh_sem);
printf("Recovery code awake\n"); printf("%s: Recovery code awake\n", ahd_name(ahd));
ret = del_timer_sync(&timer); ret = del_timer_sync(&timer);
if (ret == 0) { if (ret == 0) {
printf("Timer Expired\n"); printf("%s: Timer Expired (active %d)\n",
ahd_name(ahd), dev->active);
retval = FAILED; retval = FAILED;
} }
} }
ahd_unlock(ahd, &flags); ahd_unlock(ahd, &flags);
return (retval); return (retval);
} }
......
This diff is collapsed.
This diff is collapsed.
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