Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev - We can't share the per-lun DSA entry for untagged ...
details: https://anonhg.NetBSD.org/src/rev/6d894f2806b2
branches: trunk
changeset: 526112:6d894f2806b2
user: bouyer <bouyer%NetBSD.org@localhost>
date: Thu Apr 25 19:34:02 2002 +0000
description:
- We can't share the per-lun DSA entry for untagged and tag table DSA;
there may be tagged commands still running when we queue a request sense
command.
Solve this by using 2 DSA entry per LUN
- Now that we have the command DSA before select, we can load T/L/Q in
SCRATCHC. This makes the selection timeout handler simpler.
- Avoid a race condition when setting the free flag in the cmd ring (see
comment in the script)
- don't forget to update the ID in the head of LUN table after a sync/wide
negotiation. This fixes the command timeout at the first data command
after negotiation (the bus reset handler did update the ID properly,
so subsequent commands were OK).
- for DMA interrupts, clear fifo if it's not empty. Leaving the fifo dirty
would prevent subsequent interrupts from coming in.
- Various improvements in debug messages
- misc cleanups.
diffstat:
sys/dev/ic/esiop.c | 280 +++++++++++++++++++++------------------
sys/dev/ic/esiopvar.h | 3 +-
sys/dev/microcode/siop/esiop.ss | 28 ++-
3 files changed, 166 insertions(+), 145 deletions(-)
diffs (truncated from 681 to 300 lines):
diff -r 78c0ba23f94f -r 6d894f2806b2 sys/dev/ic/esiop.c
--- a/sys/dev/ic/esiop.c Thu Apr 25 19:32:59 2002 +0000
+++ b/sys/dev/ic/esiop.c Thu Apr 25 19:34:02 2002 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: esiop.c,v 1.8 2002/04/24 09:43:14 bouyer Exp $ */
+/* $NetBSD: esiop.c,v 1.9 2002/04/25 19:34:02 bouyer Exp $ */
/*
* Copyright (c) 2002 Manuel Bouyer.
@@ -33,7 +33,7 @@
/* SYM53c7/8xx PCI-SCSI I/O Processors driver */
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: esiop.c,v 1.8 2002/04/24 09:43:14 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: esiop.c,v 1.9 2002/04/25 19:34:02 bouyer Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -94,10 +94,10 @@
void esiop_morecbd __P((struct esiop_softc *));
void esiop_moretagtbl __P((struct esiop_softc *));
void siop_add_reselsw __P((struct esiop_softc *, int));
-struct esiop_cmd * esiop_cmd_find __P((struct esiop_softc *, int, u_int32_t));
void esiop_target_register __P((struct esiop_softc *, u_int32_t));
-static int nintr = 0;
+void esiop_update_scntl3 __P((struct esiop_softc *,
+ struct siop_common_target *));
#ifdef SIOP_STATS
static int esiop_stat_intr = 0;
@@ -369,32 +369,37 @@
u_int32_t tflags;
u_int32_t addr;
int freetarget = 0;
- int restart = 0;
int slot;
int retval = 0;
again:
istat = bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_ISTAT);
if ((istat & (ISTAT_INTF | ISTAT_DIP | ISTAT_SIP)) == 0) {
- if (istat & ISTAT_SEM) {
- bus_space_write_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
- SIOP_ISTAT, (istat & ~ISTAT_SEM));
- esiop_checkdone(sc);
- }
return retval;
}
retval = 1;
- nintr++;
- if (nintr > 100) {
- panic("esiop: intr loop");
- }
INCSTAT(esiop_stat_intr);
if (istat & ISTAT_INTF) {
bus_space_write_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
SIOP_ISTAT, ISTAT_INTF);
esiop_checkdone(sc);
+ if (sc->sc_flags & SCF_CHAN_NOSLOT) {
+ /*
+ * at last one command terminated,
+ * so we should have free slots now
+ */
+ sc->sc_flags &= ~SCF_CHAN_NOSLOT;
+ scsipi_channel_thaw(&sc->sc_c.sc_chan, 1);
+ }
goto again;
}
+
+ if ((istat &(ISTAT_DIP | ISTAT_SIP | ISTAT_ABRT)) ==
+ (ISTAT_DIP | ISTAT_ABRT)) {
+ bus_space_write_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
+ SIOP_ISTAT, 0);
+ }
+
/* get CMD from T/L/Q */
tflags = bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
SIOP_SCRATCHC);
@@ -480,13 +485,15 @@
printf(" parity");
if (dstat & DSTAT_DFE)
printf(" dma fifo empty");
+ else
+ siop_clearfifo(&sc->sc_c);
printf(", DSP=0x%x DSA=0x%x: ",
(int)(bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
SIOP_DSP) - sc->sc_c.sc_scriptaddr),
bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSA));
if (esiop_cmd)
- printf("last msg_in=0x%x status=0x%x\n",
- esiop_cmd->cmd_tables->msg_in[0],
+ printf("T/L/Q=%d/%d/%d last msg_in=0x%x status=0x%x\n",
+ target, lun, tag, esiop_cmd->cmd_tables->msg_in[0],
le32toh(esiop_cmd->cmd_tables->status));
else
printf(" current T/L/Q invalid\n");
@@ -595,21 +602,17 @@
goto reset;
}
if ((sist & (SIST1_STO << 8)) && need_reset == 0) {
- /* selection time out, assume there's no device here */
/*
- * SCRATCHC has not been loaded yet, we have to find
- * params by ourselve. scratchE0 should point to
- * the slot.
+ * selection time out, assume there's no device here
+ * We also have to update the ring pointer ourselve
*/
slot = bus_space_read_1(sc->sc_c.sc_rt,
sc->sc_c.sc_rh, SIOP_SCRATCHE);
esiop_script_sync(sc,
BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
- target = bus_space_read_1(sc->sc_c.sc_rt,
- sc->sc_c.sc_rh, SIOP_SDID);
- esiop_cmd = esiop_cmd_find(sc, target,
- esiop_script_read(sc,
- sc->sc_shedoffset + slot * CMD_SLOTSIZE) & ~0x3);
+#ifdef SIOP_DEBUG_SCHED
+ printf("sel timeout target %d, slot %d\n", target, slot);
+#endif
/*
* mark this slot as free, and advance to next slot
*/
@@ -633,12 +636,6 @@
esiop_script_sync(sc,
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
if (esiop_cmd) {
- xs = esiop_cmd->cmd_c.xs;
- esiop_target = (struct esiop_target *)
- esiop_cmd->cmd_c.siop_target;
- lun = xs->xs_periph->periph_lun;
- tag = esiop_cmd->cmd_c.tag;
- esiop_lun = esiop_target->esiop_lun[lun];
esiop_cmd->cmd_c.status = CMDST_DONE;
xs->error = XS_SELTIMEOUT;
freetarget = 1;
@@ -899,53 +896,65 @@
if (esiop_cmd->cmd_tables->msg_in[2] == MSG_EXT_PPR) {
switch (siop_ppr_neg(&esiop_cmd->cmd_c)) {
case SIOP_NEG_MSGOUT:
+ esiop_update_scntl3(sc,
+ esiop_cmd->cmd_c.siop_target);
esiop_table_sync(esiop_cmd,
BUS_DMASYNC_PREREAD |
BUS_DMASYNC_PREWRITE);
CALL_SCRIPT(Ent_send_msgout);
- return(1);
+ return 1;
case SIOP_NEG_ACK:
+ esiop_update_scntl3(sc,
+ esiop_cmd->cmd_c.siop_target);
CALL_SCRIPT(Ent_msgin_ack);
- return(1);
+ return 1;
default:
panic("invalid retval from "
"siop_wdtr_neg()");
}
- return(1);
+ return 1;
}
if (esiop_cmd->cmd_tables->msg_in[2] == MSG_EXT_WDTR) {
switch (siop_wdtr_neg(&esiop_cmd->cmd_c)) {
case SIOP_NEG_MSGOUT:
+ esiop_update_scntl3(sc,
+ esiop_cmd->cmd_c.siop_target);
esiop_table_sync(esiop_cmd,
BUS_DMASYNC_PREREAD |
BUS_DMASYNC_PREWRITE);
CALL_SCRIPT(Ent_send_msgout);
- return(1);
+ return 1;
case SIOP_NEG_ACK:
+ esiop_update_scntl3(sc,
+ esiop_cmd->cmd_c.siop_target);
CALL_SCRIPT(Ent_msgin_ack);
- return(1);
+ return 1;
default:
panic("invalid retval from "
"siop_wdtr_neg()");
}
- return(1);
+ return 1;
}
if (esiop_cmd->cmd_tables->msg_in[2] == MSG_EXT_SDTR) {
switch (siop_sdtr_neg(&esiop_cmd->cmd_c)) {
case SIOP_NEG_MSGOUT:
+ esiop_update_scntl3(sc,
+ esiop_cmd->cmd_c.siop_target);
esiop_table_sync(esiop_cmd,
BUS_DMASYNC_PREREAD |
BUS_DMASYNC_PREWRITE);
CALL_SCRIPT(Ent_send_msgout);
- return(1);
+ return 1;
case SIOP_NEG_ACK:
+ esiop_update_scntl3(sc,
+ esiop_cmd->cmd_c.siop_target);
CALL_SCRIPT(Ent_msgin_ack);
- return(1);
+ return 1;
default:
panic("invalid retval from "
"siop_wdtr_neg()");
}
- return(1);
+ return 1;
}
/* send a message reject */
esiop_cmd->cmd_tables->msg_out[0] = MSG_MESSAGE_REJECT;
@@ -983,7 +992,7 @@
case A_int_resfail:
printf("reselect failed\n");
CALL_SCRIPT(Ent_script_sched);
- return 1;
+ return 1;
case A_int_done:
if (xs == NULL) {
printf("%s: done without command\n",
@@ -1024,10 +1033,6 @@
#ifdef SIOP_DEBUG_INTR
printf("esiop_intr end: status %d\n", xs->status);
#endif
- if (xs->status == SCSI_OK)
- CALL_SCRIPT(Ent_script_sched);
- else
- restart = 1;
if (tag >= 0)
esiop_lun->tactive[tag] = NULL;
else
@@ -1035,15 +1040,14 @@
esiop_scsicmd_end(esiop_cmd);
if (freetarget && esiop_target->target_c.status == TARST_PROBING)
esiop_del_dev(sc, target, lun);
- if (restart)
- CALL_SCRIPT(Ent_script_sched);
+ CALL_SCRIPT(Ent_script_sched);
if (sc->sc_flags & SCF_CHAN_NOSLOT) {
/* a command terminated, so we have free slots now */
sc->sc_flags &= ~SCF_CHAN_NOSLOT;
scsipi_channel_thaw(&sc->sc_c.sc_chan, 1);
}
- return retval;
+ return 1;
}
void
@@ -1181,22 +1185,22 @@
for (slot = 0; slot < A_ncmd_slots; slot++) {
slotdsa = esiop_script_read(sc,
sc->sc_shedoffset + slot * CMD_SLOTSIZE);
- if (slotdsa & A_f_cmd_free)
- continue;
- if ((slotdsa & ~A_f_cmd_free) == esiop_cmd->cmd_c.dsa)
+ /* if the slot has any flag, it won't match the DSA */
+ if (slotdsa == esiop_cmd->cmd_c.dsa) { /* found it */
+ /* Mark this slot as ignore */
+ esiop_script_write(sc,
+ sc->sc_shedoffset + slot * CMD_SLOTSIZE,
+ esiop_cmd->cmd_c.dsa | A_f_cmd_ignore);
+ /* ask to requeue */
+ esiop_cmd->cmd_c.xs->error = XS_REQUEUE;
+ esiop_cmd->cmd_c.xs->status = SCSI_SIOP_NOCHECK;
+ esiop_lun->tactive[tag] = NULL;
+ esiop_scsicmd_end(esiop_cmd);
break;
+ }
}
- if (slot > ESIOP_NTAG)
- continue; /* didn't find it */
- /* Mark this slot as ignore */
- esiop_script_write(sc, sc->sc_shedoffset + slot * CMD_SLOTSIZE,
- esiop_cmd->cmd_c.dsa | A_f_cmd_ignore);
- /* ask to requeue */
- esiop_cmd->cmd_c.xs->error = XS_REQUEUE;
- esiop_cmd->cmd_c.xs->status = SCSI_SIOP_NOCHECK;
- esiop_lun->tactive[tag] = NULL;
- esiop_scsicmd_end(esiop_cmd);
}
+ esiop_script_sync(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
}
/*
@@ -1236,9 +1240,9 @@
esiop_cmd->cmd_c.flags &= ~CMDFL_TAG;
esiop_cmd->cmd_c.tag = -1;
/* update DSA table */
- esiop_script_write(sc, esiop_target->lun_table_offset + lun + 2,
+ esiop_script_write(sc, esiop_target->lun_table_offset +
+ lun * 2 + A_target_luntbl / sizeof(u_int32_t),
esiop_cmd->cmd_c.dsa);
- esiop_lun->lun_flags &= ~LUNF_TAGTABLE;
esiop_script_sync(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
return 0;
}
@@ -1263,6 +1267,7 @@
printf("%s: scsi bus reset\n", sc->sc_c.sc_dev.dv_xname);
Home |
Main Index |
Thread Index |
Old Index