Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev Properly compute xs->resid, instead of assuming it'l...



details:   https://anonhg.NetBSD.org/src/rev/8017e3a39851
branches:  trunk
changeset: 566683:8017e3a39851
user:      bouyer <bouyer%NetBSD.org@localhost>
date:      Mon May 17 11:10:24 2004 +0000

description:
Properly compute xs->resid, instead of assuming it'll always be 0 when
a command is done.

diffstat:

 sys/dev/ic/esiop.c              |  53 ++++++++++++++++++++++++++++++++++------
 sys/dev/ic/esiopvar.h           |   3 +-
 sys/dev/ic/siop.c               |  38 ++++++++++++++++++++++++++---
 sys/dev/ic/siop_common.c        |  12 ++++++--
 sys/dev/microcode/siop/esiop.ss |   3 +-
 5 files changed, 91 insertions(+), 18 deletions(-)

diffs (291 lines):

diff -r 26818a595447 -r 8017e3a39851 sys/dev/ic/esiop.c
--- a/sys/dev/ic/esiop.c        Mon May 17 11:00:01 2004 +0000
+++ b/sys/dev/ic/esiop.c        Mon May 17 11:10:24 2004 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: esiop.c,v 1.27 2004/03/16 19:10:43 bouyer Exp $        */
+/*     $NetBSD: esiop.c,v 1.28 2004/05/17 11:10:24 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.27 2004/03/16 19:10:43 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: esiop.c,v 1.28 2004/05/17 11:10:24 bouyer Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -627,7 +627,13 @@
                                 * and the command should terminate.
                                 */
                                        INCSTAT(esiop_stat_intr_shortxfer);
-                                       if ((dstat & DSTAT_DFE) == 0)
+                                       /*
+                                        * sdp not needed here, but this
+                                        * will cause xs->resid to be adjusted
+                                        */
+                                       if (scratchc0 & A_f_c_data)
+                                               siop_sdp(&esiop_cmd->cmd_c);
+                                       else if ((dstat & DSTAT_DFE) == 0)
                                                siop_clearfifo(&sc->sc_c);
                                        /* no table to flush here */
                                        CALL_SCRIPT(Ent_status);
@@ -709,7 +715,7 @@
                                esiop_cmd->cmd_c.status = CMDST_DONE;
                                xs->error = XS_SELTIMEOUT;
                                freetarget = 1;
-                               goto end;
+                               goto end_nodata;
                        } else {
                                printf("%s: selection timeout without "
                                    "command, target %d (sdid 0x%x), "
@@ -728,7 +734,7 @@
                         if (esiop_cmd) {
                                esiop_cmd->cmd_tables->status =
                                    htole32(SCSI_CHECK);
-                               goto end;
+                               goto end_nodata;
                        }
                        printf("%s: unexpected disconnect without "
                            "command\n", sc->sc_c.sc_dev.dv_xname);
@@ -766,7 +772,7 @@
                if (esiop_cmd) {
                        esiop_cmd->cmd_c.status = CMDST_DONE;
                        xs->error = XS_SELTIMEOUT;
-                       goto end;
+                       goto end_nodata;
                }
                need_reset = 1;
        }
@@ -811,7 +817,7 @@
                            sc->sc_c.sc_rh, SIOP_DSP) - sc->sc_c.sc_scriptaddr));
                        if (xs) {
                                xs->error = XS_SELTIMEOUT;
-                               goto end;
+                               goto end_nodata;
                        } else {
                                goto reset;
                        }
@@ -1050,6 +1056,15 @@
                         * Don't call memmove in this case.
                         */
                        if (offset < SIOP_NSG) {
+                               int i;
+                               /*
+                                * adjust xs->resid for already-transfered
+                                * data
+                                */
+                               for (i = 0; i < offset; i++)
+                                       xs->resid -= le32toh(
+                                           esiop_cmd->cmd_tables->data[i].count
+                                           );
                                memmove(&esiop_cmd->cmd_tables->data[0],
                                    &esiop_cmd->cmd_tables->data[offset],
                                    (SIOP_NSG - offset) * sizeof(scr_table_t));
@@ -1083,7 +1098,7 @@
                        printf("unknown irqcode %x\n", irqcode);
                        if (xs) {
                                xs->error = XS_SELTIMEOUT;
-                               goto end;
+                               goto end_nodata;
                        }
                        goto reset;
                }
