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/pci/vga_pci.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) 2005 John Baldwin <jhb@FreeBSD.org>
    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 the author nor the names of any co-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 
   30 #include <sys/cdefs.h>
   31 __FBSDID("$FreeBSD: releng/9.0/sys/dev/pci/vga_pci.c 216590 2010-12-20 14:54:24Z jhb $");
   32 
   33 /*
   34  * Simple driver for PCI VGA display devices.  Drivers such as agp(4) and
   35  * drm(4) should attach as children of this device.
   36  *
   37  * XXX: The vgapci name is a hack until we somehow merge the isa vga driver
   38  * in or rename it.
   39  */
   40 
   41 #include <sys/param.h>
   42 #include <sys/bus.h>
   43 #include <sys/kernel.h>
   44 #include <sys/module.h>
   45 #include <sys/rman.h>
   46 #include <sys/sysctl.h>
   47 #include <sys/systm.h>
   48 
   49 #include <dev/pci/pcireg.h>
   50 #include <dev/pci/pcivar.h>
   51 
   52 struct vga_resource {
   53         struct resource *vr_res;
   54         int     vr_refs;
   55 };
   56 
   57 struct vga_pci_softc {
   58         device_t        vga_msi_child;  /* Child driver using MSI. */
   59         struct vga_resource vga_res[PCIR_MAX_BAR_0 + 1];
   60 };
   61 
   62 SYSCTL_DECL(_hw_pci);
   63 
   64 int vga_pci_default_unit = -1;
   65 TUNABLE_INT("hw.pci.default_vgapci_unit", &vga_pci_default_unit);
   66 SYSCTL_INT(_hw_pci, OID_AUTO, default_vgapci_unit, CTLFLAG_RDTUN,
   67     &vga_pci_default_unit, -1, "Default VGA-compatible display");
   68 
   69 static int
   70 vga_pci_probe(device_t dev)
   71 {
   72         device_t bdev;
   73         int unit;
   74         uint16_t bctl;
   75 
   76         switch (pci_get_class(dev)) {
   77         case PCIC_DISPLAY:
   78                 break;
   79         case PCIC_OLD:
   80                 if (pci_get_subclass(dev) != PCIS_OLD_VGA)
   81                         return (ENXIO);
   82                 break;
   83         default:
   84                 return (ENXIO);
   85         }
   86 
   87         /* Probe default display. */
   88         unit = device_get_unit(dev);
   89         bdev = device_get_parent(device_get_parent(dev));
   90         bctl = pci_read_config(bdev, PCIR_BRIDGECTL_1, 2);
   91         if (vga_pci_default_unit < 0 && (bctl & PCIB_BCR_VGA_ENABLE) != 0)
   92                 vga_pci_default_unit = unit;
   93         if (vga_pci_default_unit == unit)
   94                 device_set_flags(dev, 1);
   95 
   96         device_set_desc(dev, "VGA-compatible display");
   97         return (BUS_PROBE_GENERIC);
   98 }
   99 
  100 static int
  101 vga_pci_attach(device_t dev)
  102 {
  103 
  104         bus_generic_probe(dev);
  105 
  106         /* Always create a drm child for now to make it easier on drm. */
  107         device_add_child(dev, "drm", -1);
  108         bus_generic_attach(dev);
  109         return (0);
  110 }
  111 
  112 static int
  113 vga_pci_suspend(device_t dev)
  114 {
  115 
  116         return (bus_generic_suspend(dev));
  117 }
  118 
  119 static int
  120 vga_pci_resume(device_t dev)
  121 {
  122 
  123         return (bus_generic_resume(dev));
  124 }
  125 
  126 /* Bus interface. */
  127 
  128 static int
  129 vga_pci_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
  130 {
  131 
  132         return (BUS_READ_IVAR(device_get_parent(dev), dev, which, result));
  133 }
  134 
  135 static int
  136 vga_pci_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
  137 {
  138 
  139         return (EINVAL);
  140 }
  141 
  142 static int
  143 vga_pci_setup_intr(device_t dev, device_t child, struct resource *irq,
  144     int flags, driver_filter_t *filter, driver_intr_t *intr, void *arg,
  145     void **cookiep)
  146 {
  147         return (BUS_SETUP_INTR(device_get_parent(dev), dev, irq, flags,
  148             filter, intr, arg, cookiep));
  149 }
  150 
  151 static int
  152 vga_pci_teardown_intr(device_t dev, device_t child, struct resource *irq,
  153     void *cookie)
  154 {
  155         return (BUS_TEARDOWN_INTR(device_get_parent(dev), dev, irq, cookie));
  156 }
  157 
  158 static struct resource *
  159 vga_pci_alloc_resource(device_t dev, device_t child, int type, int *rid,
  160     u_long start, u_long end, u_long count, u_int flags)
  161 {
  162         struct vga_pci_softc *sc;
  163         int bar;
  164 
  165         switch (type) {
  166         case SYS_RES_MEMORY:
  167         case SYS_RES_IOPORT:
  168                 /*
  169                  * For BARs, we cache the resource so that we only allocate it
  170                  * from the PCI bus once.
  171                  */
  172                 bar = PCI_RID2BAR(*rid);
  173                 if (bar < 0 || bar > PCIR_MAX_BAR_0)
  174                         return (NULL);
  175                 sc = device_get_softc(dev);
  176                 if (sc->vga_res[bar].vr_res == NULL)
  177                         sc->vga_res[bar].vr_res = bus_alloc_resource(dev, type,
  178                             rid, start, end, count, flags);
  179                 if (sc->vga_res[bar].vr_res != NULL)
  180                         sc->vga_res[bar].vr_refs++;
  181                 return (sc->vga_res[bar].vr_res);
  182         }
  183         return (bus_alloc_resource(dev, type, rid, start, end, count, flags));
  184 }
  185 
  186 static int
  187 vga_pci_release_resource(device_t dev, device_t child, int type, int rid,
  188     struct resource *r)
  189 {
  190         struct vga_pci_softc *sc;
  191         int bar, error;
  192 
  193         switch (type) {
  194         case SYS_RES_MEMORY:
  195         case SYS_RES_IOPORT:
  196                 /*
  197                  * For BARs, we release the resource from the PCI bus
  198                  * when the last child reference goes away.
  199                  */
  200                 bar = PCI_RID2BAR(rid);
  201                 if (bar < 0 || bar > PCIR_MAX_BAR_0)
  202                         return (EINVAL);
  203                 sc = device_get_softc(dev);
  204                 if (sc->vga_res[bar].vr_res == NULL)
  205                         return (EINVAL);
  206                 KASSERT(sc->vga_res[bar].vr_res == r,
  207                     ("vga_pci resource mismatch"));
  208                 if (sc->vga_res[bar].vr_refs > 1) {
  209                         sc->vga_res[bar].vr_refs--;
  210                         return (0);
  211                 }
  212                 KASSERT(sc->vga_res[bar].vr_refs > 0,
  213                     ("vga_pci resource reference count underflow"));
  214                 error = bus_release_resource(dev, type, rid, r);
  215                 if (error == 0) {
  216                         sc->vga_res[bar].vr_res = NULL;
  217                         sc->vga_res[bar].vr_refs = 0;
  218                 }
  219                 return (error);
  220         }
  221 
  222         return (bus_release_resource(dev, type, rid, r));
  223 }
  224 
  225 /* PCI interface. */
  226 
  227 static uint32_t
  228 vga_pci_read_config(device_t dev, device_t child, int reg, int width)
  229 {
  230 
  231         return (pci_read_config(dev, reg, width));
  232 }
  233 
  234 static void
  235 vga_pci_write_config(device_t dev, device_t child, int reg,
  236     uint32_t val, int width)
  237 {
  238 
  239         pci_write_config(dev, reg, val, width);
  240 }
  241 
  242 static int
  243 vga_pci_enable_busmaster(device_t dev, device_t child)
  244 {
  245 
  246         return (pci_enable_busmaster(dev));
  247 }
  248 
  249 static int
  250 vga_pci_disable_busmaster(device_t dev, device_t child)
  251 {
  252 
  253         return (pci_disable_busmaster(dev));
  254 }
  255 
  256 static int
  257 vga_pci_enable_io(device_t dev, device_t child, int space)
  258 {
  259 
  260         device_printf(dev, "child %s requested pci_enable_io\n",
  261             device_get_nameunit(child));
  262         return (pci_enable_io(dev, space));
  263 }
  264 
  265 static int
  266 vga_pci_disable_io(device_t dev, device_t child, int space)
  267 {
  268 
  269         device_printf(dev, "child %s requested pci_disable_io\n",
  270             device_get_nameunit(child));
  271         return (pci_disable_io(dev, space));
  272 }
  273 
  274 static int
  275 vga_pci_get_vpd_ident(device_t dev, device_t child, const char **identptr)
  276 {
  277 
  278         return (pci_get_vpd_ident(dev, identptr));
  279 }
  280 
  281 static int
  282 vga_pci_get_vpd_readonly(device_t dev, device_t child, const char *kw,
  283     const char **vptr)
  284 {
  285 
  286         return (pci_get_vpd_readonly(dev, kw, vptr));
  287 }
  288 
  289 static int
  290 vga_pci_set_powerstate(device_t dev, device_t child, int state)
  291 {
  292 
  293         device_printf(dev, "child %s requested pci_set_powerstate\n",
  294             device_get_nameunit(child));
  295         return (pci_set_powerstate(dev, state));
  296 }
  297 
  298 static int
  299 vga_pci_get_powerstate(device_t dev, device_t child)
  300 {
  301 
  302         device_printf(dev, "child %s requested pci_get_powerstate\n",
  303             device_get_nameunit(child));
  304         return (pci_get_powerstate(dev));
  305 }
  306 
  307 static int
  308 vga_pci_assign_interrupt(device_t dev, device_t child)
  309 {
  310 
  311         device_printf(dev, "child %s requested pci_assign_interrupt\n",
  312             device_get_nameunit(child));
  313         return (PCI_ASSIGN_INTERRUPT(device_get_parent(dev), dev));
  314 }
  315 
  316 static int
  317 vga_pci_find_extcap(device_t dev, device_t child, int capability,
  318     int *capreg)
  319 {
  320 
  321         return (pci_find_extcap(dev, capability, capreg));
  322 }
  323 
  324 static int
  325 vga_pci_alloc_msi(device_t dev, device_t child, int *count)
  326 {
  327         struct vga_pci_softc *sc;
  328         int error;
  329 
  330         sc = device_get_softc(dev);
  331         if (sc->vga_msi_child != NULL)
  332                 return (EBUSY);
  333         error = pci_alloc_msi(dev, count);
  334         if (error == 0)
  335                 sc->vga_msi_child = child;
  336         return (error);
  337 }
  338 
  339 static int
  340 vga_pci_alloc_msix(device_t dev, device_t child, int *count)
  341 {
  342         struct vga_pci_softc *sc;
  343         int error;
  344 
  345         sc = device_get_softc(dev);
  346         if (sc->vga_msi_child != NULL)
  347                 return (EBUSY);
  348         error = pci_alloc_msix(dev, count);
  349         if (error == 0)
  350                 sc->vga_msi_child = child;
  351         return (error);
  352 }
  353 
  354 static int
  355 vga_pci_remap_msix(device_t dev, device_t child, int count,
  356     const u_int *vectors)
  357 {
  358         struct vga_pci_softc *sc;
  359 
  360         sc = device_get_softc(dev);
  361         if (sc->vga_msi_child != child)
  362                 return (ENXIO);
  363         return (pci_remap_msix(dev, count, vectors));
  364 }
  365 
  366 static int
  367 vga_pci_release_msi(device_t dev, device_t child)
  368 {
  369         struct vga_pci_softc *sc;
  370         int error;
  371 
  372         sc = device_get_softc(dev);
  373         if (sc->vga_msi_child != child)
  374                 return (ENXIO);
  375         error = pci_release_msi(dev);
  376         if (error == 0)
  377                 sc->vga_msi_child = NULL;
  378         return (error);
  379 }
  380 
  381 static int
  382 vga_pci_msi_count(device_t dev, device_t child)
  383 {
  384 
  385         return (pci_msi_count(dev));
  386 }
  387 
  388 static int
  389 vga_pci_msix_count(device_t dev, device_t child)
  390 {
  391 
  392         return (pci_msix_count(dev));
  393 }
  394 
  395 static device_method_t vga_pci_methods[] = {
  396         /* Device interface */
  397         DEVMETHOD(device_probe,         vga_pci_probe),
  398         DEVMETHOD(device_attach,        vga_pci_attach),
  399         DEVMETHOD(device_shutdown,      bus_generic_shutdown),
  400         DEVMETHOD(device_suspend,       vga_pci_suspend),
  401         DEVMETHOD(device_resume,        vga_pci_resume),
  402 
  403         /* Bus interface */
  404         DEVMETHOD(bus_read_ivar,        vga_pci_read_ivar),
  405         DEVMETHOD(bus_write_ivar,       vga_pci_write_ivar),
  406         DEVMETHOD(bus_setup_intr,       vga_pci_setup_intr),
  407         DEVMETHOD(bus_teardown_intr,    vga_pci_teardown_intr),
  408         DEVMETHOD(bus_alloc_resource,   vga_pci_alloc_resource),
  409         DEVMETHOD(bus_release_resource, vga_pci_release_resource),
  410         DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
  411         DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
  412 
  413         /* PCI interface */
  414         DEVMETHOD(pci_read_config,      vga_pci_read_config),
  415         DEVMETHOD(pci_write_config,     vga_pci_write_config),
  416         DEVMETHOD(pci_enable_busmaster, vga_pci_enable_busmaster),
  417         DEVMETHOD(pci_disable_busmaster, vga_pci_disable_busmaster),
  418         DEVMETHOD(pci_enable_io,        vga_pci_enable_io),
  419         DEVMETHOD(pci_disable_io,       vga_pci_disable_io),
  420         DEVMETHOD(pci_get_vpd_ident,    vga_pci_get_vpd_ident),
  421         DEVMETHOD(pci_get_vpd_readonly, vga_pci_get_vpd_readonly),
  422         DEVMETHOD(pci_get_powerstate,   vga_pci_get_powerstate),
  423         DEVMETHOD(pci_set_powerstate,   vga_pci_set_powerstate),
  424         DEVMETHOD(pci_assign_interrupt, vga_pci_assign_interrupt),
  425         DEVMETHOD(pci_find_extcap,      vga_pci_find_extcap),
  426         DEVMETHOD(pci_alloc_msi,        vga_pci_alloc_msi),
  427         DEVMETHOD(pci_alloc_msix,       vga_pci_alloc_msix),
  428         DEVMETHOD(pci_remap_msix,       vga_pci_remap_msix),
  429         DEVMETHOD(pci_release_msi,      vga_pci_release_msi),
  430         DEVMETHOD(pci_msi_count,        vga_pci_msi_count),
  431         DEVMETHOD(pci_msix_count,       vga_pci_msix_count),
  432 
  433         { 0, 0 }
  434 };
  435 
  436 static driver_t vga_pci_driver = {
  437         "vgapci",
  438         vga_pci_methods,
  439         sizeof(struct vga_pci_softc),
  440 };
  441 
  442 static devclass_t vga_devclass;
  443 
  444 DRIVER_MODULE(vgapci, pci, vga_pci_driver, vga_devclass, 0, 0);

Cache object: 0bf748e30f55e8b17b94ae39f33507e5


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