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/dev/cardbus/rbus.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 /*      $NetBSD: rbus.c,v 1.19 2003/11/02 09:56:38 wiz Exp $    */
    2 /*
    3  * Copyright (c) 1999 and 2000
    4  *     HAYAKAWA Koichi.  All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  * 3. All advertising materials mentioning features or use of this software
   15  *    must display the following acknowledgement:
   16  *      This product includes software developed by HAYAKAWA Koichi.
   17  * 4. 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 ``AS IS'' AND ANY EXPRESS OR
   21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   23  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   25  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   30  */
   31 
   32 #include <sys/cdefs.h>
   33 __KERNEL_RCSID(0, "$NetBSD: rbus.c,v 1.19 2003/11/02 09:56:38 wiz Exp $");
   34 
   35 #include <sys/param.h>
   36 #include <sys/systm.h>
   37 #include <sys/device.h>
   38 #include <sys/malloc.h>
   39 #include <sys/extent.h>
   40 
   41 #include <machine/bus.h>
   42 
   43 #include <dev/cardbus/rbus.h>
   44 
   45 /* #define RBUS_DEBUG */
   46 
   47 #if defined RBUS_DEBUG
   48 #define STATIC
   49 #define DPRINTF(a) printf a
   50 #else
   51 #define STATIC static
   52 #define DPRINTF(a)
   53 #endif
   54 
   55 
   56 
   57 static rbus_tag_t rbus_new_body __P((bus_space_tag_t bt, rbus_tag_t parent,
   58                                     struct extent *ex, bus_addr_t start,
   59                                     bus_addr_t end, bus_addr_t offset,
   60                                     int flags));
   61 
   62 
   63 int
   64 rbus_space_alloc(rbt, addr, size, mask, align, flags, addrp, bshp)
   65         rbus_tag_t rbt;
   66         bus_addr_t addr;
   67         bus_size_t size;
   68         bus_addr_t mask, align;
   69         int flags;
   70         bus_addr_t *addrp;
   71         bus_space_handle_t *bshp;
   72 {
   73         return rbus_space_alloc_subregion(rbt, rbt->rb_start, rbt->rb_end,
   74             addr, size, mask, align, flags, addrp, bshp);
   75 }
   76 
   77 
   78 
   79 
   80 int
   81 rbus_space_alloc_subregion(rbt, substart, subend, addr, size, mask, align, flags, addrp, bshp)
   82         rbus_tag_t rbt;
   83         bus_addr_t addr;
   84         bus_addr_t substart;
   85         bus_addr_t subend;
   86         bus_size_t size;
   87         bus_addr_t mask, align;
   88         int flags;
   89         bus_addr_t *addrp;
   90         bus_space_handle_t *bshp;
   91 {
   92         bus_addr_t decodesize = mask + 1;
   93         bus_addr_t boundary, search_addr;
   94         int val;
   95         u_long result;
   96         int exflags = EX_FAST | EX_NOWAIT | EX_MALLOCOK;
   97 
   98         DPRINTF(("rbus_space_alloc: addr %lx, size %lx, mask %lx, align %lx\n",
   99             (u_long)addr, (u_long)size, (u_long)mask, (u_long)align));
  100 
  101         addr += rbt->rb_offset;
  102 
  103         if (mask == 0) {
  104                 /* FULL Decode */
  105                 decodesize = 0;
  106         }
  107 
  108         if (rbt->rb_flags == RBUS_SPACE_ASK_PARENT) {
  109                 return rbus_space_alloc(rbt->rb_parent, addr, size, mask,
  110                     align, flags, addrp, bshp);
  111         } else if (rbt->rb_flags == RBUS_SPACE_SHARE ||
  112             rbt->rb_flags == RBUS_SPACE_DEDICATE) {
  113                 /* rbt has its own sh_extent */
  114 
  115                 /*
  116                  * sanity check: the subregion [substart, subend] should be
  117                  * smaller than the region included in sh_extent.
  118                  */
  119                 if (substart < rbt->rb_ext->ex_start
  120                     || subend > rbt->rb_ext->ex_end) {
  121                         DPRINTF(("rbus: out of range\n"));
  122                         return 1;
  123                 }
  124 
  125                 if (decodesize == align) {
  126                         if(extent_alloc_subregion(rbt->rb_ext, substart,
  127                             subend, size, align, 0, exflags, &result)) {
  128                                 return 1;
  129                         }
  130                 } else if (decodesize == 0) {
  131                         /* maybe, the resister is overflowed. */
  132       
  133                         if (extent_alloc_subregion(rbt->rb_ext, addr,
  134                             addr + size, size, 1, 0, exflags, &result)) {
  135                                 return 1;
  136                         }
  137                 } else {
  138 
  139                         boundary = decodesize > align ? decodesize : align;
  140 
  141                         search_addr = (substart & ~(boundary - 1)) + addr;
  142 
  143                         if (search_addr < substart) {
  144                                 search_addr += boundary;
  145                         }
  146 
  147                         val = 1;
  148                         for (; search_addr + size <= subend;
  149                              search_addr += boundary) {
  150                                 val = extent_alloc_subregion(rbt->rb_ext,
  151                                     search_addr, search_addr + size, size,
  152                                     align, 0, exflags, &result);
  153                                 DPRINTF(("rbus: trying [%lx:%lx] %lx\n",
  154                                     (u_long)search_addr,
  155                                     (u_long)search_addr + size, (u_long)align));
  156                                 if (val == 0) {
  157                                         break;
  158                                 }
  159                         }
  160                         if (val != 0) {
  161                                 /* no space found */
  162                                 DPRINTF(("rbus: no space found\n"));
  163                                 return 1;
  164                         }
  165                 }
  166 
  167                 if(md_space_map(rbt->rb_bt, result, size, flags, bshp)) {
  168                         /* map failed */
  169                         extent_free(rbt->rb_ext, result, size, exflags);
  170                         return 1;
  171                 }
  172 
  173                 if (addrp != NULL) {
  174                         *addrp = result + rbt->rb_offset;
  175                 }
  176                 return 0;
  177         } else {
  178                 /* error!! */
  179                 DPRINTF(("rbus: no rbus type\n"));
  180                 return 1;
  181         }
  182 }
  183 
  184 
  185 
  186 
  187 
  188 int
  189 rbus_space_free(rbt, bsh, size, addrp)
  190         rbus_tag_t rbt;
  191         bus_space_handle_t bsh;
  192         bus_size_t size;
  193         bus_addr_t *addrp;
  194 {
  195         int exflags = EX_FAST | EX_NOWAIT;
  196         bus_addr_t addr;
  197         int status = 1;
  198 
  199         if (rbt->rb_flags == RBUS_SPACE_ASK_PARENT) {
  200                 status = rbus_space_free(rbt->rb_parent, bsh, size, &addr);
  201         } else if (rbt->rb_flags == RBUS_SPACE_SHARE ||
  202             rbt->rb_flags == RBUS_SPACE_DEDICATE) {
  203                 md_space_unmap(rbt->rb_bt, bsh, size, &addr);
  204 
  205                 extent_free(rbt->rb_ext, addr, size, exflags);
  206 
  207                 status = 0;
  208         } else {
  209                 /* error. INVALID rbustag */
  210                 status = 1;
  211         }
  212         if (addrp != NULL) {
  213                 *addrp = addr;
  214         }
  215         return status;
  216 }
  217 
  218 
  219 
  220 /*
  221  * static rbus_tag_t
  222  * rbus_new_body(bus_space_tag_t bt, rbus_tag_t parent,
  223  *               struct extent *ex, bus_addr_t start, bus_size_t end,
  224  *               bus_addr_t offset, int flags)
  225  *
  226  */
  227 static rbus_tag_t
  228 rbus_new_body(bt, parent, ex, start, end, offset, flags)
  229         bus_space_tag_t bt;
  230         rbus_tag_t parent;
  231         struct extent *ex;
  232         bus_addr_t start, end, offset;
  233         int flags;
  234 {
  235         rbus_tag_t rb;
  236 
  237         /* sanity check */
  238         if (parent != NULL) {
  239                 if (start < parent->rb_start || end > parent->rb_end) {
  240                         /*
  241                          * out of range: [start, size] should be
  242                          * contained in parent space
  243                          */
  244                         return 0;
  245                         /* Should I invoke panic? */
  246                 }
  247         }
  248 
  249         if (NULL == (rb = (rbus_tag_t)malloc(sizeof(struct rbustag), M_DEVBUF,
  250             M_NOWAIT))) {
  251                 panic("no memory for rbus instance");
  252         }
  253 
  254         rb->rb_bt = bt;
  255         rb->rb_parent = parent;
  256         rb->rb_start = start;
  257         rb->rb_end = end;
  258         rb->rb_offset = offset;
  259         rb->rb_flags = flags;
  260         rb->rb_ext = ex;
  261 
  262         DPRINTF(("rbus_new_body: [%lx, %lx] type %s name [%s]\n",
  263             (u_long)start, (u_long)end,
  264             flags == RBUS_SPACE_SHARE ? "share" :
  265             flags == RBUS_SPACE_DEDICATE ? "dedicated" :
  266             flags == RBUS_SPACE_ASK_PARENT ? "parent" : "invalid",
  267             ex != NULL ? ex->ex_name : "noname"));
  268 
  269         return rb;
  270 }
  271 
  272 
  273 
  274 /*
  275  * rbus_tag_t rbus_new(rbus_tag_t parent, bus_addr_t start, bus_size_t
  276  *                     size, bus_addr_t offset, int flags)
  277  *
  278  *  This function makes a new child rbus instance.
  279  */
  280 rbus_tag_t
  281 rbus_new(parent, start, size, offset, flags)
  282         rbus_tag_t parent;
  283         bus_addr_t start;
  284         bus_size_t size;
  285         bus_addr_t offset;
  286         int flags;
  287 {
  288         rbus_tag_t rb;
  289         struct extent *ex = NULL;
  290         bus_addr_t end = start + size;
  291 
  292         if (flags == RBUS_SPACE_SHARE) {
  293                 ex = parent->rb_ext;
  294         } else if (flags == RBUS_SPACE_DEDICATE) {
  295                 if (NULL == (ex = extent_create("rbus", start, end, M_DEVBUF,
  296                     NULL, 0, EX_NOCOALESCE|EX_NOWAIT))) {
  297                         return NULL;
  298                 }
  299         } else if (flags == RBUS_SPACE_ASK_PARENT) {
  300                 ex = NULL;
  301         } else {
  302                 /* Invalid flag */
  303                 return 0;
  304         }
  305 
  306         rb = rbus_new_body(parent->rb_bt, parent, ex, start, start + size,
  307             offset, flags);
  308 
  309         if ((rb == NULL) && (flags == RBUS_SPACE_DEDICATE)) {
  310                 extent_destroy(ex);
  311         }
  312 
  313         return rb;
  314 }
  315 
  316 
  317 
  318 
  319 /*
  320  * rbus_tag_t rbus_new_root_delegate(bus_space_tag, bus_addr_t,
  321  *                                   bus_size_t, bus_addr_t offset)
  322  *
  323  *  This function makes a root rbus instance.
  324  */
  325 rbus_tag_t
  326 rbus_new_root_delegate(bt, start, size, offset)
  327         bus_space_tag_t bt;
  328         bus_addr_t start;
  329         bus_size_t size;
  330         bus_addr_t offset;
  331 {
  332         rbus_tag_t rb;
  333         struct extent *ex;
  334 
  335         if (NULL == (ex = extent_create("rbus root", start, start + size,
  336             M_DEVBUF, NULL, 0, EX_NOCOALESCE|EX_NOWAIT))) {
  337                 return NULL;
  338         }
  339 
  340         rb = rbus_new_body(bt, NULL, ex, start, start + size, offset,
  341             RBUS_SPACE_DEDICATE);
  342 
  343         if (rb == NULL) {
  344                 extent_destroy(ex);
  345         }
  346 
  347         return rb;
  348 }
  349 
  350 
  351 
  352 /*
  353  * rbus_tag_t rbus_new_root_share(bus_space_tag, struct extent *,
  354  *                                 bus_addr_t, bus_size_t, bus_addr_t offset)
  355  *
  356  *  This function makes a root rbus instance.
  357  */
  358 rbus_tag_t
  359 rbus_new_root_share(bt, ex, start, size, offset)
  360         bus_space_tag_t bt;
  361         struct extent *ex;
  362         bus_addr_t start;
  363         bus_size_t size;
  364         bus_addr_t offset;
  365 {
  366         /* sanity check */
  367         if (start < ex->ex_start || start + size > ex->ex_end) {
  368                 /*
  369                  * out of range: [start, size] should be contained in
  370                  * parent space
  371                  */
  372                 return 0;
  373                 /* Should I invoke panic? */
  374         }
  375 
  376         return rbus_new_body(bt, NULL, ex, start, start + size, offset,
  377             RBUS_SPACE_SHARE);
  378 }
  379 
  380 
  381 
  382 
  383 
  384 /*
  385  * int rbus_delete (rbus_tag_t rb)
  386  *
  387  *   This function deletes the rbus structure pointed in the argument.
  388  */
  389 int
  390 rbus_delete(rb)
  391         rbus_tag_t rb;
  392 {
  393         DPRINTF(("rbus_delete called [%s]\n",
  394             rb->rb_ext != NULL ? rb->rb_ext->ex_name : "noname"));
  395         if (rb->rb_flags == RBUS_SPACE_DEDICATE) {
  396                 extent_destroy(rb->rb_ext);
  397         }
  398 
  399         free(rb, M_DEVBUF);
  400 
  401         return 0;
  402 }

Cache object: 42a59c54af9f8393b034a8cdf2ccca0e


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