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/nlm/xlp_pci.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 /*-
    2  * Copyright (c) 2003-2009 RMI Corporation
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  * 3. Neither the name of RMI Corporation, nor the names of its contributors,
   14  *    may be used to endorse or promote products derived from this software
   15  *    without specific prior written permission.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   27  * SUCH DAMAGE.
   28  *
   29  * NETLOGIC_BSD */
   30 #include <sys/cdefs.h>
   31 __FBSDID("$FreeBSD: stable/9/sys/mips/nlm/xlp_pci.c 229093 2011-12-31 14:12:12Z hselasky $");
   32 
   33 #include <sys/param.h>
   34 #include <sys/systm.h>
   35 #include <sys/types.h>
   36 #include <sys/kernel.h>
   37 #include <sys/module.h>
   38 #include <sys/malloc.h>
   39 #include <sys/bus.h>
   40 #include <sys/endian.h>
   41 #include <sys/rman.h>
   42 
   43 #include <vm/vm.h>
   44 #include <vm/vm_param.h>
   45 #include <vm/pmap.h>
   46 
   47 #include <sys/pciio.h>
   48 #include <dev/pci/pcivar.h>
   49 #include <dev/pci/pcireg.h>
   50 #include <dev/uart/uart.h>
   51 #include <dev/uart/uart_bus.h>
   52 #include <dev/uart/uart_cpu.h>
   53 
   54 #include <machine/bus.h>
   55 #include <machine/md_var.h>
   56 #include <machine/intr_machdep.h>
   57 #include <machine/cpuregs.h>
   58 
   59 #include <mips/nlm/hal/haldefs.h>
   60 #include <mips/nlm/interrupt.h>
   61 #include <mips/nlm/hal/iomap.h>
   62 #include <mips/nlm/hal/mips-extns.h>
   63 #include <mips/nlm/hal/pic.h>
   64 #include <mips/nlm/hal/pcibus.h>
   65 #include <mips/nlm/hal/uart.h>
   66 #include <mips/nlm/xlp.h>
   67 
   68 #include "pcib_if.h"
   69 
   70 struct xlp_pcib_softc {
   71         bus_dma_tag_t   sc_pci_dmat;    /* PCI DMA tag pointer */
   72 };
   73 
   74 static devclass_t pcib_devclass;
   75 static struct rman irq_rman, port_rman, mem_rman, emul_rman;
   76 
   77 static void
   78 xlp_pci_init_resources(void)
   79 {
   80 
   81         irq_rman.rm_start = 0;
   82         irq_rman.rm_end = 255;
   83         irq_rman.rm_type = RMAN_ARRAY;
   84         irq_rman.rm_descr = "PCI Mapped Interrupts";
   85         if (rman_init(&irq_rman)
   86             || rman_manage_region(&irq_rman, 0, 255))
   87                 panic("pci_init_resources irq_rman");
   88 
   89         port_rman.rm_start = 0;
   90         port_rman.rm_end = ~0ul;
   91         port_rman.rm_type = RMAN_ARRAY;
   92         port_rman.rm_descr = "I/O ports";
   93         if (rman_init(&port_rman)
   94             || rman_manage_region(&port_rman, 0x14000000UL, 0x15ffffffUL))
   95                 panic("pci_init_resources port_rman");
   96 
   97         mem_rman.rm_start = 0;
   98         mem_rman.rm_end = ~0ul;
   99         mem_rman.rm_type = RMAN_ARRAY;
  100         mem_rman.rm_descr = "I/O memory";
  101         if (rman_init(&mem_rman)
  102             || rman_manage_region(&mem_rman, 0xd0000000ULL, 0xdfffffffULL))
  103                 panic("pci_init_resources mem_rman");
  104 
  105         emul_rman.rm_start = 0;
  106         emul_rman.rm_end = ~0ul;
  107         emul_rman.rm_type = RMAN_ARRAY;
  108         emul_rman.rm_descr = "Emulated MEMIO";
  109         if (rman_init(&emul_rman)
  110             || rman_manage_region(&emul_rman, 0x18000000ULL, 0x18ffffffULL))
  111                 panic("pci_init_resources emul_rman");
  112 
  113 }
  114 
  115 static int
  116 xlp_pcib_probe(device_t dev)
  117 {
  118 
  119         device_set_desc(dev, "XLP PCI bus");
  120 
  121         xlp_pci_init_resources();
  122         return (0);
  123 }
  124 
  125 static int
  126 xlp_pcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
  127 {
  128 
  129         switch (which) {
  130         case PCIB_IVAR_DOMAIN:
  131                 *result = 0;
  132                 return (0);
  133         case PCIB_IVAR_BUS:
  134                 *result = 0;
  135                 return (0);
  136         }
  137         return (ENOENT);
  138 }
  139 
  140 static int
  141 xlp_pcib_write_ivar(device_t dev, device_t child, int which, uintptr_t result)
  142 {
  143         switch (which) {
  144         case PCIB_IVAR_DOMAIN:
  145                 return (EINVAL);
  146         case PCIB_IVAR_BUS:
  147                 return (EINVAL);
  148         }
  149         return (ENOENT);
  150 }
  151 
  152 static int
  153 xlp_pcib_maxslots(device_t dev)
  154 {
  155 
  156         return (PCI_SLOTMAX);
  157 }
  158 
  159 static u_int32_t
  160 xlp_pcib_read_config(device_t dev, u_int b, u_int s, u_int f,
  161     u_int reg, int width)
  162 {
  163         uint32_t data = 0;
  164         uint64_t cfgaddr;
  165         int     regindex = reg/sizeof(uint32_t);
  166 
  167         cfgaddr = nlm_pcicfg_base(XLP_HDR_OFFSET(0, b, s, f));
  168         if ((width == 2) && (reg & 1))
  169                 return 0xFFFFFFFF;
  170         else if ((width == 4) && (reg & 3))
  171                 return 0xFFFFFFFF;
  172 
  173         data = nlm_read_pci_reg(cfgaddr, regindex);
  174 
  175         /* 
  176          * Fix up read data in some SoC devices 
  177          * to emulate complete PCIe header
  178          */
  179         if (b == 0) {
  180                 int dev = s % 8;
  181 
  182                 /* Fake intpin on config read for UART/I2C, USB, SD/Flash */
  183                 if (regindex == 0xf && 
  184                     (dev == 6 || dev == 2 || dev == 7))
  185                         data |= 0x1 << 8;       /* Fake int pin */
  186         }
  187 
  188         if (width == 1)
  189                 return ((data >> ((reg & 3) << 3)) & 0xff);
  190         else if (width == 2)
  191                 return ((data >> ((reg & 3) << 3)) & 0xffff);
  192         else
  193                 return (data);
  194 }
  195 
  196 static void
  197 xlp_pcib_write_config(device_t dev, u_int b, u_int s, u_int f,
  198     u_int reg, u_int32_t val, int width)
  199 {
  200         uint64_t cfgaddr;
  201         uint32_t data = 0;
  202         int     regindex = reg / sizeof(uint32_t);
  203 
  204         cfgaddr = nlm_pcicfg_base(XLP_HDR_OFFSET(0, b, s, f));
  205         if ((width == 2) && (reg & 1))
  206                 return;
  207         else if ((width == 4) && (reg & 3))
  208                 return;
  209 
  210         if (width == 1) {
  211                 data = nlm_read_pci_reg(cfgaddr, regindex);
  212                 data = (data & ~(0xff << ((reg & 3) << 3))) |
  213                     (val << ((reg & 3) << 3));
  214         } else if (width == 2) {
  215                 data = nlm_read_pci_reg(cfgaddr, regindex);
  216                 data = (data & ~(0xffff << ((reg & 3) << 3))) |
  217                     (val << ((reg & 3) << 3));
  218         } else {
  219                 data = val;
  220         }
  221 
  222         nlm_write_pci_reg(cfgaddr, regindex, data);
  223 
  224         return;
  225 }
  226 
  227 static int 
  228 xlp_pcib_attach(device_t dev)
  229 {
  230         struct xlp_pcib_softc *sc;
  231         sc = device_get_softc(dev);
  232 
  233         device_add_child(dev, "pci", 0);
  234         bus_generic_attach(dev);
  235 
  236         return (0);
  237 }
  238 
  239 static void
  240 xlp_pcib_identify(driver_t * driver, device_t parent)
  241 {
  242 
  243         BUS_ADD_CHILD(parent, 0, "pcib", 0);
  244 }
  245 
  246 /*
  247  * XLS PCIe can have upto 4 links, and each link has its on IRQ
  248  * Find the link on which the device is on 
  249  */
  250 static int
  251 xlp_pcie_link(device_t pcib, device_t dev)
  252 {
  253         device_t parent, tmp;
  254 
  255         /* find the lane on which the slot is connected to */
  256         printf("xlp_pcie_link : bus %s dev %s\n", device_get_nameunit(pcib),
  257                 device_get_nameunit(dev));
  258         tmp = dev;
  259         while (1) {
  260                 parent = device_get_parent(tmp);
  261                 if (parent == NULL || parent == pcib) {
  262                         device_printf(dev, "Cannot find parent bus\n");
  263                         return (-1);
  264                 }
  265                 if (strcmp(device_get_nameunit(parent), "pci0") == 0)
  266                         break;
  267                 tmp = parent;
  268         }
  269         return (pci_get_function(tmp));
  270 }
  271 
  272 /*
  273  * Find the IRQ for the link, each link has a different interrupt 
  274  * at the XLP pic
  275  */
  276 static int
  277 xlp_pcie_link_irt(int link)
  278 {
  279 
  280         if( (link < 0) || (link > 3))
  281                 return (-1);
  282 
  283         return PIC_IRT_PCIE_LINK_INDEX(link);
  284 }
  285 
  286 static int
  287 xlp_alloc_msi(device_t pcib, device_t dev, int count, int maxcount, int *irqs)
  288 {
  289         int i, link;
  290 
  291         /*
  292          * Each link has 32 MSIs that can be allocated, but for now
  293          * we only support one device per link.
  294          * msi_alloc() equivalent is needed when we start supporting 
  295          * bridges on the PCIe link.
  296          */
  297         link = xlp_pcie_link(pcib, dev);
  298         if (link == -1)
  299                 return (ENXIO);
  300 
  301         /*
  302          * encode the irq so that we know it is a MSI interrupt when we
  303          * setup interrupts
  304          */
  305         for (i = 0; i < count; i++)
  306                 irqs[i] = 64 + link * 32 + i;
  307 
  308         return (0);
  309 }
  310 
  311 static int
  312 xlp_release_msi(device_t pcib, device_t dev, int count, int *irqs)
  313 {
  314         device_printf(dev, "%s: msi release %d\n", device_get_nameunit(pcib),
  315             count);
  316         return (0);
  317 }
  318 
  319 static int
  320 xlp_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr,
  321     uint32_t *data)
  322 {
  323         int msi, irt;
  324 
  325         if (irq >= 64) {
  326                 msi = irq - 64;
  327                 *addr = MIPS_MSI_ADDR(0);
  328 
  329                 irt = xlp_pcie_link_irt(msi/32);
  330                 if (irt != -1)
  331                         *data = MIPS_MSI_DATA(xlp_irt_to_irq(irt));
  332                 return (0);
  333         } else {
  334                 device_printf(dev, "%s: map_msi for irq %d  - ignored", 
  335                     device_get_nameunit(pcib), irq);
  336                 return (ENXIO);
  337         }
  338 }
  339 
  340 static void
  341 bridge_pcie_ack(int irq)
  342 {
  343         uint32_t node,reg;
  344         uint64_t base;
  345 
  346         node = nlm_nodeid();
  347         reg = PCIE_MSI_STATUS;
  348 
  349         switch(irq) {
  350                 case PIC_PCIE_0_IRQ:
  351                         base = nlm_pcicfg_base(XLP_IO_PCIE0_OFFSET(node));
  352                         break;
  353                 case PIC_PCIE_1_IRQ:
  354                         base = nlm_pcicfg_base(XLP_IO_PCIE1_OFFSET(node));
  355                         break;
  356                 case PIC_PCIE_2_IRQ:
  357                         base = nlm_pcicfg_base(XLP_IO_PCIE2_OFFSET(node));
  358                         break;
  359                 case PIC_PCIE_3_IRQ:
  360                         base = nlm_pcicfg_base(XLP_IO_PCIE3_OFFSET(node));
  361                         break;
  362                 default:
  363                         return;
  364         }
  365 
  366         nlm_write_pci_reg(base, reg, 0xFFFFFFFF);
  367 
  368         return;
  369 }
  370 
  371 static int
  372 mips_platform_pci_setup_intr(device_t dev, device_t child,
  373     struct resource *irq, int flags, driver_filter_t *filt,
  374     driver_intr_t *intr, void *arg, void **cookiep)
  375 {
  376         int error = 0;
  377         int xlpirq;
  378         int node,base,val,link;
  379         void *extra_ack;
  380 
  381         error = rman_activate_resource(irq);
  382         if (error)
  383                 return error;
  384         if (rman_get_start(irq) != rman_get_end(irq)) {
  385                 device_printf(dev, "Interrupt allocation %lu != %lu\n",
  386                     rman_get_start(irq), rman_get_end(irq));
  387                 return (EINVAL);
  388         }
  389         xlpirq = rman_get_start(irq);
  390         device_printf(dev, "setup intr %d\n", xlpirq);
  391 
  392         if (strcmp(device_get_name(dev), "pcib") != 0) {
  393                 device_printf(dev, "ret 0 on dev\n");
  394                 return (0);
  395         }
  396 
  397         /* 
  398          * temporary hack for MSI, we support just one device per
  399          * link, and assign the link interrupt to the device interrupt
  400          */
  401         if (xlpirq >= 64) {
  402                 xlpirq -= 64;
  403                 if (xlpirq % 32 != 0)
  404                         return (0);
  405 
  406                 node = nlm_nodeid();
  407                 link = (xlpirq / 32);
  408                 base = nlm_pcicfg_base(XLP_IO_PCIE_OFFSET(node,link));
  409 
  410                 /* MSI Interrupt Vector enable at bridge's configuration */
  411                 nlm_write_pci_reg(base, PCIE_MSI_EN, PCIE_MSI_VECTOR_INT_EN);
  412 
  413                 val = nlm_read_pci_reg(base, PCIE_INT_EN0);
  414                 /* MSI Interrupt enable at bridge's configuration */
  415                 nlm_write_pci_reg(base, PCIE_INT_EN0,
  416                                 (val | PCIE_MSI_INT_EN));
  417 
  418                 /* legacy interrupt disable at bridge */
  419                 val = nlm_read_pci_reg(base, PCIE_BRIDGE_CMD);
  420                 nlm_write_pci_reg(base, PCIE_BRIDGE_CMD,
  421                                 (val | PCIM_CMD_INTxDIS));
  422 
  423                 /* MSI address update at bridge */
  424                 val = nlm_read_pci_reg(base, PCIE_BRIDGE_MSI_ADDRL);
  425                 nlm_write_pci_reg(base, PCIE_BRIDGE_MSI_ADDRL,
  426                                 (val | MSI_MIPS_ADDR_BASE));
  427 
  428                 val = nlm_read_pci_reg(base, PCIE_BRIDGE_MSI_CAP);
  429                 /* MSI capability enable at bridge */
  430                 nlm_write_pci_reg(base, PCIE_BRIDGE_MSI_CAP, 
  431                                 (val |
  432                                 (PCIM_MSICTRL_MSI_ENABLE << 16) |
  433                                 (PCIM_MSICTRL_MMC_32 << 16)));
  434 
  435                 xlpirq = xlp_pcie_link_irt(xlpirq / 32);
  436                 if (xlpirq == -1)
  437                         return (EINVAL);
  438                 xlpirq = xlp_irt_to_irq(xlpirq);
  439         }
  440         /* Set all irqs to CPU 0 for now */
  441         nlm_pic_write_irt_direct(xlp_pic_base, xlp_irq_to_irt(xlpirq), 1, 0,
  442                                  PIC_LOCAL_SCHEDULING, xlpirq, 0);
  443         extra_ack = NULL;
  444         if (xlpirq >= PIC_PCIE_0_IRQ &&
  445             xlpirq <= PIC_PCIE_3_IRQ)
  446                 extra_ack = bridge_pcie_ack;
  447         xlp_establish_intr(device_get_name(child), filt,
  448             intr, arg, xlpirq, flags, cookiep, extra_ack);
  449 
  450         return (0);
  451 }
  452 
  453 static int
  454 mips_platform_pci_teardown_intr(device_t dev, device_t child,
  455     struct resource *irq, void *cookie)
  456 {
  457         if (strcmp(device_get_name(child), "pci") == 0) {
  458                 /* if needed reprogram the pic to clear pcix related entry */
  459                 device_printf(dev, "teardown intr\n");
  460         }
  461         return (bus_generic_teardown_intr(dev, child, irq, cookie));
  462 }
  463 
  464 static void
  465 assign_soc_resource(device_t child, int type, u_long *startp, u_long *endp,
  466     u_long *countp, struct rman **rm, bus_space_tag_t *bst, vm_offset_t *va)
  467 {
  468         int devid = pci_get_device(child);
  469         int inst = pci_get_function(child);
  470         int node = pci_get_slot(child) / 8;
  471 
  472         *rm = NULL;
  473         *va = 0;
  474         *bst = 0;
  475         switch (devid) {
  476         case PCI_DEVICE_ID_NLM_UART:
  477                 switch (type) {
  478                 case SYS_RES_IRQ:
  479                         *startp = *endp = PIC_UART_0_IRQ + inst;
  480                         *countp = 1;
  481                         break;
  482                 case SYS_RES_MEMORY: 
  483                         *va = nlm_get_uart_regbase(node, inst);
  484                         *startp = MIPS_KSEG1_TO_PHYS(va);
  485                         *countp = 0x100;
  486                         *rm = &emul_rman;
  487                         *bst = uart_bus_space_mem;
  488                         break;
  489                 };
  490                 break;
  491 
  492         case PCI_DEVICE_ID_NLM_EHCI:
  493                 if (type == SYS_RES_IRQ) {
  494                         if (inst == 0)
  495                                 *startp = *endp = PIC_EHCI_0_IRQ;
  496                         else if (inst == 3)
  497                                 *startp = *endp = PIC_EHCI_1_IRQ;
  498                         else
  499                                 device_printf(child, "bad instance %d\n", inst);
  500 
  501                         *countp = 1; 
  502                 }
  503                 break;
  504         }
  505 
  506         /* default to rmi_bus_space for SoC resources */
  507         if (type == SYS_RES_MEMORY && *bst == 0)
  508                 *bst = rmi_bus_space;
  509 }
  510 
  511 static struct resource *
  512 xlp_pci_alloc_resource(device_t bus, device_t child, int type, int *rid,
  513     u_long start, u_long end, u_long count, u_int flags)
  514 {
  515         struct rman *rm = NULL;
  516         struct resource *rv;
  517         vm_offset_t va = 0;
  518         int needactivate = flags & RF_ACTIVE;
  519         bus_space_tag_t bst = 0;
  520 
  521         /*
  522          * For SoC PCI devices, we have to assign resources correctly
  523          * since the IRQ and MEM resources depend on the block.
  524          * If the address is not from BAR0, then we use emul_rman
  525          */
  526         if (pci_get_bus(child) == 0 &&
  527             pci_get_vendor(child) == PCI_VENDOR_NETLOGIC)
  528                 assign_soc_resource(child, type, &start, &end,
  529                     &count, &rm, &bst, &va);
  530         if (rm == NULL) {
  531                 switch (type) {
  532                 case SYS_RES_IRQ:
  533                         rm = &irq_rman;
  534                         break;
  535         
  536                 case SYS_RES_IOPORT:
  537                         rm = &port_rman;
  538                         break;
  539 
  540                 case SYS_RES_MEMORY:
  541                         rm = &mem_rman;
  542                         break;
  543 
  544                 default:
  545                         return (0);
  546                 }
  547         }
  548 
  549         rv = rman_reserve_resource(rm, start, end, count, flags, child);
  550         if (rv == 0)
  551                 return (0);
  552 
  553         rman_set_rid(rv, *rid);
  554 
  555         if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) {
  556                 if (va == 0)
  557                         va = (vm_offset_t)pmap_mapdev(start, count);
  558                 if (bst == 0)
  559                         bst = rmi_pci_bus_space;
  560 
  561                 rman_set_bushandle(rv, va);
  562                 rman_set_virtual(rv, (void *)va);
  563                 rman_set_bustag(rv, bst);
  564         }
  565 
  566         if (needactivate) {
  567                 if (bus_activate_resource(child, type, *rid, rv)) {
  568                         rman_release_resource(rv);
  569                         return (NULL);
  570                 }
  571         }
  572 
  573         return (rv);
  574 }
  575 
  576 static int
  577 xlp_pci_release_resource(device_t bus, device_t child, int type, int rid,
  578     struct resource *r)
  579 {
  580 
  581         return (rman_release_resource(r));
  582 }
  583 
  584 static bus_dma_tag_t
  585 xlp_pci_get_dma_tag(device_t bus, device_t child)
  586 {
  587         struct xlp_pcib_softc *sc;
  588 
  589         sc = device_get_softc(bus);
  590         return (sc->sc_pci_dmat);
  591 }
  592 
  593 static int
  594 xlp_pci_activate_resource(device_t bus, device_t child, int type, int rid,
  595     struct resource *r)
  596 {
  597 
  598         return (rman_activate_resource(r));
  599 }
  600 
  601 static int
  602 xlp_pci_deactivate_resource(device_t bus, device_t child, int type, int rid,
  603     struct resource *r)
  604 {
  605 
  606         return (rman_deactivate_resource(r));
  607 }
  608 
  609 static int
  610 mips_pci_route_interrupt(device_t bus, device_t dev, int pin)
  611 {
  612         int irt, link;
  613 
  614         /*
  615          * Validate requested pin number.
  616          */
  617         device_printf(bus, "route  %s %d", device_get_nameunit(dev), pin);
  618         if ((pin < 1) || (pin > 4))
  619                 return (255);
  620 
  621         link = xlp_pcie_link(bus, dev);
  622         irt = xlp_pcie_link_irt(link);
  623         if (irt != -1)
  624                 return (xlp_irt_to_irq(irt));
  625 
  626         return (255);
  627 }
  628 
  629 static device_method_t xlp_pcib_methods[] = {
  630         /* Device interface */
  631         DEVMETHOD(device_identify, xlp_pcib_identify),
  632         DEVMETHOD(device_probe, xlp_pcib_probe),
  633         DEVMETHOD(device_attach, xlp_pcib_attach),
  634 
  635         /* Bus interface */
  636         DEVMETHOD(bus_read_ivar, xlp_pcib_read_ivar),
  637         DEVMETHOD(bus_write_ivar, xlp_pcib_write_ivar),
  638         DEVMETHOD(bus_alloc_resource, xlp_pci_alloc_resource),
  639         DEVMETHOD(bus_release_resource, xlp_pci_release_resource),
  640         DEVMETHOD(bus_get_dma_tag, xlp_pci_get_dma_tag),
  641         DEVMETHOD(bus_activate_resource, xlp_pci_activate_resource),
  642         DEVMETHOD(bus_deactivate_resource, xlp_pci_deactivate_resource),
  643         DEVMETHOD(bus_setup_intr, mips_platform_pci_setup_intr),
  644         DEVMETHOD(bus_teardown_intr, mips_platform_pci_teardown_intr),
  645 
  646         /* pcib interface */
  647         DEVMETHOD(pcib_maxslots, xlp_pcib_maxslots),
  648         DEVMETHOD(pcib_read_config, xlp_pcib_read_config),
  649         DEVMETHOD(pcib_write_config, xlp_pcib_write_config),
  650         DEVMETHOD(pcib_route_interrupt, mips_pci_route_interrupt),
  651 
  652         DEVMETHOD(pcib_alloc_msi, xlp_alloc_msi),
  653         DEVMETHOD(pcib_release_msi, xlp_release_msi),
  654         DEVMETHOD(pcib_map_msi, xlp_map_msi),
  655 
  656         DEVMETHOD_END
  657 };
  658 
  659 static driver_t xlp_pcib_driver = {
  660         "pcib",
  661         xlp_pcib_methods,
  662         sizeof(struct xlp_pcib_softc),
  663 };
  664 
  665 DRIVER_MODULE(pcib, nexus, xlp_pcib_driver, pcib_devclass, 0, 0);

Cache object: 0466b5b7321e032ef7e0b968d60e0e34


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