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

Cache object: af6f6902dae76316aa931fafad3fcda7


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