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/sparc64/sbus/lsi64854.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 /*-
    2  * Copyright (c) 2004 Scott Long
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  *
   26  */
   27 
   28 /*      $NetBSD: lsi64854.c,v 1.25 2005/02/27 00:27:02 perry Exp $ */
   29 
   30 /*-
   31  * Copyright (c) 1998 The NetBSD Foundation, Inc.
   32  * All rights reserved.
   33  *
   34  * This code is derived from software contributed to The NetBSD Foundation
   35  * by Paul Kranenburg.
   36  *
   37  * Redistribution and use in source and binary forms, with or without
   38  * modification, are permitted provided that the following conditions
   39  * are met:
   40  * 1. Redistributions of source code must retain the above copyright
   41  *    notice, this list of conditions and the following disclaimer.
   42  * 2. Redistributions in binary form must reproduce the above copyright
   43  *    notice, this list of conditions and the following disclaimer in the
   44  *    documentation and/or other materials provided with the distribution.
   45  * 3. All advertising materials mentioning features or use of this software
   46  *    must display the following acknowledgement:
   47  *        This product includes software developed by the NetBSD
   48  *        Foundation, Inc. and its contributors.
   49  * 4. Neither the name of The NetBSD Foundation nor the names of its
   50  *    contributors may be used to endorse or promote products derived
   51  *    from this software without specific prior written permission.
   52  *
   53  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   54  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   55  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   56  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   57  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   58  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   59  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   60  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   61  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   62  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   63  * POSSIBILITY OF SUCH DAMAGE.
   64  */
   65 
   66 #include <sys/cdefs.h>
   67 __FBSDID("$FreeBSD$");
   68 
   69 #include <sys/param.h>
   70 #include <sys/systm.h>
   71 #include <sys/bus.h>
   72 #include <sys/kernel.h>
   73 #include <sys/lock.h>
   74 #include <sys/mutex.h>
   75 #include <sys/rman.h>
   76 
   77 #include <machine/bus.h>
   78 
   79 #include <cam/cam.h>
   80 #include <cam/cam_ccb.h>
   81 #include <cam/scsi/scsi_all.h>
   82 
   83 #include <sparc64/sbus/lsi64854reg.h>
   84 #include <sparc64/sbus/lsi64854var.h>
   85 
   86 #include <dev/esp/ncr53c9xreg.h>
   87 #include <dev/esp/ncr53c9xvar.h>
   88 
   89 #ifdef DEBUG
   90 #define LDB_SCSI        1
   91 #define LDB_ENET        2
   92 #define LDB_PP          4
   93 #define LDB_ANY         0xff
   94 int lsi64854debug = 0;
   95 #define DPRINTF(a,x)                                                    \
   96         do {                                                            \
   97                 if ((lsi64854debug & (a)) != 0)                         \
   98                         printf x;                                       \
   99         } while (/* CONSTCOND */0)
  100 #else
  101 #define DPRINTF(a,x)
  102 #endif
  103 
  104 /*
  105  * The rules say we cannot transfer more than the limit of this DMA chip (64k
  106  * for old and 16Mb for new), and we cannot cross a 16Mb boundary.
  107  */
  108 #define MAX_DMA_SZ      (64 * 1024)
  109 #define BOUNDARY        (16 * 1024 * 1024)
  110 
  111 static void     lsi64854_reset(struct lsi64854_softc *);
  112 static void     lsi64854_map_scsi(void *, bus_dma_segment_t *, int, int);
  113 static int      lsi64854_setup(struct lsi64854_softc *, void **, size_t *,
  114                     int, size_t *);
  115 static int      lsi64854_scsi_intr(void *);
  116 static int      lsi64854_enet_intr(void *);
  117 static int      lsi64854_setup_pp(struct lsi64854_softc *, void **,
  118                     size_t *, int, size_t *);
  119 static int      lsi64854_pp_intr(void *);
  120 
  121 /*
  122  * Finish attaching this DMA device.
  123  * Front-end must fill in these fields:
  124  *      sc_res
  125  *      sc_burst
  126  *      sc_channel (one of SCSI, ENET, PP)
  127  *      sc_client (one of SCSI, ENET, PP `soft_c' pointers)
  128  */
  129 int
  130 lsi64854_attach(struct lsi64854_softc *sc)
  131 {
  132         bus_dma_lock_t *lockfunc;
  133         struct ncr53c9x_softc *nsc;
  134         void *lockfuncarg;
  135         uint32_t csr;
  136         int error;
  137 
  138         lockfunc = NULL;
  139         lockfuncarg = NULL;
  140         sc->sc_maxdmasize = MAX_DMA_SZ;
  141 
  142         switch (sc->sc_channel) {
  143         case L64854_CHANNEL_SCSI:
  144                 nsc = sc->sc_client;
  145                 if (NCR_LOCK_INITIALIZED(nsc) == 0) {
  146                         device_printf(sc->sc_dev, "mutex not initialized\n");
  147                         return (ENXIO);
  148                 }
  149                 lockfunc = busdma_lock_mutex;
  150                 lockfuncarg = &nsc->sc_lock;
  151                 sc->sc_maxdmasize = nsc->sc_maxxfer;
  152                 sc->intr = lsi64854_scsi_intr;
  153                 sc->setup = lsi64854_setup;
  154                 break;
  155         case L64854_CHANNEL_ENET:
  156                 sc->intr = lsi64854_enet_intr;
  157                 break;
  158         case L64854_CHANNEL_PP:
  159                 sc->intr = lsi64854_pp_intr;
  160                 sc->setup = lsi64854_setup_pp;
  161                 break;
  162         default:
  163                 device_printf(sc->sc_dev, "unknown channel\n");
  164         }
  165         sc->reset = lsi64854_reset;
  166 
  167         if (sc->setup != NULL) {
  168                 error = bus_dma_tag_create(
  169                     sc->sc_parent_dmat,         /* parent */
  170                     1, BOUNDARY,                /* alignment, boundary */
  171                     BUS_SPACE_MAXADDR_32BIT,    /* lowaddr */
  172                     BUS_SPACE_MAXADDR,          /* highaddr */
  173                     NULL, NULL,                 /* filter, filterarg */
  174                     sc->sc_maxdmasize,          /* maxsize */
  175                     1,                          /* nsegments */
  176                     sc->sc_maxdmasize,          /* maxsegsize */
  177                     BUS_DMA_ALLOCNOW,           /* flags */
  178                     lockfunc, lockfuncarg,      /* lockfunc, lockfuncarg */
  179                     &sc->sc_buffer_dmat);
  180                 if (error != 0) {
  181                         device_printf(sc->sc_dev,
  182                             "cannot allocate buffer DMA tag\n");
  183                         return (error);
  184                 }
  185 
  186                 error = bus_dmamap_create(sc->sc_buffer_dmat, 0,
  187                     &sc->sc_dmamap);
  188                 if (error != 0) {
  189                         device_printf(sc->sc_dev, "DMA map create failed\n");
  190                         bus_dma_tag_destroy(sc->sc_buffer_dmat);
  191                         return (error);
  192                 }
  193         }
  194 
  195         csr = L64854_GCSR(sc);
  196         sc->sc_rev = csr & L64854_DEVID;
  197         if (sc->sc_rev == DMAREV_HME)
  198                 return (0);
  199         device_printf(sc->sc_dev, "DMA rev. ");
  200         switch (sc->sc_rev) {
  201         case DMAREV_0:
  202                 printf("");
  203                 break;
  204         case DMAREV_ESC:
  205                 printf("ESC");
  206                 break;
  207         case DMAREV_1:
  208                 printf("1");
  209                 break;
  210         case DMAREV_PLUS:
  211                 printf("1+");
  212                 break;
  213         case DMAREV_2:
  214                 printf("2");
  215                 break;
  216         default:
  217                 printf("unknown (0x%x)", sc->sc_rev);
  218         }
  219 
  220         DPRINTF(LDB_ANY, (", burst 0x%x, csr 0x%x", sc->sc_burst, csr));
  221         printf("\n");
  222 
  223         return (0);
  224 }
  225 
  226 int
  227 lsi64854_detach(struct lsi64854_softc *sc)
  228 {
  229 
  230         if (sc->setup != NULL) {
  231                 bus_dmamap_sync(sc->sc_buffer_dmat, sc->sc_dmamap,
  232                     (L64854_GCSR(sc) & L64854_WRITE) != 0 ?
  233                     BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
  234                 bus_dmamap_unload(sc->sc_buffer_dmat, sc->sc_dmamap);
  235                 bus_dmamap_destroy(sc->sc_buffer_dmat, sc->sc_dmamap);
  236                 bus_dma_tag_destroy(sc->sc_buffer_dmat);
  237         }
  238 
  239         return (0);
  240 }
  241 
  242 /*
  243  * DMAWAIT waits while condition is true.
  244  */
  245 #define DMAWAIT(SC, COND, MSG, DONTPANIC) do if (COND) {                \
  246         int count = 500000;                                             \
  247         while ((COND) && --count > 0) DELAY(1);                         \
  248         if (count == 0) {                                               \
  249                 printf("%s: line %d: CSR = 0x%lx\n", __FILE__, __LINE__, \
  250                         (u_long)L64854_GCSR(SC));                       \
  251                 if (DONTPANIC)                                          \
  252                         printf(MSG);                                    \
  253                 else                                                    \
  254                         panic(MSG);                                     \
  255         }                                                               \
  256 } while (/* CONSTCOND */0)
  257 
  258 #define DMA_DRAIN(sc, dontpanic) do {                                   \
  259         uint32_t csr;                                                   \
  260         /*                                                              \
  261          * DMA rev0 & rev1: we are not allowed to touch the DMA "flush" \
  262          *     and "drain" bits while it is still thinking about a      \
  263          *     request.                                                 \
  264          * other revs: D_ESC_R_PEND bit reads as 0                      \
  265          */                                                             \
  266         DMAWAIT(sc, L64854_GCSR(sc) & D_ESC_R_PEND, "R_PEND", dontpanic);\
  267         if (sc->sc_rev != DMAREV_HME) {                                 \
  268                 /*                                                      \
  269                  * Select drain bit based on revision                   \
  270                  * also clears errors and D_TC flag                     \
  271                  */                                                     \
  272                 csr = L64854_GCSR(sc);                                  \
  273                 if (sc->sc_rev == DMAREV_1 || sc->sc_rev == DMAREV_0)   \
  274                         csr |= D_ESC_DRAIN;                             \
  275                 else                                                    \
  276                         csr |= L64854_INVALIDATE;                       \
  277                                                                         \
  278                 L64854_SCSR(sc, csr);                                   \
  279         }                                                               \
  280         /*                                                              \
  281          * Wait for draining to finish                                  \
  282          * rev0 & rev1 call this PACKCNT                                \
  283          */                                                             \
  284         DMAWAIT(sc, L64854_GCSR(sc) & L64854_DRAINING, "DRAINING",      \
  285             dontpanic);                                                 \
  286 } while (/* CONSTCOND */0)
  287 
  288 #define DMA_FLUSH(sc, dontpanic) do {                                   \
  289         uint32_t csr;                                                   \
  290         /*                                                              \
  291          * DMA rev0 & rev1: we are not allowed to touch the DMA "flush" \
  292          *     and "drain" bits while it is still thinking about a      \
  293          *     request.                                                 \
  294          * other revs: D_ESC_R_PEND bit reads as 0                      \
  295          */                                                             \
  296         DMAWAIT(sc, L64854_GCSR(sc) & D_ESC_R_PEND, "R_PEND", dontpanic);\
  297         csr = L64854_GCSR(sc);                                  \
  298         csr &= ~(L64854_WRITE|L64854_EN_DMA); /* no-ops on ENET */      \
  299         csr |= L64854_INVALIDATE;               /* XXX FAS ? */         \
  300         L64854_SCSR(sc, csr);                                           \
  301 } while (/* CONSTCOND */0)
  302 
  303 static void
  304 lsi64854_reset(struct lsi64854_softc *sc)
  305 {
  306         bus_dma_tag_t dmat;
  307         bus_dmamap_t dmam;
  308         uint32_t csr;
  309 
  310         DMA_FLUSH(sc, 1);
  311         csr = L64854_GCSR(sc);
  312 
  313         DPRINTF(LDB_ANY, ("%s: csr 0x%x\n", __func__, csr));
  314 
  315         if (sc->sc_dmasize != 0) {
  316                 dmat = sc->sc_buffer_dmat;
  317                 dmam = sc->sc_dmamap;
  318                 bus_dmamap_sync(dmat, dmam, (csr & D_WRITE) != 0 ?
  319                     BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
  320                 bus_dmamap_unload(dmat, dmam);
  321         }
  322 
  323         if (sc->sc_rev == DMAREV_HME)
  324                 L64854_SCSR(sc, csr | D_HW_RESET_FAS366);
  325 
  326         csr |= L64854_RESET;            /* reset DMA */
  327         L64854_SCSR(sc, csr);
  328         DELAY(200);                     /* > 10 Sbus clocks(?) */
  329 
  330         /*DMAWAIT1(sc); why was this here? */
  331         csr = L64854_GCSR(sc);
  332         csr &= ~L64854_RESET;           /* de-assert reset line */
  333         L64854_SCSR(sc, csr);
  334         DELAY(5);                       /* allow a few ticks to settle */
  335 
  336         csr = L64854_GCSR(sc);
  337         csr |= L64854_INT_EN;           /* enable interrupts */
  338         if (sc->sc_rev > DMAREV_1 && sc->sc_channel == L64854_CHANNEL_SCSI) {
  339                 if (sc->sc_rev == DMAREV_HME)
  340                         csr |= D_TWO_CYCLE;
  341                 else
  342                         csr |= D_FASTER;
  343         }
  344 
  345         /* Set burst */
  346         switch (sc->sc_rev) {
  347         case DMAREV_HME:
  348         case DMAREV_2:
  349                 csr &= ~L64854_BURST_SIZE;
  350                 if (sc->sc_burst == 32)
  351                         csr |= L64854_BURST_32;
  352                 else if (sc->sc_burst == 16)
  353                         csr |= L64854_BURST_16;
  354                 else
  355                         csr |= L64854_BURST_0;
  356                 break;
  357         case DMAREV_ESC:
  358                 csr |= D_ESC_AUTODRAIN; /* Auto-drain */
  359                 if (sc->sc_burst == 32)
  360                         csr &= ~D_ESC_BURST;
  361                 else
  362                         csr |= D_ESC_BURST;
  363                 break;
  364         default:
  365                 break;
  366         }
  367         L64854_SCSR(sc, csr);
  368 
  369         if (sc->sc_rev == DMAREV_HME) {
  370                 bus_write_4(sc->sc_res, L64854_REG_ADDR, 0);
  371                 sc->sc_dmactl = csr;
  372         }
  373         sc->sc_active = 0;
  374 
  375         DPRINTF(LDB_ANY, ("%s: done, csr 0x%x\n", __func__, csr));
  376 }
  377 
  378 static void
  379 lsi64854_map_scsi(void *arg, bus_dma_segment_t *segs, int nseg, int error)
  380 {
  381         struct lsi64854_softc *sc;
  382 
  383         sc = (struct lsi64854_softc *)arg;
  384 
  385         if (error != 0)
  386                 return;
  387         if (nseg != 1)
  388                 panic("%s: cannot map %d segments\n", __func__, nseg);
  389 
  390         bus_dmamap_sync(sc->sc_buffer_dmat, sc->sc_dmamap,
  391             sc->sc_datain != 0 ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
  392         bus_write_4(sc->sc_res, L64854_REG_ADDR, segs[0].ds_addr);
  393 }
  394 
  395 /*
  396  * setup a DMA transfer
  397  */
  398 static int
  399 lsi64854_setup(struct lsi64854_softc *sc, void **addr, size_t *len,
  400     int datain, size_t *dmasize)
  401 {
  402         long bcnt;
  403         int error;
  404         uint32_t csr;
  405 
  406         DMA_FLUSH(sc, 0);
  407 
  408 #if 0
  409         DMACSR(sc) &= ~D_INT_EN;
  410 #endif
  411         sc->sc_dmaaddr = addr;
  412         sc->sc_dmalen = len;
  413         sc->sc_datain = datain;
  414 
  415         KASSERT(*dmasize <= sc->sc_maxdmasize,
  416             ("%s: transfer size %ld too large", __func__, (long)*dmasize));
  417 
  418         sc->sc_dmasize = *dmasize;
  419 
  420         DPRINTF(LDB_ANY, ("%s: dmasize=%ld\n", __func__, (long)*dmasize));
  421 
  422         /*
  423          * XXX what length?
  424          */
  425         if (sc->sc_rev == DMAREV_HME) {
  426                 L64854_SCSR(sc, sc->sc_dmactl | L64854_RESET);
  427                 L64854_SCSR(sc, sc->sc_dmactl);
  428 
  429                 bus_write_4(sc->sc_res, L64854_REG_CNT, *dmasize);
  430         }
  431 
  432         /*
  433          * Load the transfer buffer and program the DMA address.
  434          * Note that the NCR53C9x core can't handle EINPROGRESS so we set
  435          * BUS_DMA_NOWAIT.
  436          */
  437         if (*dmasize != 0) {
  438                 error = bus_dmamap_load(sc->sc_buffer_dmat, sc->sc_dmamap,
  439                     *sc->sc_dmaaddr, *dmasize, lsi64854_map_scsi, sc,
  440                     BUS_DMA_NOWAIT);
  441                 if (error != 0)
  442                         return (error);
  443         }
  444 
  445         if (sc->sc_rev == DMAREV_ESC) {
  446                 /* DMA ESC chip bug work-around */
  447                 bcnt = *dmasize;
  448                 if (((bcnt + (long)*sc->sc_dmaaddr) & PAGE_MASK_8K) != 0)
  449                         bcnt = roundup(bcnt, PAGE_SIZE_8K);
  450                 bus_write_4(sc->sc_res, L64854_REG_CNT, bcnt);
  451         }
  452 
  453         /* Setup the DMA control register. */
  454         csr = L64854_GCSR(sc);
  455 
  456         if (datain != 0)
  457                 csr |= L64854_WRITE;
  458         else
  459                 csr &= ~L64854_WRITE;
  460         csr |= L64854_INT_EN;
  461 
  462         if (sc->sc_rev == DMAREV_HME)
  463                 csr |= (D_DSBL_SCSI_DRN | D_EN_DMA);
  464 
  465         L64854_SCSR(sc, csr);
  466 
  467         return (0);
  468 }
  469 
  470 /*
  471  * Pseudo (chained) interrupt from the esp driver to kick the
  472  * current running DMA transfer.  Called from ncr53c9x_intr()
  473  * for now.
  474  *
  475  * return 1 if it was a DMA continue.
  476  */
  477 static int
  478 lsi64854_scsi_intr(void *arg)
  479 {
  480         struct lsi64854_softc *sc = arg;
  481         struct ncr53c9x_softc *nsc = sc->sc_client;
  482         bus_dma_tag_t dmat;
  483         bus_dmamap_t dmam;
  484         size_t dmasize;
  485         int lxfer, resid, trans;
  486         uint32_t csr;
  487 
  488         csr = L64854_GCSR(sc);
  489 
  490         DPRINTF(LDB_SCSI, ("%s: addr 0x%x, csr %b\n", __func__,
  491             bus_read_4(sc->sc_res, L64854_REG_ADDR), csr, DDMACSR_BITS));
  492 
  493         if (csr & (D_ERR_PEND | D_SLAVE_ERR)) {
  494                 device_printf(sc->sc_dev, "error: csr=%b\n", csr,
  495                     DDMACSR_BITS);
  496                 csr &= ~D_EN_DMA;       /* Stop DMA. */
  497                 /* Invalidate the queue; SLAVE_ERR bit is write-to-clear */
  498                 csr |= D_INVALIDATE | D_SLAVE_ERR;
  499                 L64854_SCSR(sc, csr);
  500                 return (-1);
  501         }
  502 
  503         /* This is an "assertion" :) */
  504         if (sc->sc_active == 0)
  505                 panic("%s: DMA wasn't active", __func__);
  506 
  507         DMA_DRAIN(sc, 0);
  508 
  509         /* DMA has stopped */
  510         csr &= ~D_EN_DMA;
  511         L64854_SCSR(sc, csr);
  512         sc->sc_active = 0;
  513 
  514         dmasize = sc->sc_dmasize;
  515         if (dmasize == 0) {
  516                 /* A "Transfer Pad" operation completed. */
  517                 DPRINTF(LDB_SCSI, ("%s: discarded %d bytes (tcl=%d, "
  518                     "tcm=%d)\n", __func__, NCR_READ_REG(nsc, NCR_TCL) |
  519                     (NCR_READ_REG(nsc, NCR_TCM) << 8),
  520                     NCR_READ_REG(nsc, NCR_TCL), NCR_READ_REG(nsc, NCR_TCM)));
  521                 return (0);
  522         }
  523 
  524         resid = 0;
  525         /*
  526          * If a transfer onto the SCSI bus gets interrupted by the device
  527          * (e.g. for a SAVEPOINTER message), the data in the FIFO counts
  528          * as residual since the NCR53C9X counter registers get decremented
  529          * as bytes are clocked into the FIFO.
  530          */
  531         if ((csr & D_WRITE) == 0 &&
  532             (resid = (NCR_READ_REG(nsc, NCR_FFLAG) & NCRFIFO_FF)) != 0) {
  533                 DPRINTF(LDB_SCSI, ("%s: empty esp FIFO of %d ", __func__,
  534                     resid));
  535                 if (nsc->sc_rev == NCR_VARIANT_FAS366 &&
  536                     (NCR_READ_REG(nsc, NCR_CFG3) & NCRFASCFG3_EWIDE))
  537                         resid <<= 1;
  538         }
  539 
  540         if ((nsc->sc_espstat & NCRSTAT_TC) == 0) {
  541                 lxfer = nsc->sc_features & NCR_F_LARGEXFER;
  542                 /*
  543                  * "Terminal count" is off, so read the residue
  544                  * out of the NCR53C9X counter registers.
  545                  */
  546                 resid += (NCR_READ_REG(nsc, NCR_TCL) |
  547                     (NCR_READ_REG(nsc, NCR_TCM) << 8) |
  548                     (lxfer != 0 ? (NCR_READ_REG(nsc, NCR_TCH) << 16) : 0));
  549 
  550                 if (resid == 0 && dmasize == 65536 && lxfer == 0)
  551                         /* A transfer of 64k is encoded as TCL=TCM=0. */
  552                         resid = 65536;
  553         }
  554 
  555         trans = dmasize - resid;
  556         if (trans < 0) {                        /* transferred < 0? */
  557 #if 0
  558                 /*
  559                  * This situation can happen in perfectly normal operation
  560                  * if the ESP is reselected while using DMA to select
  561                  * another target.  As such, don't print the warning.
  562                  */
  563                 device_printf(sc->sc_dev, "xfer (%d) > req (%d)\n", trans,
  564                     dmasize);
  565 #endif
  566                 trans = dmasize;
  567         }
  568 
  569         DPRINTF(LDB_SCSI, ("%s: tcl=%d, tcm=%d, tch=%d; trans=%d, resid=%d\n",
  570             __func__, NCR_READ_REG(nsc, NCR_TCL), NCR_READ_REG(nsc, NCR_TCM),
  571             (nsc->sc_features & NCR_F_LARGEXFER) != 0 ?
  572             NCR_READ_REG(nsc, NCR_TCH) : 0, trans, resid));
  573 
  574         if (dmasize != 0) {
  575                 dmat = sc->sc_buffer_dmat;
  576                 dmam = sc->sc_dmamap;
  577                 bus_dmamap_sync(dmat, dmam, (csr & D_WRITE) != 0 ?
  578                     BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
  579                 bus_dmamap_unload(dmat, dmam);
  580         }
  581 
  582         *sc->sc_dmalen -= trans;
  583         *sc->sc_dmaaddr = (char *)*sc->sc_dmaaddr + trans;
  584 
  585 #if 0   /* this is not normal operation just yet */
  586         if (*sc->sc_dmalen == 0 || nsc->sc_phase != nsc->sc_prevphase)
  587                 return (0);
  588 
  589         /* and again */
  590         dma_start(sc, sc->sc_dmaaddr, sc->sc_dmalen, DMACSR(sc) & D_WRITE);
  591         return (1);
  592 #endif
  593         return (0);
  594 }
  595 
  596 /*
  597  * Pseudo (chained) interrupt to le(4) driver to handle DMA errors
  598  */
  599 static int
  600 lsi64854_enet_intr(void *arg)
  601 {
  602         struct lsi64854_softc *sc = arg;
  603         uint32_t csr;
  604         int i, rv;
  605 
  606         csr = L64854_GCSR(sc);
  607 
  608         /* If the DMA logic shows an interrupt, claim it */
  609         rv = ((csr & E_INT_PEND) != 0) ? 1 : 0;
  610 
  611         if (csr & (E_ERR_PEND | E_SLAVE_ERR)) {
  612                 device_printf(sc->sc_dev, "error: csr=%b\n", csr,
  613                     EDMACSR_BITS);
  614                 csr &= ~L64854_EN_DMA;  /* Stop DMA. */
  615                 /* Invalidate the queue; SLAVE_ERR bit is write-to-clear */
  616                 csr |= E_INVALIDATE | E_SLAVE_ERR;
  617                 L64854_SCSR(sc, csr);
  618                 /* Will be drained with the LE_C0_IDON interrupt. */
  619                 sc->sc_dodrain = 1;
  620                 return (-1);
  621         }
  622 
  623         /* XXX - is this necessary with E_DSBL_WR_INVAL on? */
  624         if (sc->sc_dodrain) {
  625                 i = 10;
  626                 csr |= E_DRAIN;
  627                 L64854_SCSR(sc, csr);
  628                 while (i-- > 0 && (L64854_GCSR(sc) & E_DRAINING))
  629                         DELAY(1);
  630                 sc->sc_dodrain = 0;
  631         }
  632 
  633         return (rv);
  634 }
  635 
  636 static void
  637 lsi64854_map_pp(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
  638 {
  639         struct lsi64854_softc *sc;
  640 
  641         sc = (struct lsi64854_softc *)arg;
  642 
  643         if (error != 0)
  644                 return;
  645         if (nsegs != 1)
  646                 panic("%s: cannot map %d segments\n", __func__, nsegs);
  647 
  648         bus_dmamap_sync(sc->sc_buffer_dmat, sc->sc_dmamap,
  649             sc->sc_datain != 0 ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
  650         bus_write_4(sc->sc_res, L64854_REG_ADDR, segs[0].ds_addr);
  651 
  652         bus_write_4(sc->sc_res, L64854_REG_CNT, sc->sc_dmasize);
  653 }
  654 
  655 /*
  656  * Setup a DMA transfer.
  657  */
  658 static int
  659 lsi64854_setup_pp(struct lsi64854_softc *sc, void **addr, size_t *len,
  660     int datain, size_t *dmasize)
  661 {
  662         int error;
  663         uint32_t csr;
  664 
  665         DMA_FLUSH(sc, 0);
  666 
  667         sc->sc_dmaaddr = addr;
  668         sc->sc_dmalen = len;
  669         sc->sc_datain = datain;
  670 
  671         DPRINTF(LDB_PP, ("%s: pp start %ld@%p,%d\n", __func__,
  672             (long)*sc->sc_dmalen, *sc->sc_dmaaddr, datain != 0 ? 1 : 0));
  673 
  674         KASSERT(*dmasize <= sc->sc_maxdmasize,
  675             ("%s: transfer size %ld too large", __func__, (long)*dmasize));
  676 
  677         sc->sc_dmasize = *dmasize;
  678 
  679         DPRINTF(LDB_PP, ("%s: dmasize=%ld\n", __func__, (long)*dmasize));
  680 
  681         /* Load the transfer buffer and program the DMA address. */
  682         if (*dmasize != 0) {
  683                 error = bus_dmamap_load(sc->sc_buffer_dmat, sc->sc_dmamap,
  684                     *sc->sc_dmaaddr, *dmasize, lsi64854_map_pp, sc,
  685                     BUS_DMA_NOWAIT);
  686                 if (error != 0)
  687                         return (error);
  688         }
  689 
  690         /* Setup the DMA control register. */
  691         csr = L64854_GCSR(sc);
  692         csr &= ~L64854_BURST_SIZE;
  693         if (sc->sc_burst == 32)
  694                 csr |= L64854_BURST_32;
  695         else if (sc->sc_burst == 16)
  696                 csr |= L64854_BURST_16;
  697         else
  698                 csr |= L64854_BURST_0;
  699         csr |= P_EN_DMA | P_INT_EN | P_EN_CNT;
  700 #if 0
  701         /* This bit is read-only in PP csr register. */
  702         if (datain != 0)
  703                 csr |= P_WRITE;
  704         else
  705                 csr &= ~P_WRITE;
  706 #endif
  707         L64854_SCSR(sc, csr);
  708 
  709         return (0);
  710 }
  711 
  712 /*
  713  * Parallel port DMA interrupt
  714  */
  715 static int
  716 lsi64854_pp_intr(void *arg)
  717 {
  718         struct lsi64854_softc *sc = arg;
  719         bus_dma_tag_t dmat;
  720         bus_dmamap_t dmam;
  721         size_t dmasize;
  722         int ret, trans, resid = 0;
  723         uint32_t csr;
  724 
  725         csr = L64854_GCSR(sc);
  726 
  727         DPRINTF(LDB_PP, ("%s: addr 0x%x, csr %b\n", __func__,
  728             bus_read_4(sc->sc_res, L64854_REG_ADDR), csr, PDMACSR_BITS));
  729 
  730         if ((csr & (P_ERR_PEND | P_SLAVE_ERR)) != 0) {
  731                 resid = bus_read_4(sc->sc_res, L64854_REG_CNT);
  732                 device_printf(sc->sc_dev, "error: resid %d csr=%b\n", resid,
  733                     csr, PDMACSR_BITS);
  734                 csr &= ~P_EN_DMA;       /* Stop DMA. */
  735                 /* Invalidate the queue; SLAVE_ERR bit is write-to-clear */
  736                 csr |= P_INVALIDATE | P_SLAVE_ERR;
  737                 L64854_SCSR(sc, csr);
  738                 return (-1);
  739         }
  740 
  741         ret = (csr & P_INT_PEND) != 0;
  742 
  743         if (sc->sc_active != 0) {
  744                 DMA_DRAIN(sc, 0);
  745                 resid = bus_read_4(sc->sc_res, L64854_REG_CNT);
  746         }
  747 
  748         /* DMA has stopped */
  749         csr &= ~D_EN_DMA;
  750         L64854_SCSR(sc, csr);
  751         sc->sc_active = 0;
  752 
  753         dmasize = sc->sc_dmasize;
  754         trans = dmasize - resid;
  755         if (trans < 0)                          /* transferred < 0? */
  756                 trans = dmasize;
  757         *sc->sc_dmalen -= trans;
  758         *sc->sc_dmaaddr = (char *)*sc->sc_dmaaddr + trans;
  759 
  760         if (dmasize != 0) {
  761                 dmat = sc->sc_buffer_dmat;
  762                 dmam = sc->sc_dmamap;
  763                 bus_dmamap_sync(dmat, dmam, (csr & D_WRITE) != 0 ?
  764                     BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
  765                 bus_dmamap_unload(dmat, dmam);
  766         }
  767 
  768         return (ret != 0);
  769 }

Cache object: 1076994784a7633abe3e41a002bf71ae


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