@@ -1092,6 +1107,12 @@
        /* We just should't get there */
        panic("siop_intr: I shouldn't be there !");
 
+end_nodata:
+       /*
+        * no data was transfered, and the script didn't update tlp with the
+        * current offset (which is still 0) 
+        */
+       ((struct esiop_xfer *)esiop_cmd->cmd_tables)->tlq = 0;
 end:
        /*
         * restart the script now if command completed properly
@@ -1119,6 +1140,21 @@
 {
        struct scsipi_xfer *xs = esiop_cmd->cmd_c.xs;
        struct esiop_softc *sc = (struct esiop_softc *)esiop_cmd->cmd_c.siop_sc;
+       int offset, i;
+
+       /* scratcha was saved in tlq by script. fetch offset from it */
+       offset =
+           (le32toh(((struct esiop_xfer *)esiop_cmd->cmd_tables)->tlq) >> 8)
+           & 0xff;
+       /*
+        * update resid. If we completed a xfer with
+        * some data transfers, offset will be at last 1.
+        * If it's 0 then either no data was transfered at
+        * all, or resid was already adjusted by a save
+        * data pointer, or a phase mismatch.
+        */
+       for (i = 0; i < offset; i++)
+               xs->resid -= le32toh(esiop_cmd->cmd_tables->data[i].count);
 
        switch(xs->status) {
        case SCSI_OK:
@@ -1173,7 +1209,6 @@
        callout_stop(&esiop_cmd->cmd_c.xs->xs_callout);
        esiop_cmd->cmd_c.status = CMDST_FREE;
        TAILQ_INSERT_TAIL(&sc->free_list, esiop_cmd, next);
-       xs->resid = 0;
        scsipi_done (xs);
 }
 
diff -r 26818a595447 -r 8017e3a39851 sys/dev/ic/esiopvar.h
--- a/sys/dev/ic/esiopvar.h     Mon May 17 11:00:01 2004 +0000
+++ b/sys/dev/ic/esiopvar.h     Mon May 17 11:10:24 2004 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: esiopvar.h,v 1.8 2003/11/02 11:07:45 wiz Exp $ */
+/*     $NetBSD: esiopvar.h,v 1.9 2004/05/17 11:10:24 bouyer Exp $      */
 
 /*
  * Copyright (c) 2002 Manuel Bouyer.
@@ -53,6 +53,7 @@
 struct esiop_xfer {
        struct siop_common_xfer siop_tables;
        u_int32_t tlq; /* target/lun/tag loaded in scratchC by script */
+                     /* will also containt scratcha at end of command */
 } __attribute__((__packed__));
 
 /*
diff -r 26818a595447 -r 8017e3a39851 sys/dev/ic/siop.c
--- a/sys/dev/ic/siop.c Mon May 17 11:00:01 2004 +0000
+++ b/sys/dev/ic/siop.c Mon May 17 11:10:24 2004 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: siop.c,v 1.72 2004/03/16 19:10:43 bouyer Exp $ */
+/*     $NetBSD: siop.c,v 1.73 2004/05/17 11:10:24 bouyer Exp $ */
 
 /*
  * Copyright (c) 2000 Manuel Bouyer.
@@ -33,7 +33,7 @@
 /* SYM53c7/8xx PCI-SCSI I/O Processors driver */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: siop.c,v 1.72 2004/03/16 19:10:43 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: siop.c,v 1.73 2004/05/17 11:10:24 bouyer Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -494,7 +494,13 @@
                                 * and the command should terminate.
                                 */
                                        INCSTAT(siop_stat_intr_shortxfer);
-                                       if ((dstat & DSTAT_DFE) == 0)
+                                       /*
+                                        * sdp not needed here, but this
+                                        * will cause xs->resid to be adjusted
+                                        */
+                                       if (scratcha0 & A_flag_data)
+                                               siop_sdp(&siop_cmd->cmd_c);
+                                       else if ((dstat & DSTAT_DFE) == 0)
                                                siop_clearfifo(&sc->sc_c);
                                        /* no table to flush here */
                                        CALL_SCRIPT(Ent_status);
