Source-Changes-HG archive

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

[src/trunk]: src/sys/dev - do sync/wide negotiation



details:   https://anonhg.NetBSD.org/src/rev/154c3951af0e
branches:  trunk
changeset: 485668:154c3951af0e
user:      bouyer <bouyer%NetBSD.org@localhost>
date:      Tue May 02 19:03:02 2000 +0000

description:
- do sync/wide negotiation
- use a circular queue for the start slots, so that order has better chances
  to be preserved.

diffstat:

 sys/dev/ic/siop.c      |  677 ++++++++++++++++++++++++++++++++++++++----------
 sys/dev/ic/siopreg.h   |   39 ++-
 sys/dev/ic/siopvar.h   |   17 +-
 sys/dev/pci/siop_pci.c |   40 +-
 4 files changed, 604 insertions(+), 169 deletions(-)

diffs (truncated from 1240 to 300 lines):

diff -r 0971e73780d2 -r 154c3951af0e sys/dev/ic/siop.c
--- a/sys/dev/ic/siop.c Tue May 02 19:02:28 2000 +0000
+++ b/sys/dev/ic/siop.c Tue May 02 19:03:02 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: siop.c,v 1.6 2000/04/27 16:49:07 bouyer Exp $  */
+/*     $NetBSD: siop.c,v 1.7 2000/05/02 19:03:02 bouyer Exp $  */
 
 /*
  * Copyright (c) 2000 Manuel Bouyer.
@@ -108,7 +108,7 @@
  */
 struct siop_cmd {
        TAILQ_ENTRY (siop_cmd) next;
-       struct siop_softc *siop_sc; /* pointer to adapter */
+       struct siop_target *siop_target; /* pointer to our target def */
        struct scsipi_xfer *xs; /* xfer from the upper level */
        struct siop_xfer *siop_table; /* tables dealing with this xfer */
        bus_addr_t      dsa; /* DSA value to load */
@@ -133,9 +133,31 @@
 /* initial number of cmd descriptors */
 #define SIOP_NCMD 10
 
+/* per-target struct */
+struct siop_target {
+       int status;     /* target status see below */
+       int flags;      /* target flags, see below */
+       u_int32_t id;   /* for SELECT FROM */
+       struct cmd_list active_list[8]; /* per-lun active cmds */
+       struct siop_softc *siop_sc; /* points back to our adapter */
+};
+
+/* target status */
+#define TARST_PROBING  0 /* target is being probed */
+#define TARST_ASYNC    1 /* target needs sync/wide negotiation */
+#define TARST_WIDE_NEG 2 /* target is doing wide negotiation */
+#define TARST_SYNC_NEG 3 /* target is doing sync negotiation */
+#define TARST_OK       4 /* sync/wide agreement is valid */
+
+/* target flags */
+#define TARF_SYNC      0x00 /* target is sync */
+#define TARF_WIDE      0x01 /* target is wide */
+
 void   siop_reset __P((struct siop_softc *));
 void   siop_handle_reset __P((struct siop_softc *));
 void   siop_scsicmd_end __P((struct siop_cmd *));
+void   siop_wdtr_neg __P((struct siop_cmd *siop_cmd));
+void   siop_sdtr_neg __P((struct siop_cmd *siop_cmd));
 void   siop_start __P((struct siop_softc *));
 void   siop_timeout __P((void *));
 void   siop_minphys __P((struct buf *));
@@ -180,7 +202,7 @@
        struct siop_cmd *siop_cmd;
        int ops;
 {
-       struct siop_softc *sc  = siop_cmd->siop_sc;
+       struct siop_softc *sc  = siop_cmd->siop_target->siop_sc;
        bus_addr_t offset;
        
        offset = sc->sc_scriptdma->dm_segs[0].ds_addr - siop_cmd->dsa;
@@ -238,8 +260,6 @@
                return;
        }
        TAILQ_INIT(&sc->free_list);
-       for (i = 0; i < 16; i++) 
-               TAILQ_INIT(&sc->active_list[i]);
        /* allocate cmd list */
        sc->cmds =
            malloc(sizeof(struct siop_cmd) * SIOP_NCMD, M_DEVBUF, M_NOWAIT);
@@ -267,7 +287,6 @@
                            sc->sc_dev.dv_xname, error);
                        return;
                }
-               sc->cmds[i].siop_sc = sc;
                sc->cmds[i].siop_table =
                    &((struct siop_xfer *)(&sc->sc_script[CMD_OFF/4]))[i];
                sc->cmds[i].dsa = sc->sc_scriptdma->dm_segs[0].ds_addr +
