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/kern/subr_busdma.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) 2009 The DragonFly Project.  All rights reserved.
    3  *
    4  * This code is derived from software contributed to The DragonFly Project
    5  * by Sepherosa Ziehau <sepherosa@gmail.com>
    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  *
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in
   15  *    the documentation and/or other materials provided with the
   16  *    distribution.
   17  * 3. Neither the name of The DragonFly Project nor the names of its
   18  *    contributors may be used to endorse or promote products derived
   19  *    from this software without specific, prior written permission.
   20  *
   21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
   24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
   25  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
   26  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
   27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
   29  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   31  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   32  * SUCH DAMAGE.
   33  */
   34 
   35 #include <sys/param.h>
   36 #include <sys/systm.h>
   37 #include <sys/bus_dma.h>
   38 #include <sys/mbuf.h>
   39 
   40 static void
   41 _bus_dmamem_coherent_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error)
   42 {
   43         bus_addr_t *addr = arg;
   44 
   45         if (error)
   46                 return;
   47 
   48         KASSERT(nseg == 1, ("too many DMA segments, %d should be 1", nseg));
   49         *addr = segs->ds_addr;
   50 }
   51 
   52 int
   53 bus_dmamem_coherent(bus_dma_tag_t parent,
   54                     bus_size_t alignment, bus_size_t boundary,
   55                     bus_addr_t lowaddr, bus_addr_t highaddr,
   56                     bus_size_t maxsize, int flags,
   57                     bus_dmamem_t *dmem)
   58 {
   59         int error;
   60 
   61         bzero(dmem, sizeof(*dmem));
   62 
   63         error = bus_dma_tag_create(parent, alignment, boundary,
   64                                    lowaddr, highaddr, NULL, NULL,
   65                                    maxsize, 1, maxsize, 0,
   66                                    &dmem->dmem_tag);
   67         if (error)
   68                 return error;
   69 
   70         error = bus_dmamem_alloc(dmem->dmem_tag, &dmem->dmem_addr,
   71                                  flags | BUS_DMA_COHERENT, &dmem->dmem_map);
   72         if (error) {
   73                 bus_dma_tag_destroy(dmem->dmem_tag);
   74                 bzero(dmem, sizeof(*dmem));
   75                 return error;
   76         }
   77 
   78         error = bus_dmamap_load(dmem->dmem_tag, dmem->dmem_map,
   79                                 dmem->dmem_addr, maxsize,
   80                                 _bus_dmamem_coherent_cb, &dmem->dmem_busaddr,
   81                                 flags & BUS_DMA_NOWAIT);
   82         if (error) {
   83                 if (error == EINPROGRESS) {
   84                         panic("DMA coherent memory loading is still "
   85                               "in progress\n");
   86                 }
   87                 bus_dmamem_free(dmem->dmem_tag, dmem->dmem_addr,
   88                                 dmem->dmem_map);
   89                 bus_dma_tag_destroy(dmem->dmem_tag);
   90                 bzero(dmem, sizeof(*dmem));
   91                 return error;
   92         }
   93         return 0;
   94 }
   95 
   96 void *
   97 bus_dmamem_coherent_any(bus_dma_tag_t parent,
   98                         bus_size_t alignment, bus_size_t size, int flags,
   99                         bus_dma_tag_t *dtag, bus_dmamap_t *dmap,
  100                         bus_addr_t *busaddr)
  101 {
  102         bus_dmamem_t dmem;
  103         int error;
  104 
  105         error = bus_dmamem_coherent(parent, alignment, 0,
  106                                     BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR,
  107                                     size, flags, &dmem);
  108         if (error)
  109                 return NULL;
  110 
  111         *dtag = dmem.dmem_tag;
  112         *dmap = dmem.dmem_map;
  113         *busaddr = dmem.dmem_busaddr;
  114 
  115         return dmem.dmem_addr;
  116 }
  117 
  118 int
  119 bus_dmamap_load_mbuf_defrag(bus_dma_tag_t dmat, bus_dmamap_t map,
  120                             struct mbuf **m_head,
  121                             bus_dma_segment_t *segs, int maxsegs,
  122                             int *nsegs, int flags)
  123 {
  124         struct mbuf *m = *m_head;
  125         int error;
  126 
  127         error = bus_dmamap_load_mbuf_segment(dmat, map, m,
  128                         segs, maxsegs, nsegs, flags);
  129         if (error == EFBIG) {
  130                 struct mbuf *m_new;
  131 
  132                 m_new = m_defrag(m, MB_DONTWAIT);
  133                 if (m_new == NULL)
  134                         return ENOBUFS;
  135                 else
  136                         *m_head = m = m_new;
  137 
  138                 error = bus_dmamap_load_mbuf_segment(dmat, map, m,
  139                                 segs, maxsegs, nsegs, flags);
  140         }
  141         return error;
  142 }

Cache object: 186a944419c5b1162d92a32e68aed0ea


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