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


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

FreeBSD/Linux Kernel Cross Reference
sys/dev/ncv/ncr53c500.c

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

    1 /*      $NecBSD: ncr53c500.c,v 1.30.12.3 2001/06/26 07:31:41 honda Exp $        */
    2 /*      $NetBSD$        */
    3 
    4 #define NCV_DEBUG
    5 #define NCV_STATICS
    6 #define NCV_IO_CONTROL_FLAGS    (0)
    7 
    8 /*-
    9  * [NetBSD for NEC PC-98 series]
   10  *  Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001
   11  *      NetBSD/pc98 porting staff. All rights reserved.
   12  *  Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001
   13  *      Naofumi HONDA. All rights reserved.
   14  * 
   15  *  Redistribution and use in source and binary forms, with or without
   16  *  modification, are permitted provided that the following conditions
   17  *  are met:
   18  *  1. Redistributions of source code must retain the above copyright
   19  *     notice, this list of conditions and the following disclaimer.
   20  *  2. Redistributions in binary form must reproduce the above copyright
   21  *     notice, this list of conditions and the following disclaimer in the
   22  *     documentation and/or other materials provided with the distribution.
   23  *  3. The name of the author may not be used to endorse or promote products
   24  *     derived from this software without specific prior written permission.
   25  * 
   26  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   27  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   28  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   29  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
   30  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   31  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
   32  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
   34  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
   35  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   36  * POSSIBILITY OF SUCH DAMAGE.
   37  */
   38 
   39 #include <sys/cdefs.h>
   40 __FBSDID("$FreeBSD: releng/8.4/sys/dev/ncv/ncr53c500.c 158651 2006-05-16 14:37:58Z phk $");
   41 
   42 #include <sys/param.h>
   43 #include <sys/systm.h>
   44 #include <sys/kernel.h>
   45 #if defined(__FreeBSD__) && __FreeBSD_version >= 500001
   46 #include <sys/bio.h>
   47 #endif  /* __FreeBSD__ */
   48 #include <sys/buf.h>
   49 #include <sys/queue.h>
   50 #include <sys/malloc.h>
   51 #include <sys/errno.h>
   52 
   53 #ifdef __NetBSD__
   54 #include <sys/device.h>
   55 #include <machine/bus.h>
   56 #include <machine/intr.h>
   57 
   58 #include <dev/scsipi/scsi_all.h>
   59 #include <dev/scsipi/scsipi_all.h>
   60 #include <dev/scsipi/scsiconf.h>
   61 #include <dev/scsipi/scsi_disk.h>
   62 
   63 #include <machine/dvcfg.h>
   64 #include <machine/physio_proc.h>
   65 
   66 #include <i386/Cbus/dev/scsi_low.h>
   67 
   68 #include <i386/Cbus/dev/ncr53c500reg.h>
   69 #include <i386/Cbus/dev/ncr53c500hw.h>
   70 #include <i386/Cbus/dev/ncr53c500var.h>
   71 
   72 #include <i386/Cbus/dev/ncr53c500hwtab.h>
   73 #endif /* __NetBSD__ */
   74 
   75 #ifdef __FreeBSD__
   76 #include <machine/cpu.h>
   77 #include <machine/bus.h>
   78 
   79 #include <compat/netbsd/dvcfg.h>
   80 #include <compat/netbsd/physio_proc.h>
   81 
   82 #include <cam/scsi/scsi_low.h>
   83 
   84 #include <dev/ncv/ncr53c500reg.h>
   85 #include <dev/ncv/ncr53c500hw.h>
   86 #include <dev/ncv/ncr53c500var.h>
   87 
   88 #include <dev/ncv/ncr53c500hwtab.h>
   89 #endif /* __FreeBSD__ */
   90 
   91 #define NCV_MAX_DATA_SIZE       (64 * 1024)
   92 #define NCV_DELAY_MAX           (2 * 1000 * 1000)
   93 #define NCV_DELAY_INTERVAL      (1)
   94 #define NCV_PADDING_SIZE        (32)
   95 
   96 /***************************************************
   97  * IO control
   98  ***************************************************/
   99 #define NCV_READ_INTERRUPTS_DRIVEN      0x0001
  100 #define NCV_WRITE_INTERRUPTS_DRIVEN     0x0002
  101 #define NCV_ENABLE_FAST_SCSI            0x0010
  102 #define NCV_FAST_INTERRUPTS             0x0100
  103 
  104 u_int ncv_io_control = NCV_IO_CONTROL_FLAGS;
  105 int ncv_data_read_bytes = 4096;
  106 int ncv_data_write_bytes = 4096;
  107 
  108 /***************************************************
  109  * DEBUG
  110  ***************************************************/
  111 #ifdef  NCV_DEBUG
  112 static int ncv_debug;
  113 #endif  /* NCV_DEBUG */
  114 
  115 #ifdef  NCV_STATICS
  116 static struct ncv_statics {
  117         int disconnect;
  118         int reselect;
  119 } ncv_statics;
  120 #endif  /* NCV_STATICS */
  121 
  122 /***************************************************
  123  * DEVICE STRUCTURE
  124  ***************************************************/
  125 extern struct cfdriver ncv_cd;
  126 
  127 /**************************************************************
  128  * DECLARE
  129  **************************************************************/
  130 /* static */
  131 static void ncv_pio_read(struct ncv_softc *, u_int8_t *, u_int);
  132 static void ncv_pio_write(struct ncv_softc *, u_int8_t *, u_int);
  133 static int ncv_msg(struct ncv_softc *, struct targ_info *, u_int);
  134 static int ncv_reselected(struct ncv_softc *);
  135 static int ncv_disconnected(struct ncv_softc *, struct targ_info *);
  136 
  137 static __inline void ncvhw_set_count(bus_space_tag_t, bus_space_handle_t, int);
  138 static __inline u_int ncvhw_get_count(bus_space_tag_t, bus_space_handle_t);
  139 static __inline void ncvhw_select_register_0(bus_space_tag_t, bus_space_handle_t, struct ncv_hw *);
  140 static __inline void ncvhw_select_register_1(bus_space_tag_t, bus_space_handle_t, struct ncv_hw *);
  141 static __inline void ncvhw_fpush(bus_space_tag_t, bus_space_handle_t, u_int8_t *, int);
  142 
  143 static void ncv_pdma_end(struct ncv_softc *sc, struct targ_info *);
  144 static int ncv_world_start(struct ncv_softc *, int);
  145 static void ncvhw_bus_reset(struct ncv_softc *);
  146 static void ncvhw_reset(bus_space_tag_t, bus_space_handle_t, struct ncv_hw *);
  147 static int ncvhw_check(bus_space_tag_t, bus_space_handle_t, struct ncv_hw *);
  148 static void ncvhw_init(bus_space_tag_t, bus_space_handle_t, struct ncv_hw *);
  149 static int ncvhw_start_selection(struct ncv_softc *sc, struct slccb *);
  150 static void ncvhw_attention(struct ncv_softc *);
  151 static int ncv_ccb_nexus_establish(struct ncv_softc *);
  152 static int ncv_lun_nexus_establish(struct ncv_softc *);
  153 static int ncv_target_nexus_establish(struct ncv_softc *);
  154 static int ncv_targ_init(struct ncv_softc *, struct targ_info *, int);
  155 static int ncv_catch_intr(struct ncv_softc *);
  156 #ifdef  NCV_POWER_CONTROL
  157 static int ncvhw_power(struct ncv_softc *, u_int);
  158 #endif  /* NCV_POWER_CONTROL */
  159 static __inline void ncv_setup_and_start_pio(struct ncv_softc *, u_int);
  160 
  161 struct scsi_low_funcs ncv_funcs = {
  162         SC_LOW_INIT_T ncv_world_start,
  163         SC_LOW_BUSRST_T ncvhw_bus_reset,
  164         SC_LOW_TARG_INIT_T ncv_targ_init,
  165         SC_LOW_LUN_INIT_T NULL,
  166 
  167         SC_LOW_SELECT_T ncvhw_start_selection,
  168         SC_LOW_NEXUS_T ncv_lun_nexus_establish,
  169         SC_LOW_NEXUS_T ncv_ccb_nexus_establish,
  170 
  171         SC_LOW_ATTEN_T ncvhw_attention,
  172         SC_LOW_MSG_T ncv_msg,
  173 
  174         SC_LOW_TIMEOUT_T NULL,
  175         SC_LOW_POLL_T ncvintr,
  176 
  177         NULL,   /* SC_LOW_POWER_T ncvhw_power, */
  178 };
  179 
  180 /**************************************************************
  181  * hwfuncs
  182  **************************************************************/
  183 static __inline void
  184 ncvhw_select_register_0(iot, ioh, hw)
  185         bus_space_tag_t iot;
  186         bus_space_handle_t ioh;
  187         struct ncv_hw *hw;
  188 {
  189 
  190         bus_space_write_1(iot, ioh, cr0_cfg4, hw->hw_cfg4);
  191 }
  192 
  193 static __inline void
  194 ncvhw_select_register_1(iot, ioh, hw)
  195         bus_space_tag_t iot;
  196         bus_space_handle_t ioh;
  197         struct ncv_hw *hw;
  198 {
  199 
  200         bus_space_write_1(iot, ioh, cr1_cfg5, hw->hw_cfg5);
  201 }
  202 
  203 static __inline void
  204 ncvhw_fpush(iot, ioh, buf, len)
  205         bus_space_tag_t iot;
  206         bus_space_handle_t ioh;
  207         u_int8_t *buf;
  208         int len;
  209 {
  210         int ptr;
  211 
  212         for (ptr = 0; ptr < len; ptr ++)
  213                 bus_space_write_1(iot, ioh, cr0_sfifo, buf[ptr]);
  214 }
  215 
  216 static __inline void
  217 ncvhw_set_count(iot, ioh, count)
  218         bus_space_tag_t iot;
  219         bus_space_handle_t ioh;
  220         int count;
  221 {
  222 
  223         bus_space_write_1(iot, ioh, cr0_tclsb, (u_int8_t) count);
  224         bus_space_write_1(iot, ioh, cr0_tcmsb, (u_int8_t) (count >> NBBY));
  225         bus_space_write_1(iot, ioh, cr0_tchsb, (u_int8_t) (count >> (NBBY * 2)));
  226 }
  227 
  228 static __inline u_int
  229 ncvhw_get_count(iot, ioh)
  230         bus_space_tag_t iot;
  231         bus_space_handle_t ioh;
  232 {
  233         u_int count;
  234 
  235         count = (u_int) bus_space_read_1(iot, ioh, cr0_tclsb);
  236         count |= ((u_int) bus_space_read_1(iot, ioh, cr0_tcmsb)) << NBBY;
  237         count |= ((u_int) bus_space_read_1(iot, ioh, cr0_tchsb)) << (NBBY * 2);
  238         return count;
  239 }
  240 
  241 static int
  242 ncvhw_check(iot, ioh, hw)
  243         bus_space_tag_t iot;
  244         bus_space_handle_t ioh;
  245         struct ncv_hw *hw;
  246 {
  247         u_int8_t stat;
  248 
  249         ncvhw_select_register_0(iot, ioh, hw);
  250         bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP | CMD_DMA);
  251         if (bus_space_read_1(iot, ioh, cr0_cmd) != (CMD_NOP | CMD_DMA))
  252         {
  253 #ifdef  NCV_DEBUG
  254                 printf("ncv: cr0_cmd CMD_NOP|CMD_DMA failed\n");
  255 #endif  /* NCV_DEBUG */
  256                 return ENODEV;
  257         }
  258 
  259         bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP);
  260         if (bus_space_read_1(iot, ioh, cr0_cmd) != CMD_NOP)
  261         {
  262 #ifdef  NCV_DEBUG
  263                 printf("ncv: cr0_cmd CMD_NOP failed\n");
  264 #endif  /* NCV_DEBUG */
  265                 return ENODEV;
  266         }
  267 
  268         /* hardware reset */
  269         ncvhw_reset(iot, ioh, hw);
  270         ncvhw_init(iot, ioh, hw);
  271 
  272         /* bus reset */
  273         ncvhw_select_register_0(iot, ioh, hw);
  274         bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH);
  275         bus_space_write_1(iot, ioh, cr0_cmd, CMD_RSTSCSI);
  276         bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP | CMD_DMA);
  277         SCSI_LOW_DELAY(100 * 1000);
  278 
  279         /* check response */
  280         bus_space_read_1(iot, ioh, cr0_stat);
  281         stat = bus_space_read_1(iot, ioh, cr0_istat);
  282         SCSI_LOW_DELAY(1000);
  283 
  284         if (((stat & INTR_SBR) == 0) ||
  285             (bus_space_read_1(iot, ioh, cr0_istat) & INTR_SBR))
  286         {
  287 #ifdef  NCV_DEBUG
  288                 printf("ncv: cr0_istat SCSI BUS RESET failed\n");
  289 #endif  /* NCV_DEBUG */
  290                 return ENODEV;
  291         }
  292 
  293         return 0;
  294 }
  295 
  296 static void
  297 ncvhw_reset(iot, ioh, hw)
  298         bus_space_tag_t iot;
  299         bus_space_handle_t ioh;
  300         struct ncv_hw *hw;
  301 {
  302 
  303         ncvhw_select_register_0(iot, ioh, hw);
  304 
  305         /* dummy cmd twice */
  306         bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP);
  307         bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP);
  308 
  309         /* chip reset */
  310         bus_space_write_1(iot, ioh, cr0_cmd, CMD_RSTCHIP);
  311 
  312         /* again dummy cmd twice */
  313         bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP);
  314         bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP);
  315 }
  316 
  317 static void
  318 ncvhw_init(iot, ioh, hw)
  319         bus_space_tag_t iot;
  320         bus_space_handle_t ioh;
  321         struct ncv_hw *hw;
  322 {
  323 
  324         ncvhw_select_register_0(iot, ioh, hw);
  325         bus_space_write_1(iot, ioh, cr0_clk, hw->hw_clk);
  326         bus_space_write_1(iot, ioh, cr0_srtout, SEL_TOUT);
  327         bus_space_write_1(iot, ioh, cr0_period, 0);
  328         bus_space_write_1(iot, ioh, cr0_offs, 0);
  329 
  330         bus_space_write_1(iot, ioh, cr0_cfg1, hw->hw_cfg1);
  331         bus_space_write_1(iot, ioh, cr0_cfg2, hw->hw_cfg2);
  332         bus_space_write_1(iot, ioh, cr0_cfg3, hw->hw_cfg3);
  333         bus_space_write_1(iot, ioh, cr0_tchsb, 0);
  334 
  335         ncvhw_select_register_1(iot, ioh, hw);
  336         bus_space_write_1(iot, ioh, cr1_fstat, 0x0);
  337         bus_space_write_1(iot, ioh, cr1_pflag, 0x0);
  338         bus_space_write_1(iot, ioh, cr1_atacmd, ATACMD_ENGAGE);
  339 
  340         ncvhw_select_register_0(iot, ioh, hw);
  341 }
  342 
  343 #ifdef  NCV_POWER_CONTROL
  344 static int
  345 ncvhw_power(sc, flags)
  346         struct ncv_softc *sc;
  347         u_int flags;
  348 {
  349         struct scsi_low_softc *slp = &sc->sc_sclow;
  350         bus_space_tag_t iot = sc->sc_iot;
  351         bus_space_handle_t ioh = sc->sc_ioh;
  352 
  353         if (flags == SCSI_LOW_POWDOWN)
  354         {
  355                 printf("%s power down\n", slp->sl_xname);
  356                 ncvhw_select_register_1(iot, ioh, &sc->sc_hw);
  357                 bus_space_write_1(iot, ioh, cr1_atacmd, ATACMD_POWDOWN);
  358         }
  359         else
  360         {
  361                 switch (sc->sc_rstep)
  362                 {
  363                 case 0:
  364                         printf("%s resume step O\n", slp->sl_xname);
  365                         ncvhw_select_register_1(iot, ioh, &sc->sc_hw);
  366                         bus_space_write_1(iot, ioh, cr1_atacmd, ATACMD_ENGAGE);
  367                         break;
  368 
  369                 case 1:
  370                         printf("%s resume step I\n", slp->sl_xname);
  371                         ncvhw_reset(iot, ioh, &sc->sc_hw);
  372                         ncvhw_init(iot, ioh, &sc->sc_hw);
  373                         break;
  374                 }
  375         }
  376 
  377         return 0;
  378 }
  379 #endif  /* NCV_POWER_CONTROL */
  380 
  381 /**************************************************************
  382  * scsi low interface
  383  **************************************************************/
  384 static void
  385 ncvhw_attention(sc)
  386         struct ncv_softc *sc;
  387 {
  388 
  389         bus_space_write_1(sc->sc_iot, sc->sc_ioh, cr0_cmd, CMD_SETATN);
  390         SCSI_LOW_DELAY(10);
  391 }
  392 
  393 static void
  394 ncvhw_bus_reset(sc)
  395         struct ncv_softc *sc;
  396 {
  397         bus_space_tag_t iot = sc->sc_iot;
  398         bus_space_handle_t ioh = sc->sc_ioh;
  399 
  400         ncvhw_select_register_0(iot, ioh, &sc->sc_hw);
  401         bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH);
  402         bus_space_write_1(iot, ioh, cr0_cmd, CMD_RSTSCSI);
  403         bus_space_write_1(iot, ioh, cr0_cmd, CMD_NOP | CMD_DMA);
  404 }
  405 
  406 static int
  407 ncvhw_start_selection(sc, cb)
  408         struct ncv_softc *sc;
  409         struct slccb *cb;
  410 {
  411         struct scsi_low_softc *slp = &sc->sc_sclow;
  412         bus_space_tag_t iot = sc->sc_iot;
  413         bus_space_handle_t ioh = sc->sc_ioh;
  414         struct targ_info *ti = cb->ti;
  415         int s, len;
  416         u_int flags;
  417         u_int8_t cmd;
  418 
  419         sc->sc_tmaxcnt = cb->ccb_tcmax * 1000 * 1000;
  420         sc->sc_compseq = 0;
  421         if (scsi_low_is_msgout_continue(ti, SCSI_LOW_MSG_IDENTIFY) == 0)
  422         {
  423                 cmd = CMD_SELATN;
  424                 sc->sc_selstop = 0;
  425                 flags = SCSI_LOW_MSGOUT_UNIFY | SCSI_LOW_MSGOUT_INIT;
  426         }
  427         else if (scsi_low_is_msgout_continue(ti, 
  428                         SCSI_LOW_MSG_IDENTIFY | SCSI_LOW_MSG_SIMPLE_QTAG) == 0)
  429         {
  430                 cmd = CMD_SELATN3;
  431                 sc->sc_selstop = 0;
  432                 flags = SCSI_LOW_MSGOUT_UNIFY | SCSI_LOW_MSGOUT_INIT;
  433         }       
  434         else
  435         {
  436                 cmd = CMD_SELATNS;
  437                 sc->sc_selstop = 1;
  438                 flags = SCSI_LOW_MSGOUT_INIT;
  439         }
  440 
  441         ncvhw_select_register_0(iot, ioh, &sc->sc_hw);
  442         if ((bus_space_read_1(iot, ioh, cr0_stat) & STAT_INT) != 0)
  443                 return SCSI_LOW_START_FAIL;
  444 
  445         ncv_target_nexus_establish(sc);
  446 
  447         len = scsi_low_msgout(slp, ti, flags);
  448         if (sc->sc_selstop == 0)
  449                 scsi_low_cmd(slp, ti);
  450 
  451         s = splhigh();
  452         if ((bus_space_read_1(iot, ioh, cr0_stat) & STAT_INT) != 0)
  453         {
  454                 splx(s);
  455                 return SCSI_LOW_START_FAIL;
  456         }
  457 
  458         bus_space_write_1(iot, ioh, cr0_dstid, ti->ti_id);
  459         bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH);
  460         ncvhw_fpush(iot, ioh, ti->ti_msgoutstr, len);
  461         if (sc->sc_selstop == 0)
  462         {
  463                 ncvhw_fpush(iot, ioh,
  464                             slp->sl_scp.scp_cmd, slp->sl_scp.scp_cmdlen);
  465         }
  466         bus_space_write_1(iot, ioh, cr0_cmd, cmd);
  467         splx(s);
  468 
  469         SCSI_LOW_SETUP_PHASE(ti, PH_SELSTART);
  470         return SCSI_LOW_START_OK;
  471 }
  472 
  473 static int
  474 ncv_world_start(sc, fdone)
  475         struct ncv_softc *sc;
  476         int fdone;
  477 {
  478         struct scsi_low_softc *slp = &sc->sc_sclow;
  479         bus_space_tag_t iot = sc->sc_iot;
  480         bus_space_handle_t ioh = sc->sc_ioh;
  481         u_int8_t stat;
  482 
  483         if ((slp->sl_cfgflags & CFG_NOPARITY) == 0)
  484                 sc->sc_hw.hw_cfg1 |= C1_PARENB;
  485         else
  486                 sc->sc_hw.hw_cfg1 &= ~C1_PARENB;
  487 
  488         ncvhw_reset(iot, ioh, &sc->sc_hw);
  489         ncvhw_init(iot, ioh, &sc->sc_hw);
  490 
  491         scsi_low_bus_reset(slp);
  492 
  493         ncvhw_select_register_0(iot, ioh, &sc->sc_hw);
  494         bus_space_read_1(sc->sc_iot, sc->sc_ioh, cr0_stat);
  495         stat = bus_space_read_1(sc->sc_iot, sc->sc_ioh, cr0_istat);
  496         SCSI_LOW_DELAY(1000);
  497 
  498         if (((stat & INTR_SBR) == 0) ||
  499             (bus_space_read_1(sc->sc_iot, sc->sc_ioh, cr0_istat) & INTR_SBR))
  500                 return ENODEV;
  501 
  502         SOFT_INTR_REQUIRED(slp);
  503         return 0;
  504 }
  505 
  506 static int
  507 ncv_msg(sc, ti, msg)
  508         struct ncv_softc *sc;
  509         struct targ_info *ti;
  510         u_int msg;
  511 {
  512         bus_space_tag_t iot = sc->sc_iot;
  513         bus_space_handle_t ioh = sc->sc_ioh;
  514         struct ncv_targ_info *nti = (void *) ti;
  515         u_int hwcycle, period;
  516 
  517         if ((msg & SCSI_LOW_MSG_WIDE) != 0)
  518         {
  519                 if (ti->ti_width != SCSI_LOW_BUS_WIDTH_8)
  520                 {
  521                         ti->ti_width = SCSI_LOW_BUS_WIDTH_8;
  522                         return EINVAL;
  523                 }
  524                 return 0;
  525         }
  526 
  527         if ((msg & SCSI_LOW_MSG_SYNCH) == 0)
  528                 return 0;
  529 
  530         period = ti->ti_maxsynch.period;
  531         hwcycle = (sc->sc_hw.hw_clk == 0) ? 40 : (5 * sc->sc_hw.hw_clk);
  532         hwcycle = 1000 / hwcycle;
  533 
  534         if (period < 200 / 4 && period >= 100 / 4)
  535                 nti->nti_reg_cfg3 |= sc->sc_hw.hw_cfg3_fscsi;
  536         else
  537                 nti->nti_reg_cfg3 &= ~sc->sc_hw.hw_cfg3_fscsi;
  538 
  539         period = ((period * 40 / hwcycle) + 5) / 10;
  540         nti->nti_reg_period = period & 0x1f;
  541         nti->nti_reg_offset = ti->ti_maxsynch.offset;
  542 
  543         bus_space_write_1(iot, ioh, cr0_period, nti->nti_reg_period);
  544         bus_space_write_1(iot, ioh, cr0_offs, nti->nti_reg_offset);
  545         bus_space_write_1(iot, ioh, cr0_cfg3, nti->nti_reg_cfg3);
  546         return 0;
  547 }
  548 
  549 static int
  550 ncv_targ_init(sc, ti, action)
  551         struct ncv_softc *sc;
  552         struct targ_info *ti;
  553         int action;
  554 {
  555         struct ncv_targ_info *nti = (void *) ti;
  556 
  557         if (action == SCSI_LOW_INFO_ALLOC || action == SCSI_LOW_INFO_REVOKE)
  558         {
  559                 ti->ti_width = SCSI_LOW_BUS_WIDTH_8;
  560                 ti->ti_maxsynch.period = sc->sc_hw.hw_mperiod;
  561                 ti->ti_maxsynch.offset = sc->sc_hw.hw_moffset;
  562 
  563                 nti->nti_reg_cfg3 = sc->sc_hw.hw_cfg3;
  564                 nti->nti_reg_period = 0;
  565                 nti->nti_reg_offset = 0;
  566         }
  567         return 0;
  568 }       
  569 
  570 /**************************************************************
  571  * General probe attach
  572  **************************************************************/
  573 static int ncv_setup_img(struct ncv_hw *, u_int, int);
  574 
  575 static int
  576 ncv_setup_img(hw, dvcfg, hostid)
  577         struct ncv_hw *hw;
  578         u_int dvcfg;
  579         int hostid;
  580 {
  581 
  582         if (NCV_CLKFACTOR(dvcfg) > CLK_35M_F)
  583         {
  584                 printf("ncv: invalid dvcfg flags\n");
  585                 return EINVAL;
  586         }
  587 
  588         if (NCV_C5IMG(dvcfg) != 0)
  589         {
  590                 hw->hw_cfg5 = NCV_C5IMG(dvcfg);
  591                 hw->hw_clk = NCV_CLKFACTOR(dvcfg);
  592 
  593                 if ((ncv_io_control & NCV_ENABLE_FAST_SCSI) != 0 &&
  594                     (NCV_SPECIAL(dvcfg) & NCVHWCFG_MAX10M) != 0)
  595                         hw->hw_mperiod = 100 / 4;
  596 
  597                 if (NCV_SPECIAL(dvcfg) & NCVHWCFG_FIFOBUG)
  598                         hw->hw_cfg3_fclk = 0x04;
  599 
  600                 if (NCV_SPECIAL(dvcfg) & NCVHWCFG_SCSI1)
  601                         hw->hw_cfg2 &= ~C2_SCSI2;
  602 
  603                 if (NCV_SPECIAL(dvcfg) & NCVHWCFG_SLOW)
  604                         hw->hw_cfg1 |= C1_SLOW;
  605         }
  606 
  607         /* setup configuration image 3 */
  608         if (hw->hw_clk != CLK_40M_F && hw->hw_clk <= CLK_25M_F)
  609                 hw->hw_cfg3 &= ~hw->hw_cfg3_fclk;
  610         else
  611                 hw->hw_cfg3 |= hw->hw_cfg3_fclk;
  612 
  613         /* setup configuration image 1 */
  614         hw->hw_cfg1 = (hw->hw_cfg1 & 0xf0) | hostid;
  615         return 0;
  616 }
  617 
  618 int
  619 ncvprobesubr(iot, ioh, dvcfg, hsid)
  620         bus_space_tag_t iot;
  621         bus_space_handle_t ioh;
  622         u_int dvcfg;
  623         int hsid;
  624 {
  625         struct ncv_hw hwtab;
  626 
  627         hwtab = ncv_template;
  628         if (ncv_setup_img(&hwtab, dvcfg, hsid))
  629                 return 0;
  630         if (ncvhw_check(iot, ioh, &hwtab) != 0)
  631                 return 0;
  632 
  633         return 1;
  634 }
  635 
  636 int
  637 ncvprint(aux, name)
  638         void *aux;
  639         const char *name;
  640 {
  641 
  642         if (name != NULL)
  643                 printf("%s: scsibus ", name);
  644         return UNCONF;
  645 }
  646 
  647 void
  648 ncvattachsubr(sc)
  649         struct ncv_softc *sc;
  650 {
  651         struct scsi_low_softc *slp = &sc->sc_sclow;
  652 
  653         printf("\n");
  654         sc->sc_hw = ncv_template;
  655         ncv_setup_img(&sc->sc_hw, slp->sl_cfgflags, slp->sl_hostid);
  656         slp->sl_funcs = &ncv_funcs;
  657         slp->sl_flags |= HW_READ_PADDING;
  658         sc->sc_tmaxcnt = SCSI_LOW_MIN_TOUT * 1000 * 1000; /* default */
  659 
  660         (void) scsi_low_attach(slp, 0, NCV_NTARGETS, NCV_NLUNS,
  661                                sizeof(struct ncv_targ_info), 0);
  662 }
  663 
  664 /**************************************************************
  665  * PDMA
  666  **************************************************************/
  667 static __inline void
  668 ncv_setup_and_start_pio(sc, reqlen)
  669         struct ncv_softc *sc;
  670         u_int reqlen;
  671 {
  672         bus_space_tag_t iot = sc->sc_iot;
  673         bus_space_handle_t ioh = sc->sc_ioh;
  674 
  675         ncvhw_select_register_0(iot, ioh, &sc->sc_hw);
  676         ncvhw_set_count(iot, ioh, reqlen);
  677         bus_space_write_1(iot, ioh, cr0_cmd, CMD_TRANS | CMD_DMA);
  678 
  679         ncvhw_select_register_1(iot, ioh, &sc->sc_hw);
  680         bus_space_write_1(iot, ioh, cr1_fstat, FIFO_EN);
  681 }
  682 
  683 static void
  684 ncv_pdma_end(sc, ti)
  685         struct ncv_softc *sc;
  686         struct targ_info *ti;
  687 {
  688         struct scsi_low_softc *slp = &sc->sc_sclow;
  689         bus_space_tag_t iot = sc->sc_iot;
  690         bus_space_handle_t ioh = sc->sc_ioh;
  691         int len;
  692 
  693         slp->sl_flags &= ~HW_PDMASTART;
  694         if (slp->sl_Qnexus == NULL)
  695         {
  696                 slp->sl_error |= PDMAERR;
  697                 goto out;
  698         }
  699 
  700         if (ti->ti_phase == PH_DATA)
  701         {
  702                 len = ncvhw_get_count(sc->sc_iot, sc->sc_ioh);
  703                 if (slp->sl_scp.scp_direction == SCSI_LOW_WRITE)
  704                         len += (bus_space_read_1(sc->sc_iot, sc->sc_ioh,
  705                                 cr0_sffl) & CR0_SFFLR_BMASK);
  706 
  707                 if ((u_int) len <= (u_int) sc->sc_sdatalen)
  708                 {
  709                         if ((slp->sl_scp.scp_direction == SCSI_LOW_READ) &&
  710                             sc->sc_tdatalen != len)
  711                                 goto bad;
  712 
  713                         len = sc->sc_sdatalen - len;
  714                         if ((u_int) len > (u_int) slp->sl_scp.scp_datalen)
  715                                 goto bad;
  716 
  717                         slp->sl_scp.scp_data += len;
  718                         slp->sl_scp.scp_datalen -= len;
  719                 }
  720                 else
  721                 {
  722 bad:
  723                         if ((slp->sl_error & PDMAERR) == 0)
  724                         {
  725                                 printf("%s: stragne cnt hw 0x%x soft 0x%x\n",
  726                                         slp->sl_xname, len,
  727                                         slp->sl_scp.scp_datalen);
  728                         }
  729                         slp->sl_error |= PDMAERR;
  730                 }
  731                 scsi_low_data_finish(slp);
  732         }
  733         else
  734         {
  735                 printf("%s: data phase miss\n", slp->sl_xname);
  736                 slp->sl_error |= PDMAERR;
  737         }
  738 
  739 out:
  740         ncvhw_select_register_1(iot, ioh, &sc->sc_hw);
  741         bus_space_write_1(iot, ioh, cr1_fstat, 0);
  742         ncvhw_select_register_0(iot, ioh, &sc->sc_hw);
  743 }
  744 
  745 static void
  746 ncv_pio_read(sc, buf, reqlen)
  747         struct ncv_softc *sc;
  748         u_int8_t *buf;
  749         u_int reqlen;
  750 {
  751         struct scsi_low_softc *slp = &sc->sc_sclow;
  752         bus_space_tag_t iot = sc->sc_iot;
  753         bus_space_handle_t ioh = sc->sc_ioh;
  754         int tout;
  755         register u_int8_t fstat;
  756 
  757         ncv_setup_and_start_pio(sc, reqlen);
  758         slp->sl_flags |= HW_PDMASTART;
  759         sc->sc_sdatalen = reqlen;
  760         tout = sc->sc_tmaxcnt;
  761 
  762         while (reqlen >= FIFO_F_SZ && tout -- > 0)
  763         {
  764                 fstat = bus_space_read_1(iot, ioh, cr1_fstat);
  765                 if (fstat == (u_int8_t) -1)
  766                         goto out;
  767                 if (fstat & FIFO_F)
  768                 {
  769 #define NCV_FAST32_ACCESS
  770 #ifdef  NCV_FAST32_ACCESS
  771                         bus_space_read_multi_4(iot, ioh, cr1_fdata, 
  772                                 (u_int32_t *) buf, FIFO_F_SZ / 4);
  773 #else   /* !NCV_FAST32_ACCESS */
  774                         bus_space_read_multi_2(iot, ioh, cr1_fdata, 
  775                                 (u_int16_t *) buf, FIFO_F_SZ / 2);
  776 #endif  /* !NCV_FAST32_ACCESS */
  777                         buf += FIFO_F_SZ;
  778                         reqlen -= FIFO_F_SZ;
  779                 }
  780                 else 
  781                 {
  782                         if (fstat & FIFO_BRK)
  783                                 break;
  784 
  785                         SCSI_LOW_DELAY(1);
  786                 }
  787         }
  788 
  789         while (reqlen > 0 && tout -- > 0)
  790         {
  791                 fstat = bus_space_read_1(iot, ioh, cr1_fstat);
  792                 if ((fstat & FIFO_E) == 0)
  793                 {
  794                         *buf++ = bus_space_read_1(iot, ioh, cr1_fdata);
  795                         reqlen --;
  796                 }
  797                 else
  798                 {
  799                          if (fstat & FIFO_BRK)
  800                                 break;
  801 
  802                         SCSI_LOW_DELAY(1);
  803                 }
  804         }
  805 
  806 out:
  807         ncvhw_select_register_0(iot, ioh, &sc->sc_hw);
  808         sc->sc_tdatalen = reqlen;
  809 }
  810 
  811 static void
  812 ncv_pio_write(sc, buf, reqlen)
  813         struct ncv_softc *sc;
  814         u_int8_t *buf;
  815         u_int reqlen;
  816 {
  817         struct scsi_low_softc *slp = &sc->sc_sclow;
  818         bus_space_tag_t iot = sc->sc_iot;
  819         bus_space_handle_t ioh = sc->sc_ioh;
  820         int tout;
  821         register u_int8_t fstat;
  822 
  823         ncv_setup_and_start_pio(sc, reqlen);
  824         sc->sc_sdatalen = reqlen;
  825         tout = sc->sc_tmaxcnt;
  826         slp->sl_flags |= HW_PDMASTART;
  827 
  828         while (reqlen >= FIFO_F_SZ && tout -- > 0)
  829         {
  830                 fstat = bus_space_read_1(iot, ioh, cr1_fstat);
  831                 if (fstat & FIFO_BRK)
  832                         goto done;
  833 
  834                 if ((fstat & FIFO_E) != 0)
  835                 {
  836 #ifdef  NCV_FAST32_ACCESS
  837                         bus_space_write_multi_4(iot, ioh, cr1_fdata, 
  838                                 (u_int32_t *) buf, FIFO_F_SZ / 4);
  839 #else   /* !NCV_FAST32_ACCESS */
  840                         bus_space_write_multi_2(iot, ioh, cr1_fdata, 
  841                                 (u_int16_t *) buf, FIFO_F_SZ / 2);
  842 #endif  /* !NCV_FAST32_ACCESS */
  843                         buf += FIFO_F_SZ;
  844                         reqlen -= FIFO_F_SZ;
  845                 }
  846                 else
  847                 {
  848                         SCSI_LOW_DELAY(1);
  849                 }
  850         }
  851 
  852         while (reqlen > 0 && tout -- > 0)
  853         {
  854                 fstat = bus_space_read_1(iot, ioh, cr1_fstat);
  855                 if (fstat & FIFO_BRK)
  856                         break;
  857 
  858                 if ((fstat & FIFO_F) == 0) /* fifo not full */
  859                 {
  860                         bus_space_write_1(iot, ioh, cr1_fdata, *buf++);
  861                         reqlen --;
  862                 }
  863                 else
  864                 {
  865                         SCSI_LOW_DELAY(1);
  866                 }
  867         }
  868 
  869 done:
  870         ncvhw_select_register_0(iot, ioh, &sc->sc_hw);
  871 }
  872 
  873 /**************************************************************
  874  * disconnect & reselect (HW low)
  875  **************************************************************/
  876 static int
  877 ncv_reselected(sc)
  878         struct ncv_softc *sc;
  879 {
  880         struct scsi_low_softc *slp = &sc->sc_sclow;
  881         bus_space_tag_t iot = sc->sc_iot;
  882         bus_space_handle_t ioh = sc->sc_ioh;
  883         struct targ_info *ti;
  884         u_int sid;
  885 
  886         if ((bus_space_read_1(iot, ioh, cr0_sffl) & CR0_SFFLR_BMASK) != 2)
  887         {
  888                 printf("%s illegal fifo bytes\n", slp->sl_xname);
  889                 scsi_low_restart(slp, SCSI_LOW_RESTART_HARD, "chip confused");
  890                 return EJUSTRETURN;
  891         }
  892 
  893         sid = (u_int) bus_space_read_1(iot, ioh, cr0_sfifo);
  894         sid &= ~(1 << slp->sl_hostid);
  895         sid = ffs(sid) - 1;
  896         ti = scsi_low_reselected((struct scsi_low_softc *) sc, sid);
  897         if (ti == NULL)
  898                 return EJUSTRETURN;
  899 
  900 #ifdef  NCV_STATICS
  901         ncv_statics.reselect ++;
  902 #endif  /* NCV_STATICS */
  903         bus_space_write_1(iot, ioh, cr0_dstid, sid);
  904         return 0;
  905 }
  906 
  907 static int
  908 ncv_disconnected(sc, ti)
  909         struct ncv_softc *sc;
  910         struct targ_info *ti;
  911 {
  912         struct scsi_low_softc *slp = &sc->sc_sclow;
  913         bus_space_tag_t iot = sc->sc_iot;
  914         bus_space_handle_t ioh = sc->sc_ioh;
  915 
  916         bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH);
  917         bus_space_write_1(iot, ioh, cr0_cmd, CMD_ENSEL);
  918 
  919 #ifdef  NCV_STATICS
  920         ncv_statics.disconnect ++;
  921 #endif  /* NCV_STATICS */
  922 
  923         scsi_low_disconnected(slp, ti);
  924         return 1;
  925 }
  926 
  927 /**************************************************************
  928  * SEQUENCER
  929  **************************************************************/
  930 static int
  931 ncv_target_nexus_establish(sc)
  932         struct ncv_softc *sc;
  933 {
  934         struct scsi_low_softc *slp = &sc->sc_sclow;
  935         struct targ_info *ti = slp->sl_Tnexus;
  936         struct ncv_targ_info *nti = (void *) ti;
  937         bus_space_tag_t iot = sc->sc_iot;
  938         bus_space_handle_t ioh = sc->sc_ioh;
  939 
  940         bus_space_write_1(iot, ioh, cr0_period, nti->nti_reg_period);
  941         bus_space_write_1(iot, ioh, cr0_offs, nti->nti_reg_offset);
  942         bus_space_write_1(iot, ioh, cr0_cfg3, nti->nti_reg_cfg3);
  943         return 0;
  944 }
  945 
  946 static int
  947 ncv_lun_nexus_establish(sc)
  948         struct ncv_softc *sc;
  949 {
  950 
  951         return 0;
  952 }
  953 
  954 static int
  955 ncv_ccb_nexus_establish(sc)
  956         struct ncv_softc *sc;
  957 {
  958         struct scsi_low_softc *slp = &sc->sc_sclow;
  959         struct slccb *cb = slp->sl_Qnexus;
  960 
  961         sc->sc_tmaxcnt = cb->ccb_tcmax * 1000 * 1000;
  962         return 0;
  963 }
  964 
  965 static int
  966 ncv_catch_intr(sc)
  967         struct ncv_softc *sc;
  968 {
  969         bus_space_tag_t iot = sc->sc_iot;
  970         bus_space_handle_t ioh = sc->sc_ioh;
  971         int wc;
  972         register u_int8_t status;
  973 
  974         for (wc = 0; wc < NCV_DELAY_MAX / NCV_DELAY_INTERVAL; wc ++)
  975         {
  976                 status = bus_space_read_1(iot, ioh, cr0_stat);
  977                 if ((status & STAT_INT) != 0)
  978                         return 0;
  979 
  980                 SCSI_LOW_DELAY(NCV_DELAY_INTERVAL);
  981         }
  982         return EJUSTRETURN;
  983 }
  984 
  985 int
  986 ncvintr(arg)
  987         void *arg;
  988 {
  989         struct ncv_softc *sc = arg;
  990         struct scsi_low_softc *slp = &sc->sc_sclow;
  991         bus_space_tag_t iot = sc->sc_iot;
  992         bus_space_handle_t ioh = sc->sc_ioh;
  993         struct targ_info *ti;
  994         struct physio_proc *pp;
  995         struct buf *bp;
  996         u_int derror, flags;
  997         int len;
  998         u_int8_t regv, status, ireason;
  999 
 1000 again:
 1001         if (slp->sl_flags & HW_INACTIVE)
 1002                 return 0;
 1003 
 1004         /********************************************
 1005          * Status
 1006          ********************************************/
 1007         ncvhw_select_register_0(iot, ioh, &sc->sc_hw);
 1008         status = bus_space_read_1(iot, ioh, cr0_stat);
 1009         if ((status & STAT_INT) == 0 || status == (u_int8_t) -1)
 1010                 return 0;
 1011 
 1012         ireason = bus_space_read_1(iot, ioh, cr0_istat);
 1013         if ((ireason & INTR_SBR) != 0)
 1014         {
 1015                 u_int8_t val;
 1016 
 1017                 /* avoid power off hangup */
 1018                 val = bus_space_read_1(iot, ioh, cr0_cfg1);
 1019                 bus_space_write_1(iot, ioh, cr0_cfg1, val | C1_SRR);
 1020 
 1021                 /* status init */
 1022                 scsi_low_restart(slp, SCSI_LOW_RESTART_SOFT, 
 1023                                  "bus reset (power off?)");
 1024                 return 1;
 1025         }
 1026 
 1027         /********************************************
 1028          * Debug section
 1029          ********************************************/
 1030 #ifdef  NCV_DEBUG
 1031         if (ncv_debug)
 1032         {
 1033                 scsi_low_print(slp, NULL);
 1034                 printf("%s st %x ist %x\n\n", slp->sl_xname,
 1035                         status, ireason);
 1036 #ifdef  KDB
 1037                 if (ncv_debug > 1)
 1038                         SCSI_LOW_DEBUGGER("ncv");
 1039 #endif  /* KDB */
 1040         }
 1041 #endif  /* NCV_DEBUG */
 1042 
 1043         /********************************************
 1044          * Reselect or Disconnect or Nexus check
 1045          ********************************************/
 1046         /* (I) reselect */
 1047         if (ireason == INTR_RESELECT)
 1048         {
 1049                 if (ncv_reselected(sc) == EJUSTRETURN)
 1050                         return 1;
 1051         }
 1052 
 1053         /* (II) nexus */
 1054         if ((ti = slp->sl_Tnexus) == NULL)
 1055                 return 0;
 1056 
 1057         derror = 0;
 1058         if ((status & (STAT_PE | STAT_GE)) != 0)
 1059         {
 1060                 slp->sl_error |= PARITYERR;
 1061                 if ((status & PHASE_MASK) == MESSAGE_IN_PHASE)
 1062                         scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_PARITY, 0);
 1063                 else
 1064                         scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ERROR, 1);
 1065                 derror = SCSI_LOW_DATA_PE;
 1066         }
 1067 
 1068         if ((ireason & (INTR_DIS | INTR_ILL)) != 0)
 1069         {
 1070                 if ((ireason & INTR_ILL) == 0)
 1071                         return ncv_disconnected(sc, ti);
 1072 
 1073                 slp->sl_error |= FATALIO;
 1074                 scsi_low_restart(slp, SCSI_LOW_RESTART_HARD, "illegal cmd");
 1075                 return 1;
 1076         }
 1077 
 1078         /********************************************
 1079          * Internal scsi phase
 1080          ********************************************/
 1081         switch (ti->ti_phase)
 1082         {
 1083         case PH_SELSTART:
 1084                 scsi_low_arbit_win(slp);
 1085                 SCSI_LOW_SETUP_PHASE(ti, PH_SELECTED);
 1086 
 1087                 if (sc->sc_selstop == 0)
 1088                 {
 1089                         /* XXX:
 1090                          * Here scsi phases expected are
 1091                          * DATA PHASE: 
 1092                          * MSGIN     : target wants to disconnect the host.
 1093                          * STATUSIN  : immediate command completed.
 1094                          * CMD PHASE : command out failed
 1095                          * MSGOUT    : identify command failed.
 1096                          */
 1097                         if ((status & PHASE_MASK) != MESSAGE_OUT_PHASE)
 1098                                 break;
 1099                 }
 1100                 else
 1101                 {
 1102                         if ((status & PHASE_MASK) != MESSAGE_OUT_PHASE)
 1103                                 break;
 1104                         if ((ireason & INTR_FC) != 0) 
 1105                         {
 1106                                 SCSI_LOW_ASSERT_ATN(slp);
 1107                         }
 1108                 }
 1109                 SCSI_LOW_SETUP_PHASE(ti, PH_MSGOUT);
 1110                 break;
 1111 
 1112         case PH_RESEL:
 1113                 ncv_target_nexus_establish(sc);
 1114                 if ((status & PHASE_MASK) != MESSAGE_IN_PHASE)
 1115                 {
 1116                         printf("%s: unexpected phase after reselect\n",
 1117                                 slp->sl_xname);
 1118                         slp->sl_error |= FATALIO;
 1119                         scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT, 1);
 1120                         return 1;
 1121                 }
 1122                 break;
 1123 
 1124         default:
 1125                 if ((slp->sl_flags & HW_PDMASTART) != 0)
 1126                 {
 1127                         ncv_pdma_end(sc, ti);
 1128                 }
 1129                 break;
 1130         }
 1131 
 1132         /********************************************
 1133          * Scsi phase sequencer
 1134          ********************************************/
 1135         switch (status & PHASE_MASK)
 1136         {
 1137         case DATA_OUT_PHASE: /* data out */
 1138                 SCSI_LOW_SETUP_PHASE(ti, PH_DATA);
 1139                 if (scsi_low_data(slp, ti, &bp, SCSI_LOW_WRITE) != 0)
 1140                 {
 1141                         scsi_low_attention(slp);
 1142                 }
 1143 
 1144                 pp = physio_proc_enter(bp);
 1145                 if (slp->sl_scp.scp_datalen <= 0)
 1146                 {
 1147                         if ((ireason & INTR_BS) == 0)
 1148                                 break;
 1149 
 1150                         if ((slp->sl_error & PDMAERR) == 0)
 1151                                 printf("%s: data underrun\n", slp->sl_xname);
 1152                         slp->sl_error |= PDMAERR;
 1153 
 1154                         if ((slp->sl_flags & HW_WRITE_PADDING) != 0)
 1155                         {
 1156                                 u_int8_t padding[NCV_PADDING_SIZE];
 1157 
 1158                                 SCSI_LOW_BZERO(padding, sizeof(padding));
 1159                                 ncv_pio_write(sc, padding, sizeof(padding));
 1160                         }
 1161                         else
 1162                         {
 1163                                 printf("%s: write padding required\n",
 1164                                         slp->sl_xname);
 1165                         }
 1166                 }
 1167                 else
 1168                 {
 1169                         len = slp->sl_scp.scp_datalen;
 1170                         if ((ncv_io_control & NCV_WRITE_INTERRUPTS_DRIVEN) != 0)
 1171                         {
 1172                                 if (len > ncv_data_write_bytes)
 1173                                         len = ncv_data_write_bytes;
 1174                         }
 1175                         ncv_pio_write(sc, slp->sl_scp.scp_data, len);
 1176                 }
 1177                 physio_proc_leave(pp);
 1178                 break;
 1179 
 1180         case DATA_IN_PHASE: /* data in */
 1181                 SCSI_LOW_SETUP_PHASE(ti, PH_DATA);
 1182                 if (scsi_low_data(slp, ti, &bp, SCSI_LOW_READ) != 0)
 1183                 {
 1184                         scsi_low_attention(slp);
 1185                 }
 1186 
 1187                 pp = physio_proc_enter(bp);
 1188                 if (slp->sl_scp.scp_datalen <= 0)
 1189                 {
 1190                         if ((ireason & INTR_BS) == 0)
 1191                                 break;
 1192 
 1193                         if ((slp->sl_error & PDMAERR) == 0)
 1194                                 printf("%s: data overrun\n", slp->sl_xname);
 1195                         slp->sl_error |= PDMAERR;
 1196 
 1197                         if ((slp->sl_flags & HW_READ_PADDING) != 0)
 1198                         {
 1199                                 u_int8_t padding[NCV_PADDING_SIZE];
 1200 
 1201                                 ncv_pio_read(sc, padding, sizeof(padding));
 1202                         }
 1203                         else
 1204                         {
 1205                                 printf("%s: read padding required\n",
 1206                                         slp->sl_xname);
 1207                                 break;
 1208                         }
 1209                 }
 1210                 else
 1211                 {
 1212                         len = slp->sl_scp.scp_datalen;
 1213                         if ((ncv_io_control & NCV_READ_INTERRUPTS_DRIVEN) != 0)
 1214                         {
 1215                                 if (len > ncv_data_read_bytes)
 1216                                         len = ncv_data_read_bytes;
 1217                         }
 1218                         ncv_pio_read(sc, slp->sl_scp.scp_data, len);
 1219                 }
 1220                 physio_proc_leave(pp);
 1221                 break;
 1222 
 1223         case COMMAND_PHASE: /* cmd out */
 1224                 SCSI_LOW_SETUP_PHASE(ti, PH_CMD);
 1225                 if (scsi_low_cmd(slp, ti) != 0)
 1226                 {
 1227                         scsi_low_attention(slp);
 1228                 }
 1229 
 1230                 bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH);
 1231                 ncvhw_fpush(iot, ioh,
 1232                             slp->sl_scp.scp_cmd, slp->sl_scp.scp_cmdlen);
 1233                 bus_space_write_1(iot, ioh, cr0_cmd, CMD_TRANS);
 1234                 break;
 1235 
 1236         case STATUS_PHASE: /* status in */
 1237                 SCSI_LOW_SETUP_PHASE(ti, PH_STAT);
 1238                 bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH);
 1239                 bus_space_write_1(iot, ioh, cr0_cmd, CMD_ICCS);
 1240                 sc->sc_compseq = 1;
 1241                 break;
 1242 
 1243         default:
 1244                 break;
 1245 
 1246         case MESSAGE_OUT_PHASE: /* msg out */
 1247                 SCSI_LOW_SETUP_PHASE(ti, PH_MSGOUT);
 1248                 bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH);
 1249 
 1250                 flags = SCSI_LOW_MSGOUT_UNIFY;
 1251                 if (ti->ti_ophase != ti->ti_phase)
 1252                         flags |= SCSI_LOW_MSGOUT_INIT;
 1253                 len = scsi_low_msgout(slp, ti, flags);
 1254 
 1255                 if (len > 1 && slp->sl_atten == 0)
 1256                 {
 1257                         scsi_low_attention(slp);
 1258                 }
 1259 
 1260                 ncvhw_fpush(iot, ioh, ti->ti_msgoutstr, len);
 1261                 bus_space_write_1(iot, ioh, cr0_cmd, CMD_TRANS);
 1262                 SCSI_LOW_DEASSERT_ATN(slp);
 1263                 break;
 1264 
 1265         case MESSAGE_IN_PHASE: /* msg in */
 1266                 SCSI_LOW_SETUP_PHASE(ti, PH_MSGIN);
 1267 
 1268                 len = bus_space_read_1(iot, ioh, cr0_sffl) & CR0_SFFLR_BMASK;
 1269                 if (sc->sc_compseq != 0)
 1270                 {
 1271                         sc->sc_compseq = 0;
 1272                         if ((ireason & INTR_FC) && len == 2)
 1273                         {
 1274                                 regv = bus_space_read_1(iot, ioh, cr0_sfifo);
 1275                                 scsi_low_statusin(slp, ti, regv | derror);
 1276                                 len --;
 1277                         }
 1278                         else
 1279                         {
 1280                                 slp->sl_error |= FATALIO;
 1281                                 scsi_low_assert_msg(slp, ti,
 1282                                                     SCSI_LOW_MSG_ABORT, 1);
 1283                                 bus_space_write_1(sc->sc_iot, sc->sc_ioh,
 1284                                                   cr0_cmd, CMD_MSGOK);
 1285                                 break;
 1286                         }
 1287                 }
 1288                 else if (ireason & INTR_BS)
 1289                 {
 1290                         bus_space_write_1(iot, ioh, cr0_cmd, CMD_FLUSH);
 1291                         bus_space_write_1(iot, ioh, cr0_cmd, CMD_TRANS);
 1292                         if ((ncv_io_control & NCV_FAST_INTERRUPTS) != 0)
 1293                         {
 1294                                 if (ncv_catch_intr(sc) == 0)
 1295                                         goto again;
 1296                         }
 1297                         break;
 1298                 }
 1299 
 1300                 if ((ireason & INTR_FC) && len == 1)
 1301                 {
 1302                         regv = bus_space_read_1(sc->sc_iot, sc->sc_ioh,
 1303                                                 cr0_sfifo);
 1304                         if (scsi_low_msgin(slp, ti, regv | derror) == 0)
 1305                         {
 1306                                 if (scsi_low_is_msgout_continue(ti, 0) != 0)
 1307                                 {
 1308                                         scsi_low_attention(slp);
 1309                                 }
 1310                         }
 1311                         bus_space_write_1(sc->sc_iot, sc->sc_ioh, cr0_cmd,
 1312                                 CMD_MSGOK);
 1313                         if ((ncv_io_control & NCV_FAST_INTERRUPTS) != 0)
 1314                         {
 1315                                 /* XXX: 
 1316                                  * clear a pending interrupt and sync with
 1317                                  * a next interrupt!
 1318                                  */
 1319                                 ncv_catch_intr(sc);
 1320                         }
 1321                 }
 1322                 else
 1323                 {
 1324                         slp->sl_error |= FATALIO;
 1325                         scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT, 1);
 1326                         bus_space_write_1(sc->sc_iot, sc->sc_ioh, cr0_cmd,
 1327                                 CMD_MSGOK);
 1328                 }
 1329                 break;
 1330         }
 1331 
 1332         return 1;
 1333 }

Cache object: 7df86dab3bca7316636c124bfc0f3766


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


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