@@ -300,6 +319,7 @@
            + 8         /* extra NOP at end of main script */
            - sizeof(endslot_script) /* memory needed at end of sheduler */
            ) / (sizeof(slot_script) - 8);
+       sc->sc_currshedslot = 0;
 #ifdef DEBUG
        printf("%s: script size = %d, PHY addr=0x%x, VIRT=%p nslots %d\n",
            sc->sc_dev.dv_xname, (int)sizeof(siop_script),
@@ -324,6 +344,22 @@
        sc->sc_link.device = &siop_dev;
        sc->sc_link.flags  = 0;
 
+       for (i = 0; i < 16; i++)
+               sc->targets[i] = NULL;
+
+       /* find min/max sync period for this chip */
+       sc->maxsync = 0;
+       sc->minsync = 255;
+       for (i = 0; i < sizeof(scf_period) / sizeof(scf_period[0]); i++) {
+               if (sc->clock_period != scf_period[i].clock)
+                       continue;
+               if (sc->maxsync < scf_period[i].period)
+                       sc->maxsync = scf_period[i].period;
+               if (sc->minsync > scf_period[i].period)
+                       sc->minsync = scf_period[i].period;
+       }
+       if (sc->maxsync == 255 || sc->minsync == 0)
+               panic("siop: can't find my sync parameters\n");
        siop_reset(sc);
 #ifdef DUMP_SCRIPT
        siop_dump_script(sc);
@@ -338,6 +374,7 @@
 {
        int i, j;
        u_int32_t *scr;
+       u_int32_t stest3;
        bus_addr_t physaddr;
 
        /* reset the chip */
@@ -387,7 +424,7 @@
        bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SCNTL0,
            SCNTL0_ARB_MASK | SCNTL0_EPC | SCNTL0_AAP);
        bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SCNTL1, 0);
-       bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SCNTL3, 0x3);
+       bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SCNTL3, sc->clock_div);
        bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_DIEN, 0xff);
        bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_SIEN0,
            0xff & ~(SIEN0_CMP | SIEN0_SEL | SIEN0_RSL));
@@ -401,7 +438,31 @@
            sc->sc_link.scsipi_scsi.adapter_target | SCID_RRE);
        bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_RESPID0,
            1 << sc->sc_link.scsipi_scsi.adapter_target);
-       bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_DCNTL, 0);
+       bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_DCNTL, DCNTL_COM);
+
+       /* enable clock doubler or quadruler if appropriate */
+       if (sc->features & (SF_CHIP_DBLR | SF_CHIP_QUAD)) {
+               stest3 = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_STEST3);
+               bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_STEST1,
+                   STEST1_DBLEN);
+               if (sc->features & SF_CHIP_QUAD) {
+                       /* wait for PPL to lock */
+                       while ((bus_space_read_1(sc->sc_rt, sc->sc_rh,
+                           SIOP_STEST4) & STEST4_LOCK) == 0)
+                               delay(10);
+               } else {
+                       /* data sheet says 20us - more won't hurt */
+                       delay(100);
+               }
+               /* halt scsi clock, select doubler/quad, restart clock */
+               bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_STEST3,
+                   stest3 | STEST3_HSC);
+               bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_STEST1,
+                   STEST1_DBLEN | STEST1_DBLSEL);
+               bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_STEST3, stest3);
+       } else {
+               bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_STEST1, 0);
+       }
 
        /* start script */
        siop_script_sync(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
@@ -427,12 +488,13 @@
        void *v;
 {
        struct siop_softc *sc = v;
+       struct siop_target *siop_target;
        struct siop_cmd *siop_cmd;
        struct scsipi_xfer *xs;
        u_int8_t istat, sist0, sist1, sstat1, dstat, scntl1;
        u_int32_t irqcode;
        int need_reset = 0;
-       int offset, target;
+       int offset, target, lun;
        bus_addr_t dsa;
 
        istat = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_ISTAT);
@@ -462,7 +524,8 @@
                dstat = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_DSTAT);
                if (dstat & DSTAT_SSI) {
                        printf("single step dsp 0x%08x dsa 0x08%x\n",
-                           bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSP),
+                           (int)(bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSP) -
+                           sc->sc_scriptdma->dm_segs[0].ds_addr),
                            bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSA));
                        if ((dstat & ~(DSTAT_DFE | DSTAT_SSI)) == 0 &&
                            (istat & ISTAT_SIP) == 0) {
@@ -485,7 +548,8 @@
                if (dstat & DSTAT_DFE)
                        printf(" dma fifo empty");
                printf(", DSP=0x%x DSA=0x%x: ",
-                   bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSP),
+                   (int)(bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSP) -
+                   sc->sc_scriptdma->dm_segs[0].ds_addr),
                    bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSA));
                p = sc->sc_script +
                    (bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSP) -
