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/mips/adm5120/admpci.c

Version: -  FREEBSD  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

    1 /* $NetBSD: admpci.c,v 1.1 2007/03/20 08:52:02 dyoung Exp $ */
    2 
    3 /*-
    4  * Copyright (c) 2007 David Young.  All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or
    7  * without modification, are permitted provided that the following
    8  * conditions 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
   12  *    copyright notice, this list of conditions and the following
   13  *    disclaimer in the documentation and/or other materials provided
   14  *    with the distribution.
   15  * 3. The name of the author may not be used to endorse or promote
   16  *    products derived from this software without specific prior
   17  *    written permission.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
   20  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
   21  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
   22  * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR
   23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
   24  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
   26  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
   28  * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   29  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
   30  * OF SUCH DAMAGE.
   31  */
   32 /*-
   33  * Copyright (c) 2006 Itronix Inc.
   34  * All rights reserved.
   35  *
   36  * Written by Garrett D'Amore for Itronix Inc.
   37  *
   38  * Redistribution and use in source and binary forms, with or without
   39  * modification, are permitted provided that the following conditions
   40  * are met:
   41  * 1. Redistributions of source code must retain the above copyright
   42  *    notice, this list of conditions and the following disclaimer.
   43  * 2. Redistributions in binary form must reproduce the above copyright
   44  *    notice, this list of conditions and the following disclaimer in the
   45  *    documentation and/or other materials provided with the distribution.
   46  * 3. The name of Itronix Inc. may not be used to endorse
   47  *    or promote products derived from this software without specific
   48  *    prior written permission.
   49  *
   50  * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
   51  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   52  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   53  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
   54  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   55  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   56  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   57  * ON ANY THEORY OF LIABILITY, WHETHER IN
   58  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   59  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   60  * POSSIBILITY OF SUCH DAMAGE.
   61  */ 
   62 
   63 #include <sys/cdefs.h>
   64 __FBSDID("$FreeBSD: releng/8.4/sys/mips/adm5120/admpci.c 230714 2012-01-29 01:22:48Z marius $");
   65 
   66 #include <sys/param.h>
   67 #include <sys/systm.h>
   68 
   69 #include <sys/bus.h>
   70 #include <sys/interrupt.h>
   71 #include <sys/malloc.h>
   72 #include <sys/kernel.h>
   73 #include <sys/module.h>
   74 #include <sys/rman.h>
   75 
   76 #include <vm/vm.h>
   77 #include <vm/pmap.h>
   78 #include <vm/vm_extern.h>
   79 
   80 #include <machine/bus.h>
   81 #include <machine/cpu.h>
   82 #include <machine/pmap.h>
   83 
   84 #include <dev/pci/pcivar.h>
   85 #include <dev/pci/pcireg.h>
   86 
   87 #include <dev/pci/pcib_private.h>
   88 #include "pcib_if.h"
   89 
   90 #include <mips/adm5120/adm5120reg.h>
   91 
   92 #ifdef ADMPCI_DEBUG
   93 int admpci_debug = 1;
   94 #define ADMPCI_DPRINTF(__fmt, ...)              \
   95 do {                                            \
   96         if (admpci_debug)                       \
   97                 printf((__fmt), __VA_ARGS__);   \
   98 } while (/*CONSTCOND*/0)
   99 #else /* !ADMPCI_DEBUG */
  100 #define ADMPCI_DPRINTF(__fmt, ...)      do { } while (/*CONSTCOND*/0)
  101 #endif /* ADMPCI_DEBUG */
  102 
  103 #define ADMPCI_TAG_BUS_MASK             __BITS(23, 16)
  104 /* Bit 11 is reserved.  It selects the AHB-PCI bridge.  Let device 0
  105  * be the bridge.  For all other device numbers, let bit[11] == 0.
  106  */
  107 #define ADMPCI_TAG_DEVICE_MASK          __BITS(15, 11)
  108 #define ADMPCI_TAG_DEVICE_SUBMASK       __BITS(15, 12)
  109 #define ADMPCI_TAG_DEVICE_BRIDGE        __BIT(11)
  110 #define ADMPCI_TAG_FUNCTION_MASK        __BITS(10, 8)
  111 #define ADMPCI_TAG_REGISTER_MASK        __BITS(7, 0)
  112 
  113 #define ADMPCI_MAX_DEVICE
  114 
  115 struct admpci_softc {
  116         device_t                sc_dev;
  117         bus_space_tag_t         sc_st;
  118 
  119         /* Access to PCI config registers */
  120         bus_space_handle_t      sc_addrh;
  121         bus_space_handle_t      sc_datah;
  122 
  123         int                     sc_busno;
  124         struct rman             sc_mem_rman;
  125         struct rman             sc_io_rman;
  126         struct rman             sc_irq_rman;
  127         uint32_t                sc_mem;
  128         uint32_t                sc_io;
  129 };
  130 
  131 static int
  132 admpci_probe(device_t dev)
  133 {
  134 
  135         return (0);
  136 }
  137 
  138 static int
  139 admpci_attach(device_t dev)
  140 {
  141         int busno = 0;
  142         struct admpci_softc *sc = device_get_softc(dev);
  143 
  144         sc->sc_dev = dev;
  145         sc->sc_busno = busno;
  146 
  147         /* Use KSEG1 to access IO ports for it is uncached */
  148         sc->sc_io = MIPS_PHYS_TO_KSEG1(ADM5120_BASE_PCI_IO);
  149         sc->sc_io_rman.rm_type = RMAN_ARRAY;
  150         sc->sc_io_rman.rm_descr = "ADMPCI I/O Ports";
  151         if (rman_init(&sc->sc_io_rman) != 0 ||
  152                 rman_manage_region(&sc->sc_io_rman, 0, 0xffff) != 0) {
  153                 panic("admpci_attach: failed to set up I/O rman");
  154         }
  155 
  156         /* Use KSEG1 to access PCI memory for it is uncached */
  157         sc->sc_mem = MIPS_PHYS_TO_KSEG1(ADM5120_BASE_PCI_MEM);
  158         sc->sc_mem_rman.rm_type = RMAN_ARRAY;
  159         sc->sc_mem_rman.rm_descr = "ADMPCI PCI Memory";
  160         if (rman_init(&sc->sc_mem_rman) != 0 ||
  161             rman_manage_region(&sc->sc_mem_rman, 
  162             sc->sc_mem, sc->sc_mem + 0x100000) != 0) {
  163                 panic("admpci_attach: failed to set up memory rman");
  164         }
  165 
  166         sc->sc_irq_rman.rm_type = RMAN_ARRAY;
  167         sc->sc_irq_rman.rm_descr = "ADMPCI PCI IRQs";
  168         if (rman_init(&sc->sc_irq_rman) != 0 ||
  169             rman_manage_region(&sc->sc_irq_rman, 1, 31) != 0)
  170                 panic("admpci_attach: failed to set up IRQ rman");
  171 
  172         if (bus_space_map(sc->sc_st, ADM5120_BASE_PCI_CONFADDR, 4, 0, 
  173             &sc->sc_addrh) != 0) {
  174                 device_printf(sc->sc_dev, "unable to address space\n");
  175                 panic("bus_space_map failed");
  176         }
  177 
  178         if (bus_space_map(sc->sc_st, ADM5120_BASE_PCI_CONFDATA, 4, 0, 
  179             &sc->sc_datah) != 0) {
  180                 device_printf(sc->sc_dev, "unable to address space\n");
  181                 panic("bus_space_map failed");
  182         }
  183 
  184         device_add_child(dev, "pci", busno);
  185         return (bus_generic_attach(dev));
  186 }
  187 
  188 static int
  189 admpci_maxslots(device_t dev)
  190 {
  191 
  192         return (PCI_SLOTMAX);
  193 }
  194 
  195 static uint32_t
  196 admpci_make_addr(int bus, int slot, int func, int reg)
  197 {
  198 
  199         return (0x80000000 | (bus << 16) | (slot << 11) | (func << 8) | reg);
  200 }
  201 
  202 static uint32_t
  203 admpci_read_config(device_t dev, int bus, int slot, int func, int reg,
  204     int bytes)
  205 {
  206         struct admpci_softc *sc = device_get_softc(dev);
  207         uint32_t data;
  208         uint32_t shift, mask;
  209         bus_addr_t addr;
  210 
  211         ADMPCI_DPRINTF("%s: sc %p tag (%x, %x, %x) reg %d\n", __func__, 
  212                         (void *)sc, bus, slot, func, reg);
  213 
  214         addr = admpci_make_addr(bus, slot, func, reg);
  215 
  216         ADMPCI_DPRINTF("%s: sc_addrh %p sc_datah %p addr %p\n", __func__,
  217             (void *)sc->sc_addrh, (void *)sc->sc_datah, (void *)addr);
  218 
  219         bus_space_write_4(sc->sc_io, sc->sc_addrh, 0, addr);
  220         data = bus_space_read_4(sc->sc_io, sc->sc_datah, 0);
  221 
  222         switch (reg % 4) {
  223         case 3:
  224                 shift = 24;
  225                 break;
  226         case 2:
  227                 shift = 16;
  228                 break;
  229         case 1:
  230                 shift = 8;
  231                 break;
  232         default:
  233                 shift = 0;
  234                 break;
  235         }       
  236 
  237         switch (bytes) {
  238         case 1:
  239                 mask = 0xff;
  240                 data = (data >> shift) & mask;
  241                 break;
  242         case 2:
  243                 mask = 0xffff;
  244                 if (reg % 4 == 0)
  245                         data = data & mask;
  246                 else
  247                         data = (data >> 16) & mask;
  248                 break;
  249         case 4:
  250                 break;
  251         default:
  252                 panic("%s: wrong bytes count", __func__);
  253                 break;
  254         }
  255 
  256         ADMPCI_DPRINTF("%s: read 0x%x\n", __func__, data);
  257         return (data);
  258 }
  259 
  260 static void
  261 admpci_write_config(device_t dev, int bus, int slot, int func, int reg,
  262     uint32_t data, int bytes)
  263 {
  264         struct admpci_softc *sc = device_get_softc(dev);
  265         bus_addr_t addr;
  266         uint32_t reg_data;
  267         uint32_t shift, mask;
  268 
  269         ADMPCI_DPRINTF("%s: sc %p tag (%x, %x, %x) reg %d\n", __func__, 
  270                         (void *)sc, bus, slot, func, reg);
  271 
  272         if (bytes != 4) {
  273                 reg_data = admpci_read_config(dev, bus, slot, func, reg, 4);
  274 
  275                 switch (reg % 4) {
  276                 case 3:
  277                         shift = 24;
  278                         break;
  279                 case 2:
  280                         shift = 16;
  281                         break;
  282                 case 1:
  283                         shift = 8;
  284                         break;
  285                 default:
  286                         shift = 0;
  287                         break;
  288                 }       
  289 
  290                 switch (bytes) {
  291                 case 1:
  292                         mask = 0xff;
  293                         data = (reg_data & ~ (mask << shift)) | (data << shift);
  294                         break;
  295                 case 2:
  296                         mask = 0xffff;
  297                         if (reg % 4 == 0)
  298                                 data = (reg_data & ~mask) | data;
  299                         else
  300                                 data = (reg_data & ~ (mask << shift)) | 
  301                                     (data << shift);
  302                         break;
  303                 case 4:
  304                         break;
  305                 default:
  306                         panic("%s: wrong bytes count", __func__);
  307                         break;
  308                 }
  309         }
  310 
  311         addr = admpci_make_addr(bus, slot, func, reg);
  312 
  313         ADMPCI_DPRINTF("%s: sc_addrh %p sc_datah %p addr %p\n", __func__,
  314             (void *)sc->sc_addrh, (void *)sc->sc_datah, (void *)addr);
  315 
  316         bus_space_write_4(sc->sc_io, sc->sc_addrh, 0, addr);
  317         bus_space_write_4(sc->sc_io, sc->sc_datah, 0, data);
  318 }
  319 
  320 static int
  321 admpci_route_interrupt(device_t pcib, device_t dev, int pin)
  322 {
  323         /* TODO: implement */
  324         return (0);
  325 }
  326 
  327 static int
  328 admpci_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
  329 {
  330         struct admpci_softc *sc = device_get_softc(dev);
  331 
  332         switch (which) {
  333         case PCIB_IVAR_DOMAIN:
  334                 *result = 0;
  335                 return (0);
  336         case PCIB_IVAR_BUS:
  337                 *result = sc->sc_busno;
  338                 return (0);
  339         }
  340 
  341         return (ENOENT);
  342 }
  343 
  344 static int
  345 admpci_write_ivar(device_t dev, device_t child, int which, uintptr_t result)
  346 {
  347         struct admpci_softc * sc = device_get_softc(dev);
  348 
  349         switch (which) {
  350         case PCIB_IVAR_BUS:
  351                 sc->sc_busno = result;
  352                 return (0);
  353         }
  354         return (ENOENT);
  355 }
  356 
  357 static struct resource *
  358 admpci_alloc_resource(device_t bus, device_t child, int type, int *rid,
  359     u_long start, u_long end, u_long count, u_int flags)
  360 {
  361 
  362         return (NULL);
  363 #if 0
  364         struct admpci_softc *sc = device_get_softc(bus);        
  365         struct resource *rv = NULL;
  366         struct rman *rm;
  367         bus_space_handle_t bh = 0;
  368 
  369         switch (type) {
  370         case SYS_RES_IRQ:
  371                 rm = &sc->sc_irq_rman;
  372                 break;
  373         case SYS_RES_MEMORY:
  374                 rm = &sc->sc_mem_rman;
  375                 bh = sc->sc_mem;
  376                 break;
  377         case SYS_RES_IOPORT:
  378                 rm = &sc->sc_io_rman;
  379                 bh = sc->sc_io;
  380                 break;
  381         default:
  382                 return (NULL);
  383         }
  384 
  385         rv = rman_reserve_resource(rm, start, end, count, flags, child);
  386         if (rv == NULL)
  387                 return (NULL);
  388         rman_set_rid(rv, *rid);
  389         if (type != SYS_RES_IRQ) {
  390                 bh += (rman_get_start(rv));
  391 
  392                 rman_set_bustag(rv, sc->sc_st);
  393                 rman_set_bushandle(rv, bh);
  394                 if (flags & RF_ACTIVE) {
  395                         if (bus_activate_resource(child, type, *rid, rv)) {
  396                                 rman_release_resource(rv);
  397                                 return (NULL);
  398                         }
  399                 } 
  400         }
  401         return (rv);
  402 #endif
  403 }
  404 
  405 static int
  406 admpci_activate_resource(device_t bus, device_t child, int type, int rid,
  407     struct resource *r)
  408 {
  409         bus_space_handle_t p;
  410         int error;
  411         
  412         if ((type == SYS_RES_MEMORY) || (type == SYS_RES_IOPORT)) {
  413                 error = bus_space_map(rman_get_bustag(r),
  414                     rman_get_bushandle(r), rman_get_size(r), 0, &p);
  415                 if (error) 
  416                         return (error);
  417                 rman_set_bushandle(r, p);
  418         }
  419         return (rman_activate_resource(r));
  420 }
  421 
  422 static int
  423 admpci_setup_intr(device_t dev, device_t child, struct resource *ires, 
  424                 int flags, driver_filter_t *filt, driver_intr_t *handler, 
  425                 void *arg, void **cookiep)
  426 {
  427 
  428 #if 0
  429         struct admpci_softc *sc = device_get_softc(dev);
  430         struct intr_event *event;
  431         int irq, error;
  432 
  433         irq = rman_get_start(ires);
  434         if (irq >= ICU_LEN || irq == 2)
  435                 panic("%s: bad irq or type", __func__);
  436 
  437         event = sc->sc_eventstab[irq];
  438         if (event == NULL) {
  439                 error = intr_event_create(&event, (void *)irq, 0,
  440                     (void (*)(void *))NULL, "admpci intr%d:", irq);
  441                 if (error)
  442                         return 0;
  443                 sc->sc_eventstab[irq] = event;
  444         }
  445 
  446         intr_event_add_handler(event, device_get_nameunit(child), filt, 
  447             handler, arg, intr_priority(flags), flags, cookiep);
  448 
  449         /* Enable it, set trigger mode. */
  450         sc->sc_imask &= ~(1 << irq);
  451         sc->sc_elcr &= ~(1 << irq);
  452 
  453         admpci_set_icus(sc);
  454 #endif
  455 
  456         return (0);
  457 }
  458 
  459 static int
  460 admpci_teardown_intr(device_t dev, device_t child, struct resource *res,
  461     void *cookie)
  462 {
  463 
  464         return (intr_event_remove_handler(cookie));
  465 }
  466 
  467 static device_method_t admpci_methods[] = {
  468         /* Device interface */
  469         DEVMETHOD(device_probe,         admpci_probe),
  470         DEVMETHOD(device_attach,        admpci_attach),
  471         DEVMETHOD(device_shutdown,      bus_generic_shutdown),
  472         DEVMETHOD(device_suspend,       bus_generic_suspend),
  473         DEVMETHOD(device_resume,        bus_generic_resume),
  474 
  475         /* Bus interface */
  476         DEVMETHOD(bus_read_ivar,        admpci_read_ivar),
  477         DEVMETHOD(bus_write_ivar,       admpci_write_ivar),
  478         DEVMETHOD(bus_alloc_resource,   admpci_alloc_resource),
  479         DEVMETHOD(bus_release_resource, bus_generic_release_resource),
  480         DEVMETHOD(bus_activate_resource, admpci_activate_resource),
  481         DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
  482         DEVMETHOD(bus_setup_intr,       admpci_setup_intr),
  483         DEVMETHOD(bus_teardown_intr,    admpci_teardown_intr),
  484 
  485         /* pcib interface */
  486         DEVMETHOD(pcib_maxslots,        admpci_maxslots),
  487         DEVMETHOD(pcib_read_config,     admpci_read_config),
  488         DEVMETHOD(pcib_write_config,    admpci_write_config),
  489         DEVMETHOD(pcib_route_interrupt, admpci_route_interrupt),
  490 
  491         DEVMETHOD_END
  492 };
  493 
  494 static driver_t admpci_driver = {
  495         "pcib",
  496         admpci_methods,
  497         sizeof(struct admpci_softc),
  498 };
  499 
  500 static devclass_t admpci_devclass;
  501 
  502 DRIVER_MODULE(admpci, obio, admpci_driver, admpci_devclass, 0, 0);

Cache object: ca46c05e0f6f214b9867e9406813a4f7


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