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/x86/x86/busdma_machdep.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  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 1997, 1998 Justin T. Gibbs.
    5  * Copyright (c) 2013 The FreeBSD Foundation
    6  * All rights reserved.
    7  *
    8  * This software was developed by Konstantin Belousov <kib@FreeBSD.org>
    9  * under sponsorship from the FreeBSD Foundation.
   10  *
   11  * Redistribution and use in source and binary forms, with or without
   12  * modification, are permitted provided that the following conditions
   13  * are met:
   14  * 1. Redistributions of source code must retain the above copyright
   15  *    notice, this list of conditions, and the following disclaimer,
   16  *    without modification, immediately at the beginning of the file.
   17  * 2. The name of the author may not be used to endorse or promote products
   18  *    derived from this software without specific prior written permission.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   23  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
   24  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   30  * SUCH DAMAGE.
   31  */
   32 
   33 #include <sys/cdefs.h>
   34 __FBSDID("$FreeBSD$");
   35 
   36 #include "opt_acpi.h"
   37 
   38 #include <sys/param.h>
   39 #include <sys/systm.h>
   40 #include <sys/malloc.h>
   41 #include <sys/bus.h>
   42 #include <sys/kernel.h>
   43 #include <sys/ktr.h>
   44 #include <sys/lock.h>
   45 #include <sys/memdesc.h>
   46 #include <sys/mutex.h>
   47 #include <sys/uio.h>
   48 #include <sys/vmmeter.h>
   49 #include <vm/vm.h>
   50 #include <vm/vm_extern.h>
   51 #include <vm/vm_param.h>
   52 #include <vm/vm_page.h>
   53 #include <vm/vm_phys.h>
   54 #include <vm/pmap.h>
   55 #include <machine/bus.h>
   56 #include <x86/include/busdma_impl.h>
   57 
   58 /*
   59  * Return true if a match is made.
   60  *
   61  * To find a match walk the chain of bus_dma_tag_t's looking for 'paddr'.
   62  *
   63  * If paddr is within the bounds of the dma tag then call the filter callback
   64  * to check for a match, if there is no filter callback then assume a match.
   65  */
   66 int
   67 bus_dma_run_filter(struct bus_dma_tag_common *tc, vm_paddr_t paddr)
   68 {
   69         int retval;
   70 
   71         retval = 0;
   72         do {
   73                 if ((paddr >= BUS_SPACE_MAXADDR ||
   74                     (paddr > tc->lowaddr && paddr <= tc->highaddr) ||
   75                     !vm_addr_align_ok(paddr, tc->alignment)) &&
   76                     (tc->filter == NULL ||
   77                     (*tc->filter)(tc->filterarg, paddr) != 0))
   78                         retval = 1;
   79 
   80                 tc = tc->parent;                
   81         } while (retval == 0 && tc != NULL);
   82         return (retval);
   83 }
   84 
   85 int
   86 common_bus_dma_tag_create(struct bus_dma_tag_common *parent,
   87     bus_size_t alignment, bus_addr_t boundary, bus_addr_t lowaddr,
   88     bus_addr_t highaddr, bus_dma_filter_t *filter, void *filterarg,
   89     bus_size_t maxsize, int nsegments, bus_size_t maxsegsz, int flags,
   90     bus_dma_lock_t *lockfunc, void *lockfuncarg, size_t sz, void **dmat)
   91 {
   92         void *newtag;
   93         struct bus_dma_tag_common *common;
   94 
   95         KASSERT(sz >= sizeof(struct bus_dma_tag_common), ("sz"));
   96         /* Basic sanity checking */
   97         if (boundary != 0 && boundary < maxsegsz)
   98                 maxsegsz = boundary;
   99         if (maxsegsz == 0)
  100                 return (EINVAL);
  101         /* Return a NULL tag on failure */
  102         *dmat = NULL;
  103 
  104         newtag = malloc(sz, M_DEVBUF, M_ZERO | M_NOWAIT);
  105         if (newtag == NULL) {
  106                 CTR4(KTR_BUSDMA, "%s returned tag %p tag flags 0x%x error %d",
  107                     __func__, newtag, 0, ENOMEM);
  108                 return (ENOMEM);
  109         }
  110 
  111         common = newtag;
  112         common->impl = &bus_dma_bounce_impl;
  113         common->parent = parent;
  114         common->alignment = alignment;
  115         common->boundary = boundary;
  116         common->lowaddr = trunc_page((vm_paddr_t)lowaddr) + (PAGE_SIZE - 1);
  117         common->highaddr = trunc_page((vm_paddr_t)highaddr) + (PAGE_SIZE - 1);
  118         common->filter = filter;
  119         common->filterarg = filterarg;
  120         common->maxsize = maxsize;
  121         common->nsegments = nsegments;
  122         common->maxsegsz = maxsegsz;
  123         common->flags = flags;
  124         common->ref_count = 1; /* Count ourself */
  125         if (lockfunc != NULL) {
  126                 common->lockfunc = lockfunc;
  127                 common->lockfuncarg = lockfuncarg;
  128         } else {
  129                 common->lockfunc = _busdma_dflt_lock;
  130                 common->lockfuncarg = NULL;
  131         }
  132 
  133         /* Take into account any restrictions imposed by our parent tag */
  134         if (parent != NULL) {
  135                 common->impl = parent->impl;
  136                 common->lowaddr = MIN(parent->lowaddr, common->lowaddr);
  137                 common->highaddr = MAX(parent->highaddr, common->highaddr);
  138                 if (common->boundary == 0)
  139                         common->boundary = parent->boundary;
  140                 else if (parent->boundary != 0) {
  141                         common->boundary = MIN(parent->boundary,
  142                             common->boundary);
  143                 }
  144                 if (common->filter == NULL) {
  145                         /*
  146                          * Short circuit looking at our parent directly
  147                          * since we have encapsulated all of its information
  148                          */
  149                         common->filter = parent->filter;
  150                         common->filterarg = parent->filterarg;
  151                         common->parent = parent->parent;
  152                 }
  153                 common->domain = parent->domain;
  154                 atomic_add_int(&parent->ref_count, 1);
  155         }
  156         common->domain = vm_phys_domain_match(common->domain, 0ul,
  157             common->lowaddr);
  158         *dmat = common;
  159         return (0);
  160 }
  161 
  162 int
  163 bus_dma_tag_set_domain(bus_dma_tag_t dmat, int domain)
  164 {
  165         struct bus_dma_tag_common *tc;
  166 
  167         tc = (struct bus_dma_tag_common *)dmat;
  168         domain = vm_phys_domain_match(domain, 0ul, tc->lowaddr);
  169         /* Only call the callback if it changes. */
  170         if (domain == tc->domain)
  171                 return (0);
  172         tc->domain = domain;
  173         return (tc->impl->tag_set_domain(dmat));
  174 }
  175 
  176 /*
  177  * Allocate a device specific dma_tag.
  178  */
  179 int
  180 bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignment,
  181     bus_addr_t boundary, bus_addr_t lowaddr, bus_addr_t highaddr,
  182     bus_dma_filter_t *filter, void *filterarg, bus_size_t maxsize,
  183     int nsegments, bus_size_t maxsegsz, int flags, bus_dma_lock_t *lockfunc,
  184     void *lockfuncarg, bus_dma_tag_t *dmat)
  185 {
  186         struct bus_dma_tag_common *tc;
  187         int error;
  188 
  189         if (parent == NULL) {
  190                 error = bus_dma_bounce_impl.tag_create(parent, alignment,
  191                     boundary, lowaddr, highaddr, filter, filterarg, maxsize,
  192                     nsegments, maxsegsz, flags, lockfunc, lockfuncarg, dmat);
  193         } else {
  194                 tc = (struct bus_dma_tag_common *)parent;
  195                 error = tc->impl->tag_create(parent, alignment,
  196                     boundary, lowaddr, highaddr, filter, filterarg, maxsize,
  197                     nsegments, maxsegsz, flags, lockfunc, lockfuncarg, dmat);
  198         }
  199         return (error);
  200 }
  201 
  202 void
  203 bus_dma_template_clone(bus_dma_template_t *t, bus_dma_tag_t dmat)
  204 {
  205         struct bus_dma_tag_common *common;
  206 
  207         if (t == NULL || dmat == NULL)
  208                 return;
  209 
  210         common = (struct bus_dma_tag_common *)dmat;
  211 
  212         t->parent = (bus_dma_tag_t)common->parent;
  213         t->alignment = common->alignment;
  214         t->boundary = common->boundary;
  215         t->lowaddr = common->lowaddr;
  216         t->highaddr = common->highaddr;
  217         t->maxsize = common->maxsize;
  218         t->nsegments = common->nsegments;
  219         t->maxsegsize = common->maxsegsz;
  220         t->flags = common->flags;
  221         t->lockfunc = common->lockfunc;
  222         t->lockfuncarg = common->lockfuncarg;
  223 }
  224 
  225 int
  226 bus_dma_tag_destroy(bus_dma_tag_t dmat)
  227 {
  228         struct bus_dma_tag_common *tc;
  229 
  230         tc = (struct bus_dma_tag_common *)dmat;
  231         return (tc->impl->tag_destroy(dmat));
  232 }

Cache object: 83bc98704d0dca320bcb3de4aa655bb9


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