patch-2.4.9 linux/drivers/scsi/aic7xxx/aic7xxx_inline.h
Next file: linux/drivers/scsi/aic7xxx/aic7xxx_linux.c
Previous file: linux/drivers/scsi/aic7xxx/aic7xxx_93cx6.c
Back to the patch index
Back to the overall index
- Lines: 232
- Date:
Sun Aug 12 10:51:42 2001
- Orig file:
v2.4.8/linux/drivers/scsi/aic7xxx/aic7xxx_inline.h
- Orig date:
Fri May 4 15:16:28 2001
diff -u --recursive --new-file v2.4.8/linux/drivers/scsi/aic7xxx/aic7xxx_inline.h linux/drivers/scsi/aic7xxx/aic7xxx_inline.h
@@ -28,7 +28,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: //depot/src/aic7xxx/aic7xxx_inline.h#21 $
+ * $Id: //depot/src/aic7xxx/aic7xxx_inline.h#27 $
*
* $FreeBSD: src/sys/dev/aic7xxx/aic7xxx_inline.h,v 1.8 2000/11/12 05:19:46 gibbs Exp $
*/
@@ -37,8 +37,8 @@
#define _AIC7XXX_INLINE_H_
/************************* Sequencer Execution Control ************************/
-static __inline int ahc_is_paused(struct ahc_softc *ahc);
static __inline void ahc_pause_bug_fix(struct ahc_softc *ahc);
+static __inline int ahc_is_paused(struct ahc_softc *ahc);
static __inline void ahc_pause(struct ahc_softc *ahc);
static __inline void ahc_unpause(struct ahc_softc *ahc);
@@ -146,6 +146,13 @@
struct ahc_dma_seg *sg);
static __inline uint32_t
ahc_hscb_busaddr(struct ahc_softc *ahc, u_int index);
+static __inline void ahc_sync_scb(struct ahc_softc *ahc,
+ struct scb *scb, int op);
+static __inline void ahc_sync_sglist(struct ahc_softc *ahc,
+ struct scb *scb, int op);
+static __inline uint32_t
+ ahc_targetcmd_offset(struct ahc_softc *ahc,
+ u_int index);
static __inline struct ahc_dma_seg *
ahc_sg_bus_to_virt(struct scb *scb, uint32_t sg_busaddr)
@@ -177,6 +184,33 @@
+ (sizeof(struct hardware_scb) * index));
}
+static __inline void
+ahc_sync_scb(struct ahc_softc *ahc, struct scb *scb, int op)
+{
+ ahc_dmamap_sync(ahc, ahc->scb_data->hscb_dmat,
+ ahc->scb_data->hscb_dmamap,
+ /*offset*/(scb->hscb - ahc->hscbs) * sizeof(*scb->hscb),
+ /*len*/sizeof(*scb->hscb), op);
+}
+
+static __inline void
+ahc_sync_sglist(struct ahc_softc *ahc, struct scb *scb, int op)
+{
+ if (scb->sg_count == 0)
+ return;
+
+ ahc_dmamap_sync(ahc, ahc->scb_data->sg_dmat, scb->sg_map->sg_dmamap,
+ /*offset*/(scb->sg_list - scb->sg_map->sg_vaddr)
+ * sizeof(struct ahc_dma_seg),
+ /*len*/sizeof(struct ahc_dma_seg) * scb->sg_count, op);
+}
+
+static __inline uint32_t
+ahc_targetcmd_offset(struct ahc_softc *ahc, u_int index)
+{
+ return (((uint8_t *)&ahc->targetcmds[index]) - ahc->qoutfifo);
+}
+
/******************************** Debugging ***********************************/
static __inline char *ahc_name(struct ahc_softc *ahc);
@@ -219,8 +253,6 @@
sgptr = ahc_le32toh(scb->hscb->sgptr);
if ((sgptr & SG_RESID_VALID) != 0)
ahc_calc_residual(scb);
- else
- ahc_set_residual(scb, 0);
}
/*
@@ -284,8 +316,13 @@
static __inline struct scb *
ahc_lookup_scb(struct ahc_softc *ahc, u_int tag)
{
- return (ahc->scb_data->scbindex[tag]);
+ struct scb* scb;
+ scb = ahc->scb_data->scbindex[tag];
+ if (scb != NULL)
+ ahc_sync_scb(ahc, scb,
+ BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
+ return (scb);
}
static __inline void
@@ -342,6 +379,14 @@
* Keep a history of SCBs we've downloaded in the qinfifo.
*/
ahc->qinfifo[ahc->qinfifonext++] = scb->hscb->tag;
+
+ /*
+ * Make sure our data is consistant from the
+ * perspective of the adapter.
+ */
+ ahc_sync_scb(ahc, scb, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
+
+ /* Tell the adapter about the newly queued SCB */
if ((ahc->features & AHC_QUEUE_REGS) != 0) {
ahc_outb(ahc, HNSCB_QOFF, ahc->qinfifonext);
} else {
@@ -373,8 +418,31 @@
}
/************************** Interrupt Processing ******************************/
-static __inline u_int ahc_check_cmdcmpltqueues(struct ahc_softc *ahc);
-static __inline void ahc_intr(struct ahc_softc *ahc);
+static __inline void ahc_sync_qoutfifo(struct ahc_softc *ahc, int op);
+static __inline void ahc_sync_tqinfifo(struct ahc_softc *ahc, int op);
+static __inline u_int ahc_check_cmdcmpltqueues(struct ahc_softc *ahc);
+static __inline void ahc_intr(struct ahc_softc *ahc);
+
+static __inline void
+ahc_sync_qoutfifo(struct ahc_softc *ahc, int op)
+{
+ ahc_dmamap_sync(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap,
+ /*offset*/0, /*len*/256, op);
+}
+
+static __inline void
+ahc_sync_tqinfifo(struct ahc_softc *ahc, int op)
+{
+#ifdef AHC_TARGET_MODE
+ if ((ahc->flags & AHC_TARGETROLE) != 0) {
+ ahc_dmamap_sync(ahc, ahc->shared_data_dmat,
+ ahc->shared_data_dmamap,
+ ahc_targetcmd_offset(ahc, 0),
+ sizeof(struct target_cmd) * AHC_TMODE_CMDS,
+ op);
+ }
+#endif
+}
/*
* See if the firmware has posted any completed commands
@@ -388,12 +456,21 @@
u_int retval;
retval = 0;
+ ahc_dmamap_sync(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap,
+ /*offset*/ahc->qoutfifonext, /*len*/1,
+ BUS_DMASYNC_POSTREAD);
if (ahc->qoutfifo[ahc->qoutfifonext] != SCB_LIST_NULL)
retval |= AHC_RUN_QOUTFIFO;
#ifdef AHC_TARGET_MODE
- if ((ahc->flags & AHC_TARGETROLE) != 0
- && ahc->targetcmds[ahc->tqinfifonext].cmd_valid != 0)
- retval |= AHC_RUN_TQINFIFO;
+ if ((ahc->flags & AHC_TARGETROLE) != 0) {
+ ahc_dmamap_sync(ahc, ahc->shared_data_dmat,
+ ahc->shared_data_dmamap,
+ ahc_targetcmd_offset(ahc, ahc->tqinfifofnext),
+ /*len*/sizeof(struct target_cmd),
+ BUS_DMASYNC_POSTREAD);
+ if (ahc->targetcmds[ahc->tqinfifonext].cmd_valid != 0)
+ retval |= AHC_RUN_TQINFIFO;
+ }
#endif
return (retval);
}
@@ -418,36 +495,13 @@
intstat = CMDCMPLT;
else {
intstat = ahc_inb(ahc, INTSTAT);
- /*
- * We can't generate queuestat once above
- * or we are exposed to a race when our
- * interrupt is shared with another device.
- * if instat showed a command complete interrupt,
- * but our first generation of queue stat
- * "just missed" the delivery of this transaction,
- * we would clear the command complete interrupt
- * below without ever servicing the completed
- * command.
- */
- queuestat = ahc_check_cmdcmpltqueues(ahc);
-#if AHC_PCI_CONFIG > 0
- if (ahc->unsolicited_ints > 500
- && (ahc->chip & AHC_PCI) != 0
- && (ahc_inb(ahc, ERROR) & PCIERRSTAT) != 0)
- ahc->bus_intr(ahc);
+ queuestat = AHC_RUN_QOUTFIFO;
+#ifdef AHC_TARGET_MODE
+ if ((ahc->flags & AHC_TARGETROLE) != 0)
+ queuestat |= AHC_RUN_TQINFIFO;
#endif
}
- if (intstat == 0xFF && (ahc->features & AHC_REMOVABLE) != 0)
- /* Hot eject */
- return;
-
- if ((intstat & INT_PEND) == 0) {
- ahc->unsolicited_ints++;
- return;
- }
- ahc->unsolicited_ints = 0;
-
if (intstat & CMDCMPLT) {
ahc_outb(ahc, CLRINT, CLRCMDINT);
@@ -469,6 +523,25 @@
ahc_run_tqinfifo(ahc, /*paused*/FALSE);
#endif
}
+
+ if (intstat == 0xFF && (ahc->features & AHC_REMOVABLE) != 0)
+ /* Hot eject */
+ return;
+
+ if ((intstat & INT_PEND) == 0) {
+#if AHC_PCI_CONFIG > 0
+ if (ahc->unsolicited_ints > 500) {
+ ahc->unsolicited_ints = 0;
+ if ((ahc->chip & AHC_PCI) != 0
+ && (ahc_inb(ahc, ERROR) & PCIERRSTAT) != 0)
+ ahc->bus_intr(ahc);
+ }
+#endif
+ ahc->unsolicited_ints++;
+ return;
+ }
+ ahc->unsolicited_ints = 0;
+
if (intstat & BRKADRINT) {
ahc_handle_brkadrint(ahc);
/* Fatal error, no more interrupts to handle. */
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)