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: releng/6.4/sys/sparc64/sbus/lsi64854.c 146392 2005-05-19 14:51:10Z marius $");
   68 
   69 #include <sys/param.h>
   70 #include <sys/systm.h>
   71 #include <sys/bus.h>
   72 #include <sys/kernel.h>
   73 #include <sys/resource.h>
   74 #include <sys/lock.h>
   75 #include <sys/mutex.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 void    lsi64854_reset(struct lsi64854_softc *);
   90 int     lsi64854_setup(struct lsi64854_softc *, caddr_t *, size_t *, int,
   91             size_t *);
   92 int     lsi64854_setup_pp(struct lsi64854_softc *, caddr_t *, size_t *, int,
   93             size_t *);
   94 
   95 #ifdef DEBUG
   96 #define LDB_SCSI        1
   97 #define LDB_ENET        2
   98 #define LDB_PP          4
   99 #define LDB_ANY         0xff
  100 int lsi64854debug = 0;
  101 #define DPRINTF(a,x) do { if (lsi64854debug & (a)) printf x ; } while (0)
  102 #else
  103 #define DPRINTF(a,x)
  104 #endif
  105 
  106 #define MAX_DMA_SZ      (16*1024*1024)
  107 
  108 /*
  109  * Finish attaching this DMA device.
  110  * Front-end must fill in these fields:
  111  *      sc_regs
  112  *      sc_burst
  113  *      sc_channel (one of SCSI, ENET, PP)
  114  *      sc_client (one of SCSI, ENET, PP `soft_c' pointers)
  115  */
  116 int
  117 lsi64854_attach(struct lsi64854_softc *sc)
  118 {
  119         uint32_t csr;
  120         int error;
  121 
  122         /* Indirect functions */
  123         switch (sc->sc_channel) {
  124         case L64854_CHANNEL_SCSI:
  125                 sc->intr = lsi64854_scsi_intr;
  126                 sc->setup = lsi64854_setup;
  127                 break;
  128         case L64854_CHANNEL_ENET:
  129                 sc->intr = lsi64854_enet_intr;
  130                 break;
  131         case L64854_CHANNEL_PP:
  132                 sc->setup = lsi64854_setup_pp;
  133                 break;
  134         default:
  135                 device_printf(sc->sc_dev, "unknown channel\n");
  136         }
  137         sc->reset = lsi64854_reset;
  138 
  139         /* Allocate a dmamap */
  140         error = bus_dma_tag_create(
  141             sc->sc_parent_dmat,         /* parent */
  142             1, 0,                       /* alignment, boundary */
  143             BUS_SPACE_MAXADDR,          /* lowaddr */
  144             BUS_SPACE_MAXADDR,          /* highaddr */
  145             NULL, NULL,                 /* filter, filterarg */
  146             MAX_DMA_SZ,                 /* maxsize */
  147             1,                          /* nsegments */
  148             MAX_DMA_SZ,                 /* maxsegsize */
  149             BUS_DMA_ALLOCNOW,           /* flags */
  150             NULL, NULL,                 /* lockfunc, lockarg */
  151             &sc->sc_buffer_dmat);
  152         if (error != 0) {
  153                 device_printf(sc->sc_dev, "cannot allocate buffer DMA tag\n");
  154                 return (error);
  155         }
  156 
  157         error = bus_dmamap_create(sc->sc_buffer_dmat, 0, &sc->sc_dmamap);
  158         if (error != 0) {
  159                 device_printf(sc->sc_dev, "DMA map create failed\n");
  160                 bus_dma_tag_destroy(sc->sc_buffer_dmat);
  161                 return (error);
  162         }
  163 
  164         csr = L64854_GCSR(sc);
  165         sc->sc_rev = csr & L64854_DEVID;
  166         if (sc->sc_rev == DMAREV_HME)
  167                 return (0);
  168         device_printf(sc->sc_dev, "DMA rev. ");
  169         switch (sc->sc_rev) {
  170         case DMAREV_0:
  171                 printf("");
  172                 break;
  173         case DMAREV_ESC:
  174                 printf("ESC");
  175                 break;
  176         case DMAREV_1:
  177                 printf("1");
  178                 break;
  179         case DMAREV_PLUS:
  180                 printf("1+");
  181                 break;
  182         case DMAREV_2:
  183                 printf("2");
  184                 break;
  185         default:
  186                 printf("unknown (0x%x)", sc->sc_rev);
  187         }
  188 
  189         DPRINTF(LDB_ANY, (", burst 0x%x, csr 0x%x", sc->sc_burst, csr));
  190         printf("\n");
  191 
  192         return (0);
  193 }
  194 
  195 int
  196 lsi64854_detach(struct lsi64854_softc *sc)
  197 {
  198 
  199         if (sc->setup)
  200                 bus_dmamap_unload(sc->sc_buffer_dmat, sc->sc_dmamap);
  201         bus_dmamap_destroy(sc->sc_buffer_dmat, sc->sc_dmamap);
  202         bus_dma_tag_destroy(sc->sc_buffer_dmat);
  203 
  204         return (0);
  205 }
  206 
  207 /*
  208  * DMAWAIT  waits while condition is true
  209  */
  210 #define DMAWAIT(SC, COND, MSG, DONTPANIC) do if (COND) {                \
  211         int count = 500000;                                             \
  212         while ((COND) && --count > 0) DELAY(1);                         \
  213         if (count == 0) {                                               \
  214                 printf("%s: line %d: CSR = 0x%lx\n", __FILE__, __LINE__, \
  215                         (u_long)L64854_GCSR(SC));                       \
  216                 if (DONTPANIC)                                          \
  217                         printf(MSG);                                    \
  218                 else                                                    \
  219                         panic(MSG);                                     \
  220         }                                                               \
  221 } while (0)
  222 
  223 #define DMA_DRAIN(sc, dontpanic) do {                                   \
  224         uint32_t csr;                                                   \
  225         /*                                                              \
  226          * DMA rev0 & rev1: we are not allowed to touch the DMA "flush" \
  227          *     and "drain" bits while it is still thinking about a      \
  228          *     request.                                                 \
  229          * other revs: D_ESC_R_PEND bit reads as 0                      \
  230          */                                                             \
  231         DMAWAIT(sc, L64854_GCSR(sc) & D_ESC_R_PEND, "R_PEND", dontpanic);\
  232         if (sc->sc_rev != DMAREV_HME) {                                 \
  233                 /*                                                      \
  234                  * Select drain bit based on revision                   \
  235                  * also clears errors and D_TC flag                     \
  236                  */                                                     \
  237                 csr = L64854_GCSR(sc);                                  \
  238                 if (sc->sc_rev == DMAREV_1 || sc->sc_rev == DMAREV_0)   \
  239                         csr |= D_ESC_DRAIN;                             \
  240                 else                                                    \
  241                         csr |= L64854_INVALIDATE;                       \
  242                                                                         \
  243                 L64854_SCSR(sc,csr);                                    \
  244         }                                                               \
  245         /*                                                              \
  246          * Wait for draining to finish                                  \
  247          * rev0 & rev1 call this PACKCNT                                \
  248          */                                                             \
  249         DMAWAIT(sc, L64854_GCSR(sc) & L64854_DRAINING, "DRAINING", dontpanic);\
  250 } while(0)
  251 
  252 #define DMA_FLUSH(sc, dontpanic) do {                                   \
  253         uint32_t csr;                                                   \
  254         /*                                                              \
  255          * DMA rev0 & rev1: we are not allowed to touch the DMA "flush" \
  256          *     and "drain" bits while it is still thinking about a      \
  257          *     request.                                                 \
  258          * other revs: D_ESC_R_PEND bit reads as 0                      \
  259          */                                                             \
  260         DMAWAIT(sc, L64854_GCSR(sc) & D_ESC_R_PEND, "R_PEND", dontpanic);\
  261         csr = L64854_GCSR(sc);                                  \
  262         csr &= ~(L64854_WRITE|L64854_EN_DMA); /* no-ops on ENET */      \
  263         csr |= L64854_INVALIDATE;               /* XXX FAS ? */         \
  264         L64854_SCSR(sc,csr);                                            \
  265 } while(0)
  266 
  267 void
  268 lsi64854_reset(struct lsi64854_softc *sc)
  269 {
  270         uint32_t csr;
  271 
  272         DMA_FLUSH(sc, 1);
  273         csr = L64854_GCSR(sc);
  274 
  275         DPRINTF(LDB_ANY, ("%s: csr 0x%x\n", __func__, csr));
  276 
  277         /*
  278          * XXX is sync needed?
  279         if (sc->sc_dmamap->dm_nsegs > 0)
  280                 bus_dmamap_unload(sc->sc_buffer_dmat, sc->sc_dmamap);
  281          */
  282 
  283         if (sc->sc_rev == DMAREV_HME)
  284                 L64854_SCSR(sc, csr | D_HW_RESET_FAS366);
  285 
  286         csr |= L64854_RESET;            /* reset DMA */
  287         L64854_SCSR(sc, csr);
  288         DELAY(200);                     /* > 10 Sbus clocks(?) */
  289 
  290         /*DMAWAIT1(sc); why was this here? */
  291         csr = L64854_GCSR(sc);
  292         csr &= ~L64854_RESET;           /* de-assert reset line */
  293         L64854_SCSR(sc, csr);
  294         DELAY(5);                       /* allow a few ticks to settle */
  295 
  296         csr = L64854_GCSR(sc);
  297         csr |= L64854_INT_EN;           /* enable interrupts */
  298         if (sc->sc_rev > DMAREV_1 && sc->sc_channel == L64854_CHANNEL_SCSI) {
  299                 if (sc->sc_rev == DMAREV_HME)
  300                         csr |= D_TWO_CYCLE;
  301                 else
  302                         csr |= D_FASTER;
  303         }
  304 
  305         /* Set burst */
  306         switch (sc->sc_rev) {
  307         case DMAREV_HME:
  308         case DMAREV_2:
  309                 csr &= ~L64854_BURST_SIZE;
  310                 if (sc->sc_burst == 32)
  311                         csr |= L64854_BURST_32;
  312                 else if (sc->sc_burst == 16)
  313                         csr |= L64854_BURST_16;
  314                 else
  315                         csr |= L64854_BURST_0;
  316                 break;
  317         case DMAREV_ESC:
  318                 csr |= D_ESC_AUTODRAIN; /* Auto-drain */
  319                 if (sc->sc_burst == 32)
  320                         csr &= ~D_ESC_BURST;
  321                 else
  322                         csr |= D_ESC_BURST;
  323                 break;
  324         default:
  325                 break;
  326         }
  327         L64854_SCSR(sc, csr);
  328 
  329         if (sc->sc_rev == DMAREV_HME) {
  330                 bus_space_write_4(sc->sc_regt, sc->sc_regh, L64854_REG_ADDR, 0);
  331                 sc->sc_dmactl = csr;
  332         }
  333         sc->sc_active = 0;
  334 
  335         DPRINTF(LDB_ANY, ("%s: done, csr 0x%x\n", __func__, csr));
  336 }
  337 
  338 static void
  339 lsi64854_map_scsi(void *arg, bus_dma_segment_t *segs, int nseg, int error)
  340 {
  341         struct lsi64854_softc *sc;
  342 
  343         sc = (struct lsi64854_softc *)arg;
  344 
  345         if (nseg != 1)
  346                 panic("%s: cannot map %d segments\n", __func__, nseg);
  347 
  348         bus_dmamap_sync(sc->sc_buffer_dmat, sc->sc_dmamap,
  349             sc->sc_datain ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
  350         bus_space_write_4(sc->sc_regt, sc->sc_regh, L64854_REG_ADDR,
  351             segs[0].ds_addr);
  352 }
  353 
  354 #define DMAMAX(a)       (MAX_DMA_SZ - ((a) & (MAX_DMA_SZ-1)))
  355 /*
  356  * setup a DMA transfer
  357  */
  358 int
  359 lsi64854_setup(struct lsi64854_softc *sc, caddr_t *addr, size_t *len,
  360     int datain, size_t *dmasize)
  361 {
  362         uint32_t csr;
  363 
  364         DMA_FLUSH(sc, 0);
  365 
  366 #if 0
  367         DMACSR(sc) &= ~D_INT_EN;
  368 #endif
  369         sc->sc_dmaaddr = addr;
  370         sc->sc_dmalen = len;
  371         sc->sc_datain = datain;
  372 
  373         /*
  374          * The rules say we cannot transfer more than the limit
  375          * of this DMA chip (64k for old and 16Mb for new),
  376          * and we cannot cross a 16Mb boundary.
  377          */
  378         *dmasize = sc->sc_dmasize =
  379             ulmin(*dmasize, DMAMAX((size_t) *sc->sc_dmaaddr));
  380 
  381         DPRINTF(LDB_ANY, ("%s: dmasize=%ld\n", __func__, (long)sc->sc_dmasize));
  382 
  383         /*
  384          * XXX what length?
  385          */
  386         if (sc->sc_rev == DMAREV_HME) {
  387                 L64854_SCSR(sc, sc->sc_dmactl | L64854_RESET);
  388                 L64854_SCSR(sc, sc->sc_dmactl);
  389 
  390                 bus_space_write_4(sc->sc_regt, sc->sc_regh, L64854_REG_CNT,
  391                     *dmasize);
  392         }
  393 
  394         /* Program the DMA address */
  395         if (sc->sc_dmasize)
  396                 if (bus_dmamap_load(sc->sc_buffer_dmat, sc->sc_dmamap,
  397                     *sc->sc_dmaaddr, sc->sc_dmasize, lsi64854_map_scsi, sc, 0))
  398                         panic("%s: cannot allocate DVMA address", __func__);
  399 
  400         if (sc->sc_rev == DMAREV_ESC) {
  401                 /* DMA ESC chip bug work-around */
  402                 long bcnt = sc->sc_dmasize;
  403                 long eaddr = bcnt + (long)*sc->sc_dmaaddr;
  404                 if ((eaddr & PAGE_MASK_8K) != 0)
  405                         bcnt = roundup(bcnt, PAGE_SIZE_8K);
  406                 bus_space_write_4(sc->sc_regt, sc->sc_regh, L64854_REG_CNT,
  407                     bcnt);
  408         }
  409 
  410         /* Setup DMA control register */
  411         csr = L64854_GCSR(sc);
  412 
  413         if (datain)
  414                 csr |= L64854_WRITE;
  415         else
  416                 csr &= ~L64854_WRITE;
  417         csr |= L64854_INT_EN;
  418 
  419         if (sc->sc_rev == DMAREV_HME)
  420                 csr |= (D_DSBL_SCSI_DRN | D_EN_DMA);
  421 
  422         L64854_SCSR(sc, csr);
  423 
  424         return (0);
  425 }
  426 
  427 /*
  428  * Pseudo (chained) interrupt from the esp driver to kick the
  429  * current running DMA transfer. Called from ncr53c9x_intr()
  430  * for now.
  431  *
  432  * return 1 if it was a DMA continue.
  433  */
  434 int
  435 lsi64854_scsi_intr(void *arg)
  436 {
  437         struct lsi64854_softc *sc = arg;
  438         struct ncr53c9x_softc *nsc = sc->sc_client;
  439         int trans, resid;
  440         uint32_t csr;
  441 
  442         csr = L64854_GCSR(sc);
  443 
  444         DPRINTF(LDB_SCSI, ("%s: addr 0x%x, csr %b\n", __func__,
  445              bus_space_read_4(sc->sc_regt, sc->sc_regh, L64854_REG_ADDR), csr,
  446              DDMACSR_BITS));
  447 
  448         if (csr & (D_ERR_PEND|D_SLAVE_ERR)) {
  449                 device_printf(sc->sc_dev, "error: csr=%b\n", csr, DDMACSR_BITS);
  450                 csr &= ~D_EN_DMA;       /* Stop DMA */
  451                 /* Invalidate the queue; SLAVE_ERR bit is write-to-clear */
  452                 csr |= D_INVALIDATE|D_SLAVE_ERR;
  453                 L64854_SCSR(sc, csr);
  454                 return (-1);
  455         }
  456 
  457         /* This is an "assertion" :) */
  458         if (sc->sc_active == 0)
  459                 panic("%s: DMA wasn't active", __func__);
  460 
  461         DMA_DRAIN(sc, 0);
  462 
  463         /* DMA has stopped */
  464         csr &= ~D_EN_DMA;
  465         L64854_SCSR(sc, csr);
  466         sc->sc_active = 0;
  467 
  468         if (sc->sc_dmasize == 0) {
  469                 /* A "Transfer Pad" operation completed */
  470                 DPRINTF(LDB_SCSI, ("%s: discarded %d bytes (tcl=%d, tcm=%d)\n",
  471                     __func__, NCR_READ_REG(nsc, NCR_TCL) |
  472                     (NCR_READ_REG(nsc, NCR_TCM) << 8),
  473                     NCR_READ_REG(nsc, NCR_TCL), NCR_READ_REG(nsc, NCR_TCM)));
  474                 return (0);
  475         }
  476 
  477         resid = 0;
  478         /*
  479          * If a transfer onto the SCSI bus gets interrupted by the device
  480          * (e.g. for a SAVEPOINTER message), the data in the FIFO counts
  481          * as residual since the NCR53C9X counter registers get decremented
  482          * as bytes are clocked into the FIFO.
  483          */
  484         if (!(csr & D_WRITE) &&
  485             (resid = (NCR_READ_REG(nsc, NCR_FFLAG) & NCRFIFO_FF)) != 0) {
  486                 DPRINTF(LDB_SCSI, ("%s: empty esp FIFO of %d ", __func__,
  487                     resid));
  488                 if (nsc->sc_rev == NCR_VARIANT_FAS366 &&
  489                     (NCR_READ_REG(nsc, NCR_CFG3) & NCRFASCFG3_EWIDE))
  490                         resid <<= 1;
  491         }
  492 
  493         if ((nsc->sc_espstat & NCRSTAT_TC) == 0) {
  494                 /*
  495                  * `Terminal count' is off, so read the residue
  496                  * out of the NCR53C9X counter registers.
  497                  */
  498                 resid += (NCR_READ_REG(nsc, NCR_TCL) |
  499                     (NCR_READ_REG(nsc, NCR_TCM) << 8) |
  500                     ((nsc->sc_cfg2 & NCRCFG2_FE) ?
  501                     (NCR_READ_REG(nsc, NCR_TCH) << 16) : 0));
  502 
  503                 if (resid == 0 && sc->sc_dmasize == 65536 &&
  504                     (nsc->sc_cfg2 & NCRCFG2_FE) == 0)
  505                         /* A transfer of 64K is encoded as `TCL=TCM=0' */
  506                         resid = 65536;
  507         }
  508 
  509         trans = sc->sc_dmasize - resid;
  510         if (trans < 0) {                        /* transfered < 0? */
  511 #if 0
  512                 /*
  513                  * This situation can happen in perfectly normal operation
  514                  * if the ESP is reselected while using DMA to select
  515                  * another target.  As such, don't print the warning.
  516                  */
  517                 device_printf(sc->sc_dev, "xfer (%d) > req (%d)\n", trans,
  518                     sc->sc_dmasize);
  519 #endif
  520                 trans = sc->sc_dmasize;
  521         }
  522 
  523         DPRINTF(LDB_SCSI, ("%s: tcl=%d, tcm=%d, tch=%d; trans=%d, resid=%d\n",
  524             __func__, NCR_READ_REG(nsc, NCR_TCL), NCR_READ_REG(nsc, NCR_TCM),
  525             (nsc->sc_cfg2 & NCRCFG2_FE) ? NCR_READ_REG(nsc, NCR_TCH) : 0,
  526             trans, resid));
  527 
  528 #if 0 /* XXX */
  529         if (sc->sc_dmamap->dm_nsegs > 0) {
  530                 bus_dmamap_sync(sc->sc_buffer_dmat, sc->sc_dmamap,
  531                     (csr & D_WRITE) != 0 ? BUS_DMASYNC_POSTREAD :
  532                     BUS_DMASYNC_POSTWRITE);
  533                 bus_dmamap_unload(sc->sc_buffer_dmat, sc->sc_dmamap);
  534         }
  535 #endif
  536 
  537         *sc->sc_dmalen -= trans;
  538         *sc->sc_dmaaddr += trans;
  539 
  540 #if 0   /* this is not normal operation just yet */
  541         if (*sc->sc_dmalen == 0 || nsc->sc_phase != nsc->sc_prevphase)
  542                 return (0);
  543 
  544         /* and again */
  545         dma_start(sc, sc->sc_dmaaddr, sc->sc_dmalen, DMACSR(sc) & D_WRITE);
  546         return (1);
  547 #endif
  548         return (0);
  549 }
  550 
  551 /*
  552  * Pseudo (chained) interrupt to le driver to handle DMA errors.
  553  */
  554 int
  555 lsi64854_enet_intr(void *arg)
  556 {
  557         struct lsi64854_softc *sc = arg;
  558         uint32_t csr;
  559         static int dodrain = 0;
  560         int rv;
  561 
  562         csr = L64854_GCSR(sc);
  563 
  564         /* If the DMA logic shows an interrupt, claim it */
  565         rv = ((csr & E_INT_PEND) != 0) ? 1 : 0;
  566 
  567         if (csr & (E_ERR_PEND|E_SLAVE_ERR)) {
  568                 device_printf(sc->sc_dev, "error: csr=%b\n", csr, EDMACSR_BITS);
  569                 csr &= ~L64854_EN_DMA;  /* Stop DMA */
  570                 /* Invalidate the queue; SLAVE_ERR bit is write-to-clear */
  571                 csr |= E_INVALIDATE|E_SLAVE_ERR;
  572                 L64854_SCSR(sc, csr);
  573                 DMA_RESET(sc);
  574                 dodrain = 1;
  575                 return (1);
  576         }
  577 
  578         if (dodrain) {  /* XXX - is this necessary with D_DSBL_WRINVAL on? */
  579                 int i = 10;
  580                 csr |= E_DRAIN;
  581                 L64854_SCSR(sc, csr);
  582                 while (i-- > 0 && (L64854_GCSR(sc) & D_DRAINING))
  583                         DELAY(1);
  584         }
  585 
  586         (*sc->sc_intrchain)(sc->sc_intrchainarg);
  587 
  588         return (rv);
  589 }
  590 
  591 static void
  592 lsi64854_map_pp(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
  593 {
  594         struct lsi64854_softc *sc;
  595 
  596         sc = (struct lsi64854_softc *)arg;
  597 
  598         if (nsegs != 1)
  599                 panic("%s: cannot map %d segments\n", __func__, nsegs);
  600 
  601         bus_dmamap_sync(sc->sc_buffer_dmat, sc->sc_dmamap, sc->sc_datain ?
  602             BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
  603         bus_space_write_4(sc->sc_regt, sc->sc_regh, L64854_REG_ADDR,
  604             segs[0].ds_addr);
  605 
  606         bus_space_write_4(sc->sc_regt, sc->sc_regh, L64854_REG_CNT,
  607             sc->sc_dmasize);
  608 }
  609 
  610 /*
  611  * setup a DMA transfer
  612  */
  613 int
  614 lsi64854_setup_pp(struct lsi64854_softc *sc, caddr_t *addr, size_t *len,
  615     int datain, size_t *dmasize)
  616 {
  617         uint32_t csr;
  618 
  619         DMA_FLUSH(sc, 0);
  620 
  621         sc->sc_dmaaddr = addr;
  622         sc->sc_dmalen = len;
  623         sc->sc_datain = datain;
  624 
  625         DPRINTF(LDB_PP, ("%s: pp start %ld@%p,%d\n", __func__,
  626             (long)*sc->sc_dmalen, *sc->sc_dmaaddr, datain ? 1 : 0));
  627 
  628         /*
  629          * the rules say we cannot transfer more than the limit
  630          * of this DMA chip (64k for old and 16Mb for new),
  631          * and we cannot cross a 16Mb boundary.
  632          */
  633         *dmasize = sc->sc_dmasize =
  634             ulmin(*dmasize, DMAMAX((size_t) *sc->sc_dmaaddr));
  635 
  636         DPRINTF(LDB_PP, ("%s: dmasize=%ld\n", __func__, (long)sc->sc_dmasize));
  637 
  638         /* Program the DMA address */
  639         if (sc->sc_dmasize)
  640                 if (bus_dmamap_load(sc->sc_buffer_dmat, sc->sc_dmamap,
  641                     *sc->sc_dmaaddr, sc->sc_dmasize, lsi64854_map_pp, sc, 0))
  642                         panic("%s: pp cannot allocate DVMA address", __func__);
  643 
  644         /* Setup DMA control register */
  645         csr = L64854_GCSR(sc);
  646         csr &= ~L64854_BURST_SIZE;
  647         if (sc->sc_burst == 32)
  648                 csr |= L64854_BURST_32;
  649         else if (sc->sc_burst == 16)
  650                 csr |= L64854_BURST_16;
  651         else
  652                 csr |= L64854_BURST_0;
  653         csr |= P_EN_DMA|P_INT_EN|P_EN_CNT;
  654 #if 0
  655         /* This bit is read-only in PP csr register */
  656         if (datain)
  657                 csr |= P_WRITE;
  658         else
  659                 csr &= ~P_WRITE;
  660 #endif
  661         L64854_SCSR(sc, csr);
  662 
  663         return (0);
  664 }
  665 
  666 /*
  667  * Parallel port DMA interrupt.
  668  */
  669 int
  670 lsi64854_pp_intr(void *arg)
  671 {
  672         struct lsi64854_softc *sc = arg;
  673         int ret, trans, resid = 0;
  674         uint32_t csr;
  675 
  676         csr = L64854_GCSR(sc);
  677 
  678         DPRINTF(LDB_PP, ("%s: addr 0x%x, csr %b\n", __func__,
  679             bus_space_read_4(sc->sc_regt, sc->sc_regh, L64854_REG_ADDR), csr,
  680             PDMACSR_BITS));
  681 
  682         if (csr & (P_ERR_PEND|P_SLAVE_ERR)) {
  683                 resid = bus_space_read_4(sc->sc_regt, sc->sc_regh,
  684                     L64854_REG_CNT);
  685                 device_printf(sc->sc_dev, "error: resid %d csr=%b\n", resid,
  686                     csr, PDMACSR_BITS);
  687                 csr &= ~P_EN_DMA;       /* Stop DMA */
  688                 /* Invalidate the queue; SLAVE_ERR bit is write-to-clear */
  689                 csr |= P_INVALIDATE|P_SLAVE_ERR;
  690                 L64854_SCSR(sc, csr);
  691                 return (1);
  692         }
  693 
  694         ret = (csr & P_INT_PEND) != 0;
  695 
  696         if (sc->sc_active != 0) {
  697                 DMA_DRAIN(sc, 0);
  698                 resid = bus_space_read_4(sc->sc_regt, sc->sc_regh,
  699                     L64854_REG_CNT);
  700         }
  701 
  702         /* DMA has stopped */
  703         csr &= ~D_EN_DMA;
  704         L64854_SCSR(sc, csr);
  705         sc->sc_active = 0;
  706 
  707         trans = sc->sc_dmasize - resid;
  708         if (trans < 0)                          /* transfered < 0? */
  709                 trans = sc->sc_dmasize;
  710         *sc->sc_dmalen -= trans;
  711         *sc->sc_dmaaddr += trans;
  712 
  713 #if 0 /* XXX */
  714         if (sc->sc_dmamap->dm_nsegs > 0) {
  715                 bus_dmamap_sync(sc->sc_buffer_dmat, sc->sc_dmamap,
  716                     (csr & D_WRITE) != 0 ? BUS_DMASYNC_POSTREAD :
  717                     BUS_DMASYNC_POSTWRITE);
  718                 bus_dmamap_unload(sc->sc_buffer_dmat, sc->sc_dmamap);
  719         }
  720 #endif
  721 
  722         return (ret != 0);
  723 }

Cache object: 189283399d1b58f7f5c8611b603d2ec8


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