The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/ic/siop.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: siop.c,v 1.72 2004/03/16 19:10:43 bouyer Exp $ */
    2 
    3 /*
    4  * Copyright (c) 2000 Manuel Bouyer.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  * 3. All advertising materials mentioning features or use of this software
   15  *    must display the following acknowledgement:
   16  *      This product includes software developed by Manuel Bouyer.
   17  * 4. The name of the author may not be used to endorse or promote products
   18  *    derived from this software without specific prior written permission.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   23  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,     
   24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   25  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   30  *
   31  */
   32 
   33 /* SYM53c7/8xx PCI-SCSI I/O Processors driver */
   34 
   35 #include <sys/cdefs.h>
   36 __KERNEL_RCSID(0, "$NetBSD: siop.c,v 1.72 2004/03/16 19:10:43 bouyer Exp $");
   37 
   38 #include <sys/param.h>
   39 #include <sys/systm.h>
   40 #include <sys/device.h>
   41 #include <sys/malloc.h>
   42 #include <sys/buf.h>
   43 #include <sys/kernel.h>
   44 
   45 #include <uvm/uvm_extern.h>
   46 
   47 #include <machine/endian.h>
   48 #include <machine/bus.h>
   49 
   50 #include <dev/microcode/siop/siop.out>
   51 
   52 #include <dev/scsipi/scsi_all.h>
   53 #include <dev/scsipi/scsi_message.h>
   54 #include <dev/scsipi/scsipi_all.h>
   55 
   56 #include <dev/scsipi/scsiconf.h>
   57 
   58 #include <dev/ic/siopreg.h>
   59 #include <dev/ic/siopvar_common.h>
   60 #include <dev/ic/siopvar.h>
   61 
   62 #include "opt_siop.h"
   63 
   64 #ifndef DEBUG
   65 #undef DEBUG
   66 #endif
   67 #undef SIOP_DEBUG
   68 #undef SIOP_DEBUG_DR
   69 #undef SIOP_DEBUG_INTR
   70 #undef SIOP_DEBUG_SCHED
   71 #undef DUMP_SCRIPT
   72 
   73 #define SIOP_STATS
   74 
   75 #ifndef SIOP_DEFAULT_TARGET
   76 #define SIOP_DEFAULT_TARGET 7
   77 #endif
   78 
   79 /* number of cmd descriptors per block */
   80 #define SIOP_NCMDPB (PAGE_SIZE / sizeof(struct siop_xfer))
   81 
   82 /* Number of scheduler slot (needs to match script) */
   83 #define SIOP_NSLOTS 40
   84 
   85 void    siop_reset __P((struct siop_softc *));
   86 void    siop_handle_reset __P((struct siop_softc *));
   87 int     siop_handle_qtag_reject __P((struct siop_cmd *));
   88 void    siop_scsicmd_end __P((struct siop_cmd *));
   89 void    siop_unqueue __P((struct siop_softc *, int, int));
   90 static void     siop_start __P((struct siop_softc *, struct siop_cmd *));
   91 void    siop_timeout __P((void *));
   92 int     siop_scsicmd __P((struct scsipi_xfer *));
   93 void    siop_scsipi_request __P((struct scsipi_channel *,
   94                         scsipi_adapter_req_t, void *));
   95 void    siop_dump_script __P((struct siop_softc *));
   96 void    siop_morecbd __P((struct siop_softc *));
   97 struct siop_lunsw *siop_get_lunsw __P((struct siop_softc *));
   98 void    siop_add_reselsw __P((struct siop_softc *, int));
   99 void    siop_update_scntl3 __P((struct siop_softc *,
  100                         struct siop_common_target *));
  101 
  102 #ifdef SIOP_STATS
  103 static int siop_stat_intr = 0;
  104 static int siop_stat_intr_shortxfer = 0;
  105 static int siop_stat_intr_sdp = 0;
  106 static int siop_stat_intr_done = 0;
  107 static int siop_stat_intr_xferdisc = 0;
  108 static int siop_stat_intr_lunresel = 0;
  109 static int siop_stat_intr_qfull = 0;
  110 void siop_printstats __P((void));
  111 #define INCSTAT(x) x++
  112 #else
  113 #define INCSTAT(x) 
  114 #endif
  115 
  116 static __inline__ void siop_script_sync __P((struct siop_softc *, int));
  117 static __inline__ void
  118 siop_script_sync(sc, ops)
  119         struct siop_softc *sc;
  120         int ops;
  121 {
  122         if ((sc->sc_c.features & SF_CHIP_RAM) == 0)
  123                 bus_dmamap_sync(sc->sc_c.sc_dmat, sc->sc_c.sc_scriptdma, 0,
  124                     PAGE_SIZE, ops);
  125 }
  126 
  127 static __inline__ u_int32_t siop_script_read __P((struct siop_softc *, u_int));
  128 static __inline__ u_int32_t
  129 siop_script_read(sc, offset)
  130         struct siop_softc *sc;
  131         u_int offset;
  132 {
  133         if (sc->sc_c.features & SF_CHIP_RAM) {
  134                 return bus_space_read_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh,
  135                     offset * 4);
  136         } else {
  137                 return le32toh(sc->sc_c.sc_script[offset]);
  138         }
  139 }
  140 
  141 static __inline__ void siop_script_write __P((struct siop_softc *, u_int,
  142         u_int32_t));
  143 static __inline__ void
  144 siop_script_write(sc, offset, val)
  145         struct siop_softc *sc;
  146         u_int offset;
  147         u_int32_t val;
  148 {
  149         if (sc->sc_c.features & SF_CHIP_RAM) {
  150                 bus_space_write_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh,
  151                     offset * 4, val);
  152         } else {
  153                 sc->sc_c.sc_script[offset] = htole32(val);
  154         }
  155 }
  156 
  157 void
  158 siop_attach(sc)
  159         struct siop_softc *sc;
  160 {
  161         if (siop_common_attach(&sc->sc_c) != 0)
  162                 return;
  163 
  164         TAILQ_INIT(&sc->free_list);
  165         TAILQ_INIT(&sc->cmds);
  166         TAILQ_INIT(&sc->lunsw_list);
  167         sc->sc_currschedslot = 0;
  168 #ifdef SIOP_DEBUG
  169         printf("%s: script size = %d, PHY addr=0x%x, VIRT=%p\n",
  170             sc->sc_c.sc_dev.dv_xname, (int)sizeof(siop_script),
  171             (u_int32_t)sc->sc_c.sc_scriptaddr, sc->sc_c.sc_script);
  172 #endif
  173 
  174         sc->sc_c.sc_adapt.adapt_max_periph = SIOP_NTAG - 1;
  175         sc->sc_c.sc_adapt.adapt_request = siop_scsipi_request;
  176 
  177         /* Do a bus reset, so that devices fall back to narrow/async */
  178         siop_resetbus(&sc->sc_c);
  179         /*
  180          * siop_reset() will reset the chip, thus clearing pending interrupts
  181          */
  182         siop_reset(sc);
  183 #ifdef DUMP_SCRIPT
  184         siop_dump_script(sc);
  185 #endif
  186 
  187         config_found((struct device*)sc, &sc->sc_c.sc_chan, scsiprint);
  188 }
  189 
  190 void
  191 siop_reset(sc)
  192         struct siop_softc *sc;
  193 {
  194         int i, j;
  195         struct siop_lunsw *lunsw;
  196 
  197         siop_common_reset(&sc->sc_c);
  198 
  199         /* copy and patch the script */
  200         if (sc->sc_c.features & SF_CHIP_RAM) {
  201                 bus_space_write_region_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh, 0,
  202                     siop_script, sizeof(siop_script) / sizeof(siop_script[0]));
  203                 for (j = 0; j <
  204                     (sizeof(E_abs_msgin_Used) / sizeof(E_abs_msgin_Used[0]));
  205                     j++) {
  206                         bus_space_write_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh,
  207                             E_abs_msgin_Used[j] * 4,
  208                             sc->sc_c.sc_scriptaddr + Ent_msgin_space);
  209                 }
  210                 if (sc->sc_c.features & SF_CHIP_LED0) {
  211                         bus_space_write_region_4(sc->sc_c.sc_ramt,
  212                             sc->sc_c.sc_ramh,
  213                             Ent_led_on1, siop_led_on,
  214                             sizeof(siop_led_on) / sizeof(siop_led_on[0]));
  215                         bus_space_write_region_4(sc->sc_c.sc_ramt,
  216                             sc->sc_c.sc_ramh,
  217                             Ent_led_on2, siop_led_on,
  218                             sizeof(siop_led_on) / sizeof(siop_led_on[0]));
  219                         bus_space_write_region_4(sc->sc_c.sc_ramt,
  220                             sc->sc_c.sc_ramh,
  221                             Ent_led_off, siop_led_off,
  222                             sizeof(siop_led_off) / sizeof(siop_led_off[0]));
  223                 }
  224         } else {
  225                 for (j = 0;
  226                     j < (sizeof(siop_script) / sizeof(siop_script[0])); j++) {
  227                         sc->sc_c.sc_script[j] = htole32(siop_script[j]);
  228                 }
  229                 for (j = 0; j <
  230                     (sizeof(E_abs_msgin_Used) / sizeof(E_abs_msgin_Used[0]));
  231                     j++) {
  232                         sc->sc_c.sc_script[E_abs_msgin_Used[j]] =
  233                             htole32(sc->sc_c.sc_scriptaddr + Ent_msgin_space);
  234                 }
  235                 if (sc->sc_c.features & SF_CHIP_LED0) {
  236                         for (j = 0; j < (sizeof(siop_led_on) /
  237                             sizeof(siop_led_on[0])); j++)
  238                                 sc->sc_c.sc_script[
  239                                     Ent_led_on1 / sizeof(siop_led_on[0]) + j
  240                                     ] = htole32(siop_led_on[j]);
  241                         for (j = 0; j < (sizeof(siop_led_on) /
  242                             sizeof(siop_led_on[0])); j++)
  243                                 sc->sc_c.sc_script[
  244                                     Ent_led_on2 / sizeof(siop_led_on[0]) + j
  245                                     ] = htole32(siop_led_on[j]);
  246                         for (j = 0; j < (sizeof(siop_led_off) /
  247                             sizeof(siop_led_off[0])); j++)
  248                                 sc->sc_c.sc_script[
  249                                    Ent_led_off / sizeof(siop_led_off[0]) + j
  250                                    ] = htole32(siop_led_off[j]);
  251                 }
  252         }
  253         sc->script_free_lo = sizeof(siop_script) / sizeof(siop_script[0]);
  254         sc->script_free_hi = sc->sc_c.ram_size / 4;
  255         sc->sc_ntargets = 0;
  256 
  257         /* free used and unused lun switches */
  258         while((lunsw = TAILQ_FIRST(&sc->lunsw_list)) != NULL) {
  259 #ifdef SIOP_DEBUG
  260                 printf("%s: free lunsw at offset %d\n",
  261                                 sc->sc_c.sc_dev.dv_xname, lunsw->lunsw_off);
  262 #endif
  263                 TAILQ_REMOVE(&sc->lunsw_list, lunsw, next);
  264                 free(lunsw, M_DEVBUF);
  265         }
  266         TAILQ_INIT(&sc->lunsw_list);
  267         /* restore reselect switch */
  268         for (i = 0; i < sc->sc_c.sc_chan.chan_ntargets; i++) {
  269                 struct siop_target *target;
  270                 if (sc->sc_c.targets[i] == NULL)
  271                         continue;
  272 #ifdef SIOP_DEBUG
  273                 printf("%s: restore sw for target %d\n",
  274                                 sc->sc_c.sc_dev.dv_xname, i);
  275 #endif
  276                 target = (struct siop_target *)sc->sc_c.targets[i];
  277                 free(target->lunsw, M_DEVBUF);
  278                 target->lunsw = siop_get_lunsw(sc);
  279                 if (target->lunsw == NULL) {
  280                         printf("%s: can't alloc lunsw for target %d\n",
  281                             sc->sc_c.sc_dev.dv_xname, i);
  282                         break;
  283                 }
  284                 siop_add_reselsw(sc, i);
  285         }
  286 
  287         /* start script */
  288         if ((sc->sc_c.features & SF_CHIP_RAM) == 0) {
  289                 bus_dmamap_sync(sc->sc_c.sc_dmat, sc->sc_c.sc_scriptdma, 0,
  290                     PAGE_SIZE, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
  291         }
  292         bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSP,
  293             sc->sc_c.sc_scriptaddr + Ent_reselect);
  294 }
  295 
  296 #if 0
  297 #define CALL_SCRIPT(ent) do {\
  298         printf ("start script DSA 0x%lx DSP 0x%lx\n", \
  299             siop_cmd->cmd_c.dsa, \
  300             sc->sc_c.sc_scriptaddr + ent); \
  301 bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSP, sc->sc_c.sc_scriptaddr + ent); \
  302 } while (0)
  303 #else
  304 #define CALL_SCRIPT(ent) do {\
  305 bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSP, sc->sc_c.sc_scriptaddr + ent); \
  306 } while (0)
  307 #endif
  308 
  309 int
  310 siop_intr(v)
  311         void *v;
  312 {
  313         struct siop_softc *sc = v;
  314         struct siop_target *siop_target;
  315         struct siop_cmd *siop_cmd;
  316         struct siop_lun *siop_lun;
  317         struct scsipi_xfer *xs;
  318         int istat, sist, sstat1, dstat = 0; /* XXX: gcc */
  319         u_int32_t irqcode;
  320         int need_reset = 0;
  321         int offset, target, lun, tag;
  322         bus_addr_t dsa;
  323         struct siop_cbd *cbdp;
  324         int freetarget = 0;
  325         int restart = 0;
  326 
  327         istat = bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_ISTAT);
  328         if ((istat & (ISTAT_INTF | ISTAT_DIP | ISTAT_SIP)) == 0)
  329                 return 0;
  330         INCSTAT(siop_stat_intr);
  331         if (istat & ISTAT_INTF) {
  332                 printf("INTRF\n");
  333                 bus_space_write_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
  334                     SIOP_ISTAT, ISTAT_INTF);
  335         }
  336         if ((istat &(ISTAT_DIP | ISTAT_SIP | ISTAT_ABRT)) ==
  337             (ISTAT_DIP | ISTAT_ABRT)) {
  338                 /* clear abort */
  339                 bus_space_write_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
  340                     SIOP_ISTAT, 0);
  341         }
  342         /* use DSA to find the current siop_cmd */
  343         siop_cmd = NULL;
  344         dsa = bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSA);
  345         TAILQ_FOREACH(cbdp, &sc->cmds, next) {
  346                 if (dsa >= cbdp->xferdma->dm_segs[0].ds_addr &&
  347                     dsa < cbdp->xferdma->dm_segs[0].ds_addr + PAGE_SIZE) {
  348                         dsa -= cbdp->xferdma->dm_segs[0].ds_addr;
  349                         siop_cmd = &cbdp->cmds[dsa / sizeof(struct siop_xfer)];
  350                         siop_table_sync(siop_cmd,
  351                             BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
  352                         break;
  353                 }
  354         } 
  355         if (siop_cmd) {
  356                 xs = siop_cmd->cmd_c.xs;
  357                 siop_target = (struct siop_target *)siop_cmd->cmd_c.siop_target;
  358                 target = siop_cmd->cmd_c.xs->xs_periph->periph_target;
  359                 lun = siop_cmd->cmd_c.xs->xs_periph->periph_lun;
  360                 tag = siop_cmd->cmd_c.tag;
  361                 siop_lun = siop_target->siop_lun[lun];
  362 #ifdef DIAGNOSTIC
  363                 if (siop_cmd->cmd_c.status != CMDST_ACTIVE) {
  364                         printf("siop_cmd (lun %d) for DSA 0x%x "
  365                             "not active (%d)\n", lun, (u_int)dsa,
  366                             siop_cmd->cmd_c.status);
  367                         xs = NULL;
  368                         siop_target = NULL;
  369                         target = -1;
  370                         lun = -1;
  371                         tag = -1;
  372                         siop_lun = NULL;
  373                         siop_cmd = NULL;
  374                 } else if (siop_lun->siop_tag[tag].active != siop_cmd) {
  375                         printf("siop_cmd (lun %d tag %d) not in siop_lun "
  376                             "active (%p != %p)\n", lun, tag, siop_cmd,
  377                             siop_lun->siop_tag[tag].active);
  378                 }
  379 #endif
  380         } else {
  381                 xs = NULL;
  382                 siop_target = NULL;
  383                 target = -1;
  384                 lun = -1;
  385                 tag = -1;
  386                 siop_lun = NULL;
  387         }
  388         if (istat & ISTAT_DIP) {
  389                 dstat = bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
  390                     SIOP_DSTAT);
  391                 if (dstat & DSTAT_ABRT) {
  392                         /* was probably generated by a bus reset IOCTL */
  393                         if ((dstat & DSTAT_DFE) == 0)
  394                                 siop_clearfifo(&sc->sc_c);
  395                         goto reset;
  396                 }
  397                 if (dstat & DSTAT_SSI) {
  398                         printf("single step dsp 0x%08x dsa 0x08%x\n",
  399                             (int)(bus_space_read_4(sc->sc_c.sc_rt,
  400                             sc->sc_c.sc_rh, SIOP_DSP) -
  401                             sc->sc_c.sc_scriptaddr),
  402                             bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
  403                                 SIOP_DSA));
  404                         if ((dstat & ~(DSTAT_DFE | DSTAT_SSI)) == 0 &&
  405                             (istat & ISTAT_SIP) == 0) {
  406                                 bus_space_write_1(sc->sc_c.sc_rt,
  407                                     sc->sc_c.sc_rh, SIOP_DCNTL,
  408                                     bus_space_read_1(sc->sc_c.sc_rt,
  409                                     sc->sc_c.sc_rh, SIOP_DCNTL) | DCNTL_STD);
  410                         }
  411                         return 1;
  412                 }
  413 
  414                 if (dstat & ~(DSTAT_SIR | DSTAT_DFE | DSTAT_SSI)) {
  415                 printf("DMA IRQ:");
  416                 if (dstat & DSTAT_IID)
  417                         printf(" Illegal instruction");
  418                 if (dstat & DSTAT_BF)
  419                         printf(" bus fault");
  420                 if (dstat & DSTAT_MDPE)
  421                         printf(" parity");
  422                 if (dstat & DSTAT_DFE)
  423                         printf(" DMA fifo empty");
  424                 else
  425                         siop_clearfifo(&sc->sc_c);
  426                 printf(", DSP=0x%x DSA=0x%x: ",
  427                     (int)(bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
  428                         SIOP_DSP) - sc->sc_c.sc_scriptaddr),
  429                     bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSA));
  430                 if (siop_cmd)
  431                         printf("last msg_in=0x%x status=0x%x\n",
  432                             siop_cmd->cmd_tables->msg_in[0],
  433                             le32toh(siop_cmd->cmd_tables->status));
  434                 else 
  435                         printf("%s: current DSA invalid\n",
  436                             sc->sc_c.sc_dev.dv_xname);
  437                 need_reset = 1;
  438                 }
  439         }
  440         if (istat & ISTAT_SIP) {
  441                 if (istat & ISTAT_DIP)
  442                         delay(10);
  443                 /*
  444                  * Can't read sist0 & sist1 independently, or we have to
  445                  * insert delay
  446                  */
  447                 sist = bus_space_read_2(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
  448                     SIOP_SIST0);
  449                 sstat1 = bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
  450                     SIOP_SSTAT1);
  451 #ifdef SIOP_DEBUG_INTR
  452                 printf("scsi interrupt, sist=0x%x sstat1=0x%x "
  453                     "DSA=0x%x DSP=0x%lx\n", sist,
  454                     bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
  455                         SIOP_SSTAT1),
  456                     bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSA),
  457                     (u_long)(bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
  458                         SIOP_DSP) -
  459                     sc->sc_c.sc_scriptaddr));
  460 #endif
  461                 if (sist & SIST0_RST) {
  462                         siop_handle_reset(sc);
  463                         /* no table to flush here */
  464                         return 1;
  465                 }
  466                 if (sist & SIST0_SGE) {
  467                         if (siop_cmd)
  468                                 scsipi_printaddr(xs->xs_periph);
  469                         else
  470                                 printf("%s:", sc->sc_c.sc_dev.dv_xname);
  471                         printf("scsi gross error\n");
  472                         goto reset;
  473                 }
  474                 if ((sist & SIST0_MA) && need_reset == 0) {
  475                         if (siop_cmd) { 
  476                                 int scratcha0;
  477                                 dstat = bus_space_read_1(sc->sc_c.sc_rt,
  478                                     sc->sc_c.sc_rh, SIOP_DSTAT);
  479                                 /*
  480                                  * first restore DSA, in case we were in a S/G
  481                                  * operation.
  482                                  */
  483                                 bus_space_write_4(sc->sc_c.sc_rt,
  484                                     sc->sc_c.sc_rh,
  485                                     SIOP_DSA, siop_cmd->cmd_c.dsa);
  486                                 scratcha0 = bus_space_read_1(sc->sc_c.sc_rt,
  487                                     sc->sc_c.sc_rh, SIOP_SCRATCHA);
  488                                 switch (sstat1 & SSTAT1_PHASE_MASK) {
  489                                 case SSTAT1_PHASE_STATUS:
  490                                 /*
  491                                  * previous phase may be aborted for any reason
  492                                  * ( for example, the target has less data to
  493                                  * transfer than requested). Just go to status
  494                                  * and the command should terminate.
  495                                  */
  496                                         INCSTAT(siop_stat_intr_shortxfer);
  497                                         if ((dstat & DSTAT_DFE) == 0)
  498                                                 siop_clearfifo(&sc->sc_c);
  499                                         /* no table to flush here */
  500                                         CALL_SCRIPT(Ent_status);
  501                                         return 1;
  502                                 case SSTAT1_PHASE_MSGIN:
  503                                         /*
  504                                          * target may be ready to disconnect
  505                                          * Save data pointers just in case.
  506                                          */
  507                                         INCSTAT(siop_stat_intr_xferdisc);
  508                                         if (scratcha0 & A_flag_data)
  509                                                 siop_sdp(&siop_cmd->cmd_c);
  510                                         else if ((dstat & DSTAT_DFE) == 0)
  511                                                 siop_clearfifo(&sc->sc_c);
  512                                         bus_space_write_1(sc->sc_c.sc_rt,
  513                                             sc->sc_c.sc_rh, SIOP_SCRATCHA,
  514                                             scratcha0 & ~A_flag_data);
  515                                         siop_table_sync(siop_cmd,
  516                                             BUS_DMASYNC_PREREAD |
  517                                             BUS_DMASYNC_PREWRITE);
  518                                         CALL_SCRIPT(Ent_msgin);
  519                                         return 1;
  520                                 }
  521                                 printf("%s: unexpected phase mismatch %d\n",
  522                                     sc->sc_c.sc_dev.dv_xname,
  523                                     sstat1 & SSTAT1_PHASE_MASK);
  524                         } else {
  525                                 printf("%s: phase mismatch without command\n",
  526                                     sc->sc_c.sc_dev.dv_xname);
  527                         }
  528                         need_reset = 1;
  529                 }
  530                 if (sist & SIST0_PAR) {
  531                         /* parity error, reset */
  532                         if (siop_cmd)
  533                                 scsipi_printaddr(xs->xs_periph);
  534                         else
  535                                 printf("%s:", sc->sc_c.sc_dev.dv_xname);
  536                         printf("parity error\n");
  537                         goto reset;
  538                 }
  539                 if ((sist & (SIST1_STO << 8)) && need_reset == 0) {
  540                         /* selection time out, assume there's no device here */
  541                         if (siop_cmd) {
  542                                 siop_cmd->cmd_c.status = CMDST_DONE;
  543                                 xs->error = XS_SELTIMEOUT;
  544                                 freetarget = 1;
  545                                 goto end;
  546                         } else {
  547                                 printf("%s: selection timeout without "
  548                                     "command\n", sc->sc_c.sc_dev.dv_xname);
  549                                 need_reset = 1;
  550                         }
  551                 }
  552                 if (sist & SIST0_UDC) {
  553                         /*
  554                          * unexpected disconnect. Usually the target signals
  555                          * a fatal condition this way. Attempt to get sense.
  556                          */
  557                          if (siop_cmd) {
  558                                 siop_cmd->cmd_tables->status =
  559                                     htole32(SCSI_CHECK);
  560                                 goto end;
  561                         }
  562                         printf("%s: unexpected disconnect without "
  563                             "command\n", sc->sc_c.sc_dev.dv_xname);
  564                         goto reset;
  565                 }
  566                 if (sist & (SIST1_SBMC << 8)) {
  567                         /* SCSI bus mode change */
  568                         if (siop_modechange(&sc->sc_c) == 0 || need_reset == 1)
  569                                 goto reset;
  570                         if ((istat & ISTAT_DIP) && (dstat & DSTAT_SIR)) {
  571                                 /*
  572                                  * we have a script interrupt, it will
  573                                  * restart the script.
  574                                  */
  575                                 goto scintr;
  576                         }
  577                         /*
  578                          * else we have to restart it ourselve, at the
  579                          * interrupted instruction.
  580                          */
  581                         bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
  582                             SIOP_DSP,
  583                             bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
  584                             SIOP_DSP) - 8);
  585                         return 1;
  586                 }
  587                 /* Else it's an unhandled exception (for now). */
  588                 printf("%s: unhandled scsi interrupt, sist=0x%x sstat1=0x%x "
  589                     "DSA=0x%x DSP=0x%x\n", sc->sc_c.sc_dev.dv_xname, sist,
  590                     bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
  591                         SIOP_SSTAT1),
  592                     bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSA),
  593                     (int)(bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
  594                         SIOP_DSP) - sc->sc_c.sc_scriptaddr));
  595                 if (siop_cmd) {
  596                         siop_cmd->cmd_c.status = CMDST_DONE;
  597                         xs->error = XS_SELTIMEOUT;
  598                         goto end;
  599                 }
  600                 need_reset = 1;
  601         }
  602         if (need_reset) {
  603 reset:
  604                 /* fatal error, reset the bus */
  605                 siop_resetbus(&sc->sc_c);
  606                 /* no table to flush here */
  607                 return 1;
  608         }
  609 
  610 scintr:
  611         if ((istat & ISTAT_DIP) && (dstat & DSTAT_SIR)) { /* script interrupt */
  612                 irqcode = bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
  613                     SIOP_DSPS);
  614 #ifdef SIOP_DEBUG_INTR
  615                 printf("script interrupt 0x%x\n", irqcode);
  616 #endif
  617                 /*
  618                  * no command, or an inactive command is only valid for a
  619                  * reselect interrupt
  620                  */
  621                 if ((irqcode & 0x80) == 0) {
  622                         if (siop_cmd == NULL) {
  623                                 printf(
  624                         "%s: script interrupt (0x%x) with invalid DSA !!!\n",
  625                                     sc->sc_c.sc_dev.dv_xname, irqcode);
  626                                 goto reset;
  627                         }
  628                         if (siop_cmd->cmd_c.status != CMDST_ACTIVE) {
  629                                 printf("%s: command with invalid status "
  630                                     "(IRQ code 0x%x current status %d) !\n",
  631                                     sc->sc_c.sc_dev.dv_xname,
  632                                     irqcode, siop_cmd->cmd_c.status);
  633                                 xs = NULL;
  634                         }
  635                 }
  636                 switch(irqcode) {
  637                 case A_int_err:
  638                         printf("error, DSP=0x%x\n",
  639                             (int)(bus_space_read_4(sc->sc_c.sc_rt,
  640                             sc->sc_c.sc_rh, SIOP_DSP) - sc->sc_c.sc_scriptaddr));
  641                         if (xs) {
  642                                 xs->error = XS_SELTIMEOUT;
  643                                 goto end;
  644                         } else {
  645                                 goto reset;
  646                         }
  647                 case A_int_reseltarg:
  648                         printf("%s: reselect with invalid target\n",
  649                                     sc->sc_c.sc_dev.dv_xname);
  650                         goto reset;
  651                 case A_int_resellun: 
  652                         INCSTAT(siop_stat_intr_lunresel);
  653                         target = bus_space_read_1(sc->sc_c.sc_rt,
  654                             sc->sc_c.sc_rh, SIOP_SCRATCHA) & 0xf;
  655                         lun = bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
  656                             SIOP_SCRATCHA + 1);
  657                         tag = bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
  658                             SIOP_SCRATCHA + 2);
  659                         siop_target =
  660                             (struct siop_target *)sc->sc_c.targets[target];
  661                         if (siop_target == NULL) {
  662                                 printf("%s: reselect with invalid target %d\n",
  663                                     sc->sc_c.sc_dev.dv_xname, target);
  664                                 goto reset;
  665                         }
  666                         siop_lun = siop_target->siop_lun[lun];
  667                         if (siop_lun == NULL) {
  668                                 printf("%s: target %d reselect with invalid "
  669                                     "lun %d\n", sc->sc_c.sc_dev.dv_xname,
  670                                     target, lun);
  671                                 goto reset;
  672                         }
  673                         if (siop_lun->siop_tag[tag].active == NULL) {
  674                                 printf("%s: target %d lun %d tag %d reselect "
  675                                     "without command\n",
  676                                     sc->sc_c.sc_dev.dv_xname,
  677                                     target, lun, tag);
  678                                 goto reset;
  679                         }
  680                         siop_cmd = siop_lun->siop_tag[tag].active;
  681                         bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
  682                             SIOP_DSP, siop_cmd->cmd_c.dsa +
  683                             sizeof(struct siop_common_xfer) +
  684                             Ent_ldsa_reload_dsa);
  685                         siop_table_sync(siop_cmd, BUS_DMASYNC_PREWRITE);
  686                         return 1;
  687                 case A_int_reseltag:
  688                         printf("%s: reselect with invalid tag\n",
  689                                     sc->sc_c.sc_dev.dv_xname);
  690                         goto reset;
  691                 case A_int_msgin:
  692                 {
  693                         int msgin = bus_space_read_1(sc->sc_c.sc_rt,
  694                             sc->sc_c.sc_rh, SIOP_SFBR);
  695                         if (msgin == MSG_MESSAGE_REJECT) {
  696                                 int msg, extmsg;
  697                                 if (siop_cmd->cmd_tables->msg_out[0] & 0x80) {
  698                                         /*
  699                                          * message was part of a identify +
  700                                          * something else. Identify shouldn't
  701                                          * have been rejected.
  702                                          */
  703                                         msg =
  704                                             siop_cmd->cmd_tables->msg_out[1];
  705                                         extmsg =
  706                                             siop_cmd->cmd_tables->msg_out[3];
  707                                 } else {
  708                                         msg = siop_cmd->cmd_tables->msg_out[0];
  709                                         extmsg =
  710                                             siop_cmd->cmd_tables->msg_out[2];
  711                                 }
  712                                 if (msg == MSG_MESSAGE_REJECT) {
  713                                         /* MSG_REJECT  for a MSG_REJECT  !*/
  714                                         if (xs)
  715                                                 scsipi_printaddr(xs->xs_periph);
  716                                         else
  717                                                 printf("%s: ",
  718                                                    sc->sc_c.sc_dev.dv_xname);
  719                                         printf("our reject message was "
  720                                             "rejected\n");
  721                                         goto reset;
  722                                 }
  723                                 if (msg == MSG_EXTENDED &&
  724                                     extmsg == MSG_EXT_WDTR) {
  725                                         /* WDTR rejected, initiate sync */
  726                                         if ((siop_target->target_c.flags &
  727                                            TARF_SYNC) == 0) {
  728                                                 siop_target->target_c.status =
  729                                                     TARST_OK;
  730                                                 siop_update_xfer_mode(&sc->sc_c,
  731                                                     target);
  732                                                 /* no table to flush here */
  733                                                 CALL_SCRIPT(Ent_msgin_ack);
  734                                                 return 1;
  735                                         }
  736                                         siop_target->target_c.status =
  737                                             TARST_SYNC_NEG;
  738                                         siop_sdtr_msg(&siop_cmd->cmd_c, 0,
  739                                             sc->sc_c.st_minsync,
  740                                             sc->sc_c.maxoff);
  741                                         siop_table_sync(siop_cmd,
  742                                             BUS_DMASYNC_PREREAD |
  743                                             BUS_DMASYNC_PREWRITE);
  744                                         CALL_SCRIPT(Ent_send_msgout);
  745                                         return 1;
  746                                 } else if (msg == MSG_EXTENDED &&
  747                                     extmsg == MSG_EXT_SDTR) {
  748                                         /* sync rejected */
  749                                         siop_target->target_c.offset = 0;
  750                                         siop_target->target_c.period = 0;
  751                                         siop_target->target_c.status = TARST_OK;
  752                                         siop_update_xfer_mode(&sc->sc_c,
  753                                             target);
  754                                         /* no table to flush here */
  755                                         CALL_SCRIPT(Ent_msgin_ack);
  756                                         return 1;
  757                                 } else if (msg == MSG_SIMPLE_Q_TAG || 
  758                                     msg == MSG_HEAD_OF_Q_TAG ||
  759                                     msg == MSG_ORDERED_Q_TAG) {
  760                                         if (siop_handle_qtag_reject(
  761                                             siop_cmd) == -1)
  762                                                 goto reset;
  763                                         CALL_SCRIPT(Ent_msgin_ack);
  764                                         return 1;
  765                                 }
  766                                 if (xs)
  767                                         scsipi_printaddr(xs->xs_periph);
  768                                 else
  769                                         printf("%s: ",
  770                                             sc->sc_c.sc_dev.dv_xname);
  771                                 if (msg == MSG_EXTENDED) {
  772                                         printf("scsi message reject, extended "
  773                                             "message sent was 0x%x\n", extmsg);
  774                                 } else {
  775                                         printf("scsi message reject, message "
  776                                             "sent was 0x%x\n", msg);
  777                                 }
  778                                 /* no table to flush here */
  779                                 CALL_SCRIPT(Ent_msgin_ack);
  780                                 return 1;
  781                         }
  782                         if (xs)
  783                                 scsipi_printaddr(xs->xs_periph);
  784                         else
  785                                 printf("%s: ", sc->sc_c.sc_dev.dv_xname);
  786                         printf("unhandled message 0x%x\n",
  787                             siop_cmd->cmd_tables->msg_in[0]);
  788                         siop_cmd->cmd_tables->msg_out[0] = MSG_MESSAGE_REJECT;
  789                         siop_cmd->cmd_tables->t_msgout.count= htole32(1);
  790                         siop_table_sync(siop_cmd,
  791                             BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
  792                         CALL_SCRIPT(Ent_send_msgout);
  793                         return 1;
  794                 }
  795                 case A_int_extmsgin:
  796 #ifdef SIOP_DEBUG_INTR
  797                         printf("extended message: msg 0x%x len %d\n",
  798                             siop_cmd->cmd_tables->msg_in[2], 
  799                             siop_cmd->cmd_tables->msg_in[1]);
  800 #endif
  801                         if (siop_cmd->cmd_tables->msg_in[1] >
  802                             sizeof(siop_cmd->cmd_tables->msg_in) - 2)
  803                                 printf("%s: extended message too big (%d)\n",
  804                                     sc->sc_c.sc_dev.dv_xname,
  805                                     siop_cmd->cmd_tables->msg_in[1]);
  806                         siop_cmd->cmd_tables->t_extmsgdata.count =
  807                             htole32(siop_cmd->cmd_tables->msg_in[1] - 1);
  808                         siop_table_sync(siop_cmd,
  809                             BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
  810                         CALL_SCRIPT(Ent_get_extmsgdata);
  811                         return 1;
  812                 case A_int_extmsgdata:
  813 #ifdef SIOP_DEBUG_INTR
  814                         {
  815                         int i;
  816                         printf("extended message: 0x%x, data:",
  817                             siop_cmd->cmd_tables->msg_in[2]);
  818                         for (i = 3; i < 2 + siop_cmd->cmd_tables->msg_in[1];
  819                             i++)
  820                                 printf(" 0x%x",
  821                                     siop_cmd->cmd_tables->msg_in[i]);
  822                         printf("\n");
  823                         }
  824 #endif
  825                         if (siop_cmd->cmd_tables->msg_in[2] == MSG_EXT_WDTR) {
  826                                 switch (siop_wdtr_neg(&siop_cmd->cmd_c)) {
  827                                 case SIOP_NEG_MSGOUT:
  828                                         siop_update_scntl3(sc,
  829                                             siop_cmd->cmd_c.siop_target);
  830                                         siop_table_sync(siop_cmd,
  831                                             BUS_DMASYNC_PREREAD |
  832                                             BUS_DMASYNC_PREWRITE);
  833                                         CALL_SCRIPT(Ent_send_msgout);
  834                                         return(1);
  835                                 case SIOP_NEG_ACK:
  836                                         siop_update_scntl3(sc,
  837                                             siop_cmd->cmd_c.siop_target);
  838                                         CALL_SCRIPT(Ent_msgin_ack);
  839                                         return(1);
  840                                 default:
  841                                         panic("invalid retval from "
  842                                             "siop_wdtr_neg()");
  843                                 }
  844                                 return(1);
  845                         }
  846                         if (siop_cmd->cmd_tables->msg_in[2] == MSG_EXT_SDTR) {
  847                                 switch (siop_sdtr_neg(&siop_cmd->cmd_c)) {
  848                                 case SIOP_NEG_MSGOUT:
  849                                         siop_update_scntl3(sc,
  850                                             siop_cmd->cmd_c.siop_target);
  851                                         siop_table_sync(siop_cmd,
  852                                             BUS_DMASYNC_PREREAD |
  853                                             BUS_DMASYNC_PREWRITE);
  854                                         CALL_SCRIPT(Ent_send_msgout);
  855                                         return(1);
  856                                 case SIOP_NEG_ACK:
  857                                         siop_update_scntl3(sc,
  858                                             siop_cmd->cmd_c.siop_target);
  859                                         CALL_SCRIPT(Ent_msgin_ack);
  860                                         return(1);
  861                                 default:
  862                                         panic("invalid retval from "
  863                                             "siop_wdtr_neg()");
  864                                 }
  865                                 return(1);
  866                         }
  867                         /* send a message reject */
  868                         siop_cmd->cmd_tables->msg_out[0] = MSG_MESSAGE_REJECT;
  869                         siop_cmd->cmd_tables->t_msgout.count = htole32(1);
  870                         siop_table_sync(siop_cmd,
  871                             BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
  872                         CALL_SCRIPT(Ent_send_msgout);
  873                         return 1;
  874                 case A_int_disc:
  875                         INCSTAT(siop_stat_intr_sdp);
  876                         offset = bus_space_read_1(sc->sc_c.sc_rt,
  877                             sc->sc_c.sc_rh, SIOP_SCRATCHA + 1);
  878 #ifdef SIOP_DEBUG_DR
  879                         printf("disconnect offset %d\n", offset);
  880 #endif
  881                         if (offset > SIOP_NSG) {
  882                                 printf("%s: bad offset for disconnect (%d)\n",
  883                                     sc->sc_c.sc_dev.dv_xname, offset);
  884                                 goto reset;
  885                         }
  886                         /* 
  887                          * offset == SIOP_NSG may be a valid condition if
  888                          * we get a sdp when the xfer is done.
  889                          * Don't call memmove in this case.
  890                          */
  891                         if (offset < SIOP_NSG) {
  892                                 memmove(&siop_cmd->cmd_tables->data[0],
  893                                     &siop_cmd->cmd_tables->data[offset],
  894                                     (SIOP_NSG - offset) * sizeof(scr_table_t));
  895                                 siop_table_sync(siop_cmd,
  896                                     BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
  897                         }
  898                         CALL_SCRIPT(Ent_script_sched);
  899                         return 1;
  900                 case A_int_resfail:
  901                         printf("reselect failed\n");
  902                         CALL_SCRIPT(Ent_script_sched);
  903                         return  1;
  904                 case A_int_done:
  905                         if (xs == NULL) {
  906                                 printf("%s: done without command, DSA=0x%lx\n",
  907                                     sc->sc_c.sc_dev.dv_xname,
  908                                     (u_long)siop_cmd->cmd_c.dsa);
  909                                 siop_cmd->cmd_c.status = CMDST_FREE;
  910                                 CALL_SCRIPT(Ent_script_sched);
  911                                 return 1;
  912                         }
  913 #ifdef SIOP_DEBUG_INTR
  914                         printf("done, DSA=0x%lx target id 0x%x last msg "
  915                             "in=0x%x status=0x%x\n", (u_long)siop_cmd->cmd_c.dsa,
  916                             le32toh(siop_cmd->cmd_tables->id),
  917                             siop_cmd->cmd_tables->msg_in[0],
  918                             le32toh(siop_cmd->cmd_tables->status));
  919 #endif
  920                         INCSTAT(siop_stat_intr_done);
  921                         siop_cmd->cmd_c.status = CMDST_DONE;
  922                         goto end;
  923                 default:
  924                         printf("unknown irqcode %x\n", irqcode);
  925                         if (xs) {
  926                                 xs->error = XS_SELTIMEOUT;
  927                                 goto end;
  928                         }
  929                         goto reset;
  930                 }
  931                 return 1;
  932         }
  933         /* We just should't get there */
  934         panic("siop_intr: I shouldn't be there !");
  935 
  936 end:
  937         /*
  938          * restart the script now if command completed properly
  939          * Otherwise wait for siop_scsicmd_end(), we may need to cleanup the
  940          * queue
  941          */
  942         xs->status = le32toh(siop_cmd->cmd_tables->status);
  943         if (xs->status == SCSI_OK)
  944                 CALL_SCRIPT(Ent_script_sched);
  945         else
  946                 restart = 1;
  947         siop_lun->siop_tag[tag].active = NULL;
  948         siop_scsicmd_end(siop_cmd);
  949         if (freetarget && siop_target->target_c.status == TARST_PROBING)
  950                 siop_del_dev(sc, target, lun);
  951         if (restart)
  952                 CALL_SCRIPT(Ent_script_sched);
  953         if (sc->sc_flags & SCF_CHAN_NOSLOT) {
  954                 /* a command terminated, so we have free slots now */
  955                 sc->sc_flags &= ~SCF_CHAN_NOSLOT;
  956                 scsipi_channel_thaw(&sc->sc_c.sc_chan, 1);
  957         }
  958                 
  959         return 1;
  960 }
  961 
  962 void
  963 siop_scsicmd_end(siop_cmd)
  964         struct siop_cmd *siop_cmd;
  965 {
  966         struct scsipi_xfer *xs = siop_cmd->cmd_c.xs;
  967         struct siop_softc *sc = (struct siop_softc *)siop_cmd->cmd_c.siop_sc;
  968 
  969         switch(xs->status) {
  970         case SCSI_OK:
  971                 xs->error = XS_NOERROR;
  972                 break;
  973         case SCSI_BUSY:
  974                 xs->error = XS_BUSY;
  975                 break;
  976         case SCSI_CHECK:
  977                 xs->error = XS_BUSY;
  978                 /* remove commands in the queue and scheduler */
  979                 siop_unqueue(sc, xs->xs_periph->periph_target,
  980                     xs->xs_periph->periph_lun);
  981                 break;
  982         case SCSI_QUEUE_FULL:
  983                 INCSTAT(siop_stat_intr_qfull);
  984 #ifdef SIOP_DEBUG
  985                 printf("%s:%d:%d: queue full (tag %d)\n",
  986                     sc->sc_c.sc_dev.dv_xname,
  987                     xs->xs_periph->periph_target,
  988                     xs->xs_periph->periph_lun, siop_cmd->cmd_c.tag);
  989 #endif
  990                 xs->error = XS_BUSY;
  991                 break;
  992         case SCSI_SIOP_NOCHECK:
  993                 /*
  994                  * don't check status, xs->error is already valid
  995                  */
  996                 break;
  997         case SCSI_SIOP_NOSTATUS:
  998                 /*
  999                  * the status byte was not updated, cmd was
 1000                  * aborted
 1001                  */
 1002                 xs->error = XS_SELTIMEOUT;
 1003                 break;
 1004         default:
 1005                 scsipi_printaddr(xs->xs_periph);
 1006                 printf("invalid status code %d\n", xs->status);
 1007                 xs->error = XS_DRIVER_STUFFUP;
 1008         }
 1009         if (xs->xs_control & (XS_CTL_DATA_IN | XS_CTL_DATA_OUT)) {
 1010                 bus_dmamap_sync(sc->sc_c.sc_dmat, siop_cmd->cmd_c.dmamap_data, 0,
 1011                     siop_cmd->cmd_c.dmamap_data->dm_mapsize,
 1012                     (xs->xs_control & XS_CTL_DATA_IN) ?
 1013                     BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
 1014                 bus_dmamap_unload(sc->sc_c.sc_dmat, siop_cmd->cmd_c.dmamap_data);
 1015         }
 1016         bus_dmamap_unload(sc->sc_c.sc_dmat, siop_cmd->cmd_c.dmamap_cmd);
 1017         callout_stop(&siop_cmd->cmd_c.xs->xs_callout);
 1018         siop_cmd->cmd_c.status = CMDST_FREE;
 1019         TAILQ_INSERT_TAIL(&sc->free_list, siop_cmd, next);
 1020         xs->resid = 0;
 1021         scsipi_done (xs);
 1022 }
 1023 
 1024 void
 1025 siop_unqueue(sc, target, lun)
 1026         struct siop_softc *sc;
 1027         int target;
 1028         int lun;
 1029 {
 1030         int slot, tag;
 1031         struct siop_cmd *siop_cmd;
 1032         struct siop_lun *siop_lun =
 1033             ((struct siop_target *)sc->sc_c.targets[target])->siop_lun[lun];
 1034 
 1035         /* first make sure to read valid data */
 1036         siop_script_sync(sc, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
 1037 
 1038         for (tag = 1; tag < SIOP_NTAG; tag++) {
 1039                 /* look for commands in the scheduler, not yet started */
 1040                 if (siop_lun->siop_tag[tag].active == NULL) 
 1041                         continue;
 1042                 siop_cmd = siop_lun->siop_tag[tag].active;
 1043                 for (slot = 0; slot <= sc->sc_currschedslot; slot++) {
 1044                         if (siop_script_read(sc,
 1045                             (Ent_script_sched_slot0 / 4) + slot * 2 + 1) ==
 1046                             siop_cmd->cmd_c.dsa +
 1047                             sizeof(struct siop_common_xfer) +
 1048                             Ent_ldsa_select)
 1049                                 break;
 1050                 }
 1051                 if (slot >  sc->sc_currschedslot)
 1052                         continue; /* didn't find it */
 1053                 if (siop_script_read(sc,
 1054                     (Ent_script_sched_slot0 / 4) + slot * 2) == 0x80000000)
 1055                         continue; /* already started */
 1056                 /* clear the slot */
 1057                 siop_script_write(sc, (Ent_script_sched_slot0 / 4) + slot * 2,
 1058                     0x80000000);
 1059                 /* ask to requeue */
 1060                 siop_cmd->cmd_c.xs->error = XS_REQUEUE;
 1061                 siop_cmd->cmd_c.xs->status = SCSI_SIOP_NOCHECK;
 1062                 siop_lun->siop_tag[tag].active = NULL;
 1063                 siop_scsicmd_end(siop_cmd);
 1064         }
 1065         /* update sc_currschedslot */
 1066         sc->sc_currschedslot = 0;
 1067         for (slot = SIOP_NSLOTS - 1; slot >= 0; slot--) {
 1068                 if (siop_script_read(sc,
 1069                     (Ent_script_sched_slot0 / 4) + slot * 2) != 0x80000000)
 1070                         sc->sc_currschedslot = slot;
 1071         }
 1072 }
 1073 
 1074 /*
 1075  * handle a rejected queue tag message: the command will run untagged,
 1076  * has to adjust the reselect script.
 1077  */
 1078 int
 1079 siop_handle_qtag_reject(siop_cmd)
 1080         struct siop_cmd *siop_cmd;
 1081 {
 1082         struct siop_softc *sc = (struct siop_softc *)siop_cmd->cmd_c.siop_sc;
 1083         int target = siop_cmd->cmd_c.xs->xs_periph->periph_target;
 1084         int lun = siop_cmd->cmd_c.xs->xs_periph->periph_lun;
 1085         int tag = siop_cmd->cmd_tables->msg_out[2];
 1086         struct siop_lun *siop_lun =
 1087             ((struct siop_target*)sc->sc_c.targets[target])->siop_lun[lun];
 1088 
 1089 #ifdef SIOP_DEBUG
 1090         printf("%s:%d:%d: tag message %d (%d) rejected (status %d)\n",
 1091             sc->sc_c.sc_dev.dv_xname, target, lun, tag, siop_cmd->cmd_c.tag,
 1092             siop_cmd->cmd_c.status);
 1093 #endif
 1094 
 1095         if (siop_lun->siop_tag[0].active != NULL) {
 1096                 printf("%s: untagged command already running for target %d "
 1097                     "lun %d (status %d)\n", sc->sc_c.sc_dev.dv_xname,
 1098                     target, lun, siop_lun->siop_tag[0].active->cmd_c.status);
 1099                 return -1;
 1100         }
 1101         /* clear tag slot */
 1102         siop_lun->siop_tag[tag].active = NULL;
 1103         /* add command to non-tagged slot */
 1104         siop_lun->siop_tag[0].active = siop_cmd;
 1105         siop_cmd->cmd_c.tag = 0;
 1106         /* adjust reselect script if there is one */
 1107         if (siop_lun->siop_tag[0].reseloff > 0) {
 1108                 siop_script_write(sc,
 1109                     siop_lun->siop_tag[0].reseloff + 1,
 1110                     siop_cmd->cmd_c.dsa + sizeof(struct siop_common_xfer) +
 1111                     Ent_ldsa_reload_dsa);
 1112                 siop_table_sync(siop_cmd, BUS_DMASYNC_PREWRITE);
 1113         }
 1114         return 0;
 1115 }
 1116 
 1117 /*
 1118  * handle a bus reset: reset chip, unqueue all active commands, free all
 1119  * target struct and report lossage to upper layer.
 1120  * As the upper layer may requeue immediatly we have to first store
 1121  * all active commands in a temporary queue.
 1122  */
 1123 void
 1124 siop_handle_reset(sc)
 1125         struct siop_softc *sc;
 1126 {
 1127         struct siop_cmd *siop_cmd;
 1128         struct siop_lun *siop_lun;
 1129         int target, lun, tag;
 1130         /*
 1131          * scsi bus reset. reset the chip and restart
 1132          * the queue. Need to clean up all active commands
 1133          */
 1134         printf("%s: scsi bus reset\n", sc->sc_c.sc_dev.dv_xname);
 1135         /* stop, reset and restart the chip */
 1136         siop_reset(sc);
 1137         if (sc->sc_flags & SCF_CHAN_NOSLOT) {
 1138                 /* chip has been reset, all slots are free now */
 1139                 sc->sc_flags &= ~SCF_CHAN_NOSLOT;
 1140                 scsipi_channel_thaw(&sc->sc_c.sc_chan, 1);
 1141         }
 1142         /*
 1143          * Process all commands: first commands being executed
 1144          */
 1145         for (target = 0; target < sc->sc_c.sc_chan.chan_ntargets;
 1146             target++) {
 1147                 if (sc->sc_c.targets[target] == NULL)
 1148                         continue;
 1149                 for (lun = 0; lun < 8; lun++) {
 1150                         struct siop_target *siop_target = 
 1151                             (struct siop_target *)sc->sc_c.targets[target];
 1152                         siop_lun = siop_target->siop_lun[lun];
 1153                         if (siop_lun == NULL)
 1154                                 continue;
 1155                         for (tag = 0; tag <
 1156                             ((sc->sc_c.targets[target]->flags & TARF_TAG) ?
 1157                             SIOP_NTAG : 1);
 1158                             tag++) {
 1159                                 siop_cmd = siop_lun->siop_tag[tag].active;
 1160                                 if (siop_cmd == NULL)
 1161                                         continue;
 1162                                 scsipi_printaddr(siop_cmd->cmd_c.xs->xs_periph);
 1163                                 printf("command with tag id %d reset\n", tag);
 1164                                 siop_cmd->cmd_c.xs->error =
 1165                                     (siop_cmd->cmd_c.flags & CMDFL_TIMEOUT) ?
 1166                                     XS_TIMEOUT : XS_RESET;
 1167                                 siop_cmd->cmd_c.xs->status = SCSI_SIOP_NOCHECK;
 1168                                 siop_lun->siop_tag[tag].active = NULL;
 1169                                 siop_cmd->cmd_c.status = CMDST_DONE;
 1170                                 siop_scsicmd_end(siop_cmd);
 1171                         }
 1172                 }
 1173                 sc->sc_c.targets[target]->status = TARST_ASYNC;
 1174                 sc->sc_c.targets[target]->flags &= ~TARF_ISWIDE;
 1175                 sc->sc_c.targets[target]->period =
 1176                     sc->sc_c.targets[target]->offset = 0;
 1177                 siop_update_xfer_mode(&sc->sc_c, target);
 1178         }
 1179 
 1180         scsipi_async_event(&sc->sc_c.sc_chan, ASYNC_EVENT_RESET, NULL);
 1181 }
 1182 
 1183 void
 1184 siop_scsipi_request(chan, req, arg)
 1185         struct scsipi_channel *chan;
 1186         scsipi_adapter_req_t req;
 1187         void *arg;
 1188 {
 1189         struct scsipi_xfer *xs;
 1190         struct scsipi_periph *periph;
 1191         struct siop_softc *sc = (void *)chan->chan_adapter->adapt_dev;
 1192         struct siop_cmd *siop_cmd;
 1193         struct siop_target *siop_target;
 1194         int s, error, i;
 1195         int target;
 1196         int lun;
 1197 
 1198         switch (req) {
 1199         case ADAPTER_REQ_RUN_XFER:
 1200                 xs = arg;
 1201                 periph = xs->xs_periph;
 1202                 target = periph->periph_target;
 1203                 lun = periph->periph_lun;
 1204 
 1205                 s = splbio();
 1206 #ifdef SIOP_DEBUG_SCHED
 1207                 printf("starting cmd for %d:%d\n", target, lun);
 1208 #endif
 1209                 siop_cmd = TAILQ_FIRST(&sc->free_list);
 1210                 if (siop_cmd == NULL) {
 1211                         xs->error = XS_RESOURCE_SHORTAGE;
 1212                         scsipi_done(xs);
 1213                         splx(s);
 1214                         return;
 1215                 }
 1216                 TAILQ_REMOVE(&sc->free_list, siop_cmd, next);
 1217 #ifdef DIAGNOSTIC
 1218                 if (siop_cmd->cmd_c.status != CMDST_FREE)
 1219                         panic("siop_scsicmd: new cmd not free");
 1220 #endif
 1221                 siop_target = (struct siop_target*)sc->sc_c.targets[target];
 1222                 if (siop_target == NULL) {
 1223 #ifdef SIOP_DEBUG
 1224                         printf("%s: alloc siop_target for target %d\n",
 1225                                 sc->sc_c.sc_dev.dv_xname, target);
 1226 #endif
 1227                         sc->sc_c.targets[target] =
 1228                             malloc(sizeof(struct siop_target),
 1229                                 M_DEVBUF, M_NOWAIT);
 1230                         if (sc->sc_c.targets[target] == NULL) {
 1231                                 printf("%s: can't malloc memory for "
 1232                                     "target %d\n", sc->sc_c.sc_dev.dv_xname,
 1233                                     target);
 1234                                 xs->error = XS_RESOURCE_SHORTAGE;
 1235                                 scsipi_done(xs);
 1236                                 splx(s);
 1237                                 return;
 1238                         }
 1239                         siop_target =
 1240                             (struct siop_target*)sc->sc_c.targets[target];
 1241                         siop_target->target_c.status = TARST_PROBING;
 1242                         siop_target->target_c.flags = 0;
 1243                         siop_target->target_c.id =
 1244                             sc->sc_c.clock_div << 24; /* scntl3 */
 1245                         siop_target->target_c.id |=  target << 16; /* id */
 1246                         /* siop_target->target_c.id |= 0x0 << 8; scxfer is 0 */
 1247 
 1248                         /* get a lun switch script */
 1249                         siop_target->lunsw = siop_get_lunsw(sc);
 1250                         if (siop_target->lunsw == NULL) {
 1251                                 printf("%s: can't alloc lunsw for target %d\n",
 1252                                     sc->sc_c.sc_dev.dv_xname, target);
 1253                                 xs->error = XS_RESOURCE_SHORTAGE;
 1254                                 scsipi_done(xs);
 1255                                 splx(s);
 1256                                 return;
 1257                         }
 1258                         for (i=0; i < 8; i++)
 1259                                 siop_target->siop_lun[i] = NULL;
 1260                         siop_add_reselsw(sc, target);
 1261                 }
 1262                 if (siop_target->siop_lun[lun] == NULL) {
 1263                         siop_target->siop_lun[lun] =
 1264                             malloc(sizeof(struct siop_lun), M_DEVBUF,
 1265                             M_NOWAIT|M_ZERO);
 1266                         if (siop_target->siop_lun[lun] == NULL) {
 1267                                 printf("%s: can't alloc siop_lun for "
 1268                                     "target %d lun %d\n",
 1269                                     sc->sc_c.sc_dev.dv_xname, target, lun);
 1270                                 xs->error = XS_RESOURCE_SHORTAGE;
 1271                                 scsipi_done(xs);
 1272                                 splx(s);
 1273                                 return;
 1274                         }
 1275                 }
 1276                 siop_cmd->cmd_c.siop_target = sc->sc_c.targets[target];
 1277                 siop_cmd->cmd_c.xs = xs;
 1278                 siop_cmd->cmd_c.flags = 0;
 1279                 siop_cmd->cmd_c.status = CMDST_READY;
 1280 
 1281                 /* load the DMA maps */
 1282                 error = bus_dmamap_load(sc->sc_c.sc_dmat,
 1283                     siop_cmd->cmd_c.dmamap_cmd,
 1284                     xs->cmd, xs->cmdlen, NULL, BUS_DMA_NOWAIT);
 1285                 if (error) {
 1286                         printf("%s: unable to load cmd DMA map: %d\n",
 1287                             sc->sc_c.sc_dev.dv_xname, error);
 1288                         xs->error = XS_DRIVER_STUFFUP;
 1289                         scsipi_done(xs);
 1290                         splx(s);
 1291                         return;
 1292                 }
 1293                 if (xs->xs_control & (XS_CTL_DATA_IN | XS_CTL_DATA_OUT)) {
 1294                         error = bus_dmamap_load(sc->sc_c.sc_dmat,
 1295                             siop_cmd->cmd_c.dmamap_data, xs->data, xs->datalen,
 1296                             NULL, BUS_DMA_NOWAIT | BUS_DMA_STREAMING |
 1297                             ((xs->xs_control & XS_CTL_DATA_IN) ?
 1298                              BUS_DMA_READ : BUS_DMA_WRITE));
 1299                         if (error) {
 1300                                 printf("%s: unable to load cmd DMA map: %d",
 1301                                     sc->sc_c.sc_dev.dv_xname, error);
 1302                                 xs->error = XS_DRIVER_STUFFUP;
 1303                                 scsipi_done(xs);
 1304                                 bus_dmamap_unload(sc->sc_c.sc_dmat,
 1305                                     siop_cmd->cmd_c.dmamap_cmd);
 1306                                 splx(s);
 1307                                 return;
 1308                         }
 1309                         bus_dmamap_sync(sc->sc_c.sc_dmat,
 1310                             siop_cmd->cmd_c.dmamap_data, 0,
 1311                             siop_cmd->cmd_c.dmamap_data->dm_mapsize,
 1312                             (xs->xs_control & XS_CTL_DATA_IN) ?
 1313                             BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
 1314                 }
 1315                 bus_dmamap_sync(sc->sc_c.sc_dmat, siop_cmd->cmd_c.dmamap_cmd, 0,
 1316                     siop_cmd->cmd_c.dmamap_cmd->dm_mapsize,
 1317                     BUS_DMASYNC_PREWRITE);
 1318 
 1319                 if (xs->xs_tag_type) {
 1320                         /* use tag_id + 1, tag 0 is reserved for untagged cmds*/
 1321                         siop_cmd->cmd_c.tag = xs->xs_tag_id + 1;
 1322                 } else {
 1323                         siop_cmd->cmd_c.tag = 0;
 1324                 }
 1325                 siop_setuptables(&siop_cmd->cmd_c);
 1326                 siop_table_sync(siop_cmd,
 1327                     BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 1328                 siop_start(sc, siop_cmd);
 1329                 if (xs->xs_control & XS_CTL_POLL) {
 1330                         /* poll for command completion */
 1331                         while ((xs->xs_status & XS_STS_DONE) == 0) {
 1332                                 delay(1000);
 1333                                 siop_intr(sc);
 1334                         }
 1335                 }
 1336                 splx(s);
 1337                 return;
 1338 
 1339         case ADAPTER_REQ_GROW_RESOURCES:
 1340 #ifdef SIOP_DEBUG
 1341                 printf("%s grow resources (%d)\n", sc->sc_c.sc_dev.dv_xname,
 1342                     sc->sc_c.sc_adapt.adapt_openings);
 1343 #endif
 1344                 siop_morecbd(sc);
 1345                 return;
 1346 
 1347         case ADAPTER_REQ_SET_XFER_MODE:
 1348         {
 1349                 struct scsipi_xfer_mode *xm = arg;
 1350                 if (sc->sc_c.targets[xm->xm_target] == NULL)
 1351                         return;
 1352                 s = splbio();
 1353                 if (xm->xm_mode & PERIPH_CAP_TQING)
 1354                         sc->sc_c.targets[xm->xm_target]->flags |= TARF_TAG;
 1355                 if ((xm->xm_mode & PERIPH_CAP_WIDE16) &&
 1356                     (sc->sc_c.features & SF_BUS_WIDE))
 1357                         sc->sc_c.targets[xm->xm_target]->flags |= TARF_WIDE;
 1358                 if (xm->xm_mode & PERIPH_CAP_SYNC)
 1359                         sc->sc_c.targets[xm->xm_target]->flags |= TARF_SYNC;
 1360                 if ((xm->xm_mode & (PERIPH_CAP_SYNC | PERIPH_CAP_WIDE16)) ||
 1361                     sc->sc_c.targets[xm->xm_target]->status == TARST_PROBING)
 1362                         sc->sc_c.targets[xm->xm_target]->status =
 1363                             TARST_ASYNC;
 1364 
 1365                 for (lun = 0; lun < sc->sc_c.sc_chan.chan_nluns; lun++) {
 1366                         if (scsipi_lookup_periph(chan,
 1367                             xm->xm_target, lun) != NULL) {
 1368                                 /* allocate a lun sw entry for this device */
 1369                                 siop_add_dev(sc, xm->xm_target, lun);
 1370                         }
 1371                 }
 1372 
 1373                 splx(s);
 1374         }
 1375         }
 1376 }
 1377 
 1378 static void
 1379 siop_start(sc, siop_cmd)
 1380         struct siop_softc *sc;
 1381         struct siop_cmd *siop_cmd;
 1382 {
 1383         struct siop_lun *siop_lun;
 1384         struct siop_xfer *siop_xfer;
 1385         u_int32_t dsa;
 1386         int timeout;
 1387         int target, lun, slot;
 1388 
 1389         /*
 1390          * first make sure to read valid data
 1391          */
 1392         siop_script_sync(sc, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
 1393 
 1394         /*
 1395          * The queue management here is a bit tricky: the script always looks
 1396          * at the slot from first to last, so if we always use the first 
 1397          * free slot commands can stay at the tail of the queue ~forever.
 1398          * The algorithm used here is to restart from the head when we know
 1399          * that the queue is empty, and only add commands after the last one.
 1400          * When we're at the end of the queue wait for the script to clear it.
 1401          * The best thing to do here would be to implement a circular queue,
 1402          * but using only 53c720 features this can be "interesting".
 1403          * A mid-way solution could be to implement 2 queues and swap orders.
 1404          */
 1405         slot = sc->sc_currschedslot;
 1406         /*
 1407          * If the instruction is 0x80000000 (JUMP foo, IF FALSE) the slot is
 1408          * free. As this is the last used slot, all previous slots are free,
 1409          * we can restart from 0.
 1410          */
 1411         if (siop_script_read(sc, (Ent_script_sched_slot0 / 4) + slot * 2) ==
 1412             0x80000000) {
 1413                 slot = sc->sc_currschedslot = 0;
 1414         } else {
 1415                 slot++;
 1416         }
 1417         target = siop_cmd->cmd_c.xs->xs_periph->periph_target;
 1418         lun = siop_cmd->cmd_c.xs->xs_periph->periph_lun;
 1419         siop_lun =
 1420             ((struct siop_target*)sc->sc_c.targets[target])->siop_lun[lun];
 1421         /* if non-tagged command active, panic: this shouldn't happen */
 1422         if (siop_lun->siop_tag[0].active != NULL) {
 1423                 panic("siop_start: tagged cmd while untagged running");
 1424         }
 1425 #ifdef DIAGNOSTIC
 1426         /* sanity check the tag if needed */
 1427         if (siop_cmd->cmd_c.flags & CMDFL_TAG) {
 1428                 if (siop_lun->siop_tag[siop_cmd->cmd_c.tag].active != NULL)
 1429                         panic("siop_start: tag not free");
 1430                 if (siop_cmd->cmd_c.tag >= SIOP_NTAG) {
 1431                         scsipi_printaddr(siop_cmd->cmd_c.xs->xs_periph);
 1432                         printf(": tag id %d\n", siop_cmd->cmd_c.tag);
 1433                         panic("siop_start: invalid tag id");
 1434                 }
 1435         }
 1436 #endif
 1437         /*
 1438          * find a free scheduler slot and load it.
 1439          */
 1440         for (; slot < SIOP_NSLOTS; slot++) {
 1441                 /*
 1442                  * If cmd if 0x80000000 the slot is free
 1443                  */
 1444                 if (siop_script_read(sc,
 1445                     (Ent_script_sched_slot0 / 4) + slot * 2) ==
 1446                     0x80000000)
 1447                         break;
 1448         }
 1449         if (slot == SIOP_NSLOTS) {
 1450                 /*
 1451                  * no more free slot, no need to continue. freeze the queue
 1452                  * and requeue this command.
 1453                  */
 1454                 scsipi_channel_freeze(&sc->sc_c.sc_chan, 1);
 1455                 sc->sc_flags |= SCF_CHAN_NOSLOT;
 1456                 siop_cmd->cmd_c.xs->error = XS_REQUEUE;
 1457                 siop_cmd->cmd_c.xs->status = SCSI_SIOP_NOCHECK;
 1458                 siop_scsicmd_end(siop_cmd);
 1459                 return;
 1460         }
 1461 #ifdef SIOP_DEBUG_SCHED
 1462         printf("using slot %d for DSA 0x%lx\n", slot,
 1463             (u_long)siop_cmd->cmd_c.dsa);
 1464 #endif
 1465         /* mark command as active */
 1466         if (siop_cmd->cmd_c.status == CMDST_READY)
 1467                 siop_cmd->cmd_c.status = CMDST_ACTIVE;
 1468         else
 1469                 panic("siop_start: bad status");
 1470         siop_lun->siop_tag[siop_cmd->cmd_c.tag].active = siop_cmd;
 1471         /* patch scripts with DSA addr */
 1472         dsa = siop_cmd->cmd_c.dsa;
 1473         /* first reselect switch, if we have an entry */
 1474         if (siop_lun->siop_tag[siop_cmd->cmd_c.tag].reseloff > 0)
 1475                 siop_script_write(sc,
 1476                     siop_lun->siop_tag[siop_cmd->cmd_c.tag].reseloff + 1,
 1477                     dsa + sizeof(struct siop_common_xfer) +
 1478                     Ent_ldsa_reload_dsa);
 1479         /* CMD script: MOVE MEMORY addr */
 1480         siop_xfer = (struct siop_xfer*)siop_cmd->cmd_tables;
 1481         siop_xfer->resel[E_ldsa_abs_slot_Used[0]] = 
 1482            htole32(sc->sc_c.sc_scriptaddr + Ent_script_sched_slot0 + slot * 8);
 1483                 siop_table_sync(siop_cmd, BUS_DMASYNC_PREWRITE);
 1484         /* scheduler slot: JUMP ldsa_select */
 1485         siop_script_write(sc,
 1486             (Ent_script_sched_slot0 / 4) + slot * 2 + 1,
 1487             dsa + sizeof(struct siop_common_xfer) + Ent_ldsa_select);
 1488         /* handle timeout */
 1489         if ((siop_cmd->cmd_c.xs->xs_control & XS_CTL_POLL) == 0) {
 1490                 /* start exire timer */
 1491                 timeout = mstohz(siop_cmd->cmd_c.xs->timeout);
 1492                 if (timeout == 0)
 1493                         timeout = 1;
 1494                 callout_reset( &siop_cmd->cmd_c.xs->xs_callout,
 1495                     timeout, siop_timeout, siop_cmd);
 1496         }
 1497         /*
 1498          * Change JUMP cmd so that this slot will be handled
 1499          */
 1500         siop_script_write(sc, (Ent_script_sched_slot0 / 4) + slot * 2,
 1501             0x80080000);
 1502         sc->sc_currschedslot = slot;
 1503 
 1504         /* make sure SCRIPT processor will read valid data */
 1505         siop_script_sync(sc,BUS_DMASYNC_PREREAD |  BUS_DMASYNC_PREWRITE);
 1506         /* Signal script it has some work to do */
 1507         bus_space_write_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
 1508             SIOP_ISTAT, ISTAT_SIGP);
 1509         /* and wait for IRQ */
 1510         return;
 1511 }
 1512 
 1513 void
 1514 siop_timeout(v)
 1515         void *v;
 1516 {
 1517         struct siop_cmd *siop_cmd = v;
 1518         struct siop_softc *sc = (struct siop_softc *)siop_cmd->cmd_c.siop_sc;
 1519         int s;
 1520 
 1521         scsipi_printaddr(siop_cmd->cmd_c.xs->xs_periph);
 1522         printf("command timeout, CDB: ");
 1523         scsipi_print_cdb(siop_cmd->cmd_c.xs->cmd);
 1524         printf("\n");
 1525 
 1526         s = splbio();
 1527         /* reset the scsi bus */
 1528         siop_resetbus(&sc->sc_c);
 1529 
 1530         /* deactivate callout */
 1531         callout_stop(&siop_cmd->cmd_c.xs->xs_callout);
 1532         /* mark command as being timed out; siop_intr will handle it */
 1533         /*
 1534          * mark command has being timed out and just return;
 1535          * the bus reset will generate an interrupt,
 1536          * it will be handled in siop_intr()
 1537          */
 1538         siop_cmd->cmd_c.flags |= CMDFL_TIMEOUT;
 1539         splx(s);
 1540         return;
 1541 
 1542 }
 1543 
 1544 void
 1545 siop_dump_script(sc)
 1546         struct siop_softc *sc;
 1547 {
 1548         int i;
 1549         for (i = 0; i < PAGE_SIZE / 4; i += 2) {
 1550                 printf("0x%04x: 0x%08x 0x%08x", i * 4,
 1551                     le32toh(sc->sc_c.sc_script[i]),
 1552                     le32toh(sc->sc_c.sc_script[i+1]));
 1553                 if ((le32toh(sc->sc_c.sc_script[i]) & 0xe0000000) ==
 1554                     0xc0000000) {
 1555                         i++;
 1556                         printf(" 0x%08x", le32toh(sc->sc_c.sc_script[i+1]));
 1557                 }
 1558                 printf("\n");
 1559         }
 1560 }
 1561 
 1562 void
 1563 siop_morecbd(sc)
 1564         struct siop_softc *sc;
 1565 {
 1566         int error, i, j, s;
 1567         bus_dma_segment_t seg;
 1568         int rseg;
 1569         struct siop_cbd *newcbd;
 1570         struct siop_xfer *xfer;
 1571         bus_addr_t dsa;
 1572         u_int32_t *scr;
 1573 
 1574         /* allocate a new list head */
 1575         newcbd = malloc(sizeof(struct siop_cbd), M_DEVBUF, M_NOWAIT|M_ZERO);
 1576         if (newcbd == NULL) {
 1577                 printf("%s: can't allocate memory for command descriptors "
 1578                     "head\n", sc->sc_c.sc_dev.dv_xname);
 1579                 return;
 1580         }
 1581 
 1582         /* allocate cmd list */
 1583         newcbd->cmds = malloc(sizeof(struct siop_cmd) * SIOP_NCMDPB,
 1584             M_DEVBUF, M_NOWAIT|M_ZERO);
 1585         if (newcbd->cmds == NULL) {
 1586                 printf("%s: can't allocate memory for command descriptors\n",
 1587                     sc->sc_c.sc_dev.dv_xname);
 1588                 goto bad3;
 1589         }
 1590         error = bus_dmamem_alloc(sc->sc_c.sc_dmat, PAGE_SIZE, PAGE_SIZE, 0, &seg,
 1591             1, &rseg, BUS_DMA_NOWAIT);
 1592         if (error) {
 1593                 printf("%s: unable to allocate cbd DMA memory, error = %d\n",
 1594                     sc->sc_c.sc_dev.dv_xname, error);
 1595                 goto bad2;
 1596         }
 1597         error = bus_dmamem_map(sc->sc_c.sc_dmat, &seg, rseg, PAGE_SIZE,
 1598             (caddr_t *)&newcbd->xfers, BUS_DMA_NOWAIT|BUS_DMA_COHERENT);
 1599         if (error) {
 1600                 printf("%s: unable to map cbd DMA memory, error = %d\n",
 1601                     sc->sc_c.sc_dev.dv_xname, error);
 1602                 goto bad2;
 1603         }
 1604         error = bus_dmamap_create(sc->sc_c.sc_dmat, PAGE_SIZE, 1, PAGE_SIZE, 0,
 1605             BUS_DMA_NOWAIT, &newcbd->xferdma);
 1606         if (error) {
 1607                 printf("%s: unable to create cbd DMA map, error = %d\n",
 1608                     sc->sc_c.sc_dev.dv_xname, error);
 1609                 goto bad1;
 1610         }
 1611         error = bus_dmamap_load(sc->sc_c.sc_dmat, newcbd->xferdma, newcbd->xfers,
 1612             PAGE_SIZE, NULL, BUS_DMA_NOWAIT);
 1613         if (error) {
 1614                 printf("%s: unable to load cbd DMA map, error = %d\n",
 1615                     sc->sc_c.sc_dev.dv_xname, error);
 1616                 goto bad0;
 1617         }
 1618 #ifdef DEBUG
 1619         printf("%s: alloc newcdb at PHY addr 0x%lx\n", sc->sc_c.sc_dev.dv_xname,
 1620             (unsigned long)newcbd->xferdma->dm_segs[0].ds_addr);
 1621 #endif
 1622         for (i = 0; i < SIOP_NCMDPB; i++) {
 1623                 error = bus_dmamap_create(sc->sc_c.sc_dmat, MAXPHYS, SIOP_NSG,
 1624                     MAXPHYS, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
 1625                     &newcbd->cmds[i].cmd_c.dmamap_data);
 1626                 if (error) {
 1627                         printf("%s: unable to create data DMA map for cbd: "
 1628                             "error %d\n",
 1629                             sc->sc_c.sc_dev.dv_xname, error);
 1630                         goto bad0;
 1631                 }
 1632                 error = bus_dmamap_create(sc->sc_c.sc_dmat,
 1633                     sizeof(struct scsipi_generic), 1,
 1634                     sizeof(struct scsipi_generic), 0,
 1635                     BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
 1636                     &newcbd->cmds[i].cmd_c.dmamap_cmd);
 1637                 if (error) {
 1638                         printf("%s: unable to create cmd DMA map for cbd %d\n",
 1639                             sc->sc_c.sc_dev.dv_xname, error);
 1640                         goto bad0;
 1641                 }
 1642                 newcbd->cmds[i].cmd_c.siop_sc = &sc->sc_c;
 1643                 newcbd->cmds[i].siop_cbdp = newcbd;
 1644                 xfer = &newcbd->xfers[i];
 1645                 newcbd->cmds[i].cmd_tables = (struct siop_common_xfer *)xfer;
 1646                 memset(newcbd->cmds[i].cmd_tables, 0, sizeof(struct siop_xfer));
 1647                 dsa = newcbd->xferdma->dm_segs[0].ds_addr +
 1648                     i * sizeof(struct siop_xfer);
 1649                 newcbd->cmds[i].cmd_c.dsa = dsa;
 1650                 newcbd->cmds[i].cmd_c.status = CMDST_FREE;
 1651                 xfer->siop_tables.t_msgout.count= htole32(1);
 1652                 xfer->siop_tables.t_msgout.addr = htole32(dsa);
 1653                 xfer->siop_tables.t_msgin.count= htole32(1);
 1654                 xfer->siop_tables.t_msgin.addr = htole32(dsa +
 1655                                 offsetof(struct siop_common_xfer, msg_in));
 1656                 xfer->siop_tables.t_extmsgin.count= htole32(2);
 1657                 xfer->siop_tables.t_extmsgin.addr = htole32(dsa +
 1658                                 offsetof(struct siop_common_xfer, msg_in) + 1);
 1659                 xfer->siop_tables.t_extmsgdata.addr = htole32(dsa +
 1660                                 offsetof(struct siop_common_xfer, msg_in) + 3);
 1661                 xfer->siop_tables.t_status.count= htole32(1);
 1662                 xfer->siop_tables.t_status.addr = htole32(dsa +
 1663                                 offsetof(struct siop_common_xfer, status));
 1664                 /* The select/reselect script */
 1665                 scr = &xfer->resel[0];
 1666                 for (j = 0; j < sizeof(load_dsa) / sizeof(load_dsa[0]); j++)
 1667                         scr[j] = htole32(load_dsa[j]);
 1668                 /*
 1669                  * 0x78000000 is a 'move data8 to reg'. data8 is the second
 1670                  * octet, reg offset is the third.
 1671                  */
 1672                 scr[Ent_rdsa0 / 4] =
 1673                     htole32(0x78100000 | ((dsa & 0x000000ff) <<  8));
 1674                 scr[Ent_rdsa1 / 4] =
 1675                     htole32(0x78110000 | ( dsa & 0x0000ff00       ));
 1676                 scr[Ent_rdsa2 / 4] =
 1677                     htole32(0x78120000 | ((dsa & 0x00ff0000) >>  8));
 1678                 scr[Ent_rdsa3 / 4] =
 1679                     htole32(0x78130000 | ((dsa & 0xff000000) >> 16));
 1680                 scr[E_ldsa_abs_reselected_Used[0]] =
 1681                     htole32(sc->sc_c.sc_scriptaddr + Ent_reselected);
 1682                 scr[E_ldsa_abs_reselect_Used[0]] =
 1683                     htole32(sc->sc_c.sc_scriptaddr + Ent_reselect);
 1684                 scr[E_ldsa_abs_selected_Used[0]] =
 1685                     htole32(sc->sc_c.sc_scriptaddr + Ent_selected);
 1686                 scr[E_ldsa_abs_data_Used[0]] =
 1687                     htole32(dsa + sizeof(struct siop_common_xfer) +
 1688                     Ent_ldsa_data);
 1689                 /* JUMP foo, IF FALSE - used by MOVE MEMORY to clear the slot */
 1690                 scr[Ent_ldsa_data / 4] = htole32(0x80000000);
 1691                 s = splbio();
 1692                 TAILQ_INSERT_TAIL(&sc->free_list, &newcbd->cmds[i], next);
 1693                 splx(s);
 1694 #ifdef SIOP_DEBUG
 1695                 printf("tables[%d]: in=0x%x out=0x%x status=0x%x\n", i,
 1696                     le32toh(newcbd->cmds[i].cmd_tables->t_msgin.addr),
 1697                     le32toh(newcbd->cmds[i].cmd_tables->t_msgout.addr),
 1698                     le32toh(newcbd->cmds[i].cmd_tables->t_status.addr));
 1699 #endif
 1700         }
 1701         s = splbio();
 1702         TAILQ_INSERT_TAIL(&sc->cmds, newcbd, next);
 1703         sc->sc_c.sc_adapt.adapt_openings += SIOP_NCMDPB;
 1704         splx(s);
 1705         return;
 1706 bad0:
 1707         bus_dmamap_unload(sc->sc_c.sc_dmat, newcbd->xferdma);
 1708         bus_dmamap_destroy(sc->sc_c.sc_dmat, newcbd->xferdma);
 1709 bad1:
 1710         bus_dmamem_free(sc->sc_c.sc_dmat, &seg, rseg);
 1711 bad2:
 1712         free(newcbd->cmds, M_DEVBUF);
 1713 bad3:
 1714         free(newcbd, M_DEVBUF);
 1715         return;
 1716 }
 1717 
 1718 struct siop_lunsw *
 1719 siop_get_lunsw(sc)
 1720         struct siop_softc *sc;
 1721 {
 1722         struct siop_lunsw *lunsw;
 1723         int i;
 1724 
 1725         if (sc->script_free_lo + (sizeof(lun_switch) / sizeof(lun_switch[0])) >=
 1726             sc->script_free_hi)
 1727                 return NULL;
 1728         lunsw = TAILQ_FIRST(&sc->lunsw_list);
 1729         if (lunsw != NULL) {
 1730 #ifdef SIOP_DEBUG
 1731                 printf("siop_get_lunsw got lunsw at offset %d\n",
 1732                     lunsw->lunsw_off);
 1733 #endif
 1734                 TAILQ_REMOVE(&sc->lunsw_list, lunsw, next);
 1735                 return lunsw;
 1736         }
 1737         lunsw = malloc(sizeof(struct siop_lunsw), M_DEVBUF, M_NOWAIT|M_ZERO);
 1738         if (lunsw == NULL)
 1739                 return NULL;
 1740 #ifdef SIOP_DEBUG
 1741         printf("allocating lunsw at offset %d\n", sc->script_free_lo);
 1742 #endif
 1743         if (sc->sc_c.features & SF_CHIP_RAM) {
 1744                 bus_space_write_region_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh,
 1745                     sc->script_free_lo * 4, lun_switch,
 1746                     sizeof(lun_switch) / sizeof(lun_switch[0]));
 1747                 bus_space_write_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh,
 1748                     (sc->script_free_lo + E_abs_lunsw_return_Used[0]) * 4,
 1749                     sc->sc_c.sc_scriptaddr + Ent_lunsw_return);
 1750         } else {
 1751                 for (i = 0; i < sizeof(lun_switch) / sizeof(lun_switch[0]);
 1752                     i++)
 1753                         sc->sc_c.sc_script[sc->script_free_lo + i] =
 1754                             htole32(lun_switch[i]);
 1755                 sc->sc_c.sc_script[
 1756                     sc->script_free_lo + E_abs_lunsw_return_Used[0]] = 
 1757                     htole32(sc->sc_c.sc_scriptaddr + Ent_lunsw_return);
 1758         }
 1759         lunsw->lunsw_off = sc->script_free_lo;
 1760         lunsw->lunsw_size = sizeof(lun_switch) / sizeof(lun_switch[0]);
 1761         sc->script_free_lo += lunsw->lunsw_size;
 1762         siop_script_sync(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 1763         return lunsw;
 1764 }
 1765 
 1766 void
 1767 siop_add_reselsw(sc, target)
 1768         struct siop_softc *sc;
 1769         int target;
 1770 {
 1771         int i, j;
 1772         struct siop_target *siop_target;
 1773         struct siop_lun *siop_lun;
 1774 
 1775         siop_target = (struct siop_target *)sc->sc_c.targets[target];
 1776         /*
 1777          * add an entry to resel switch
 1778          */
 1779         siop_script_sync(sc, BUS_DMASYNC_POSTWRITE);
 1780         for (i = 0; i < 15; i++) {
 1781                 siop_target->reseloff = Ent_resel_targ0 / 4 + i * 2;
 1782                 if ((siop_script_read(sc, siop_target->reseloff) & 0xff)
 1783                     == 0xff) { /* it's free */
 1784 #ifdef SIOP_DEBUG
 1785                         printf("siop: target %d slot %d offset %d\n",
 1786                             target, i, siop_target->reseloff);
 1787 #endif
 1788                         /* JUMP abs_foo, IF target | 0x80; */
 1789                         siop_script_write(sc, siop_target->reseloff,
 1790                             0x800c0080 | target);
 1791                         siop_script_write(sc, siop_target->reseloff + 1,
 1792                             sc->sc_c.sc_scriptaddr +
 1793                             siop_target->lunsw->lunsw_off * 4 +
 1794                             Ent_lun_switch_entry);
 1795                         break;
 1796                 }
 1797         }
 1798         if (i == 15) /* no free slot, shouldn't happen */
 1799                 panic("siop: resel switch full");
 1800 
 1801         sc->sc_ntargets++;
 1802         for (i = 0; i < 8; i++) {
 1803                 siop_lun = siop_target->siop_lun[i];
 1804                 if (siop_lun == NULL)
 1805                         continue;
 1806                 if (siop_lun->reseloff > 0) {
 1807                         siop_lun->reseloff = 0;
 1808                         for (j = 0; j < SIOP_NTAG; j++)
 1809                                 siop_lun->siop_tag[j].reseloff = 0;
 1810                         siop_add_dev(sc, target, i);
 1811                 }
 1812         }
 1813         siop_update_scntl3(sc, sc->sc_c.targets[target]);
 1814         siop_script_sync(sc, BUS_DMASYNC_PREWRITE);
 1815 }
 1816 
 1817 void
 1818 siop_update_scntl3(sc, _siop_target)
 1819         struct siop_softc *sc;
 1820         struct siop_common_target *_siop_target;
 1821 {
 1822         struct siop_target *siop_target = (struct siop_target *)_siop_target;
 1823         /* MOVE target->id >> 24 TO SCNTL3 */
 1824         siop_script_write(sc,
 1825             siop_target->lunsw->lunsw_off + (Ent_restore_scntl3 / 4),
 1826             0x78030000 | ((siop_target->target_c.id >> 16) & 0x0000ff00));
 1827         /* MOVE target->id >> 8 TO SXFER */
 1828         siop_script_write(sc,
 1829             siop_target->lunsw->lunsw_off + (Ent_restore_scntl3 / 4) + 2,
 1830             0x78050000 | (siop_target->target_c.id & 0x0000ff00));
 1831         siop_script_sync(sc, BUS_DMASYNC_PREWRITE);
 1832 }
 1833 
 1834 void
 1835 siop_add_dev(sc, target, lun)
 1836         struct siop_softc *sc;
 1837         int target;
 1838         int lun;
 1839 {
 1840         struct siop_lunsw *lunsw;
 1841         struct siop_target *siop_target =
 1842             (struct siop_target *)sc->sc_c.targets[target];
 1843         struct siop_lun *siop_lun = siop_target->siop_lun[lun];
 1844         int i, ntargets;
 1845 
 1846         if (siop_lun->reseloff > 0)
 1847                 return;
 1848         lunsw = siop_target->lunsw;
 1849         if ((lunsw->lunsw_off + lunsw->lunsw_size) < sc->script_free_lo) {
 1850                 /*
 1851                  * can't extend this slot. Probably not worth trying to deal
 1852                  * with this case
 1853                  */
 1854 #ifdef DEBUG
 1855                 printf("%s:%d:%d: can't allocate a lun sw slot\n",
 1856                     sc->sc_c.sc_dev.dv_xname, target, lun);
 1857 #endif
 1858                 return;
 1859         }
 1860         /* count how many free targets we still have to probe */
 1861         ntargets =  sc->sc_c.sc_chan.chan_ntargets - 1 - sc->sc_ntargets;
 1862 
 1863         /*
 1864          * we need 8 bytes for the lun sw additional entry, and
 1865          * eventually sizeof(tag_switch) for the tag switch entry.
 1866          * Keep enough free space for the free targets that could be
 1867          * probed later.
 1868          */
 1869         if (sc->script_free_lo + 2 +
 1870             (ntargets * sizeof(lun_switch) / sizeof(lun_switch[0])) >=
 1871             ((siop_target->target_c.flags & TARF_TAG) ?
 1872             sc->script_free_hi - (sizeof(tag_switch) / sizeof(tag_switch[0])) :
 1873             sc->script_free_hi)) {
 1874                 /*
 1875                  * not enough space, probably not worth dealing with it.
 1876                  * We can hold 13 tagged-queuing capable devices in the 4k RAM.
 1877                  */
 1878 #ifdef DEBUG
 1879                 printf("%s:%d:%d: not enough memory for a lun sw slot\n",
 1880                     sc->sc_c.sc_dev.dv_xname, target, lun);
 1881 #endif
 1882                 return;
 1883         }
 1884 #ifdef SIOP_DEBUG
 1885         printf("%s:%d:%d: allocate lun sw entry\n",
 1886             sc->sc_c.sc_dev.dv_xname, target, lun);
 1887 #endif
 1888         /* INT int_resellun */
 1889         siop_script_write(sc, sc->script_free_lo, 0x98080000);
 1890         siop_script_write(sc, sc->script_free_lo + 1, A_int_resellun);
 1891         /* Now the slot entry: JUMP abs_foo, IF lun */
 1892         siop_script_write(sc, sc->script_free_lo - 2,
 1893             0x800c0000 | lun);
 1894         siop_script_write(sc, sc->script_free_lo - 1, 0);
 1895         siop_lun->reseloff = sc->script_free_lo - 2;
 1896         lunsw->lunsw_size += 2;
 1897         sc->script_free_lo += 2;
 1898         if (siop_target->target_c.flags & TARF_TAG) {
 1899                 /* we need a tag switch */
 1900                 sc->script_free_hi -=
 1901                     sizeof(tag_switch) / sizeof(tag_switch[0]);
 1902                 if (sc->sc_c.features & SF_CHIP_RAM) {
 1903                         bus_space_write_region_4(sc->sc_c.sc_ramt,
 1904                             sc->sc_c.sc_ramh,
 1905                             sc->script_free_hi * 4, tag_switch,
 1906                             sizeof(tag_switch) / sizeof(tag_switch[0]));
 1907                 } else {
 1908                         for(i = 0;
 1909                             i < sizeof(tag_switch) / sizeof(tag_switch[0]);
 1910                             i++) {
 1911                                 sc->sc_c.sc_script[sc->script_free_hi + i] = 
 1912                                     htole32(tag_switch[i]);
 1913                         }
 1914                 }
 1915                 siop_script_write(sc, 
 1916                     siop_lun->reseloff + 1,
 1917                     sc->sc_c.sc_scriptaddr + sc->script_free_hi * 4 +
 1918                     Ent_tag_switch_entry);
 1919 
 1920                 for (i = 0; i < SIOP_NTAG; i++) {
 1921                         siop_lun->siop_tag[i].reseloff =
 1922                             sc->script_free_hi + (Ent_resel_tag0 / 4) + i * 2;
 1923                 }
 1924         } else {
 1925                 /* non-tag case; just work with the lun switch */
 1926                 siop_lun->siop_tag[0].reseloff = 
 1927                     siop_target->siop_lun[lun]->reseloff;
 1928         }
 1929         siop_script_sync(sc, BUS_DMASYNC_PREWRITE);
 1930 }
 1931 
 1932 void
 1933 siop_del_dev(sc, target, lun)
 1934         struct siop_softc *sc;
 1935         int target;
 1936         int lun;
 1937 {
 1938         int i;
 1939         struct siop_target *siop_target;
 1940 #ifdef SIOP_DEBUG
 1941                 printf("%s:%d:%d: free lun sw entry\n",
 1942                     sc->sc_c.sc_dev.dv_xname, target, lun);
 1943 #endif
 1944         if (sc->sc_c.targets[target] == NULL)
 1945                 return;
 1946         siop_target = (struct siop_target *)sc->sc_c.targets[target];
 1947         free(siop_target->siop_lun[lun], M_DEVBUF);
 1948         siop_target->siop_lun[lun] = NULL;
 1949         /* XXX compact sw entry too ? */
 1950         /* check if we can free the whole target */
 1951         for (i = 0; i < 8; i++) {
 1952                 if (siop_target->siop_lun[i] != NULL)
 1953                         return;
 1954         }
 1955 #ifdef SIOP_DEBUG
 1956         printf("%s: free siop_target for target %d lun %d lunsw offset %d\n",
 1957             sc->sc_c.sc_dev.dv_xname, target, lun,
 1958             sc->sc_c.targets[target]->lunsw->lunsw_off);
 1959 #endif
 1960         /*
 1961          * nothing here, free the target struct and resel
 1962          * switch entry
 1963          */
 1964         siop_script_write(sc, siop_target->reseloff, 0x800c00ff);
 1965         siop_script_sync(sc, BUS_DMASYNC_PREWRITE);
 1966         TAILQ_INSERT_TAIL(&sc->lunsw_list, siop_target->lunsw, next);
 1967         free(sc->sc_c.targets[target], M_DEVBUF);
 1968         sc->sc_c.targets[target] = NULL;
 1969         sc->sc_ntargets--;
 1970 }
 1971 
 1972 #ifdef SIOP_STATS
 1973 void
 1974 siop_printstats()
 1975 {
 1976         printf("siop_stat_intr %d\n", siop_stat_intr);
 1977         printf("siop_stat_intr_shortxfer %d\n", siop_stat_intr_shortxfer);
 1978         printf("siop_stat_intr_xferdisc %d\n", siop_stat_intr_xferdisc);
 1979         printf("siop_stat_intr_sdp %d\n", siop_stat_intr_sdp);
 1980         printf("siop_stat_intr_done %d\n", siop_stat_intr_done);
 1981         printf("siop_stat_intr_lunresel %d\n", siop_stat_intr_lunresel);
 1982         printf("siop_stat_intr_qfull %d\n", siop_stat_intr_qfull);
 1983 }
 1984 #endif

Cache object: 5ab3bbb4c94efc8f98edda224c2f13b7


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.