@@ -889,6 +895,15 @@
                         * Don't call memmove in this case.
                         */
                        if (offset < SIOP_NSG) {
+                               int i;
+                               /*
+                                * adjust xs->resid for already-transfered
+                                * data
+                                */
+                               for (i = 0; i < offset; i++)
+                                       xs->resid -= le32toh(
+                                           siop_cmd->cmd_tables->data[i].count
+                                           );
                                memmove(&siop_cmd->cmd_tables->data[0],
                                    &siop_cmd->cmd_tables->data[offset],
                                    (SIOP_NSG - offset) * sizeof(scr_table_t));
@@ -918,6 +933,22 @@
                            le32toh(siop_cmd->cmd_tables->status));
 #endif
                        INCSTAT(siop_stat_intr_done);
+                       /*
+                        * update resid. If we completed a xfer with
+                        * some data transfers, offset will be at last 1.
+                        * If it's 0 then either no data was transfered at
+                        * all, or resid was already adjusted by a save
+                        * data pointer, or a phase mismatch.
+                        */
+                       offset = bus_space_read_1(sc->sc_c.sc_rt,
+                           sc->sc_c.sc_rh, SIOP_SCRATCHA + 1);
+                       {
+                               int i;
+                               for (i = 0; i < offset; i++)
+                                       xs->resid -= le32toh(
+                                           siop_cmd->cmd_tables->data[i].count
+                                           );
+                       }
                        siop_cmd->cmd_c.status = CMDST_DONE;
                        goto end;
                default:
@@ -1017,7 +1048,6 @@
        callout_stop(&siop_cmd->cmd_c.xs->xs_callout);
        siop_cmd->cmd_c.status = CMDST_FREE;
        TAILQ_INSERT_TAIL(&sc->free_list, siop_cmd, next);
-       xs->resid = 0;
        scsipi_done (xs);
 }
 
diff -r 26818a595447 -r 8017e3a39851 sys/dev/ic/siop_common.c
--- a/sys/dev/ic/siop_common.c  Mon May 17 11:00:01 2004 +0000
+++ b/sys/dev/ic/siop_common.c  Mon May 17 11:10:24 2004 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: siop_common.c,v 1.33 2004/03/10 22:02:53 bouyer Exp $  */
+/*     $NetBSD: siop_common.c,v 1.34 2004/05/17 11:10:24 bouyer Exp $  */
 
 /*
  * Copyright (c) 2000, 2002 Manuel Bouyer.
@@ -33,7 +33,7 @@
 /* SYM53c7/8xx PCI-SCSI I/O Processors driver */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: siop_common.c,v 1.33 2004/03/10 22:02:53 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: siop_common.c,v 1.34 2004/05/17 11:10:24 bouyer Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -735,7 +735,10 @@
 siop_sdp(siop_cmd)
        struct siop_common_cmd *siop_cmd;
 {
-       /* save data pointer. Handle async only for now */
+       /*
+        * Save data pointer when a phase mistmatch occurs. We need to compute
+        * how much of the current table was written.
+        */
        int offset, dbc, sstat;
        struct siop_common_softc *sc = siop_cmd->siop_sc;
        scr_table_t *table; /* table to patch */
@@ -790,6 +793,9 @@
                    bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_CTEST3) |
                    CTEST3_CLF);
        }
+       /* correct xs->resid for this partial transfer */
+       siop_cmd->xs->resid -= le32toh(table->count) - dbc;
+       /* "cut" already transfered data from this table */
        table->addr =
            htole32(le32toh(table->addr) + le32toh(table->count) - dbc);
        table->count = htole32(dbc);
diff -r 26818a595447 -r 8017e3a39851 sys/dev/microcode/siop/esiop.ss
--- a/sys/dev/microcode/siop/esiop.ss   Mon May 17 11:00:01 2004 +0000
+++ b/sys/dev/microcode/siop/esiop.ss   Mon May 17 11:10:24 2004 +0000
@@ -1,4 +1,4 @@
-;      $NetBSD: esiop.ss,v 1.16 2003/10/05 17:48:49 bouyer Exp $
+;      $NetBSD: esiop.ss,v 1.17 2004/05/17 11:10:24 bouyer Exp $
 
 ;
 ; Copyright (c) 2002 Manuel Bouyer.
@@ -208,6 +208,7 @@
 
 handle_cmpl:
        CALL REL(disconnect);
+       STORE NOFLUSH SCRATCHA0, 4, from tlq_offset; save current offset
        MOVE SCRATCHE1 to SFBR;
        INT int_done, IF NOT 0x00; if status is not "done", let host handle it
        MOVE SCRATCHF0 to SFBR; load pointer in done ring



Home | Main Index | Thread Index | Old Index