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;
#define INITIATOR_WILDCARD (~0)
#define SCB_LIST_NULL 0xFF00
#define SCB_LIST_NULL_LE (ahd_htole16(SCB_LIST_NULL))
#define QOUTFIFO_ENTRY_VALID 0x8000
#define QOUTFIFO_ENTRY_VALID_LE (ahd_htole16(0x8000))
#define QOUTFIFO_ENTRY_VALID 0x80
#define SCBID_IS_NULL(scbid) (((scbid) & 0xFF00 ) == SCB_LIST_NULL)
#define SCSIID_TARGET(ahd, scsiid) \
......@@ -1053,6 +1052,13 @@ typedef uint8_t ahd_mode_state;
typedef void ahd_callback_t (void *);
struct ahd_completion
{
uint16_t tag;
uint8_t sg_status;
uint8_t valid_tag;
};
struct ahd_softc {
bus_space_tag_t tags[2];
bus_space_handle_t bshs[2];
......@@ -1142,11 +1148,11 @@ struct ahd_softc {
struct seeprom_config *seep_config;
/* Command Queues */
struct ahd_completion *qoutfifo;
uint16_t qoutfifonext;
uint16_t qoutfifonext_valid_tag;
uint16_t qinfifonext;
uint16_t qinfifo[AHD_SCB_MAX];
uint16_t *qoutfifo;
/*
* Our qfreeze count. The sequencer compares
......
......@@ -39,7 +39,7 @@
*
* $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
......@@ -65,13 +65,6 @@ VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#70 $"
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) \
if ((ahd->bugs & AHD_SET_MODE_BUG) != 0) { \
mov mode call set_mode_work_around; \
......@@ -1199,7 +1192,7 @@ register TARGPCISTAT {
/*
* LQ Packet In
* The last LQ Packet received
* The last LQ Packet recieved
*/
register LQIN {
address 0x020
......@@ -3542,10 +3535,34 @@ scratch_ram {
COMPLETE_DMA_SCB_HEAD {
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 {
size 2
}
KERNEL_QFREEZE_COUNT {
size 2
}
/*
* Mode to restore on legacy idle loop exit.
*/
......@@ -3624,6 +3641,17 @@ scratch_ram {
QOUTFIFO_ENTRY_VALID_TAG {
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
* memory. This includes the qoutfifo and target mode
......@@ -3639,17 +3667,6 @@ scratch_ram {
QOUTFIFO_NEXT_ADDR {
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 {
size 1
mask SEND_MSG 0x80
......@@ -3951,6 +3968,7 @@ const SG_PREFETCH_ADDR_MASK download
const SG_SIZEOF download
const PKT_OVERRUN_BUFOFFSET download
const SCB_TRANSFER_SIZE download
const CACHELINE_MASK download
/*
* BIOS SCB offsets
......
This diff is collapsed.
This diff is collapsed.
......@@ -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,
/*offset*/0,
/*len*/AHD_SCB_MAX * sizeof(uint16_t), op);
/*len*/AHD_SCB_MAX * sizeof(struct ahd_completion), op);
}
static __inline void
......@@ -871,8 +871,8 @@ ahd_check_cmdcmpltqueues(struct ahd_softc *ahd)
ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap,
/*offset*/ahd->qoutfifonext * sizeof(*ahd->qoutfifo),
/*len*/sizeof(*ahd->qoutfifo), BUS_DMASYNC_POSTREAD);
if ((ahd->qoutfifo[ahd->qoutfifonext]
& QOUTFIFO_ENTRY_VALID_LE) == ahd->qoutfifonext_valid_tag)
if (ahd->qoutfifo[ahd->qoutfifonext].valid_tag
== ahd->qoutfifonext_valid_tag)
retval |= AHD_RUN_QOUTFIFO;
#ifdef AHD_TARGET_MODE
if ((ahd->flags & AHD_TARGETROLE) != 0
......
......@@ -1468,6 +1468,30 @@ ahd_linux_run_command(struct ahd_softc *ahd, struct ahd_linux_device *dev,
if ((tstate->auto_negotiate & mask) != 0) {
scb->flags |= SCB_AUTO_NEGOTIATE;
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) {
......@@ -2058,6 +2082,7 @@ ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
int paused;
int wait;
int disconnected;
int found;
ahd_mode_state saved_modes;
unsigned long flags;
......@@ -2176,7 +2201,8 @@ ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
last_phase = ahd_inb(ahd, LASTPHASE);
saved_scbptr = ahd_get_scbptr(ahd);
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;
bus_scb = ahd_lookup_scb(ahd, active_scbptr);
......@@ -2194,28 +2220,41 @@ ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
* bus or is in the disconnected state.
*/
saved_scsiid = ahd_inb(ahd, SAVED_SCSIID);
if (last_phase != P_BUSFREE
&& (SCB_GET_TAG(pending_scb) == active_scbptr
if (SCB_GET_TAG(pending_scb) == active_scbptr
|| (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
* and hope that the target responds.
*/
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, 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;
} 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) {
/*
* Actually re-queue this SCB in an attempt
* 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));
pending_scb->hscb->cdb_len = 0;
pending_scb->hscb->task_attribute = 0;
......@@ -2296,12 +2335,13 @@ done:
timer.expires = jiffies + (5 * HZ);
timer.function = ahd_linux_sem_timeout;
add_timer(&timer);
printf("Recovery code sleeping\n");
printf("%s: Recovery code sleeping\n", ahd_name(ahd));
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);
if (ret == 0) {
printf("Timer Expired\n");
printf("%s: Timer Expired (active %d)\n",
ahd_name(ahd), dev->active);
retval = FAILED;
}
}
......
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