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-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

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

Cache object: 4cf9bd8c38f947b7be7e6f68bf9aab47


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