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/pci/agp_amd64.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) 2004 Jung-uk Kim
    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  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  */
   26 
   27 #include <sys/cdefs.h>
   28 __FBSDID("$FreeBSD$");
   29 
   30 #include "opt_bus.h"
   31 
   32 #include <sys/param.h>
   33 #include <sys/systm.h>
   34 #include <sys/malloc.h>
   35 #include <sys/kernel.h>
   36 #include <sys/module.h>
   37 #include <sys/bus.h>
   38 #include <sys/lock.h>
   39 #include <sys/mutex.h>
   40 #include <sys/proc.h>
   41 
   42 #include <dev/pci/pcivar.h>
   43 #include <dev/pci/pcireg.h>
   44 #include <pci/agppriv.h>
   45 #include <pci/agpreg.h>
   46 
   47 #include <vm/vm.h>
   48 #include <vm/vm_object.h>
   49 #include <vm/pmap.h>
   50 #include <machine/bus.h>
   51 #include <machine/resource.h>
   52 #include <sys/rman.h>
   53 
   54 /* XXX */
   55 extern void pci_cfgregwrite(int, int, int, int, uint32_t, int);
   56 extern uint32_t pci_cfgregread(int, int, int, int, int);
   57 
   58 MALLOC_DECLARE(M_AGP);
   59 
   60 #define AMD64_MAX_MCTRL         8
   61 
   62 struct agp_amd64_softc {
   63         struct agp_softc        agp;
   64         uint32_t        initial_aperture; /* aperture size at startup */
   65         struct agp_gatt *gatt;
   66         int             mctrl[AMD64_MAX_MCTRL];
   67         int             n_mctrl;
   68 };
   69 
   70 static const char*
   71 agp_amd64_match(device_t dev)
   72 {
   73         if (pci_get_class(dev) != PCIC_BRIDGE
   74             || pci_get_subclass(dev) != PCIS_BRIDGE_HOST)
   75                 return NULL;
   76 
   77         if (agp_find_caps(dev) == 0)
   78                 return NULL;
   79 
   80         switch (pci_get_devid(dev)) {
   81         case 0x74541022:
   82                 return ("AMD 8151 AGP graphics tunnel");
   83         case 0x07551039:
   84                 return ("SiS 755 host to AGP bridge");
   85         case 0x02041106:
   86                 return ("VIA 8380 host to PCI bridge");
   87         case 0x02821106:
   88                 return ("VIA K8T800Pro host to PCI bridge");
   89         case 0x31881106:
   90                 return ("VIA 8385 host to PCI bridge");
   91         };
   92 
   93         return NULL;
   94 }
   95 
   96 static int
   97 agp_amd64_probe(device_t dev)
   98 {
   99         const char *desc;
  100 
  101         if (resource_disabled("agp", device_get_unit(dev)))
  102                 return ENXIO;
  103         if ((desc = agp_amd64_match(dev))) {
  104                 device_verbose(dev);
  105                 device_set_desc(dev, desc);
  106                 return BUS_PROBE_DEFAULT;
  107         }
  108 
  109         return ENXIO;
  110 }
  111 
  112 static int
  113 agp_amd64_attach(device_t dev)
  114 {
  115         struct agp_amd64_softc *sc = device_get_softc(dev);
  116         struct agp_gatt *gatt;
  117         int i, n, error;
  118 
  119         for (i = 0, n = 0; i < PCI_SLOTMAX && n < AMD64_MAX_MCTRL; i++)
  120                 if (pci_cfgregread(0, i, 3, 0, 4) == 0x11031022) {
  121                         sc->mctrl[n] = i;
  122                         n++;
  123                 }
  124 
  125         if (n == 0)
  126                 return ENXIO;
  127 
  128         sc->n_mctrl = n;
  129 
  130         if (bootverbose)
  131                 printf("AMD64: %d Misc. Control unit(s) found.\n", sc->n_mctrl);
  132 
  133         if ((error = agp_generic_attach(dev)))
  134                 return error;
  135 
  136         sc->initial_aperture = AGP_GET_APERTURE(dev);
  137 
  138         for (;;) {
  139                 gatt = agp_alloc_gatt(dev);
  140                 if (gatt)
  141                         break;
  142 
  143                 /*
  144                  * Probably contigmalloc failure. Try reducing the
  145                  * aperture so that the gatt size reduces.
  146                  */
  147                 if (AGP_SET_APERTURE(dev, AGP_GET_APERTURE(dev) / 2)) {
  148                         agp_generic_detach(dev);
  149                         return ENOMEM;
  150                 }
  151         }
  152         sc->gatt = gatt;
  153 
  154         /* Install the gatt and enable aperture. */
  155         for (i = 0; i < sc->n_mctrl; i++) {
  156                 pci_cfgregwrite(0, sc->mctrl[i], 3, AGP_AMD64_ATTBASE,
  157                     (uint32_t)(gatt->ag_physical >> 8) & AGP_AMD64_ATTBASE_MASK,
  158                     4);
  159                 pci_cfgregwrite(0, sc->mctrl[i], 3, AGP_AMD64_APCTRL,
  160                     (pci_cfgregread(0, sc->mctrl[i], 3, AGP_AMD64_APCTRL, 4) |
  161                     AGP_AMD64_APCTRL_GARTEN) &
  162                     ~(AGP_AMD64_APCTRL_DISGARTCPU | AGP_AMD64_APCTRL_DISGARTIO),
  163                     4);
  164         }
  165 
  166         agp_flush_cache();
  167 
  168         return 0;
  169 }
  170 
  171 static int
  172 agp_amd64_detach(device_t dev)
  173 {
  174         struct agp_amd64_softc *sc = device_get_softc(dev);
  175         int i, error;
  176 
  177         if ((error = agp_generic_detach(dev)))
  178                 return error;
  179 
  180         for (i = 0; i < sc->n_mctrl; i++)
  181                 pci_cfgregwrite(0, sc->mctrl[i], 3, AGP_AMD64_APCTRL,
  182                     pci_cfgregread(0, sc->mctrl[i], 3, AGP_AMD64_APCTRL, 4) &
  183                     ~AGP_AMD64_APCTRL_GARTEN, 4);
  184 
  185         AGP_SET_APERTURE(dev, sc->initial_aperture);
  186         agp_free_gatt(sc->gatt);
  187 
  188         return 0;
  189 }
  190 
  191 static uint32_t agp_amd64_table[] = {
  192         0x02000000,     /*   32 MB */
  193         0x04000000,     /*   64 MB */
  194         0x08000000,     /*  128 MB */
  195         0x10000000,     /*  256 MB */
  196         0x20000000,     /*  512 MB */
  197         0x40000000,     /* 1024 MB */
  198         0x80000000,     /* 2048 MB */
  199 };
  200 
  201 #define AGP_AMD64_TABLE_SIZE \
  202         (sizeof(agp_amd64_table) / sizeof(agp_amd64_table[0]))
  203 
  204 static uint32_t
  205 agp_amd64_get_aperture(device_t dev)
  206 {
  207         struct agp_amd64_softc *sc = device_get_softc(dev);
  208         uint32_t i;
  209 
  210         i = (pci_cfgregread(0, sc->mctrl[0], 3, AGP_AMD64_APCTRL, 4) &
  211                 AGP_AMD64_APCTRL_SIZE_MASK) >> 1;
  212 
  213         if (i >= AGP_AMD64_TABLE_SIZE)
  214                 return 0;
  215 
  216         return (agp_amd64_table[i]);
  217 }
  218 
  219 static int
  220 agp_amd64_set_aperture(device_t dev, uint32_t aperture)
  221 {
  222         struct agp_amd64_softc *sc = device_get_softc(dev);
  223         uint32_t i;
  224         int j;
  225 
  226         for (i = 0; i < AGP_AMD64_TABLE_SIZE; i++)
  227                 if (agp_amd64_table[i] == aperture)
  228                         break;
  229         if (i == AGP_AMD64_TABLE_SIZE)
  230                 return EINVAL;
  231 
  232         for (j = 0; j < sc->n_mctrl; j++)
  233                 pci_cfgregwrite(0, sc->mctrl[j], 3, AGP_AMD64_APCTRL,
  234                     (pci_cfgregread(0, sc->mctrl[j], 3, AGP_AMD64_APCTRL, 4) &
  235                     ~(AGP_AMD64_APCTRL_SIZE_MASK)) | (i << 1), 4);
  236 
  237         return 0;
  238 }
  239 
  240 static int
  241 agp_amd64_bind_page(device_t dev, int offset, vm_offset_t physical)
  242 {
  243         struct agp_amd64_softc *sc = device_get_softc(dev);
  244 
  245         if (offset < 0 || offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT))
  246                 return EINVAL;
  247 
  248         sc->gatt->ag_virtual[offset >> AGP_PAGE_SHIFT] = physical;
  249         return 0;
  250 }
  251 
  252 static int
  253 agp_amd64_unbind_page(device_t dev, int offset)
  254 {
  255         struct agp_amd64_softc *sc = device_get_softc(dev);
  256 
  257         if (offset < 0 || offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT))
  258                 return EINVAL;
  259 
  260         sc->gatt->ag_virtual[offset >> AGP_PAGE_SHIFT] = 0;
  261         return 0;
  262 }
  263 
  264 static void
  265 agp_amd64_flush_tlb(device_t dev)
  266 {
  267         struct agp_amd64_softc *sc = device_get_softc(dev);
  268         int i;
  269 
  270         for (i = 0; i < sc->n_mctrl; i++)
  271                 pci_cfgregwrite(0, sc->mctrl[i], 3, AGP_AMD64_CACHECTRL,
  272                     pci_cfgregread(0, sc->mctrl[i], 3, AGP_AMD64_CACHECTRL, 4) |
  273                     AGP_AMD64_CACHECTRL_INVGART, 4);
  274 }
  275 
  276 static device_method_t agp_amd64_methods[] = {
  277         /* Device interface */
  278         DEVMETHOD(device_probe,         agp_amd64_probe),
  279         DEVMETHOD(device_attach,        agp_amd64_attach),
  280         DEVMETHOD(device_detach,        agp_amd64_detach),
  281         DEVMETHOD(device_shutdown,      bus_generic_shutdown),
  282         DEVMETHOD(device_suspend,       bus_generic_suspend),
  283         DEVMETHOD(device_resume,        bus_generic_resume),
  284 
  285         /* AGP interface */
  286         DEVMETHOD(agp_get_aperture,     agp_amd64_get_aperture),
  287         DEVMETHOD(agp_set_aperture,     agp_amd64_set_aperture),
  288         DEVMETHOD(agp_bind_page,        agp_amd64_bind_page),
  289         DEVMETHOD(agp_unbind_page,      agp_amd64_unbind_page),
  290         DEVMETHOD(agp_flush_tlb,        agp_amd64_flush_tlb),
  291         DEVMETHOD(agp_enable,           agp_generic_enable),
  292         DEVMETHOD(agp_alloc_memory,     agp_generic_alloc_memory),
  293         DEVMETHOD(agp_free_memory,      agp_generic_free_memory),
  294         DEVMETHOD(agp_bind_memory,      agp_generic_bind_memory),
  295         DEVMETHOD(agp_unbind_memory,    agp_generic_unbind_memory),
  296 
  297         { 0, 0 }
  298 };
  299 
  300 static driver_t agp_amd64_driver = {
  301         "agp",
  302         agp_amd64_methods,
  303         sizeof(struct agp_amd64_softc),
  304 };
  305 
  306 static devclass_t agp_devclass;
  307 
  308 DRIVER_MODULE(agp_amd64, pci, agp_amd64_driver, agp_devclass, 0, 0);
  309 MODULE_DEPEND(agp_amd64, agp, 1, 1, 1);
  310 MODULE_DEPEND(agp_amd64, pci, 1, 1, 1);

Cache object: c9c87eb0b9b947dd2c702e63208b42de


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