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/cardbus_map.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: cardbus_map.c,v 1.14 2001/11/15 09:48:02 lukem Exp $   */
    2 
    3 /*
    4  * Copyright (c) 1999 and 2000
    5  *      HAYAKAWA Koichi.  All rights reserved.
    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  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. All advertising materials mentioning features or use of this software
   16  *    must display the following acknowledgement:
   17  *      This product includes software developed by HAYAKAWA Koichi.
   18  * 4. The name of the author may not be used to endorse or promote products
   19  *    derived from this software without specific prior written permission.
   20  *
   21  *
   22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   23  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   24  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   25  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
   26  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   27  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
   28  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
   30  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
   31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   32  * POSSIBILITY OF SUCH DAMAGE.
   33  */
   34 
   35 #include <sys/cdefs.h>
   36 __KERNEL_RCSID(0, "$NetBSD: cardbus_map.c,v 1.14 2001/11/15 09:48:02 lukem Exp $");
   37 
   38 #include <sys/param.h>
   39 #include <sys/systm.h>
   40 #include <sys/device.h>
   41 
   42 #include <machine/bus.h>
   43 
   44 #include <dev/cardbus/cardbusvar.h>
   45 
   46 #include <dev/pci/pcireg.h>     /* XXX */
   47 
   48 #if defined DEBUG && !defined CARDBUS_MAP_DEBUG
   49 #define CARDBUS_MAP_DEBUG
   50 #endif
   51 
   52 #if defined CARDBUS_MAP_DEBUG
   53 #define STATIC
   54 #define DPRINTF(a) printf a
   55 #else
   56 #define STATIC static
   57 #define DPRINTF(a)
   58 #endif
   59 
   60 
   61 static int cardbus_io_find __P((cardbus_chipset_tag_t, cardbus_function_tag_t,
   62                                 cardbustag_t, int, cardbusreg_t,
   63                                 bus_addr_t *, bus_size_t *, int *));
   64 static int cardbus_mem_find __P((cardbus_chipset_tag_t, cardbus_function_tag_t,
   65                                  cardbustag_t, int, cardbusreg_t,
   66                                  bus_addr_t *, bus_size_t *, int *));
   67 
   68 /*
   69  * static int cardbus_io_find(cardbus_chipset_tag_t cc,
   70  *                            cardbus_function_tag_t cf, cardbustag_t tag,
   71  *                            int reg, cardbusreg_t type, bus_addr_t *basep,
   72  *                            bus_size_t *sizep, int *flagsp)
   73  * This code is stolen from sys/dev/pci_map.c.
   74  */
   75 static int
   76 cardbus_io_find(cc, cf, tag, reg, type, basep, sizep, flagsp)
   77         cardbus_chipset_tag_t cc;
   78         cardbus_function_tag_t cf;
   79         cardbustag_t tag;
   80         int reg;
   81         cardbusreg_t type;
   82         bus_addr_t *basep;
   83         bus_size_t *sizep;
   84         int *flagsp;
   85 {
   86         cardbusreg_t address, mask;
   87         int s;
   88 
   89         /* EXT ROM is able to map on memory space ONLY. */
   90         if (reg == CARDBUS_ROM_REG) {
   91                 return 1;
   92         }
   93 
   94         if(reg < PCI_MAPREG_START || reg >= PCI_MAPREG_END || (reg & 3)) {
   95                 panic("cardbus_io_find: bad request");
   96         }
   97 
   98         /*
   99          * Section 6.2.5.1, `Address Maps', tells us that:
  100          *
  101          * 1) The builtin software should have already mapped the device in a
  102          * reasonable way.
  103          *
  104          * 2) A device which wants 2^n bytes of memory will hardwire the bottom
  105          * n bits of the address to 0.  As recommended, we write all 1s and see
  106          * what we get back.
  107          */
  108         s = splhigh();
  109         address = cardbus_conf_read(cc, cf, tag, reg);
  110         cardbus_conf_write(cc, cf, tag, reg, 0xffffffff);
  111         mask = cardbus_conf_read(cc, cf, tag, reg);
  112         cardbus_conf_write(cc, cf, tag, reg, address);
  113         splx(s);
  114 
  115         if (PCI_MAPREG_TYPE(address) != PCI_MAPREG_TYPE_IO) {
  116                 printf("cardbus_io_find: expected type i/o, found mem\n");
  117                 return 1;
  118         }
  119 
  120         if (PCI_MAPREG_IO_SIZE(mask) == 0) {
  121                 printf("cardbus_io_find: void region\n");
  122                 return 1;
  123         }
  124 
  125         if (basep != 0) {
  126                 *basep = PCI_MAPREG_IO_ADDR(address);
  127         }
  128         if (sizep != 0) {
  129                 *sizep = PCI_MAPREG_IO_SIZE(mask);
  130         }
  131         if (flagsp != 0) {
  132                 *flagsp = 0;
  133         }
  134 
  135         return 0;
  136 }
  137 
  138 
  139 
  140 /*
  141  * static int cardbus_mem_find(cardbus_chipset_tag_t cc,
  142  *                             cardbus_function_tag_t cf, cardbustag_t tag,
  143  *                             int reg, cardbusreg_t type, bus_addr_t *basep,
  144  *                             bus_size_t *sizep, int *flagsp)
  145  * This code is stolen from sys/dev/pci_map.c.
  146  */
  147 static int
  148 cardbus_mem_find(cc, cf, tag, reg, type, basep, sizep, flagsp)
  149         cardbus_chipset_tag_t cc;
  150         cardbus_function_tag_t cf;
  151         cardbustag_t tag;
  152         int reg;
  153         cardbusreg_t type;
  154         bus_addr_t *basep;
  155         bus_size_t *sizep;
  156         int *flagsp;
  157 {
  158         cardbusreg_t address, mask;
  159         int s;
  160 
  161         if (reg != CARDBUS_ROM_REG && 
  162             (reg < PCI_MAPREG_START || reg >= PCI_MAPREG_END || (reg & 3))) {
  163                 panic("cardbus_mem_find: bad request");
  164         }
  165 
  166         /*
  167          * Section 6.2.5.1, `Address Maps', tells us that:
  168          *
  169          * 1) The builtin software should have already mapped the device in a
  170          * reasonable way.
  171          *
  172          * 2) A device which wants 2^n bytes of memory will hardwire the bottom
  173          * n bits of the address to 0.  As recommended, we write all 1s and see
  174          * what we get back.
  175          */
  176         s = splhigh();
  177         address = cardbus_conf_read(cc, cf, tag, reg);
  178         cardbus_conf_write(cc, cf, tag, reg, 0xffffffff);
  179         mask = cardbus_conf_read(cc, cf, tag, reg);
  180         cardbus_conf_write(cc, cf, tag, reg, address);
  181         splx(s);
  182 
  183         if (reg != CARDBUS_ROM_REG) {
  184                 /* memory space BAR */
  185 
  186                 if (PCI_MAPREG_TYPE(address) != PCI_MAPREG_TYPE_MEM) {
  187                         printf("cardbus_mem_find: expected type mem, found i/o\n");
  188                         return 1;
  189                 }
  190                 if (PCI_MAPREG_MEM_TYPE(address) != PCI_MAPREG_MEM_TYPE(type)) {
  191                         printf("cardbus_mem_find: expected mem type %08x, found %08x\n",
  192                             PCI_MAPREG_MEM_TYPE(type),
  193                             PCI_MAPREG_MEM_TYPE(address));
  194                         return 1;
  195                 }
  196         }
  197 
  198         if (PCI_MAPREG_MEM_SIZE(mask) == 0) {
  199                 printf("cardbus_mem_find: void region\n");
  200                 return 1;
  201         }
  202 
  203         switch (PCI_MAPREG_MEM_TYPE(address)) {
  204         case PCI_MAPREG_MEM_TYPE_32BIT:
  205         case PCI_MAPREG_MEM_TYPE_32BIT_1M:
  206                 break;
  207         case PCI_MAPREG_MEM_TYPE_64BIT:
  208                 printf("cardbus_mem_find: 64-bit memory mapping register\n");
  209                 return 1;
  210         default:
  211                 printf("cardbus_mem_find: reserved mapping register type\n");
  212                 return 1;
  213         }
  214 
  215         if (basep != 0) {
  216                 *basep = PCI_MAPREG_MEM_ADDR(address);
  217         }
  218         if (sizep != 0) {
  219                 *sizep = PCI_MAPREG_MEM_SIZE(mask);
  220         }
  221         if (flagsp != 0) {
  222                 *flagsp = PCI_MAPREG_MEM_PREFETCHABLE(address) ?
  223                     BUS_SPACE_MAP_PREFETCHABLE : 0;
  224         }
  225         
  226         return 0;
  227 }
  228 
  229 
  230 
  231 
  232 /*
  233  * int cardbus_mapreg_map(struct cardbus_softc *, int, int, cardbusreg_t,
  234  *                        int bus_space_tag_t *, bus_space_handle_t *,
  235  *                        bus_addr_t *, bus_size_t *)
  236  *    This function maps bus-space on the value of Base Address
  237  *   Register (BAR) indexed by the argument `reg' (the second argument).
  238  *   When the value of the BAR is not valid, such as 0x00000000, a new
  239  *   address should be allocated for the BAR and new address values is
  240  *   written on the BAR.
  241  */
  242 int
  243 cardbus_mapreg_map(sc, func, reg, type, busflags, tagp, handlep, basep, sizep)
  244         struct cardbus_softc *sc;
  245         int func, reg, busflags;
  246         cardbusreg_t type;
  247         bus_space_tag_t *tagp;
  248         bus_space_handle_t *handlep;
  249         bus_addr_t *basep;
  250         bus_size_t *sizep;
  251 {
  252         cardbus_chipset_tag_t cc = sc->sc_cc;
  253         cardbus_function_tag_t cf = sc->sc_cf;
  254         bus_space_tag_t bustag;
  255 #if rbus
  256         rbus_tag_t rbustag;
  257 #endif
  258         bus_space_handle_t handle;
  259         bus_addr_t base;
  260         bus_size_t size;
  261         int flags;
  262         int status = 0;
  263 
  264         cardbustag_t tag = cardbus_make_tag(cc, cf, sc->sc_bus, sc->sc_device, func);
  265 
  266         DPRINTF(("cardbus_mapreg_map called: %s %x\n", sc->sc_dev.dv_xname,
  267            type));
  268 
  269         if (PCI_MAPREG_TYPE(type) == PCI_MAPREG_TYPE_IO) {
  270                 if (cardbus_io_find(cc, cf, tag, reg, type, &base, &size, &flags)) {
  271                         status = 1;
  272                 }
  273                 bustag = sc->sc_iot;
  274 #if rbus
  275                 rbustag = sc->sc_rbus_iot;
  276 #endif
  277         } else {
  278                 if (cardbus_mem_find(cc, cf, tag, reg, type, &base, &size, &flags)){
  279                         status = 1;
  280                 }
  281                 bustag = sc->sc_memt;
  282 #if rbus
  283                 rbustag = sc->sc_rbus_memt;
  284 #endif
  285         }
  286         if (status == 0) {
  287 #if rbus
  288                 bus_addr_t mask = size - 1;
  289                 if (base != 0) {
  290                         mask = 0xffffffff;
  291                 }
  292                 if ((*cf->cardbus_space_alloc)(cc, rbustag, base, size, mask,
  293                     size, busflags | flags, &base, &handle)) {
  294                         panic("io alloc");
  295                 }
  296 #else
  297                 bus_addr_t start = 0x8300;
  298                 bus_addr_t end = 0x8400;
  299                 if (base != 0) {
  300                         bus_addr_t start = base;
  301                         bus_addr_t end = base + size;
  302                 }
  303                 if (bus_space_alloc(bustag, start, end, size, size, 0, 0, &base, &handle)) {
  304                         panic("io alloc");
  305                 }
  306 #endif
  307         }
  308         cardbus_conf_write(cc, cf, tag, reg, base);
  309 
  310         DPRINTF(("cardbus_mapreg_map: physaddr %lx\n", (unsigned long)base));
  311 
  312         if (tagp != 0) {
  313                 *tagp = bustag;
  314         }
  315         if (handlep != 0) {
  316                 *handlep = handle;
  317         }
  318         if (basep != 0) {
  319                 *basep = base;
  320         }
  321         if (sizep != 0) {
  322                 *sizep = size;
  323         }
  324         cardbus_free_tag(cc, cf, tag);
  325 
  326         return 0;
  327 }
  328 
  329 
  330 
  331 
  332 
  333 /*
  334  * int cardbus_mapreg_unmap(struct cardbus_softc *sc, int func, int reg,
  335  *                          bus_space_tag_t tag, bus_space_handle_t handle,
  336  *                          bus_size_t size)
  337  *
  338  *   This function releases bus-space region and close memory or io
  339  *   window on the bridge.
  340  *
  341  *  Arguments:
  342  *   struct cardbus_softc *sc; the pointer to the device structure of cardbus.
  343  *   int func; the number of function on the device.
  344  *   int reg; the offset of BAR register.
  345  */
  346 int
  347 cardbus_mapreg_unmap(sc, func, reg, tag, handle, size)
  348         struct cardbus_softc *sc;
  349         int func, reg;
  350         bus_space_tag_t tag;
  351         bus_space_handle_t handle;
  352         bus_size_t size;
  353 {
  354         cardbus_chipset_tag_t cc = sc->sc_cc;
  355         cardbus_function_tag_t cf = sc->sc_cf;
  356         int st = 1;
  357         cardbustag_t cardbustag;
  358 #if rbus
  359         rbus_tag_t rbustag;
  360 
  361         if (sc->sc_iot == tag) {
  362                 /* bus space is io space */
  363                 DPRINTF(("%s: unmap i/o space\n", sc->sc_dev.dv_xname));
  364                 rbustag = sc->sc_rbus_iot;
  365         } else if (sc->sc_memt == tag) {
  366                 /* bus space is memory space */
  367                 DPRINTF(("%s: unmap mem space\n", sc->sc_dev.dv_xname));
  368                 rbustag = sc->sc_rbus_memt;
  369         } else {
  370                 return 1;
  371         }
  372 #endif
  373 
  374         cardbustag = cardbus_make_tag(cc, cf, sc->sc_bus, sc->sc_device, func);
  375 
  376         cardbus_conf_write(cc, cf, cardbustag, reg, 0);
  377 
  378 #if rbus
  379         (*cf->cardbus_space_free)(cc, rbustag, handle, size);
  380 #endif
  381 
  382         cardbus_free_tag(cc, cf, cardbustag);
  383 
  384         return st;
  385 }
  386 
  387 
  388 
  389 
  390 
  391 /*
  392  * int cardbus_save_bar(cardbus_devfunc_t);
  393  *
  394  *   This function saves the Base Address Registers at the CardBus
  395  *   function denoted by the argument.
  396  */
  397 int cardbus_save_bar(ct)
  398         cardbus_devfunc_t ct;
  399 {
  400         cardbustag_t tag = Cardbus_make_tag(ct);
  401         cardbus_chipset_tag_t cc = ct->ct_cc;
  402         cardbus_function_tag_t cf = ct->ct_cf;
  403 
  404         ct->ct_bar[0] = cardbus_conf_read(cc, cf, tag, CARDBUS_BASE0_REG);
  405         ct->ct_bar[1] = cardbus_conf_read(cc, cf, tag, CARDBUS_BASE1_REG);
  406         ct->ct_bar[2] = cardbus_conf_read(cc, cf, tag, CARDBUS_BASE2_REG);
  407         ct->ct_bar[3] = cardbus_conf_read(cc, cf, tag, CARDBUS_BASE3_REG);
  408         ct->ct_bar[4] = cardbus_conf_read(cc, cf, tag, CARDBUS_BASE4_REG);
  409         ct->ct_bar[5] = cardbus_conf_read(cc, cf, tag, CARDBUS_BASE5_REG);
  410 
  411         DPRINTF(("cardbus_save_bar: %x %x\n", ct->ct_bar[0], ct->ct_bar[1]));
  412 
  413         Cardbus_free_tag(ct, tag);
  414 
  415         return 0;
  416 }
  417 
  418 
  419 
  420 /*
  421  * int cardbus_restore_bar(cardbus_devfunc_t);
  422  *
  423  *   This function saves the Base Address Registers at the CardBus
  424  *   function denoted by the argument.
  425  */
  426 int cardbus_restore_bar(ct)
  427         cardbus_devfunc_t ct;
  428 {
  429         cardbustag_t tag = Cardbus_make_tag(ct);
  430         cardbus_chipset_tag_t cc = ct->ct_cc;
  431         cardbus_function_tag_t cf = ct->ct_cf;
  432 
  433         cardbus_conf_write(cc, cf, tag, CARDBUS_BASE0_REG, ct->ct_bar[0]);
  434         cardbus_conf_write(cc, cf, tag, CARDBUS_BASE1_REG, ct->ct_bar[1]);
  435         cardbus_conf_write(cc, cf, tag, CARDBUS_BASE2_REG, ct->ct_bar[2]);
  436         cardbus_conf_write(cc, cf, tag, CARDBUS_BASE3_REG, ct->ct_bar[3]);
  437         cardbus_conf_write(cc, cf, tag, CARDBUS_BASE4_REG, ct->ct_bar[4]);
  438         cardbus_conf_write(cc, cf, tag, CARDBUS_BASE5_REG, ct->ct_bar[5]);
  439 
  440         Cardbus_free_tag(ct, tag);
  441 
  442         return 0;
  443 }

Cache object: 1d52f8373317febcf7b364d776a1598f


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