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/esiop.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: esiop.c,v 1.32.4.2 2005/11/21 20:55:44 tron Exp $      */
    2 
    3 /*
    4  * Copyright (c) 2002 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: esiop.c,v 1.32.4.2 2005/11/21 20:55:44 tron 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/esiop.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/esiopvar.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 esiop_xfer))
   81 
   82 void    esiop_reset(struct esiop_softc *);
   83 void    esiop_checkdone(struct esiop_softc *);
   84 void    esiop_handle_reset(struct esiop_softc *);
   85 void    esiop_scsicmd_end(struct esiop_cmd *, int);
   86 void    esiop_unqueue(struct esiop_softc *, int, int);
   87 int     esiop_handle_qtag_reject(struct esiop_cmd *);
   88 static void     esiop_start(struct esiop_softc *, struct esiop_cmd *);
   89 void    esiop_timeout(void *);
   90 void    esiop_scsipi_request(struct scsipi_channel *,
   91                         scsipi_adapter_req_t, void *);
   92 void    esiop_dump_script(struct esiop_softc *);
   93 void    esiop_morecbd(struct esiop_softc *);
   94 void    esiop_moretagtbl(struct esiop_softc *);
   95 void    siop_add_reselsw(struct esiop_softc *, int);
   96 void    esiop_target_register(struct esiop_softc *, u_int32_t);
   97 
   98 void    esiop_update_scntl3(struct esiop_softc *, struct siop_common_target *);
   99 
  100 #ifdef SIOP_STATS
  101 static int esiop_stat_intr = 0;
  102 static int esiop_stat_intr_shortxfer = 0;
  103 static int esiop_stat_intr_sdp = 0;
  104 static int esiop_stat_intr_done = 0;
  105 static int esiop_stat_intr_xferdisc = 0;
  106 static int esiop_stat_intr_lunresel = 0;
  107 static int esiop_stat_intr_qfull = 0;
  108 void esiop_printstats(void);
  109 #define INCSTAT(x) x++
  110 #else
  111 #define INCSTAT(x)
  112 #endif
  113 
  114 static __inline__ void esiop_script_sync(struct esiop_softc *, int);
  115 static __inline__ void
  116 esiop_script_sync(sc, ops)
  117         struct esiop_softc *sc;
  118         int ops;
  119 {
  120         if ((sc->sc_c.features & SF_CHIP_RAM) == 0)
  121                 bus_dmamap_sync(sc->sc_c.sc_dmat, sc->sc_c.sc_scriptdma, 0,
  122                     PAGE_SIZE, ops);
  123 }
  124 
  125 static __inline__ u_int32_t esiop_script_read(struct esiop_softc *, u_int);
  126 static __inline__ u_int32_t
  127 esiop_script_read(sc, offset)
  128         struct esiop_softc *sc;
  129         u_int offset;
  130 {
  131         if (sc->sc_c.features & SF_CHIP_RAM) {
  132                 return bus_space_read_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh,
  133                     offset * 4);
  134         } else {
  135                 return le32toh(sc->sc_c.sc_script[offset]);
  136         }
  137 }
  138 
  139 static __inline__ void esiop_script_write(struct esiop_softc *, u_int,
  140         u_int32_t);
  141 static __inline__ void
  142 esiop_script_write(sc, offset, val)
  143         struct esiop_softc *sc;
  144         u_int offset;
  145         u_int32_t val;
  146 {
  147         if (sc->sc_c.features & SF_CHIP_RAM) {
  148                 bus_space_write_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh,
  149                     offset * 4, val);
  150         } else {
  151                 sc->sc_c.sc_script[offset] = htole32(val);
  152         }
  153 }
  154 
  155 void
  156 esiop_attach(sc)
  157         struct esiop_softc *sc;
  158 {
  159         struct esiop_dsatbl *tagtbl_donering;
  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->free_tagtbl);
  167         TAILQ_INIT(&sc->tag_tblblk);
  168         sc->sc_currschedslot = 0;
  169 #ifdef SIOP_DEBUG
  170         aprint_debug("%s: script size = %d, PHY addr=0x%x, VIRT=%p\n",
  171             sc->sc_c.sc_dev.dv_xname, (int)sizeof(esiop_script),
  172             (u_int32_t)sc->sc_c.sc_scriptaddr, sc->sc_c.sc_script);
  173 #endif
  174 
  175         sc->sc_c.sc_adapt.adapt_max_periph = ESIOP_NTAG;
  176         sc->sc_c.sc_adapt.adapt_request = esiop_scsipi_request;
  177 
  178         /*
  179          * get space for the CMD done slot. For this we use a tag table entry.
  180          * It's the same size and allows us to not waste 3/4 of a page
  181          */
  182 #ifdef DIAGNOSTIC
  183         if (ESIOP_NTAG != A_ndone_slots) {
  184                 aprint_error("%s: size of tag DSA table different from the done"
  185                     " ring\n", sc->sc_c.sc_dev.dv_xname);
  186                 return;
  187         }
  188 #endif
  189         esiop_moretagtbl(sc);
  190         tagtbl_donering = TAILQ_FIRST(&sc->free_tagtbl);
  191         if (tagtbl_donering == NULL) {
  192                 aprint_error("%s: no memory for command done ring\n",
  193                     sc->sc_c.sc_dev.dv_xname);
  194                 return;
  195         }
  196         TAILQ_REMOVE(&sc->free_tagtbl, tagtbl_donering, next);
  197         sc->sc_done_map = tagtbl_donering->tblblk->blkmap;
  198         sc->sc_done_offset = tagtbl_donering->tbl_offset;
  199         sc->sc_done_slot = &tagtbl_donering->tbl[0];
  200 
  201         /* Do a bus reset, so that devices fall back to narrow/async */
  202         siop_resetbus(&sc->sc_c);
  203         /*
  204          * siop_reset() will reset the chip, thus clearing pending interrupts
  205          */
  206         esiop_reset(sc);
  207 #ifdef DUMP_SCRIPT
  208         esiop_dump_script(sc);
  209 #endif
  210 
  211         config_found((struct device*)sc, &sc->sc_c.sc_chan, scsiprint);
  212 }
  213 
  214 void
  215 esiop_reset(sc)
  216         struct esiop_softc *sc;
  217 {
  218         int i, j;
  219         u_int32_t addr;
  220         u_int32_t msgin_addr, sem_addr;
  221 
  222         siop_common_reset(&sc->sc_c);
  223 
  224         /*
  225          * we copy the script at the beggining of RAM. Then there is 4 bytes
  226          * for messages in, and 4 bytes for semaphore
  227          */
  228         sc->sc_free_offset = sizeof(esiop_script) / sizeof(esiop_script[0]);
  229         msgin_addr =
  230             sc->sc_free_offset * sizeof(u_int32_t) + sc->sc_c.sc_scriptaddr;
  231         sc->sc_free_offset += 1;
  232         sc->sc_semoffset = sc->sc_free_offset;
  233         sem_addr =
  234             sc->sc_semoffset * sizeof(u_int32_t) + sc->sc_c.sc_scriptaddr;
  235         sc->sc_free_offset += 1;
  236         /* then we have the scheduler ring */
  237         sc->sc_shedoffset = sc->sc_free_offset;
  238         sc->sc_free_offset += A_ncmd_slots * CMD_SLOTSIZE;
  239         /* then the targets DSA table */
  240         sc->sc_target_table_offset = sc->sc_free_offset;
  241         sc->sc_free_offset += sc->sc_c.sc_chan.chan_ntargets;
  242         /* copy and patch the script */
  243         if (sc->sc_c.features & SF_CHIP_RAM) {
  244                 bus_space_write_region_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh, 0,
  245                     esiop_script,
  246                     sizeof(esiop_script) / sizeof(esiop_script[0]));
  247                 for (j = 0; j <
  248                     (sizeof(E_tlq_offset_Used) / sizeof(E_tlq_offset_Used[0]));
  249                     j++) {
  250                         bus_space_write_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh,
  251                             E_tlq_offset_Used[j] * 4,
  252                             sizeof(struct siop_common_xfer));
  253                 }
  254                 for (j = 0; j <
  255                     (sizeof(E_saved_offset_offset_Used) /
  256                      sizeof(E_saved_offset_offset_Used[0]));
  257                     j++) {
  258                         bus_space_write_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh,
  259                             E_saved_offset_offset_Used[j] * 4,
  260                             sizeof(struct siop_common_xfer) + 4);
  261                 }
  262                 for (j = 0; j <
  263                     (sizeof(E_abs_msgin2_Used) / sizeof(E_abs_msgin2_Used[0]));
  264                     j++) {
  265                         bus_space_write_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh,
  266                             E_abs_msgin2_Used[j] * 4, msgin_addr);
  267                 }
  268                 for (j = 0; j <
  269                     (sizeof(E_abs_sem_Used) / sizeof(E_abs_sem_Used[0]));
  270                     j++) {
  271                         bus_space_write_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh,
  272                             E_abs_sem_Used[j] * 4, sem_addr);
  273                 }
  274 
  275                 if (sc->sc_c.features & SF_CHIP_LED0) {
  276                         bus_space_write_region_4(sc->sc_c.sc_ramt,
  277                             sc->sc_c.sc_ramh,
  278                             Ent_led_on1, esiop_led_on,
  279                             sizeof(esiop_led_on) / sizeof(esiop_led_on[0]));
  280                         bus_space_write_region_4(sc->sc_c.sc_ramt,
  281                             sc->sc_c.sc_ramh,
  282                             Ent_led_on2, esiop_led_on,
  283                             sizeof(esiop_led_on) / sizeof(esiop_led_on[0]));
  284                         bus_space_write_region_4(sc->sc_c.sc_ramt,
  285                             sc->sc_c.sc_ramh,
  286                             Ent_led_off, esiop_led_off,
  287                             sizeof(esiop_led_off) / sizeof(esiop_led_off[0]));
  288                 }
  289         } else {
  290                 for (j = 0;
  291                     j < (sizeof(esiop_script) / sizeof(esiop_script[0])); j++) {
  292                         sc->sc_c.sc_script[j] = htole32(esiop_script[j]);
  293                 }
  294                 for (j = 0; j <
  295                     (sizeof(E_tlq_offset_Used) / sizeof(E_tlq_offset_Used[0]));
  296                     j++) {
  297                         sc->sc_c.sc_script[E_tlq_offset_Used[j]] =
  298                             htole32(sizeof(struct siop_common_xfer));
  299                 }
  300                 for (j = 0; j <
  301                     (sizeof(E_saved_offset_offset_Used) /
  302                      sizeof(E_saved_offset_offset_Used[0]));
  303                     j++) {
  304                         sc->sc_c.sc_script[E_saved_offset_offset_Used[j]] =
  305                             htole32(sizeof(struct siop_common_xfer) + 4);
  306                 }
  307                 for (j = 0; j <
  308                     (sizeof(E_abs_msgin2_Used) / sizeof(E_abs_msgin2_Used[0]));
  309                     j++) {
  310                         sc->sc_c.sc_script[E_abs_msgin2_Used[j]] =
  311                             htole32(msgin_addr);
  312                 }
  313                 for (j = 0; j <
  314                     (sizeof(E_abs_sem_Used) / sizeof(E_abs_sem_Used[0]));
  315                     j++) {
  316                         sc->sc_c.sc_script[E_abs_sem_Used[j]] =
  317                             htole32(sem_addr);
  318                 }
  319 
  320                 if (sc->sc_c.features & SF_CHIP_LED0) {
  321                         for (j = 0; j < (sizeof(esiop_led_on) /
  322                             sizeof(esiop_led_on[0])); j++)
  323                                 sc->sc_c.sc_script[
  324                                     Ent_led_on1 / sizeof(esiop_led_on[0]) + j
  325                                     ] = htole32(esiop_led_on[j]);
  326                         for (j = 0; j < (sizeof(esiop_led_on) /
  327                             sizeof(esiop_led_on[0])); j++)
  328                                 sc->sc_c.sc_script[
  329                                     Ent_led_on2 / sizeof(esiop_led_on[0]) + j
  330                                     ] = htole32(esiop_led_on[j]);
  331                         for (j = 0; j < (sizeof(esiop_led_off) /
  332                             sizeof(esiop_led_off[0])); j++)
  333                                 sc->sc_c.sc_script[
  334                                    Ent_led_off / sizeof(esiop_led_off[0]) + j
  335                                    ] = htole32(esiop_led_off[j]);
  336                 }
  337         }
  338         /* get base of scheduler ring */
  339         addr = sc->sc_c.sc_scriptaddr + sc->sc_shedoffset * sizeof(u_int32_t);
  340         /* init scheduler */
  341         for (i = 0; i < A_ncmd_slots; i++) {
  342                 esiop_script_write(sc,
  343                     sc->sc_shedoffset + i * CMD_SLOTSIZE, A_f_cmd_free);
  344         }
  345         sc->sc_currschedslot = 0;
  346         bus_space_write_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_SCRATCHE, 0);
  347         bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_SCRATCHD, addr);
  348         /*
  349          * 0x78000000 is a 'move data8 to reg'. data8 is the second
  350          * octet, reg offset is the third.
  351          */
  352         esiop_script_write(sc, Ent_cmdr0 / 4,
  353             0x78640000 | ((addr & 0x000000ff) <<  8));
  354         esiop_script_write(sc, Ent_cmdr1 / 4,
  355             0x78650000 | ((addr & 0x0000ff00)      ));
  356         esiop_script_write(sc, Ent_cmdr2 / 4,
  357             0x78660000 | ((addr & 0x00ff0000) >>  8));
  358         esiop_script_write(sc, Ent_cmdr3 / 4,
  359             0x78670000 | ((addr & 0xff000000) >> 16));
  360         /* done ring */
  361         for (i = 0; i < A_ndone_slots; i++)
  362                 sc->sc_done_slot[i] = 0;
  363         bus_dmamap_sync(sc->sc_c.sc_dmat, sc->sc_done_map,
  364             sc->sc_done_offset, A_ndone_slots * sizeof(u_int32_t),
  365             BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
  366         addr = sc->sc_done_map->dm_segs[0].ds_addr + sc->sc_done_offset;
  367         sc->sc_currdoneslot = 0;
  368         bus_space_write_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_SCRATCHE + 2, 0);
  369         bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_SCRATCHF, addr);
  370         esiop_script_write(sc, Ent_doner0 / 4,
  371             0x786c0000 | ((addr & 0x000000ff) <<  8));
  372         esiop_script_write(sc, Ent_doner1 / 4,
  373             0x786d0000 | ((addr & 0x0000ff00)      ));
  374         esiop_script_write(sc, Ent_doner2 / 4,
  375             0x786e0000 | ((addr & 0x00ff0000) >>  8));
  376         esiop_script_write(sc, Ent_doner3 / 4,
  377             0x786f0000 | ((addr & 0xff000000) >> 16));
  378 
  379         /* set flags */
  380         bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_SCRATCHC, 0);
  381         /* write pointer of base of target DSA table */
  382         addr = (sc->sc_target_table_offset * sizeof(u_int32_t)) +
  383             sc->sc_c.sc_scriptaddr;
  384         esiop_script_write(sc, (Ent_load_targtable / 4) + 0,
  385             esiop_script_read(sc,(Ent_load_targtable / 4) + 0) |
  386             ((addr & 0x000000ff) <<  8));
  387         esiop_script_write(sc, (Ent_load_targtable / 4) + 2,
  388             esiop_script_read(sc,(Ent_load_targtable / 4) + 2) |
  389             ((addr & 0x0000ff00)      ));
  390         esiop_script_write(sc, (Ent_load_targtable / 4) + 4,
  391             esiop_script_read(sc,(Ent_load_targtable / 4) + 4) |
  392             ((addr & 0x00ff0000) >>  8));
  393         esiop_script_write(sc, (Ent_load_targtable / 4) + 6,
  394             esiop_script_read(sc,(Ent_load_targtable / 4) + 6) |
  395             ((addr & 0xff000000) >> 16));
  396 #ifdef SIOP_DEBUG
  397         printf("%s: target table offset %d free offset %d\n",
  398             sc->sc_c.sc_dev.dv_xname, sc->sc_target_table_offset,
  399             sc->sc_free_offset);
  400 #endif
  401 
  402         /* register existing targets */
  403         for (i = 0; i < sc->sc_c.sc_chan.chan_ntargets; i++) {
  404                 if (sc->sc_c.targets[i])
  405                         esiop_target_register(sc, i);
  406         }
  407         /* start script */
  408         if ((sc->sc_c.features & SF_CHIP_RAM) == 0) {
  409                 bus_dmamap_sync(sc->sc_c.sc_dmat, sc->sc_c.sc_scriptdma, 0,
  410                     PAGE_SIZE, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
  411         }
  412         bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSP,
  413             sc->sc_c.sc_scriptaddr + Ent_reselect);
  414 }
  415 
  416 #if 0
  417 #define CALL_SCRIPT(ent) do {\
  418         printf ("start script DSA 0x%lx DSP 0x%lx\n", \
  419             esiop_cmd->cmd_c.dsa, \
  420             sc->sc_c.sc_scriptaddr + ent); \
  421 bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSP, sc->sc_c.sc_scriptaddr + ent); \
  422 } while (0)
  423 #else
  424 #define CALL_SCRIPT(ent) do {\
  425 bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSP, sc->sc_c.sc_scriptaddr + ent); \
  426 } while (0)
  427 #endif
  428 
  429 int
  430 esiop_intr(v)
  431         void *v;
  432 {
  433         struct esiop_softc *sc = v;
  434         struct esiop_target *esiop_target;
  435         struct esiop_cmd *esiop_cmd;
  436         struct esiop_lun *esiop_lun;
  437         struct scsipi_xfer *xs;
  438         int istat, sist, sstat1, dstat = 0; /* XXX: gcc */
  439         u_int32_t irqcode;
  440         int need_reset = 0;
  441         int offset, target, lun, tag;
  442         u_int32_t tflags;
  443         u_int32_t addr;
  444         int freetarget = 0;
  445         int slot;
  446         int retval = 0;
  447 
  448 again:
  449         istat = bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_ISTAT);
  450         if ((istat & (ISTAT_INTF | ISTAT_DIP | ISTAT_SIP)) == 0) {
  451                 return retval;
  452         }
  453         retval = 1;
  454         INCSTAT(esiop_stat_intr);
  455         esiop_checkdone(sc);
  456         if (istat & ISTAT_INTF) {
  457                 bus_space_write_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
  458                     SIOP_ISTAT, ISTAT_INTF);
  459                 goto again;
  460         }
  461 
  462         if ((istat &(ISTAT_DIP | ISTAT_SIP | ISTAT_ABRT)) ==
  463             (ISTAT_DIP | ISTAT_ABRT)) {
  464                 /* clear abort */
  465                 bus_space_write_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
  466                     SIOP_ISTAT, 0);
  467         }
  468 
  469         /* get CMD from T/L/Q */
  470         tflags = bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
  471             SIOP_SCRATCHC);
  472 #ifdef SIOP_DEBUG_INTR
  473                 printf("interrupt, istat=0x%x tflags=0x%x "
  474                     "DSA=0x%x DSP=0x%lx\n", istat, tflags,
  475                     bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSA),
  476                     (u_long)(bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
  477                         SIOP_DSP) -
  478                     sc->sc_c.sc_scriptaddr));
  479 #endif
  480         target = (tflags & A_f_c_target) ? ((tflags >> 8) & 0xff) : -1;
  481         if (target > sc->sc_c.sc_chan.chan_ntargets) target = -1;
  482         lun = (tflags & A_f_c_lun) ? ((tflags >> 16) & 0xff) : -1;
  483         if (lun > sc->sc_c.sc_chan.chan_nluns) lun = -1;
  484         tag = (tflags & A_f_c_tag) ? ((tflags >> 24) & 0xff) : -1;
  485 
  486         if (target >= 0 && lun >= 0) {
  487                 esiop_target = (struct esiop_target *)sc->sc_c.targets[target];
  488                 if (esiop_target == NULL) {
  489                         printf("esiop_target (target %d) not valid\n", target);
  490                         goto none;
  491                 }
  492                 esiop_lun = esiop_target->esiop_lun[lun];
  493                 if (esiop_lun == NULL) {
  494                         printf("esiop_lun (target %d lun %d) not valid\n",
  495                             target, lun);
  496                         goto none;
  497                 }
  498                 esiop_cmd =
  499                     (tag >= 0) ? esiop_lun->tactive[tag] : esiop_lun->active;
  500                 if (esiop_cmd == NULL) {
  501                         printf("esiop_cmd (target %d lun %d tag %d) not valid\n",
  502                             target, lun, tag);
  503                         goto none;
  504                 }
  505                 xs = esiop_cmd->cmd_c.xs;
  506 #ifdef DIAGNOSTIC
  507                 if (esiop_cmd->cmd_c.status != CMDST_ACTIVE) {
  508                         printf("esiop_cmd (target %d lun %d) "
  509                             "not active (%d)\n", target, lun,
  510                             esiop_cmd->cmd_c.status);
  511                         goto none;
  512                 }
  513 #endif
  514                 esiop_table_sync(esiop_cmd,
  515                     BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
  516         } else {
  517 none:
  518                 xs = NULL;
  519                 esiop_target = NULL;
  520                 esiop_lun = NULL;
  521                 esiop_cmd = NULL;
  522         }
  523         if (istat & ISTAT_DIP) {
  524                 dstat = bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
  525                     SIOP_DSTAT);
  526                 if (dstat & DSTAT_ABRT) {
  527                         /* was probably generated by a bus reset IOCTL */
  528                         if ((dstat & DSTAT_DFE) == 0)
  529                                 siop_clearfifo(&sc->sc_c);
  530                         goto reset;
  531                 }
  532                 if (dstat & DSTAT_SSI) {
  533                         printf("single step dsp 0x%08x dsa 0x08%x\n",
  534                             (int)(bus_space_read_4(sc->sc_c.sc_rt,
  535                             sc->sc_c.sc_rh, SIOP_DSP) -
  536                             sc->sc_c.sc_scriptaddr),
  537                             bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
  538                                 SIOP_DSA));
  539                         if ((dstat & ~(DSTAT_DFE | DSTAT_SSI)) == 0 &&
  540                             (istat & ISTAT_SIP) == 0) {
  541                                 bus_space_write_1(sc->sc_c.sc_rt,
  542                                     sc->sc_c.sc_rh, SIOP_DCNTL,
  543                                     bus_space_read_1(sc->sc_c.sc_rt,
  544                                     sc->sc_c.sc_rh, SIOP_DCNTL) | DCNTL_STD);
  545                         }
  546                         return 1;
  547                 }
  548 
  549                 if (dstat & ~(DSTAT_SIR | DSTAT_DFE | DSTAT_SSI)) {
  550                 printf("%s: DMA IRQ:", sc->sc_c.sc_dev.dv_xname);
  551                 if (dstat & DSTAT_IID)
  552                         printf(" Illegal instruction");
  553                 if (dstat & DSTAT_BF)
  554                         printf(" bus fault");
  555                 if (dstat & DSTAT_MDPE)
  556                         printf(" parity");
  557                 if (dstat & DSTAT_DFE)
  558                         printf(" DMA fifo empty");
  559                 else
  560                         siop_clearfifo(&sc->sc_c);
  561                 printf(", DSP=0x%x DSA=0x%x: ",
  562                     (int)(bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
  563                         SIOP_DSP) - sc->sc_c.sc_scriptaddr),
  564                     bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSA));
  565                 if (esiop_cmd)
  566                         printf("T/L/Q=%d/%d/%d last msg_in=0x%x status=0x%x\n",
  567                             target, lun, tag, esiop_cmd->cmd_tables->msg_in[0],
  568                             le32toh(esiop_cmd->cmd_tables->status));
  569                 else
  570                         printf(" current T/L/Q invalid\n");
  571                 need_reset = 1;
  572                 }
  573         }
  574         if (istat & ISTAT_SIP) {
  575                 if (istat & ISTAT_DIP)
  576                         delay(10);
  577                 /*
  578                  * Can't read sist0 & sist1 independently, or we have to
  579                  * insert delay
  580                  */
  581                 sist = bus_space_read_2(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
  582                     SIOP_SIST0);
  583                 sstat1 = bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
  584                     SIOP_SSTAT1);
  585 #ifdef SIOP_DEBUG_INTR
  586                 printf("scsi interrupt, sist=0x%x sstat1=0x%x "
  587                     "DSA=0x%x DSP=0x%lx\n", sist, sstat1,
  588                     bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSA),
  589                     (u_long)(bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
  590                         SIOP_DSP) -
  591                     sc->sc_c.sc_scriptaddr));
  592 #endif
  593                 if (sist & SIST0_RST) {
  594                         esiop_handle_reset(sc);
  595                         /* no table to flush here */
  596                         return 1;
  597                 }
  598                 if (sist & SIST0_SGE) {
  599                         if (esiop_cmd)
  600                                 scsipi_printaddr(xs->xs_periph);
  601                         else
  602                                 printf("%s:", sc->sc_c.sc_dev.dv_xname);
  603                         printf("scsi gross error\n");
  604                         if (esiop_target)
  605                                 esiop_target->target_c.flags &= ~TARF_DT;
  606 #ifdef DEBUG
  607                         printf("DSA=0x%x DSP=0x%lx\n",
  608                             bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSA),
  609                             (u_long)(bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
  610                                 SIOP_DSP) -
  611                             sc->sc_c.sc_scriptaddr));
  612                         printf("SDID 0x%x SCNTL3 0x%x SXFER 0x%x SCNTL4 0x%x\n",
  613                             bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_SDID),
  614                              bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_SCNTL3),
  615                              bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_SXFER),
  616                              bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_SCNTL4));
  617 
  618 #endif
  619                         goto reset;
  620                 }
  621                 if ((sist & SIST0_MA) && need_reset == 0) {
  622                         if (esiop_cmd) {
  623                                 int scratchc0;
  624                                 dstat = bus_space_read_1(sc->sc_c.sc_rt,
  625                                     sc->sc_c.sc_rh, SIOP_DSTAT);
  626                                 /*
  627                                  * first restore DSA, in case we were in a S/G
  628                                  * operation.
  629                                  */
  630                                 bus_space_write_4(sc->sc_c.sc_rt,
  631                                     sc->sc_c.sc_rh,
  632                                     SIOP_DSA, esiop_cmd->cmd_c.dsa);
  633                                 scratchc0 = bus_space_read_1(sc->sc_c.sc_rt,
  634                                     sc->sc_c.sc_rh, SIOP_SCRATCHC);
  635                                 switch (sstat1 & SSTAT1_PHASE_MASK) {
  636                                 case SSTAT1_PHASE_STATUS:
  637                                 /*
  638                                  * previous phase may be aborted for any reason
  639                                  * ( for example, the target has less data to
  640                                  * transfer than requested). Compute resid and
  641                                  * just go to status, the command should
  642                                  * terminate.
  643                                  */
  644                                         INCSTAT(esiop_stat_intr_shortxfer);
  645                                         if (scratchc0 & A_f_c_data)
  646                                                 siop_ma(&esiop_cmd->cmd_c);
  647                                         else if ((dstat & DSTAT_DFE) == 0)
  648                                                 siop_clearfifo(&sc->sc_c);
  649                                         CALL_SCRIPT(Ent_status);
  650                                         return 1;
  651                                 case SSTAT1_PHASE_MSGIN:
  652                                 /*
  653                                  * target may be ready to disconnect
  654                                  * Compute resid which would be used later
  655                                  * if a save data pointer is needed.
  656                                  */
  657                                         INCSTAT(esiop_stat_intr_xferdisc);
  658                                         if (scratchc0 & A_f_c_data)
  659                                                 siop_ma(&esiop_cmd->cmd_c);
  660                                         else if ((dstat & DSTAT_DFE) == 0)
  661                                                 siop_clearfifo(&sc->sc_c);
  662                                         bus_space_write_1(sc->sc_c.sc_rt,
  663                                             sc->sc_c.sc_rh, SIOP_SCRATCHC,
  664                                             scratchc0 & ~A_f_c_data);
  665                                         CALL_SCRIPT(Ent_msgin);
  666                                         return 1;
  667                                 }
  668                                 printf("%s: unexpected phase mismatch %d\n",
  669                                     sc->sc_c.sc_dev.dv_xname,
  670                                     sstat1 & SSTAT1_PHASE_MASK);
  671                         } else {
  672                                 printf("%s: phase mismatch without command\n",
  673                                     sc->sc_c.sc_dev.dv_xname);
  674                         }
  675                         need_reset = 1;
  676                 }
  677                 if (sist & SIST0_PAR) {
  678                         /* parity error, reset */
  679                         if (esiop_cmd)
  680                                 scsipi_printaddr(xs->xs_periph);
  681                         else
  682                                 printf("%s:", sc->sc_c.sc_dev.dv_xname);
  683                         printf("parity error\n");
  684                         if (esiop_target)
  685                                 esiop_target->target_c.flags &= ~TARF_DT;
  686                         goto reset;
  687                 }
  688                 if ((sist & (SIST1_STO << 8)) && need_reset == 0) {
  689                         /*
  690                          * selection time out, assume there's no device here
  691                          * We also have to update the ring pointer ourselve
  692                          */
  693                         slot = bus_space_read_1(sc->sc_c.sc_rt,
  694                             sc->sc_c.sc_rh, SIOP_SCRATCHE);
  695                         esiop_script_sync(sc,
  696                             BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
  697 #ifdef SIOP_DEBUG_SCHED
  698                         printf("sel timeout target %d, slot %d\n", target, slot);
  699 #endif
  700                         /*
  701                          * mark this slot as free, and advance to next slot
  702                          */
  703                         esiop_script_write(sc,
  704                             sc->sc_shedoffset + slot * CMD_SLOTSIZE,
  705                             A_f_cmd_free);
  706                         addr = bus_space_read_4(sc->sc_c.sc_rt,
  707                                     sc->sc_c.sc_rh, SIOP_SCRATCHD);
  708                         if (slot < (A_ncmd_slots - 1)) {
  709                                 bus_space_write_1(sc->sc_c.sc_rt,
  710                                     sc->sc_c.sc_rh, SIOP_SCRATCHE, slot + 1);
  711                                 addr = addr + sizeof(struct esiop_slot);
  712                         } else {
  713                                 bus_space_write_1(sc->sc_c.sc_rt,
  714                                     sc->sc_c.sc_rh, SIOP_SCRATCHE, 0);
  715                                 addr = sc->sc_c.sc_scriptaddr +
  716                                     sc->sc_shedoffset * sizeof(u_int32_t);
  717                         }
  718                         bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
  719                             SIOP_SCRATCHD, addr);
  720                         esiop_script_sync(sc,
  721                             BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
  722                         if (esiop_cmd) {
  723                                 esiop_cmd->cmd_c.status = CMDST_DONE;
  724                                 xs->error = XS_SELTIMEOUT;
  725                                 freetarget = 1;
  726                                 goto end;
  727                         } else {
  728                                 printf("%s: selection timeout without "
  729                                     "command, target %d (sdid 0x%x), "
  730                                     "slot %d\n",
  731                                     sc->sc_c.sc_dev.dv_xname, target,
  732                                     bus_space_read_1(sc->sc_c.sc_rt,
  733                                     sc->sc_c.sc_rh, SIOP_SDID), slot);
  734                                 need_reset = 1;
  735                         }
  736                 }
  737                 if (sist & SIST0_UDC) {
  738                         /*
  739                          * unexpected disconnect. Usually the target signals
  740                          * a fatal condition this way. Attempt to get sense.
  741                          */
  742                          if (esiop_cmd) {
  743                                 esiop_cmd->cmd_tables->status =
  744                                     htole32(SCSI_CHECK);
  745                                 goto end;
  746                         }
  747                         printf("%s: unexpected disconnect without "
  748                             "command\n", sc->sc_c.sc_dev.dv_xname);
  749                         goto reset;
  750                 }
  751                 if (sist & (SIST1_SBMC << 8)) {
  752                         /* SCSI bus mode change */
  753                         if (siop_modechange(&sc->sc_c) == 0 || need_reset == 1)
  754                                 goto reset;
  755                         if ((istat & ISTAT_DIP) && (dstat & DSTAT_SIR)) {
  756                                 /*
  757                                  * we have a script interrupt, it will
  758                                  * restart the script.
  759                                  */
  760                                 goto scintr;
  761                         }
  762                         /*
  763                          * else we have to restart it ourselve, at the
  764                          * interrupted instruction.
  765                          */
  766                         bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
  767                             SIOP_DSP,
  768                             bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
  769                             SIOP_DSP) - 8);
  770                         return 1;
  771                 }
  772                 /* Else it's an unhandled exception (for now). */
  773                 printf("%s: unhandled scsi interrupt, sist=0x%x sstat1=0x%x "
  774                     "DSA=0x%x DSP=0x%x\n", sc->sc_c.sc_dev.dv_xname, sist,
  775                     bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
  776                         SIOP_SSTAT1),
  777                     bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSA),
  778                     (int)(bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
  779                         SIOP_DSP) - sc->sc_c.sc_scriptaddr));
  780                 if (esiop_cmd) {
  781                         esiop_cmd->cmd_c.status = CMDST_DONE;
  782                         xs->error = XS_SELTIMEOUT;
  783                         goto end;
  784                 }
  785                 need_reset = 1;
  786         }
  787         if (need_reset) {
  788 reset:
  789                 /* fatal error, reset the bus */
  790                 siop_resetbus(&sc->sc_c);
  791                 /* no table to flush here */
  792                 return 1;
  793         }
  794 
  795 scintr:
  796         if ((istat & ISTAT_DIP) && (dstat & DSTAT_SIR)) { /* script interrupt */
  797                 irqcode = bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
  798                     SIOP_DSPS);
  799 #ifdef SIOP_DEBUG_INTR
  800                 printf("script interrupt 0x%x\n", irqcode);
  801 #endif
  802                 /*
  803                  * no command, or an inactive command is only valid for a
  804                  * reselect interrupt
  805                  */
  806                 if ((irqcode & 0x80) == 0) {
  807                         if (esiop_cmd == NULL) {
  808                                 printf(
  809                         "%s: script interrupt (0x%x) with invalid DSA !!!\n",
  810                                     sc->sc_c.sc_dev.dv_xname, irqcode);
  811                                 goto reset;
  812                         }
  813                         if (esiop_cmd->cmd_c.status != CMDST_ACTIVE) {
  814                                 printf("%s: command with invalid status "
  815                                     "(IRQ code 0x%x current status %d) !\n",
  816                                     sc->sc_c.sc_dev.dv_xname,
  817                                     irqcode, esiop_cmd->cmd_c.status);
  818                                 xs = NULL;
  819                         }
  820                 }
  821                 switch(irqcode) {
  822                 case A_int_err:
  823                         printf("error, DSP=0x%x\n",
  824                             (int)(bus_space_read_4(sc->sc_c.sc_rt,
  825                             sc->sc_c.sc_rh, SIOP_DSP) - sc->sc_c.sc_scriptaddr));
  826                         if (xs) {
  827                                 xs->error = XS_SELTIMEOUT;
  828                                 goto end;
  829                         } else {
  830                                 goto reset;
  831                         }
  832                 case A_int_msgin:
  833                 {
  834                         int msgin = bus_space_read_1(sc->sc_c.sc_rt,
  835                             sc->sc_c.sc_rh, SIOP_SFBR);
  836                         if (msgin == MSG_MESSAGE_REJECT) {
  837                                 int msg, extmsg;
  838                                 if (esiop_cmd->cmd_tables->msg_out[0] & 0x80) {
  839                                         /*
  840                                          * message was part of a identify +
  841                                          * something else. Identify shouldn't
  842                                          * have been rejected.
  843                                          */
  844                                         msg =
  845                                             esiop_cmd->cmd_tables->msg_out[1];
  846                                         extmsg =
  847                                             esiop_cmd->cmd_tables->msg_out[3];
  848                                 } else {
  849                                         msg =
  850                                             esiop_cmd->cmd_tables->msg_out[0];
  851                                         extmsg =
  852                                             esiop_cmd->cmd_tables->msg_out[2];
  853                                 }
  854                                 if (msg == MSG_MESSAGE_REJECT) {
  855                                         /* MSG_REJECT  for a MSG_REJECT  !*/
  856                                         if (xs)
  857                                                 scsipi_printaddr(xs->xs_periph);
  858                                         else
  859                                                 printf("%s: ",
  860                                                    sc->sc_c.sc_dev.dv_xname);
  861                                         printf("our reject message was "
  862                                             "rejected\n");
  863                                         goto reset;
  864                                 }
  865                                 if (msg == MSG_EXTENDED &&
  866                                     extmsg == MSG_EXT_WDTR) {
  867                                         /* WDTR rejected, initiate sync */
  868                                         if ((esiop_target->target_c.flags &
  869                                            TARF_SYNC) == 0) {
  870                                                 esiop_target->target_c.status =
  871                                                     TARST_OK;
  872                                                 siop_update_xfer_mode(&sc->sc_c,
  873                                                     target);
  874                                                 /* no table to flush here */
  875                                                 CALL_SCRIPT(Ent_msgin_ack);
  876                                                 return 1;
  877                                         }
  878                                         esiop_target->target_c.status =
  879                                             TARST_SYNC_NEG;
  880                                         siop_sdtr_msg(&esiop_cmd->cmd_c, 0,
  881                                             sc->sc_c.st_minsync,
  882                                             sc->sc_c.maxoff);
  883                                         esiop_table_sync(esiop_cmd,
  884                                             BUS_DMASYNC_PREREAD |
  885                                             BUS_DMASYNC_PREWRITE);
  886                                         CALL_SCRIPT(Ent_send_msgout);
  887                                         return 1;
  888                                 } else if (msg == MSG_EXTENDED &&
  889                                     extmsg == MSG_EXT_SDTR) {
  890                                         /* sync rejected */
  891                                         esiop_target->target_c.offset = 0;
  892                                         esiop_target->target_c.period = 0;
  893                                         esiop_target->target_c.status =
  894                                             TARST_OK;
  895                                         siop_update_xfer_mode(&sc->sc_c,
  896                                             target);
  897                                         /* no table to flush here */
  898                                         CALL_SCRIPT(Ent_msgin_ack);
  899                                         return 1;
  900                                 } else if (msg == MSG_EXTENDED &&
  901                                     extmsg == MSG_EXT_PPR) {
  902                                         /* PPR rejected */
  903                                         esiop_target->target_c.offset = 0;
  904                                         esiop_target->target_c.period = 0;
  905                                         esiop_target->target_c.status =
  906                                             TARST_OK;
  907                                         siop_update_xfer_mode(&sc->sc_c,
  908                                             target);
  909                                         /* no table to flush here */
  910                                         CALL_SCRIPT(Ent_msgin_ack);
  911                                         return 1;
  912                                 } else if (msg == MSG_SIMPLE_Q_TAG ||
  913                                     msg == MSG_HEAD_OF_Q_TAG ||
  914                                     msg == MSG_ORDERED_Q_TAG) {
  915                                         if (esiop_handle_qtag_reject(
  916                                             esiop_cmd) == -1)
  917                                                 goto reset;
  918                                         CALL_SCRIPT(Ent_msgin_ack);
  919                                         return 1;
  920                                 }
  921                                 if (xs)
  922                                         scsipi_printaddr(xs->xs_periph);
  923                                 else
  924                                         printf("%s: ",
  925                                             sc->sc_c.sc_dev.dv_xname);
  926                                 if (msg == MSG_EXTENDED) {
  927                                         printf("scsi message reject, extended "
  928                                             "message sent was 0x%x\n", extmsg);
  929                                 } else {
  930                                         printf("scsi message reject, message "
  931                                             "sent was 0x%x\n", msg);
  932                                 }
  933                                 /* no table to flush here */
  934                                 CALL_SCRIPT(Ent_msgin_ack);
  935                                 return 1;
  936                         }
  937                         if (msgin == MSG_IGN_WIDE_RESIDUE) {
  938                         /* use the extmsgdata table to get the second byte */
  939                                 esiop_cmd->cmd_tables->t_extmsgdata.count =
  940                                     htole32(1);
  941                                 esiop_table_sync(esiop_cmd,
  942                                     BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
  943                                 CALL_SCRIPT(Ent_get_extmsgdata);
  944                                 return 1;
  945                         }
  946                         if (xs)
  947                                 scsipi_printaddr(xs->xs_periph);
  948                         else
  949                                 printf("%s: ", sc->sc_c.sc_dev.dv_xname);
  950                         printf("unhandled message 0x%x\n", msgin);
  951                         esiop_cmd->cmd_tables->msg_out[0] = MSG_MESSAGE_REJECT;
  952                         esiop_cmd->cmd_tables->t_msgout.count= htole32(1);
  953                         esiop_table_sync(esiop_cmd,
  954                             BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
  955                         CALL_SCRIPT(Ent_send_msgout);
  956                         return 1;
  957                 }
  958                 case A_int_extmsgin:
  959 #ifdef SIOP_DEBUG_INTR
  960                         printf("extended message: msg 0x%x len %d\n",
  961                             esiop_cmd->cmd_tables->msg_in[2],
  962                             esiop_cmd->cmd_tables->msg_in[1]);
  963 #endif
  964                         if (esiop_cmd->cmd_tables->msg_in[1] >
  965                             sizeof(esiop_cmd->cmd_tables->msg_in) - 2)
  966                                 printf("%s: extended message too big (%d)\n",
  967                                     sc->sc_c.sc_dev.dv_xname,
  968                                     esiop_cmd->cmd_tables->msg_in[1]);
  969                         esiop_cmd->cmd_tables->t_extmsgdata.count =
  970                             htole32(esiop_cmd->cmd_tables->msg_in[1] - 1);
  971                         esiop_table_sync(esiop_cmd,
  972                             BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
  973                         CALL_SCRIPT(Ent_get_extmsgdata);
  974                         return 1;
  975                 case A_int_extmsgdata:
  976 #ifdef SIOP_DEBUG_INTR
  977                         {
  978                         int i;
  979                         printf("extended message: 0x%x, data:",
  980                             esiop_cmd->cmd_tables->msg_in[2]);
  981                         for (i = 3; i < 2 + esiop_cmd->cmd_tables->msg_in[1];
  982                             i++)
  983                                 printf(" 0x%x",
  984                                     esiop_cmd->cmd_tables->msg_in[i]);
  985                         printf("\n");
  986                         }
  987 #endif
  988                         if (esiop_cmd->cmd_tables->msg_in[0] ==
  989                             MSG_IGN_WIDE_RESIDUE) {
  990                         /* we got the second byte of MSG_IGN_WIDE_RESIDUE */
  991                                 if (esiop_cmd->cmd_tables->msg_in[3] != 1)
  992                                         printf("MSG_IGN_WIDE_RESIDUE: "
  993                                              "bad len %d\n",
  994                                              esiop_cmd->cmd_tables->msg_in[3]);
  995                                 switch (siop_iwr(&esiop_cmd->cmd_c)) {
  996                                 case SIOP_NEG_MSGOUT:
  997                                         esiop_table_sync(esiop_cmd,
  998                                             BUS_DMASYNC_PREREAD |
  999                                             BUS_DMASYNC_PREWRITE);
 1000                                         CALL_SCRIPT(Ent_send_msgout);
 1001                                         return 1;
 1002                                 case SIOP_NEG_ACK:
 1003                                         CALL_SCRIPT(Ent_msgin_ack);
 1004                                         return 1;
 1005                                 default:
 1006                                         panic("invalid retval from "
 1007                                             "siop_iwr()");
 1008                                 }
 1009                                 return 1;
 1010                         }
 1011                         if (esiop_cmd->cmd_tables->msg_in[2] == MSG_EXT_PPR) {
 1012                                 switch (siop_ppr_neg(&esiop_cmd->cmd_c)) {
 1013                                 case SIOP_NEG_MSGOUT:
 1014                                         esiop_update_scntl3(sc,
 1015                                             esiop_cmd->cmd_c.siop_target);
 1016                                         esiop_table_sync(esiop_cmd,
 1017                                             BUS_DMASYNC_PREREAD |
 1018                                             BUS_DMASYNC_PREWRITE);
 1019                                         CALL_SCRIPT(Ent_send_msgout);
 1020                                         return 1;
 1021                                 case SIOP_NEG_ACK:
 1022                                         esiop_update_scntl3(sc,
 1023                                             esiop_cmd->cmd_c.siop_target);
 1024                                         CALL_SCRIPT(Ent_msgin_ack);
 1025                                         return 1;
 1026                                 default:
 1027                                         panic("invalid retval from "
 1028                                             "siop_wdtr_neg()");
 1029                                 }
 1030                                 return 1;
 1031                         }
 1032                         if (esiop_cmd->cmd_tables->msg_in[2] == MSG_EXT_WDTR) {
 1033                                 switch (siop_wdtr_neg(&esiop_cmd->cmd_c)) {
 1034                                 case SIOP_NEG_MSGOUT:
 1035                                         esiop_update_scntl3(sc,
 1036                                             esiop_cmd->cmd_c.siop_target);
 1037                                         esiop_table_sync(esiop_cmd,
 1038                                             BUS_DMASYNC_PREREAD |
 1039                                             BUS_DMASYNC_PREWRITE);
 1040                                         CALL_SCRIPT(Ent_send_msgout);
 1041                                         return 1;
 1042                                 case SIOP_NEG_ACK:
 1043                                         esiop_update_scntl3(sc,
 1044                                             esiop_cmd->cmd_c.siop_target);
 1045                                         CALL_SCRIPT(Ent_msgin_ack);
 1046                                         return 1;
 1047                                 default:
 1048                                         panic("invalid retval from "
 1049                                             "siop_wdtr_neg()");
 1050                                 }
 1051                                 return 1;
 1052                         }
 1053                         if (esiop_cmd->cmd_tables->msg_in[2] == MSG_EXT_SDTR) {
 1054                                 switch (siop_sdtr_neg(&esiop_cmd->cmd_c)) {
 1055                                 case SIOP_NEG_MSGOUT:
 1056                                         esiop_update_scntl3(sc,
 1057                                             esiop_cmd->cmd_c.siop_target);
 1058                                         esiop_table_sync(esiop_cmd,
 1059                                             BUS_DMASYNC_PREREAD |
 1060                                             BUS_DMASYNC_PREWRITE);
 1061                                         CALL_SCRIPT(Ent_send_msgout);
 1062                                         return 1;
 1063                                 case SIOP_NEG_ACK:
 1064                                         esiop_update_scntl3(sc,
 1065                                             esiop_cmd->cmd_c.siop_target);
 1066                                         CALL_SCRIPT(Ent_msgin_ack);
 1067                                         return 1;
 1068                                 default:
 1069                                         panic("invalid retval from "
 1070                                             "siop_wdtr_neg()");
 1071                                 }
 1072                                 return 1;
 1073                         }
 1074                         /* send a message reject */
 1075                         esiop_cmd->cmd_tables->msg_out[0] = MSG_MESSAGE_REJECT;
 1076                         esiop_cmd->cmd_tables->t_msgout.count = htole32(1);
 1077                         esiop_table_sync(esiop_cmd,
 1078                             BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 1079                         CALL_SCRIPT(Ent_send_msgout);
 1080                         return 1;
 1081                 case A_int_disc:
 1082                         INCSTAT(esiop_stat_intr_sdp);
 1083                         offset = bus_space_read_1(sc->sc_c.sc_rt,
 1084                             sc->sc_c.sc_rh, SIOP_SCRATCHA + 1);
 1085 #ifdef SIOP_DEBUG_DR
 1086                         printf("disconnect offset %d\n", offset);
 1087 #endif
 1088                         siop_sdp(&esiop_cmd->cmd_c, offset);
 1089                         /* we start again with no offset */
 1090                         ESIOP_XFER(esiop_cmd, saved_offset) =
 1091                             htole32(SIOP_NOOFFSET);
 1092                         esiop_table_sync(esiop_cmd,
 1093                             BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 1094                         CALL_SCRIPT(Ent_script_sched);
 1095                         return 1;
 1096                 case A_int_resfail:
 1097                         printf("reselect failed\n");
 1098                         CALL_SCRIPT(Ent_script_sched);
 1099                         return 1;
 1100                 case A_int_done:
 1101                         if (xs == NULL) {
 1102                                 printf("%s: done without command\n",
 1103                                     sc->sc_c.sc_dev.dv_xname);
 1104                                 CALL_SCRIPT(Ent_script_sched);
 1105                                 return 1;
 1106                         }
 1107 #ifdef SIOP_DEBUG_INTR
 1108                         printf("done, DSA=0x%lx target id 0x%x last msg "
 1109                             "in=0x%x status=0x%x\n", (u_long)esiop_cmd->cmd_c.dsa,
 1110                             le32toh(esiop_cmd->cmd_tables->id),
 1111                             esiop_cmd->cmd_tables->msg_in[0],
 1112                             le32toh(esiop_cmd->cmd_tables->status));
 1113 #endif
 1114                         INCSTAT(esiop_stat_intr_done);
 1115                         esiop_cmd->cmd_c.status = CMDST_DONE;
 1116                         goto end;
 1117                 default:
 1118                         printf("unknown irqcode %x\n", irqcode);
 1119                         if (xs) {
 1120                                 xs->error = XS_SELTIMEOUT;
 1121                                 goto end;
 1122                         }
 1123                         goto reset;
 1124                 }
 1125                 return 1;
 1126         }
 1127         /* We just should't get there */
 1128         panic("siop_intr: I shouldn't be there !");
 1129 
 1130 end:
 1131         /*
 1132          * restart the script now if command completed properly
 1133          * Otherwise wait for siop_scsicmd_end(), we may need to cleanup the
 1134          * queue
 1135          */
 1136         xs->status = le32toh(esiop_cmd->cmd_tables->status);
 1137 #ifdef SIOP_DEBUG_INTR
 1138         printf("esiop_intr end: status %d\n", xs->status);
 1139 #endif
 1140         if (tag >= 0)
 1141                 esiop_lun->tactive[tag] = NULL;
 1142         else
 1143                 esiop_lun->active = NULL;
 1144         offset = bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
 1145             SIOP_SCRATCHA + 1);
 1146         /*
 1147          * if we got a disconnect between the last data phase
 1148          * and the status phase, offset will be 0. In this
 1149          * case, cmd_tables->saved_offset will have the proper value 
 1150          * if it got updated by the controller
 1151          */
 1152         if (offset == 0 &&
 1153             ESIOP_XFER(esiop_cmd, saved_offset) != htole32(SIOP_NOOFFSET))
 1154                 offset =
 1155                     (le32toh(ESIOP_XFER(esiop_cmd, saved_offset)) >> 8) & 0xff;
 1156 
 1157         esiop_scsicmd_end(esiop_cmd, offset);
 1158         if (freetarget && esiop_target->target_c.status == TARST_PROBING)
 1159                 esiop_del_dev(sc, target, lun);
 1160         CALL_SCRIPT(Ent_script_sched);
 1161         return 1;
 1162 }
 1163 
 1164 void
 1165 esiop_scsicmd_end(esiop_cmd, offset)
 1166         struct esiop_cmd *esiop_cmd;
 1167         int offset;
 1168 {
 1169         struct scsipi_xfer *xs = esiop_cmd->cmd_c.xs;
 1170         struct esiop_softc *sc = (struct esiop_softc *)esiop_cmd->cmd_c.siop_sc;
 1171 
 1172         siop_update_resid(&esiop_cmd->cmd_c, offset);
 1173 
 1174         switch(xs->status) {
 1175         case SCSI_OK:
 1176                 xs->error = XS_NOERROR;
 1177                 break;
 1178         case SCSI_BUSY:
 1179                 xs->error = XS_BUSY;
 1180                 break;
 1181         case SCSI_CHECK:
 1182                 xs->error = XS_BUSY;
 1183                 /* remove commands in the queue and scheduler */
 1184                 esiop_unqueue(sc, xs->xs_periph->periph_target,
 1185                     xs->xs_periph->periph_lun);
 1186                 break;
 1187         case SCSI_QUEUE_FULL:
 1188                 INCSTAT(esiop_stat_intr_qfull);
 1189 #ifdef SIOP_DEBUG
 1190                 printf("%s:%d:%d: queue full (tag %d)\n",
 1191                     sc->sc_c.sc_dev.dv_xname,
 1192                     xs->xs_periph->periph_target,
 1193                     xs->xs_periph->periph_lun, esiop_cmd->cmd_c.tag);
 1194 #endif
 1195                 xs->error = XS_BUSY;
 1196                 break;
 1197         case SCSI_SIOP_NOCHECK:
 1198                 /*
 1199                  * don't check status, xs->error is already valid
 1200                  */
 1201                 break;
 1202         case SCSI_SIOP_NOSTATUS:
 1203                 /*
 1204                  * the status byte was not updated, cmd was
 1205                  * aborted
 1206                  */
 1207                 xs->error = XS_SELTIMEOUT;
 1208                 break;
 1209         default:
 1210                 scsipi_printaddr(xs->xs_periph);
 1211                 printf("invalid status code %d\n", xs->status);
 1212                 xs->error = XS_DRIVER_STUFFUP;
 1213         }
 1214         if (xs->xs_control & (XS_CTL_DATA_IN | XS_CTL_DATA_OUT)) {
 1215                 bus_dmamap_sync(sc->sc_c.sc_dmat,
 1216                     esiop_cmd->cmd_c.dmamap_data, 0,
 1217                     esiop_cmd->cmd_c.dmamap_data->dm_mapsize,
 1218                     (xs->xs_control & XS_CTL_DATA_IN) ?
 1219                     BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
 1220                 bus_dmamap_unload(sc->sc_c.sc_dmat,
 1221                     esiop_cmd->cmd_c.dmamap_data);
 1222         }
 1223         bus_dmamap_unload(sc->sc_c.sc_dmat, esiop_cmd->cmd_c.dmamap_cmd);
 1224         callout_stop(&esiop_cmd->cmd_c.xs->xs_callout);
 1225         esiop_cmd->cmd_c.status = CMDST_FREE;
 1226         TAILQ_INSERT_TAIL(&sc->free_list, esiop_cmd, next);
 1227 #if 0
 1228         if (xs->resid != 0)
 1229                 printf("resid %d datalen %d\n", xs->resid, xs->datalen);
 1230 #endif
 1231         scsipi_done (xs);
 1232 }
 1233 
 1234 void
 1235 esiop_checkdone(sc)
 1236         struct esiop_softc *sc;
 1237 {
 1238         int target, lun, tag;
 1239         struct esiop_target *esiop_target;
 1240         struct esiop_lun *esiop_lun;
 1241         struct esiop_cmd *esiop_cmd;
 1242         u_int32_t slot;
 1243         int needsync = 0;
 1244         int status;
 1245         u_int32_t sem, offset;
 1246 
 1247         esiop_script_sync(sc, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
 1248         sem = esiop_script_read(sc, sc->sc_semoffset);
 1249         esiop_script_write(sc, sc->sc_semoffset, sem & ~A_sem_done);
 1250         if ((sc->sc_flags & SCF_CHAN_NOSLOT) && (sem & A_sem_start)) {
 1251                 /*
 1252                  * at last one command have been started,
 1253                  * so we should have free slots now
 1254                  */
 1255                 sc->sc_flags &= ~SCF_CHAN_NOSLOT;
 1256                 scsipi_channel_thaw(&sc->sc_c.sc_chan, 1);
 1257         }
 1258         esiop_script_sync(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 1259 
 1260         if ((sem & A_sem_done) == 0) {
 1261                 /* no pending done command */
 1262                 return;
 1263         }
 1264 
 1265         bus_dmamap_sync(sc->sc_c.sc_dmat, sc->sc_done_map,
 1266             sc->sc_done_offset, A_ndone_slots * sizeof(u_int32_t),
 1267             BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
 1268 next:
 1269         if (sc->sc_done_slot[sc->sc_currdoneslot] == 0) {
 1270                 if (needsync)
 1271                         bus_dmamap_sync(sc->sc_c.sc_dmat, sc->sc_done_map,
 1272                             sc->sc_done_offset,
 1273                             A_ndone_slots * sizeof(u_int32_t),
 1274                             BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 1275                 return;
 1276         }
 1277 
 1278         needsync = 1;
 1279 
 1280         slot = htole32(sc->sc_done_slot[sc->sc_currdoneslot]);
 1281         sc->sc_done_slot[sc->sc_currdoneslot] = 0;
 1282         sc->sc_currdoneslot += 1;
 1283         if (sc->sc_currdoneslot == A_ndone_slots)
 1284                 sc->sc_currdoneslot = 0;
 1285 
 1286         target =  (slot & A_f_c_target) ? (slot >> 8) & 0xff : -1;
 1287         lun =  (slot & A_f_c_lun) ? (slot >> 16) & 0xff : -1;
 1288         tag =  (slot & A_f_c_tag) ? (slot >> 24) & 0xff : -1;
 1289 
 1290         esiop_target = (target >= 0) ?
 1291             (struct esiop_target *)sc->sc_c.targets[target] : NULL;
 1292         if (esiop_target == NULL) {
 1293                 printf("esiop_target (target %d) not valid\n", target);
 1294                 goto next;
 1295         }
 1296         esiop_lun = (lun >= 0) ? esiop_target->esiop_lun[lun] : NULL;
 1297         if (esiop_lun == NULL) {
 1298                 printf("esiop_lun (target %d lun %d) not valid\n",
 1299                     target, lun);
 1300                 goto next;
 1301         }
 1302         esiop_cmd = (tag >= 0) ? esiop_lun->tactive[tag] : esiop_lun->active;
 1303         if (esiop_cmd == NULL) {
 1304                 printf("esiop_cmd (target %d lun %d tag %d) not valid\n",
 1305                     target, lun, tag);
 1306                         goto next;
 1307         }
 1308 
 1309         esiop_table_sync(esiop_cmd,
 1310                     BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
 1311         status = le32toh(esiop_cmd->cmd_tables->status);
 1312 #ifdef DIAGNOSTIC
 1313         if (status != SCSI_OK) {
 1314                 printf("command for T/L/Q %d/%d/%d status %d\n",
 1315                     target, lun, tag, status);
 1316                 goto next;
 1317         }
 1318 
 1319 #endif
 1320         /* Ok, this command has been handled */
 1321         esiop_cmd->cmd_c.xs->status = status;
 1322         if (tag >= 0)
 1323                 esiop_lun->tactive[tag] = NULL;
 1324         else
 1325                 esiop_lun->active = NULL;
 1326         /*
 1327          * scratcha was eventually saved in saved_offset by script.
 1328          * fetch offset from it
 1329          */
 1330         offset = 0;
 1331         if (ESIOP_XFER(esiop_cmd, saved_offset) != htole32(SIOP_NOOFFSET))
 1332                 offset =
 1333                     (le32toh(ESIOP_XFER(esiop_cmd, saved_offset)) >> 8) & 0xff;
 1334         esiop_scsicmd_end(esiop_cmd, offset);
 1335         goto next;
 1336 }
 1337 
 1338 void
 1339 esiop_unqueue(sc, target, lun)
 1340         struct esiop_softc *sc;
 1341         int target;
 1342         int lun;
 1343 {
 1344         int slot, tag;
 1345         u_int32_t slotdsa;
 1346         struct esiop_cmd *esiop_cmd;
 1347         struct esiop_lun *esiop_lun =
 1348             ((struct esiop_target *)sc->sc_c.targets[target])->esiop_lun[lun];
 1349 
 1350         /* first make sure to read valid data */
 1351         esiop_script_sync(sc, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
 1352 
 1353         for (tag = 0; tag < ESIOP_NTAG; tag++) {
 1354                 /* look for commands in the scheduler, not yet started */
 1355                 if (esiop_lun->tactive[tag] == NULL)
 1356                         continue;
 1357                 esiop_cmd = esiop_lun->tactive[tag];
 1358                 for (slot = 0; slot < A_ncmd_slots; slot++) {
 1359                         slotdsa = esiop_script_read(sc,
 1360                             sc->sc_shedoffset + slot * CMD_SLOTSIZE);
 1361                         /* if the slot has any flag, it won't match the DSA */
 1362                         if (slotdsa == esiop_cmd->cmd_c.dsa) { /* found it */
 1363                                 /* Mark this slot as ignore */
 1364                                 esiop_script_write(sc,
 1365                                     sc->sc_shedoffset + slot * CMD_SLOTSIZE,
 1366                                     esiop_cmd->cmd_c.dsa | A_f_cmd_ignore);
 1367                                 /* ask to requeue */
 1368                                 esiop_cmd->cmd_c.xs->error = XS_REQUEUE;
 1369                                 esiop_cmd->cmd_c.xs->status = SCSI_SIOP_NOCHECK;
 1370                                 esiop_lun->tactive[tag] = NULL;
 1371                                 esiop_scsicmd_end(esiop_cmd, 0);
 1372                                 break;
 1373                         }
 1374                 }
 1375         }
 1376         esiop_script_sync(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 1377 }
 1378 
 1379 /*
 1380  * handle a rejected queue tag message: the command will run untagged,
 1381  * has to adjust the reselect script.
 1382  */
 1383 
 1384 
 1385 int
 1386 esiop_handle_qtag_reject(esiop_cmd)
 1387         struct esiop_cmd *esiop_cmd;
 1388 {
 1389         struct esiop_softc *sc = (struct esiop_softc *)esiop_cmd->cmd_c.siop_sc;
 1390         int target = esiop_cmd->cmd_c.xs->xs_periph->periph_target;
 1391         int lun = esiop_cmd->cmd_c.xs->xs_periph->periph_lun;
 1392         int tag = esiop_cmd->cmd_tables->msg_out[2];
 1393         struct esiop_target *esiop_target =
 1394             (struct esiop_target*)sc->sc_c.targets[target];
 1395         struct esiop_lun *esiop_lun = esiop_target->esiop_lun[lun];
 1396 
 1397 #ifdef SIOP_DEBUG
 1398         printf("%s:%d:%d: tag message %d (%d) rejected (status %d)\n",
 1399             sc->sc_c.sc_dev.dv_xname, target, lun, tag, esiop_cmd->cmd_c.tag,
 1400             esiop_cmd->cmd_c.status);
 1401 #endif
 1402 
 1403         if (esiop_lun->active != NULL) {
 1404                 printf("%s: untagged command already running for target %d "
 1405                     "lun %d (status %d)\n", sc->sc_c.sc_dev.dv_xname,
 1406                     target, lun, esiop_lun->active->cmd_c.status);
 1407                 return -1;
 1408         }
 1409         /* clear tag slot */
 1410         esiop_lun->tactive[tag] = NULL;
 1411         /* add command to non-tagged slot */
 1412         esiop_lun->active = esiop_cmd;
 1413         esiop_cmd->cmd_c.flags &= ~CMDFL_TAG;
 1414         esiop_cmd->cmd_c.tag = -1;
 1415         /* update DSA table */
 1416         esiop_script_write(sc, esiop_target->lun_table_offset +
 1417             lun * 2 + A_target_luntbl / sizeof(u_int32_t),
 1418             esiop_cmd->cmd_c.dsa);
 1419         esiop_script_sync(sc, BUS_DMASYNC_PREREAD |  BUS_DMASYNC_PREWRITE);
 1420         return 0;
 1421 }
 1422 
 1423 /*
 1424  * handle a bus reset: reset chip, unqueue all active commands, free all
 1425  * target struct and report lossage to upper layer.
 1426  * As the upper layer may requeue immediatly we have to first store
 1427  * all active commands in a temporary queue.
 1428  */
 1429 void
 1430 esiop_handle_reset(sc)
 1431         struct esiop_softc *sc;
 1432 {
 1433         struct esiop_cmd *esiop_cmd;
 1434         struct esiop_lun *esiop_lun;
 1435         int target, lun, tag;
 1436         /*
 1437          * scsi bus reset. reset the chip and restart
 1438          * the queue. Need to clean up all active commands
 1439          */
 1440         printf("%s: scsi bus reset\n", sc->sc_c.sc_dev.dv_xname);
 1441         /* stop, reset and restart the chip */
 1442         esiop_reset(sc);
 1443 
 1444         if (sc->sc_flags & SCF_CHAN_NOSLOT) {
 1445                 /* chip has been reset, all slots are free now */
 1446                 sc->sc_flags &= ~SCF_CHAN_NOSLOT;
 1447                 scsipi_channel_thaw(&sc->sc_c.sc_chan, 1);
 1448         }
 1449         /*
 1450          * Process all commands: first commands completes, then commands
 1451          * being executed
 1452          */
 1453         esiop_checkdone(sc);
 1454         for (target = 0; target < sc->sc_c.sc_chan.chan_ntargets;
 1455             target++) {
 1456                 struct esiop_target *esiop_target =
 1457                     (struct esiop_target *)sc->sc_c.targets[target];
 1458                 if (esiop_target == NULL)
 1459                         continue;
 1460                 for (lun = 0; lun < 8; lun++) {
 1461                         esiop_lun = esiop_target->esiop_lun[lun];
 1462                         if (esiop_lun == NULL)
 1463                                 continue;
 1464                         for (tag = -1; tag <
 1465                             ((sc->sc_c.targets[target]->flags & TARF_TAG) ?
 1466                             ESIOP_NTAG : 0);
 1467                             tag++) {
 1468                                 if (tag >= 0)
 1469                                         esiop_cmd = esiop_lun->tactive[tag];
 1470                                 else
 1471                                         esiop_cmd = esiop_lun->active;
 1472                                 if (esiop_cmd == NULL)
 1473                                         continue;
 1474                                 scsipi_printaddr(esiop_cmd->cmd_c.xs->xs_periph);
 1475                                 printf("command with tag id %d reset\n", tag);
 1476                                 esiop_cmd->cmd_c.xs->error =
 1477                                     (esiop_cmd->cmd_c.flags & CMDFL_TIMEOUT) ?
 1478                                     XS_TIMEOUT : XS_RESET;
 1479                                 esiop_cmd->cmd_c.xs->status = SCSI_SIOP_NOCHECK;
 1480                                 if (tag >= 0)
 1481                                         esiop_lun->tactive[tag] = NULL;
 1482                                 else
 1483                                         esiop_lun->active = NULL;
 1484                                 esiop_cmd->cmd_c.status = CMDST_DONE;
 1485                                 esiop_scsicmd_end(esiop_cmd, 0);
 1486                         }
 1487                 }
 1488                 sc->sc_c.targets[target]->status = TARST_ASYNC;
 1489                 sc->sc_c.targets[target]->flags &= ~(TARF_ISWIDE | TARF_ISDT);
 1490                 sc->sc_c.targets[target]->period =
 1491                     sc->sc_c.targets[target]->offset = 0;
 1492                 siop_update_xfer_mode(&sc->sc_c, target);
 1493         }
 1494 
 1495         scsipi_async_event(&sc->sc_c.sc_chan, ASYNC_EVENT_RESET, NULL);
 1496 }
 1497 
 1498 void
 1499 esiop_scsipi_request(chan, req, arg)
 1500         struct scsipi_channel *chan;
 1501         scsipi_adapter_req_t req;
 1502         void *arg;
 1503 {
 1504         struct scsipi_xfer *xs;
 1505         struct scsipi_periph *periph;
 1506         struct esiop_softc *sc = (void *)chan->chan_adapter->adapt_dev;
 1507         struct esiop_cmd *esiop_cmd;
 1508         struct esiop_target *esiop_target;
 1509         int s, error, i;
 1510         int target;
 1511         int lun;
 1512 
 1513         switch (req) {
 1514         case ADAPTER_REQ_RUN_XFER:
 1515                 xs = arg;
 1516                 periph = xs->xs_periph;
 1517                 target = periph->periph_target;
 1518                 lun = periph->periph_lun;
 1519 
 1520                 s = splbio();
 1521                 /*
 1522                  * first check if there are pending complete commands.
 1523                  * this can free us some resources (in the rings for example).
 1524                  * we have to lock it to avoid recursion.
 1525                  */
 1526                 if ((sc->sc_flags & SCF_CHAN_ADAPTREQ) == 0) {
 1527                         sc->sc_flags |= SCF_CHAN_ADAPTREQ;
 1528                         esiop_checkdone(sc);
 1529                         sc->sc_flags &= ~SCF_CHAN_ADAPTREQ;
 1530                 }
 1531 #ifdef SIOP_DEBUG_SCHED
 1532                 printf("starting cmd for %d:%d tag %d(%d)\n", target, lun,
 1533                     xs->xs_tag_type, xs->xs_tag_id);
 1534 #endif
 1535                 esiop_cmd = TAILQ_FIRST(&sc->free_list);
 1536                 if (esiop_cmd == NULL) {
 1537                         xs->error = XS_RESOURCE_SHORTAGE;
 1538                         scsipi_done(xs);
 1539                         splx(s);
 1540                         return;
 1541                 }
 1542                 TAILQ_REMOVE(&sc->free_list, esiop_cmd, next);
 1543 #ifdef DIAGNOSTIC
 1544                 if (esiop_cmd->cmd_c.status != CMDST_FREE)
 1545                         panic("siop_scsicmd: new cmd not free");
 1546 #endif
 1547                 esiop_target = (struct esiop_target*)sc->sc_c.targets[target];
 1548                 if (esiop_target == NULL) {
 1549 #ifdef SIOP_DEBUG
 1550                         printf("%s: alloc siop_target for target %d\n",
 1551                                 sc->sc_c.sc_dev.dv_xname, target);
 1552 #endif
 1553                         sc->sc_c.targets[target] =
 1554                             malloc(sizeof(struct esiop_target),
 1555                                 M_DEVBUF, M_NOWAIT | M_ZERO);
 1556                         if (sc->sc_c.targets[target] == NULL) {
 1557                                 printf("%s: can't malloc memory for "
 1558                                     "target %d\n", sc->sc_c.sc_dev.dv_xname,
 1559                                     target);
 1560                                 xs->error = XS_RESOURCE_SHORTAGE;
 1561                                 scsipi_done(xs);
 1562                                 splx(s);
 1563                                 return;
 1564                         }
 1565                         esiop_target =
 1566                             (struct esiop_target*)sc->sc_c.targets[target];
 1567                         esiop_target->target_c.status = TARST_PROBING;
 1568                         esiop_target->target_c.flags = 0;
 1569                         esiop_target->target_c.id =
 1570                             sc->sc_c.clock_div << 24; /* scntl3 */
 1571                         esiop_target->target_c.id |=  target << 16; /* id */
 1572                         /* esiop_target->target_c.id |= 0x0 << 8; scxfer is 0 */
 1573 
 1574                         for (i=0; i < 8; i++)
 1575                                 esiop_target->esiop_lun[i] = NULL;
 1576                         esiop_target_register(sc, target);
 1577                 }
 1578                 if (esiop_target->esiop_lun[lun] == NULL) {
 1579                         esiop_target->esiop_lun[lun] =
 1580                             malloc(sizeof(struct esiop_lun), M_DEVBUF,
 1581                             M_NOWAIT|M_ZERO);
 1582                         if (esiop_target->esiop_lun[lun] == NULL) {
 1583                                 printf("%s: can't alloc esiop_lun for "
 1584                                     "target %d lun %d\n",
 1585                                     sc->sc_c.sc_dev.dv_xname, target, lun);
 1586                                 xs->error = XS_RESOURCE_SHORTAGE;
 1587                                 scsipi_done(xs);
 1588                                 splx(s);
 1589                                 return;
 1590                         }
 1591                 }
 1592                 esiop_cmd->cmd_c.siop_target = sc->sc_c.targets[target];
 1593                 esiop_cmd->cmd_c.xs = xs;
 1594                 esiop_cmd->cmd_c.flags = 0;
 1595                 esiop_cmd->cmd_c.status = CMDST_READY;
 1596 
 1597                 /* load the DMA maps */
 1598                 error = bus_dmamap_load(sc->sc_c.sc_dmat,
 1599                     esiop_cmd->cmd_c.dmamap_cmd,
 1600                     xs->cmd, xs->cmdlen, NULL, BUS_DMA_NOWAIT);
 1601                 if (error) {
 1602                         printf("%s: unable to load cmd DMA map: %d\n",
 1603                             sc->sc_c.sc_dev.dv_xname, error);
 1604                         xs->error = XS_DRIVER_STUFFUP;
 1605                         scsipi_done(xs);
 1606                         splx(s);
 1607                         return;
 1608                 }
 1609                 if (xs->xs_control & (XS_CTL_DATA_IN | XS_CTL_DATA_OUT)) {
 1610                         error = bus_dmamap_load(sc->sc_c.sc_dmat,
 1611                             esiop_cmd->cmd_c.dmamap_data, xs->data, xs->datalen,
 1612                             NULL, BUS_DMA_NOWAIT | BUS_DMA_STREAMING |
 1613                             ((xs->xs_control & XS_CTL_DATA_IN) ?
 1614                              BUS_DMA_READ : BUS_DMA_WRITE));
 1615                         if (error) {
 1616                                 printf("%s: unable to load cmd DMA map: %d",
 1617                                     sc->sc_c.sc_dev.dv_xname, error);
 1618                                 xs->error = XS_DRIVER_STUFFUP;
 1619                                 scsipi_done(xs);
 1620                                 bus_dmamap_unload(sc->sc_c.sc_dmat,
 1621                                     esiop_cmd->cmd_c.dmamap_cmd);
 1622                                 splx(s);
 1623                                 return;
 1624                         }
 1625                         bus_dmamap_sync(sc->sc_c.sc_dmat,
 1626                             esiop_cmd->cmd_c.dmamap_data, 0,
 1627                             esiop_cmd->cmd_c.dmamap_data->dm_mapsize,
 1628                             (xs->xs_control & XS_CTL_DATA_IN) ?
 1629                             BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
 1630                 }
 1631                 bus_dmamap_sync(sc->sc_c.sc_dmat, esiop_cmd->cmd_c.dmamap_cmd,
 1632                     0, esiop_cmd->cmd_c.dmamap_cmd->dm_mapsize,
 1633                     BUS_DMASYNC_PREWRITE);
 1634 
 1635                 if (xs->xs_tag_type)
 1636                         esiop_cmd->cmd_c.tag = xs->xs_tag_id;
 1637                 else
 1638                         esiop_cmd->cmd_c.tag = -1;
 1639                 siop_setuptables(&esiop_cmd->cmd_c);
 1640                 ESIOP_XFER(esiop_cmd, saved_offset) = htole32(SIOP_NOOFFSET);
 1641                 ESIOP_XFER(esiop_cmd, tlq) = htole32(A_f_c_target | A_f_c_lun);
 1642                 ESIOP_XFER(esiop_cmd, tlq) |=
 1643                     htole32((target << 8) | (lun << 16));
 1644                 if (esiop_cmd->cmd_c.flags & CMDFL_TAG) {
 1645                         ESIOP_XFER(esiop_cmd, tlq) |= htole32(A_f_c_tag);
 1646                         ESIOP_XFER(esiop_cmd, tlq) |=
 1647                             htole32(esiop_cmd->cmd_c.tag << 24);
 1648                 }
 1649 
 1650                 esiop_table_sync(esiop_cmd,
 1651                     BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 1652                 esiop_start(sc, esiop_cmd);
 1653                 if (xs->xs_control & XS_CTL_POLL) {
 1654                         /* poll for command completion */
 1655                         while ((xs->xs_status & XS_STS_DONE) == 0) {
 1656                                 delay(1000);
 1657                                 esiop_intr(sc);
 1658                         }
 1659                 }
 1660                 splx(s);
 1661                 return;
 1662 
 1663         case ADAPTER_REQ_GROW_RESOURCES:
 1664 #ifdef SIOP_DEBUG
 1665                 printf("%s grow resources (%d)\n", sc->sc_c.sc_dev.dv_xname,
 1666                     sc->sc_c.sc_adapt.adapt_openings);
 1667 #endif
 1668                 esiop_morecbd(sc);
 1669                 return;
 1670 
 1671         case ADAPTER_REQ_SET_XFER_MODE:
 1672         {
 1673                 struct scsipi_xfer_mode *xm = arg;
 1674                 if (sc->sc_c.targets[xm->xm_target] == NULL)
 1675                         return;
 1676                 s = splbio();
 1677                 if (xm->xm_mode & PERIPH_CAP_TQING) {
 1678                         sc->sc_c.targets[xm->xm_target]->flags |= TARF_TAG;
 1679                         /* allocate tag tables for this device */
 1680                         for (lun = 0;
 1681                             lun < sc->sc_c.sc_chan.chan_nluns; lun++) {
 1682                                 if (scsipi_lookup_periph(chan,
 1683                                     xm->xm_target, lun) != NULL)
 1684                                         esiop_add_dev(sc, xm->xm_target, lun);
 1685                         }
 1686                 }
 1687                 if ((xm->xm_mode & PERIPH_CAP_WIDE16) &&
 1688                     (sc->sc_c.features & SF_BUS_WIDE))
 1689                         sc->sc_c.targets[xm->xm_target]->flags |= TARF_WIDE;
 1690                 if (xm->xm_mode & PERIPH_CAP_SYNC)
 1691                         sc->sc_c.targets[xm->xm_target]->flags |= TARF_SYNC;
 1692                 if ((xm->xm_mode & PERIPH_CAP_DT) &&
 1693                     (sc->sc_c.features & SF_CHIP_DT))
 1694                         sc->sc_c.targets[xm->xm_target]->flags |= TARF_DT;
 1695                 if ((xm->xm_mode &
 1696                     (PERIPH_CAP_SYNC | PERIPH_CAP_WIDE16 | PERIPH_CAP_DT)) ||
 1697                     sc->sc_c.targets[xm->xm_target]->status == TARST_PROBING)
 1698                         sc->sc_c.targets[xm->xm_target]->status = TARST_ASYNC;
 1699 
 1700                 splx(s);
 1701         }
 1702         }
 1703 }
 1704 
 1705 static void
 1706 esiop_start(sc, esiop_cmd)
 1707         struct esiop_softc *sc;
 1708         struct esiop_cmd *esiop_cmd;
 1709 {
 1710         struct esiop_lun *esiop_lun;
 1711         struct esiop_target *esiop_target;
 1712         int timeout;
 1713         int target, lun, slot;
 1714 
 1715         /*
 1716          * first make sure to read valid data
 1717          */
 1718         esiop_script_sync(sc, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
 1719 
 1720         /*
 1721          * We use a circular queue here. sc->sc_currschedslot points to a
 1722          * free slot, unless we have filled the queue. Check this.
 1723          */
 1724         slot = sc->sc_currschedslot;
 1725         if ((esiop_script_read(sc, sc->sc_shedoffset + slot * CMD_SLOTSIZE) &
 1726             A_f_cmd_free) == 0) {
 1727                 /*
 1728                  * no more free slot, no need to continue. freeze the queue
 1729                  * and requeue this command.
 1730                  */
 1731                 scsipi_channel_freeze(&sc->sc_c.sc_chan, 1);
 1732                 sc->sc_flags |= SCF_CHAN_NOSLOT;
 1733                 esiop_script_write(sc, sc->sc_semoffset,
 1734                     esiop_script_read(sc, sc->sc_semoffset) & ~A_sem_start);
 1735                 esiop_script_sync(sc,
 1736                     BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 1737                 esiop_cmd->cmd_c.xs->error = XS_REQUEUE;
 1738                 esiop_cmd->cmd_c.xs->status = SCSI_SIOP_NOCHECK;
 1739                 esiop_scsicmd_end(esiop_cmd, 0);
 1740                 return;
 1741         }
 1742         /* OK, we can use this slot */
 1743 
 1744         target = esiop_cmd->cmd_c.xs->xs_periph->periph_target;
 1745         lun = esiop_cmd->cmd_c.xs->xs_periph->periph_lun;
 1746         esiop_target = (struct esiop_target*)sc->sc_c.targets[target];
 1747         esiop_lun = esiop_target->esiop_lun[lun];
 1748         /* if non-tagged command active, panic: this shouldn't happen */
 1749         if (esiop_lun->active != NULL) {
 1750                 panic("esiop_start: tagged cmd while untagged running");
 1751         }
 1752 #ifdef DIAGNOSTIC
 1753         /* sanity check the tag if needed */
 1754         if (esiop_cmd->cmd_c.flags & CMDFL_TAG) {
 1755                 if (esiop_lun->tactive[esiop_cmd->cmd_c.tag] != NULL)
 1756                         panic("esiop_start: tag not free");
 1757                 if (esiop_cmd->cmd_c.tag >= ESIOP_NTAG ||
 1758                     esiop_cmd->cmd_c.tag < 0) {
 1759                         scsipi_printaddr(esiop_cmd->cmd_c.xs->xs_periph);
 1760                         printf(": tag id %d\n", esiop_cmd->cmd_c.tag);
 1761                         panic("esiop_start: invalid tag id");
 1762                 }
 1763         }
 1764 #endif
 1765 #ifdef SIOP_DEBUG_SCHED
 1766         printf("using slot %d for DSA 0x%lx\n", slot,
 1767             (u_long)esiop_cmd->cmd_c.dsa);
 1768 #endif
 1769         /* mark command as active */
 1770         if (esiop_cmd->cmd_c.status == CMDST_READY)
 1771                 esiop_cmd->cmd_c.status = CMDST_ACTIVE;
 1772         else
 1773                 panic("esiop_start: bad status");
 1774         /* DSA table for reselect */
 1775         if (esiop_cmd->cmd_c.flags & CMDFL_TAG) {
 1776                 esiop_lun->tactive[esiop_cmd->cmd_c.tag] = esiop_cmd;
 1777                 /* DSA table for reselect */
 1778                 esiop_lun->lun_tagtbl->tbl[esiop_cmd->cmd_c.tag] =
 1779                     htole32(esiop_cmd->cmd_c.dsa);
 1780                 bus_dmamap_sync(sc->sc_c.sc_dmat,
 1781                     esiop_lun->lun_tagtbl->tblblk->blkmap,
 1782                     esiop_lun->lun_tagtbl->tbl_offset,
 1783                     sizeof(u_int32_t) * ESIOP_NTAG, BUS_DMASYNC_PREWRITE);
 1784         } else {
 1785                 esiop_lun->active = esiop_cmd;
 1786                 esiop_script_write(sc,
 1787                     esiop_target->lun_table_offset +
 1788                     lun * 2 + A_target_luntbl / sizeof(u_int32_t),
 1789                     esiop_cmd->cmd_c.dsa);
 1790         }
 1791         /* scheduler slot: DSA */
 1792         esiop_script_write(sc, sc->sc_shedoffset + slot * CMD_SLOTSIZE,
 1793             esiop_cmd->cmd_c.dsa);
 1794         /* make sure SCRIPT processor will read valid data */
 1795         esiop_script_sync(sc, BUS_DMASYNC_PREREAD |  BUS_DMASYNC_PREWRITE);
 1796         /* handle timeout */
 1797         if ((esiop_cmd->cmd_c.xs->xs_control & XS_CTL_POLL) == 0) {
 1798                 /* start exire timer */
 1799                 timeout = mstohz(esiop_cmd->cmd_c.xs->timeout);
 1800                 if (timeout == 0)
 1801                         timeout = 1;
 1802                 callout_reset( &esiop_cmd->cmd_c.xs->xs_callout,
 1803                     timeout, esiop_timeout, esiop_cmd);
 1804         }
 1805         /* Signal script it has some work to do */
 1806         bus_space_write_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
 1807             SIOP_ISTAT, ISTAT_SIGP);
 1808         /* update the current slot, and wait for IRQ */
 1809         sc->sc_currschedslot++;
 1810         if (sc->sc_currschedslot >= A_ncmd_slots)
 1811                 sc->sc_currschedslot = 0;
 1812         return;
 1813 }
 1814 
 1815 void
 1816 esiop_timeout(v)
 1817         void *v;
 1818 {
 1819         struct esiop_cmd *esiop_cmd = v;
 1820         struct esiop_softc *sc =
 1821             (struct esiop_softc *)esiop_cmd->cmd_c.siop_sc;
 1822         int s;
 1823 #ifdef SIOP_DEBUG
 1824         int slot, slotdsa;
 1825 #endif
 1826 
 1827         s = splbio();
 1828         esiop_table_sync(esiop_cmd,
 1829             BUS_DMASYNC_POSTREAD |
 1830             BUS_DMASYNC_POSTWRITE);
 1831         scsipi_printaddr(esiop_cmd->cmd_c.xs->xs_periph);
 1832 #ifdef SIOP_DEBUG
 1833         printf("command timeout (status %d)\n", le32toh(esiop_cmd->cmd_tables->status));
 1834 
 1835         esiop_script_sync(sc, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
 1836         for (slot = 0; slot < A_ncmd_slots; slot++) {
 1837                 slotdsa = esiop_script_read(sc,
 1838                     sc->sc_shedoffset + slot * CMD_SLOTSIZE);
 1839                 if ((slotdsa & 0x01) == 0)
 1840                         printf("slot %d not free (0x%x)\n", slot, slotdsa);
 1841         }
 1842         printf("istat 0x%x ", bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_ISTAT));
 1843         printf("DSP 0x%lx DSA 0x%x\n",
 1844             (u_long)(bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSP) - sc->sc_c.sc_scriptaddr),
 1845             bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSA));
 1846         bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_CTEST2);
 1847         printf("istat 0x%x\n", bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_ISTAT));
 1848 #else
 1849         printf("command timeout, CDB: ");
 1850         scsipi_print_cdb(esiop_cmd->cmd_c.xs->cmd);
 1851         printf("\n");
 1852 #endif
 1853         /* reset the scsi bus */
 1854         siop_resetbus(&sc->sc_c);
 1855 
 1856         /* deactivate callout */
 1857         callout_stop(&esiop_cmd->cmd_c.xs->xs_callout);
 1858         /*
 1859          * mark command has being timed out and just return;
 1860          * the bus reset will generate an interrupt,
 1861          * it will be handled in siop_intr()
 1862          */
 1863         esiop_cmd->cmd_c.flags |= CMDFL_TIMEOUT;
 1864         splx(s);
 1865         return;
 1866 
 1867 }
 1868 
 1869 void
 1870 esiop_dump_script(sc)
 1871         struct esiop_softc *sc;
 1872 {
 1873         int i;
 1874         for (i = 0; i < PAGE_SIZE / 4; i += 2) {
 1875                 printf("0x%04x: 0x%08x 0x%08x", i * 4,
 1876                     le32toh(sc->sc_c.sc_script[i]),
 1877                     le32toh(sc->sc_c.sc_script[i+1]));
 1878                 if ((le32toh(sc->sc_c.sc_script[i]) & 0xe0000000) ==
 1879                     0xc0000000) {
 1880                         i++;
 1881                         printf(" 0x%08x", le32toh(sc->sc_c.sc_script[i+1]));
 1882                 }
 1883                 printf("\n");
 1884         }
 1885 }
 1886 
 1887 void
 1888 esiop_morecbd(sc)
 1889         struct esiop_softc *sc;
 1890 {
 1891         int error, i, s;
 1892         bus_dma_segment_t seg;
 1893         int rseg;
 1894         struct esiop_cbd *newcbd;
 1895         struct esiop_xfer *xfer;
 1896         bus_addr_t dsa;
 1897 
 1898         /* allocate a new list head */
 1899         newcbd = malloc(sizeof(struct esiop_cbd), M_DEVBUF, M_NOWAIT|M_ZERO);
 1900         if (newcbd == NULL) {
 1901                 printf("%s: can't allocate memory for command descriptors "
 1902                     "head\n", sc->sc_c.sc_dev.dv_xname);
 1903                 return;
 1904         }
 1905 
 1906         /* allocate cmd list */
 1907         newcbd->cmds = malloc(sizeof(struct esiop_cmd) * SIOP_NCMDPB,
 1908             M_DEVBUF, M_NOWAIT|M_ZERO);
 1909         if (newcbd->cmds == NULL) {
 1910                 printf("%s: can't allocate memory for command descriptors\n",
 1911                     sc->sc_c.sc_dev.dv_xname);
 1912                 goto bad3;
 1913         }
 1914         error = bus_dmamem_alloc(sc->sc_c.sc_dmat, PAGE_SIZE, PAGE_SIZE, 0,
 1915             &seg, 1, &rseg, BUS_DMA_NOWAIT);
 1916         if (error) {
 1917                 printf("%s: unable to allocate cbd DMA memory, error = %d\n",
 1918                     sc->sc_c.sc_dev.dv_xname, error);
 1919                 goto bad2;
 1920         }
 1921         error = bus_dmamem_map(sc->sc_c.sc_dmat, &seg, rseg, PAGE_SIZE,
 1922             (caddr_t *)&newcbd->xfers, BUS_DMA_NOWAIT|BUS_DMA_COHERENT);
 1923         if (error) {
 1924                 printf("%s: unable to map cbd DMA memory, error = %d\n",
 1925                     sc->sc_c.sc_dev.dv_xname, error);
 1926                 goto bad2;
 1927         }
 1928         error = bus_dmamap_create(sc->sc_c.sc_dmat, PAGE_SIZE, 1, PAGE_SIZE, 0,
 1929             BUS_DMA_NOWAIT, &newcbd->xferdma);
 1930         if (error) {
 1931                 printf("%s: unable to create cbd DMA map, error = %d\n",
 1932                     sc->sc_c.sc_dev.dv_xname, error);
 1933                 goto bad1;
 1934         }
 1935         error = bus_dmamap_load(sc->sc_c.sc_dmat, newcbd->xferdma,
 1936             newcbd->xfers, PAGE_SIZE, NULL, BUS_DMA_NOWAIT);
 1937         if (error) {
 1938                 printf("%s: unable to load cbd DMA map, error = %d\n",
 1939                     sc->sc_c.sc_dev.dv_xname, error);
 1940                 goto bad0;
 1941         }
 1942 #ifdef DEBUG
 1943         printf("%s: alloc newcdb at PHY addr 0x%lx\n", sc->sc_c.sc_dev.dv_xname,
 1944             (unsigned long)newcbd->xferdma->dm_segs[0].ds_addr);
 1945 #endif
 1946         for (i = 0; i < SIOP_NCMDPB; i++) {
 1947                 error = bus_dmamap_create(sc->sc_c.sc_dmat, MAXPHYS, SIOP_NSG,
 1948                     MAXPHYS, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
 1949                     &newcbd->cmds[i].cmd_c.dmamap_data);
 1950                 if (error) {
 1951                         printf("%s: unable to create data DMA map for cbd: "
 1952                             "error %d\n",
 1953                             sc->sc_c.sc_dev.dv_xname, error);
 1954                         goto bad0;
 1955                 }
 1956                 error = bus_dmamap_create(sc->sc_c.sc_dmat,
 1957                     sizeof(struct scsipi_generic), 1,
 1958                     sizeof(struct scsipi_generic), 0,
 1959                     BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
 1960                     &newcbd->cmds[i].cmd_c.dmamap_cmd);
 1961                 if (error) {
 1962                         printf("%s: unable to create cmd DMA map for cbd %d\n",
 1963                             sc->sc_c.sc_dev.dv_xname, error);
 1964                         goto bad0;
 1965                 }
 1966                 newcbd->cmds[i].cmd_c.siop_sc = &sc->sc_c;
 1967                 newcbd->cmds[i].esiop_cbdp = newcbd;
 1968                 xfer = &newcbd->xfers[i];
 1969                 newcbd->cmds[i].cmd_tables = (struct siop_common_xfer *)xfer;
 1970                 memset(newcbd->cmds[i].cmd_tables, 0,
 1971                     sizeof(struct esiop_xfer));
 1972                 dsa = newcbd->xferdma->dm_segs[0].ds_addr +
 1973                     i * sizeof(struct esiop_xfer);
 1974                 newcbd->cmds[i].cmd_c.dsa = dsa;
 1975                 newcbd->cmds[i].cmd_c.status = CMDST_FREE;
 1976                 xfer->siop_tables.t_msgout.count= htole32(1);
 1977                 xfer->siop_tables.t_msgout.addr = htole32(dsa);
 1978                 xfer->siop_tables.t_msgin.count= htole32(1);
 1979                 xfer->siop_tables.t_msgin.addr = htole32(dsa +
 1980                         offsetof(struct siop_common_xfer, msg_in));
 1981                 xfer->siop_tables.t_extmsgin.count= htole32(2);
 1982                 xfer->siop_tables.t_extmsgin.addr = htole32(dsa +
 1983                         offsetof(struct siop_common_xfer, msg_in) + 1);
 1984                 xfer->siop_tables.t_extmsgdata.addr = htole32(dsa +
 1985                         offsetof(struct siop_common_xfer, msg_in) + 3);
 1986                 xfer->siop_tables.t_status.count= htole32(1);
 1987                 xfer->siop_tables.t_status.addr = htole32(dsa +
 1988                         offsetof(struct siop_common_xfer, status));
 1989 
 1990                 s = splbio();
 1991                 TAILQ_INSERT_TAIL(&sc->free_list, &newcbd->cmds[i], next);
 1992                 splx(s);
 1993 #ifdef SIOP_DEBUG
 1994                 printf("tables[%d]: in=0x%x out=0x%x status=0x%x "
 1995                     "offset=0x%x\n", i,
 1996                     le32toh(newcbd->cmds[i].cmd_tables->t_msgin.addr),
 1997                     le32toh(newcbd->cmds[i].cmd_tables->t_msgout.addr),
 1998                     le32toh(newcbd->cmds[i].cmd_tables->t_status.addr,
 1999                     le32toh(newcbd->cmds[i].cmd_tables->t_offset.addr));
 2000 #endif
 2001         }
 2002         s = splbio();
 2003         TAILQ_INSERT_TAIL(&sc->cmds, newcbd, next);
 2004         sc->sc_c.sc_adapt.adapt_openings += SIOP_NCMDPB;
 2005         splx(s);
 2006         return;
 2007 bad0:
 2008         bus_dmamap_unload(sc->sc_c.sc_dmat, newcbd->xferdma);
 2009         bus_dmamap_destroy(sc->sc_c.sc_dmat, newcbd->xferdma);
 2010 bad1:
 2011         bus_dmamem_free(sc->sc_c.sc_dmat, &seg, rseg);
 2012 bad2:
 2013         free(newcbd->cmds, M_DEVBUF);
 2014 bad3:
 2015         free(newcbd, M_DEVBUF);
 2016         return;
 2017 }
 2018 
 2019 void
 2020 esiop_moretagtbl(sc)
 2021         struct esiop_softc *sc;
 2022 {
 2023         int error, i, j, s;
 2024         bus_dma_segment_t seg;
 2025         int rseg;
 2026         struct esiop_dsatblblk *newtblblk;
 2027         struct esiop_dsatbl *newtbls;
 2028         u_int32_t *tbls;
 2029 
 2030         /* allocate a new list head */
 2031         newtblblk = malloc(sizeof(struct esiop_dsatblblk),
 2032             M_DEVBUF, M_NOWAIT|M_ZERO);
 2033         if (newtblblk == NULL) {
 2034                 printf("%s: can't allocate memory for tag DSA table block\n",
 2035                     sc->sc_c.sc_dev.dv_xname);
 2036                 return;
 2037         }
 2038 
 2039         /* allocate tbl list */
 2040         newtbls = malloc(sizeof(struct esiop_dsatbl) * ESIOP_NTPB,
 2041             M_DEVBUF, M_NOWAIT|M_ZERO);
 2042         if (newtbls == NULL) {
 2043                 printf("%s: can't allocate memory for command descriptors\n",
 2044                     sc->sc_c.sc_dev.dv_xname);
 2045                 goto bad3;
 2046         }
 2047         error = bus_dmamem_alloc(sc->sc_c.sc_dmat, PAGE_SIZE, PAGE_SIZE, 0,
 2048             &seg, 1, &rseg, BUS_DMA_NOWAIT);
 2049         if (error) {
 2050                 printf("%s: unable to allocate tbl DMA memory, error = %d\n",
 2051                     sc->sc_c.sc_dev.dv_xname, error);
 2052                 goto bad2;
 2053         }
 2054         error = bus_dmamem_map(sc->sc_c.sc_dmat, &seg, rseg, PAGE_SIZE,
 2055             (void *)&tbls, BUS_DMA_NOWAIT|BUS_DMA_COHERENT);
 2056         if (error) {
 2057                 printf("%s: unable to map tbls DMA memory, error = %d\n",
 2058                     sc->sc_c.sc_dev.dv_xname, error);
 2059                 goto bad2;
 2060         }
 2061         error = bus_dmamap_create(sc->sc_c.sc_dmat, PAGE_SIZE, 1, PAGE_SIZE, 0,
 2062             BUS_DMA_NOWAIT, &newtblblk->blkmap);
 2063         if (error) {
 2064                 printf("%s: unable to create tbl DMA map, error = %d\n",
 2065                     sc->sc_c.sc_dev.dv_xname, error);
 2066                 goto bad1;
 2067         }
 2068         error = bus_dmamap_load(sc->sc_c.sc_dmat, newtblblk->blkmap,
 2069             tbls, PAGE_SIZE, NULL, BUS_DMA_NOWAIT);
 2070         if (error) {
 2071                 printf("%s: unable to load tbl DMA map, error = %d\n",
 2072                     sc->sc_c.sc_dev.dv_xname, error);
 2073                 goto bad0;
 2074         }
 2075 #ifdef DEBUG
 2076         printf("%s: alloc new tag DSA table at PHY addr 0x%lx\n",
 2077             sc->sc_c.sc_dev.dv_xname,
 2078             (unsigned long)newtblblk->blkmap->dm_segs[0].ds_addr);
 2079 #endif
 2080         for (i = 0; i < ESIOP_NTPB; i++) {
 2081                 newtbls[i].tblblk = newtblblk;
 2082                 newtbls[i].tbl = &tbls[i * ESIOP_NTAG];
 2083                 newtbls[i].tbl_offset = i * ESIOP_NTAG * sizeof(u_int32_t);
 2084                 newtbls[i].tbl_dsa = newtblblk->blkmap->dm_segs[0].ds_addr +
 2085                     newtbls[i].tbl_offset;
 2086                 for (j = 0; j < ESIOP_NTAG; j++)
 2087                         newtbls[i].tbl[j] = j;
 2088                 s = splbio();
 2089                 TAILQ_INSERT_TAIL(&sc->free_tagtbl, &newtbls[i], next);
 2090                 splx(s);
 2091         }
 2092         s = splbio();
 2093         TAILQ_INSERT_TAIL(&sc->tag_tblblk, newtblblk, next);
 2094         splx(s);
 2095         return;
 2096 bad0:
 2097         bus_dmamap_unload(sc->sc_c.sc_dmat, newtblblk->blkmap);
 2098         bus_dmamap_destroy(sc->sc_c.sc_dmat, newtblblk->blkmap);
 2099 bad1:
 2100         bus_dmamem_free(sc->sc_c.sc_dmat, &seg, rseg);
 2101 bad2:
 2102         free(newtbls, M_DEVBUF);
 2103 bad3:
 2104         free(newtblblk, M_DEVBUF);
 2105         return;
 2106 }
 2107 
 2108 void
 2109 esiop_update_scntl3(sc, _siop_target)
 2110         struct esiop_softc *sc;
 2111         struct siop_common_target *_siop_target;
 2112 {
 2113         struct esiop_target *esiop_target = (struct esiop_target *)_siop_target;
 2114         esiop_script_write(sc, esiop_target->lun_table_offset,
 2115             esiop_target->target_c.id);
 2116         esiop_script_sync(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 2117 }
 2118 
 2119 void
 2120 esiop_add_dev(sc, target, lun)
 2121         struct esiop_softc *sc;
 2122         int target;
 2123         int lun;
 2124 {
 2125         struct esiop_target *esiop_target =
 2126             (struct esiop_target *)sc->sc_c.targets[target];
 2127         struct esiop_lun *esiop_lun = esiop_target->esiop_lun[lun];
 2128 
 2129         if (esiop_lun->lun_tagtbl != NULL)
 2130                 return; /* already allocated */
 2131 
 2132         /* we need a tag DSA table */
 2133         esiop_lun->lun_tagtbl= TAILQ_FIRST(&sc->free_tagtbl);
 2134         if (esiop_lun->lun_tagtbl == NULL) {
 2135                 esiop_moretagtbl(sc);
 2136                 esiop_lun->lun_tagtbl= TAILQ_FIRST(&sc->free_tagtbl);
 2137                 if (esiop_lun->lun_tagtbl == NULL) {
 2138                         /* no resources, run untagged */
 2139                         esiop_target->target_c.flags &= ~TARF_TAG;
 2140                         return;
 2141                 }
 2142         }
 2143         TAILQ_REMOVE(&sc->free_tagtbl, esiop_lun->lun_tagtbl, next);
 2144         /* Update LUN DSA table */
 2145         esiop_script_write(sc, esiop_target->lun_table_offset +
 2146            lun * 2 + A_target_luntbl_tag / sizeof(u_int32_t),
 2147             esiop_lun->lun_tagtbl->tbl_dsa);
 2148         esiop_script_sync(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 2149 }
 2150 
 2151 void
 2152 esiop_del_dev(sc, target, lun)
 2153         struct esiop_softc *sc;
 2154         int target;
 2155         int lun;
 2156 {
 2157         struct esiop_target *esiop_target;
 2158 #ifdef SIOP_DEBUG
 2159                 printf("%s:%d:%d: free lun sw entry\n",
 2160                     sc->sc_c.sc_dev.dv_xname, target, lun);
 2161 #endif
 2162         if (sc->sc_c.targets[target] == NULL)
 2163                 return;
 2164         esiop_target = (struct esiop_target *)sc->sc_c.targets[target];
 2165         free(esiop_target->esiop_lun[lun], M_DEVBUF);
 2166         esiop_target->esiop_lun[lun] = NULL;
 2167 }
 2168 
 2169 void
 2170 esiop_target_register(sc, target)
 2171         struct esiop_softc *sc;
 2172         u_int32_t target;
 2173 {
 2174         struct esiop_target *esiop_target =
 2175             (struct esiop_target *)sc->sc_c.targets[target];
 2176         struct esiop_lun *esiop_lun;
 2177         int lun;
 2178 
 2179         /* get a DSA table for this target */
 2180         esiop_target->lun_table_offset = sc->sc_free_offset;
 2181         sc->sc_free_offset += sc->sc_c.sc_chan.chan_nluns * 2 + 2;
 2182 #ifdef SIOP_DEBUG
 2183         printf("%s: lun table for target %d offset %d free offset %d\n",
 2184             sc->sc_c.sc_dev.dv_xname, target, esiop_target->lun_table_offset,
 2185             sc->sc_free_offset);
 2186 #endif
 2187         /* first 32 bytes are ID (for select) */
 2188         esiop_script_write(sc, esiop_target->lun_table_offset,
 2189             esiop_target->target_c.id);
 2190         /* Record this table in the target DSA table */
 2191         esiop_script_write(sc,
 2192             sc->sc_target_table_offset + target,
 2193             (esiop_target->lun_table_offset * sizeof(u_int32_t)) +
 2194             sc->sc_c.sc_scriptaddr);
 2195         /* if we have a tag table, register it */
 2196         for (lun = 0; lun < sc->sc_c.sc_chan.chan_nluns; lun++) {
 2197                 esiop_lun = esiop_target->esiop_lun[lun];
 2198                 if (esiop_lun == NULL)
 2199                         continue;
 2200                 if (esiop_lun->lun_tagtbl)
 2201                         esiop_script_write(sc, esiop_target->lun_table_offset +
 2202                            lun * 2 + A_target_luntbl_tag / sizeof(u_int32_t),
 2203                             esiop_lun->lun_tagtbl->tbl_dsa);
 2204         }
 2205         esiop_script_sync(sc,
 2206             BUS_DMASYNC_PREREAD |  BUS_DMASYNC_PREWRITE);
 2207 }
 2208 
 2209 #ifdef SIOP_STATS
 2210 void
 2211 esiop_printstats()
 2212 {
 2213         printf("esiop_stat_intr %d\n", esiop_stat_intr);
 2214         printf("esiop_stat_intr_shortxfer %d\n", esiop_stat_intr_shortxfer);
 2215         printf("esiop_stat_intr_xferdisc %d\n", esiop_stat_intr_xferdisc);
 2216         printf("esiop_stat_intr_sdp %d\n", esiop_stat_intr_sdp);
 2217         printf("esiop_stat_intr_done %d\n", esiop_stat_intr_done);
 2218         printf("esiop_stat_intr_lunresel %d\n", esiop_stat_intr_lunresel);
 2219         printf("esiop_stat_intr_qfull %d\n", esiop_stat_intr_qfull);
 2220 }
 2221 #endif

Cache object: f83bd1f0d0b83ed47f06398c67ed8e5b


[ 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.