@@ -519,10 +583,13 @@
                    "DSA=0x%x DSP=0x%x\n", sist0, sist1,
                    bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_SSTAT1),
                    bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSA),
-                   bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSP));
+                   bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSP) -
+                   sc->sc_scriptdma->dm_segs[0].ds_addr);
 #endif
-               if (siop_cmd)
+               if (siop_cmd) {
                        xs = siop_cmd->xs;
+                       siop_target = siop_cmd->siop_target;
+               }
                if (sist0 & SIST0_RST) {
                        siop_handle_reset(sc);
                        siop_start(sc);
@@ -606,7 +673,7 @@
                         * a fatal condition this way. Attempt to get sense.
                         */
                         if (siop_cmd)
-                               goto check_sense;
+                               goto check_sense;
                        printf("%s: unexpected disconnect without "
                            "command\n", sc->sc_dev.dv_xname);
                        goto reset;
@@ -617,7 +684,8 @@
                    sist0, sist1,
                    bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_SSTAT1),
                    bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSA),
-                   bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSP));
+                   (int)(bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSP) -
+                   sc->sc_scriptdma->dm_segs[0].ds_addr));
                if (siop_cmd) {
                        siop_cmd->status = CMDST_DONE;
                        xs->error = XS_SELTIMEOUT;
@@ -657,12 +725,15 @@
                            "status %d) !\n", sc->sc_dev.dv_xname,
                            irqcode, siop_cmd->status);
                        xs = NULL;
-               } else
+               } else {
                        xs = siop_cmd->xs;
+                       siop_target = siop_cmd->siop_target;
+               }
                switch(irqcode) {
                case A_int_err:
                        printf("error, DSP=0x%x\n",
-                           bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSP));
+                           (int)(bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSP) -
+                           sc->sc_scriptdma->dm_segs[0].ds_addr));
                        if (xs) {
                                xs->error = XS_SELTIMEOUT;
                                goto end;
@@ -684,12 +755,29 @@
                                        /* MSG_REJECT  for a MSG_REJECT  !*/
                                        goto reset;
                                }
+                               if (siop_cmd->siop_table->msg_out[0] ==
+                                       MSG_EXTENDED &&
+                                   siop_cmd->siop_table->msg_out[2] ==
+                                       MSG_EXT_WDTR) {
+                                       /* wide rejected, do sync */
+                                       siop_cmd->siop_target->status =
+                                           TARST_WIDE_NEG;
+                               } else if (siop_cmd->siop_table->msg_out[0] ==
+                                       MSG_EXTENDED &&
+                                   siop_cmd->siop_table->msg_out[2] ==
+                                       MSG_EXT_SDTR) {
+                                       /* sync rejected */
+                                       siop_cmd->siop_target->status =
+                                           TARST_OK;
+                               }
                                /* no table to flush here */
                                CALL_SCRIPT(Ent_msgin_ack);
                                return 1;
                        }
-                       printf("unhandled message 0x%x\n",
-                           siop_cmd->siop_table->msg_in[0]);
+                       printf("unhandled message 0x%x, DSP=0x%x\n",
+                           siop_cmd->siop_table->msg_in[0],
+                           (int)(bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSP) -
+                           sc->sc_scriptdma->dm_segs[0].ds_addr));
                        siop_cmd->siop_table->t_msgout.count= htole32(1);
                        siop_cmd->siop_table->t_msgout.addr =
                            htole32(siop_cmd->dsa);
@@ -727,27 +815,21 @@
                        printf("\n");
                        }
 #endif
+                       if (siop_cmd->siop_table->msg_in[2] == MSG_EXT_WDTR) {
+                               siop_wdtr_neg(siop_cmd);
+                               return(1);
+                       }
                        if (siop_cmd->siop_table->msg_in[2] == MSG_EXT_SDTR) {
-                               /* anserw with async for now */
-                               siop_cmd->siop_table->msg_out[0] = MSG_EXTENDED;
-                               siop_cmd->siop_table->msg_out[1] =
-                                   MSG_EXT_SDTR_LEN;
-                               siop_cmd->siop_table->msg_out[2] = MSG_EXT_SDTR;
-                               siop_cmd->siop_table->msg_out[3] = 0;
-                               siop_cmd->siop_table->msg_out[4] = 0;
-                               siop_cmd->siop_table->t_msgout.count =
-                                   htole32(MSG_EXT_SDTR_LEN + 2);
-                               siop_cmd->siop_table->t_msgout.addr =
-                                   htole32(siop_cmd->dsa);
-                       } else {
-                               /* send a message reject */
-                               siop_cmd->siop_table->t_msgout.count =



Home | Main Index | Thread Index | Old Index