LCOV - code coverage report
Current view: top level - dev/ic - siop.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 1072 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 24 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13