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