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/agp/agp_intel.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) 2000 Doug Rabson
    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  *      $FreeBSD: src/sys/dev/agp/agp_intel.c,v 1.36 2007/11/12 21:51:36 jhb Exp $
   27  */
   28 
   29 #include <sys/param.h>
   30 #include <sys/systm.h>
   31 #include <sys/malloc.h>
   32 #include <sys/kernel.h>
   33 #include <sys/bus.h>
   34 #include <sys/lock.h>
   35 
   36 #include <bus/pci/pcivar.h>
   37 #include <bus/pci/pcireg.h>
   38 #include "agppriv.h"
   39 #include "agpreg.h"
   40 
   41 #include <vm/vm.h>
   42 #include <vm/vm_object.h>
   43 #include <vm/pmap.h>
   44 
   45 #define MAX_APSIZE      0x3f            /* 256 MB */
   46 
   47 struct agp_intel_softc {
   48         struct agp_softc agp;
   49         u_int32_t       initial_aperture; /* aperture size at startup */
   50         struct agp_gatt *gatt;
   51         u_int           aperture_mask;
   52         u_int32_t       current_aperture; /* current aperture size */
   53 };
   54 
   55 static const char*
   56 agp_intel_match(device_t dev)
   57 {
   58         if (pci_get_class(dev) != PCIC_BRIDGE
   59             || pci_get_subclass(dev) != PCIS_BRIDGE_HOST)
   60                 return (NULL);
   61 
   62         if (agp_find_caps(dev) == 0)
   63                 return (NULL);
   64 
   65         switch (pci_get_devid(dev)) {
   66         /* Intel -- vendor 0x8086 */
   67         case 0x71808086:
   68                 return ("Intel 82443LX (440 LX) host to PCI bridge");
   69         case 0x71908086:
   70                 return ("Intel 82443BX (440 BX) host to PCI bridge");
   71         case 0x71a08086:
   72                 return ("Intel 82443GX host to PCI bridge");
   73         case 0x71a18086:
   74                 return ("Intel 82443GX host to AGP bridge");
   75         case 0x11308086:
   76                 return ("Intel 82815 (i815 GMCH) host to PCI bridge");
   77         case 0x25008086:
   78         case 0x25018086:
   79                 return ("Intel 82820 host to AGP bridge");
   80         case 0x35758086:
   81                 return ("Intel 82830 host to AGP bridge");
   82         case 0x1a218086:
   83                 return ("Intel 82840 host to AGP bridge");
   84         case 0x1a308086:
   85                 return ("Intel 82845 host to AGP bridge");
   86         case 0x25308086:
   87                 return ("Intel 82850 host to AGP bridge");
   88         case 0x33408086:
   89                 return ("Intel 82855 host to AGP bridge");
   90         case 0x25318086:
   91                 return ("Intel 82860 host to AGP bridge");
   92         case 0x25708086:
   93                 return ("Intel 82865 host to AGP bridge");
   94         case 0x255d8086:
   95                 return ("Intel E7205 host to AGP bridge");
   96         case 0x25508086:
   97                 return ("Intel E7505 host to AGP bridge");
   98         case 0x25788086:
   99                 return ("Intel 82875P host to AGP bridge");
  100         case 0x25608086:
  101                 return ("Intel 82845G host to AGP bridge");
  102         case 0x35808086:
  103                 return ("Intel 82855GM host to AGP bridge");
  104         };
  105 
  106         return (NULL);
  107 }
  108 
  109 static int
  110 agp_intel_probe(device_t dev)
  111 {
  112         const char *desc;
  113 
  114         if (resource_disabled("agp", device_get_unit(dev)))
  115                 return (ENXIO);
  116         desc = agp_intel_match(dev);
  117         if (desc) {
  118                 device_verbose(dev);
  119                 device_set_desc(dev, desc);
  120                 return (BUS_PROBE_DEFAULT);
  121         }
  122 
  123         return (ENXIO);
  124 }
  125 
  126 static void
  127 agp_intel_commit_gatt(device_t dev)
  128 {
  129         struct agp_intel_softc *sc;
  130         u_int32_t type;
  131         u_int32_t value;
  132 
  133         sc = device_get_softc(dev);
  134         type = pci_get_devid(dev);
  135 
  136         /* Install the gatt. */
  137         pci_write_config(dev, AGP_INTEL_ATTBASE, sc->gatt->ag_physical, 4);
  138 
  139         /* Enable the GLTB and setup the control register. */
  140         switch (type) {
  141         case 0x71908086: /* 440LX/EX */
  142                 pci_write_config(dev, AGP_INTEL_AGPCTRL, 0x2080, 4);
  143                 break;
  144         case 0x71808086: /* 440BX */
  145                 /*
  146                  * XXX: Should be 0xa080?  Bit 9 is undefined, and
  147                  * bit 13 being on and bit 15 being clear is illegal.
  148                  */
  149                 pci_write_config(dev, AGP_INTEL_AGPCTRL, 0x2280, 4);
  150                 break;
  151         default:
  152                 value = pci_read_config(dev, AGP_INTEL_AGPCTRL, 4);
  153                 pci_write_config(dev, AGP_INTEL_AGPCTRL, value | 0x80, 4);
  154         }
  155 
  156         /* Enable aperture accesses. */
  157         switch (type) {
  158         case 0x25008086: /* i820 */
  159         case 0x25018086: /* i820 */
  160                 pci_write_config(dev, AGP_INTEL_I820_RDCR,
  161                                  (pci_read_config(dev, AGP_INTEL_I820_RDCR, 1)
  162                                   | (1 << 1)), 1);
  163                 break;
  164         case 0x1a308086: /* i845 */
  165         case 0x25608086: /* i845G */
  166         case 0x33408086: /* i855 */
  167         case 0x35808086: /* i855GM */
  168         case 0x25708086: /* i865 */
  169         case 0x25788086: /* i875P */
  170                 pci_write_config(dev, AGP_INTEL_I845_AGPM,
  171                                  (pci_read_config(dev, AGP_INTEL_I845_AGPM, 1)
  172                                   | (1 << 1)), 1);
  173                 break;
  174         case 0x1a218086: /* i840 */
  175         case 0x25308086: /* i850 */
  176         case 0x25318086: /* i860 */
  177         case 0x255d8086: /* E7205 */
  178         case 0x25508086: /* E7505 */
  179                 pci_write_config(dev, AGP_INTEL_MCHCFG,
  180                                  (pci_read_config(dev, AGP_INTEL_MCHCFG, 2)
  181                                   | (1 << 9)), 2);
  182                 break;
  183         default: /* Intel Generic (maybe) */
  184                 pci_write_config(dev, AGP_INTEL_NBXCFG,
  185                                  (pci_read_config(dev, AGP_INTEL_NBXCFG, 4)
  186                                   & ~(1 << 10)) | (1 << 9), 4);
  187         }
  188 
  189         /* Clear errors. */
  190         switch (type) {
  191         case 0x1a218086: /* i840 */
  192                 pci_write_config(dev, AGP_INTEL_I8XX_ERRSTS, 0xc000, 2);
  193                 break;
  194         case 0x25008086: /* i820 */
  195         case 0x25018086: /* i820 */
  196         case 0x1a308086: /* i845 */
  197         case 0x25608086: /* i845G */
  198         case 0x25308086: /* i850 */
  199         case 0x33408086: /* i855 */
  200         case 0x25318086: /* i860 */
  201         case 0x25708086: /* i865 */
  202         case 0x25788086: /* i875P */
  203         case 0x255d8086: /* E7205 */
  204         case 0x25508086: /* E7505 */
  205                 pci_write_config(dev, AGP_INTEL_I8XX_ERRSTS, 0x00ff, 2);
  206                 break;
  207         default: /* Intel Generic (maybe) */
  208                 pci_write_config(dev, AGP_INTEL_ERRSTS + 1, 7, 1);
  209         }
  210 }
  211 
  212 static int
  213 agp_intel_attach(device_t dev)
  214 {
  215         struct agp_intel_softc *sc;
  216         struct agp_gatt *gatt;
  217         u_int32_t value;
  218         int error;
  219 
  220         sc = device_get_softc(dev);
  221 
  222         error = agp_generic_attach(dev);
  223         if (error)
  224                 return (error);
  225 
  226         /* Determine maximum supported aperture size. */
  227         value = pci_read_config(dev, AGP_INTEL_APSIZE, 1);
  228         pci_write_config(dev, AGP_INTEL_APSIZE, MAX_APSIZE, 1);
  229         sc->aperture_mask = pci_read_config(dev, AGP_INTEL_APSIZE, 1) &
  230             MAX_APSIZE;
  231         pci_write_config(dev, AGP_INTEL_APSIZE, value, 1);
  232         sc->current_aperture = sc->initial_aperture = AGP_GET_APERTURE(dev);
  233         if (sc->initial_aperture == 0) {
  234                 device_printf(dev, "bad initial aperture size, disabling\n");
  235                 return ENXIO;
  236         }
  237 
  238         for (;;) {
  239                 gatt = agp_alloc_gatt(dev);
  240                 if (gatt)
  241                         break;
  242 
  243                 /*
  244                  * Probably contigmalloc failure. Try reducing the
  245                  * aperture so that the gatt size reduces.
  246                  */
  247                 if (AGP_SET_APERTURE(dev, AGP_GET_APERTURE(dev) / 2)) {
  248                         agp_generic_detach(dev);
  249                         return (ENOMEM);
  250                 }
  251         }
  252         sc->gatt = gatt;
  253 
  254         agp_intel_commit_gatt(dev);
  255 
  256         return (0);
  257 }
  258 
  259 static int
  260 agp_intel_detach(device_t dev)
  261 {
  262         struct agp_intel_softc *sc;
  263         u_int32_t reg;
  264 
  265         sc = device_get_softc(dev);
  266 
  267         agp_free_cdev(dev);
  268 
  269         /* Disable aperture accesses. */
  270         switch (pci_get_devid(dev)) {
  271         case 0x25008086: /* i820 */
  272         case 0x25018086: /* i820 */
  273                 reg = pci_read_config(dev, AGP_INTEL_I820_RDCR, 1) & ~(1 << 1);
  274                 kprintf("%s: set RDCR to %02x\n", __func__, reg & 0xff);
  275                 pci_write_config(dev, AGP_INTEL_I820_RDCR, reg, 1);
  276                 break;
  277         case 0x1a308086: /* i845 */
  278         case 0x25608086: /* i845G */
  279         case 0x33408086: /* i855 */
  280         case 0x35808086: /* i855GM */
  281         case 0x25708086: /* i865 */
  282         case 0x25788086: /* i875P */
  283                 reg = pci_read_config(dev, AGP_INTEL_I845_AGPM, 1) & ~(1 << 1);
  284                 kprintf("%s: set AGPM to %02x\n", __func__, reg & 0xff);
  285                 pci_write_config(dev, AGP_INTEL_I845_AGPM, reg, 1);
  286                 break;
  287         case 0x1a218086: /* i840 */
  288         case 0x25308086: /* i850 */
  289         case 0x25318086: /* i860 */
  290         case 0x255d8086: /* E7205 */
  291         case 0x25508086: /* E7505 */
  292                 reg = pci_read_config(dev, AGP_INTEL_MCHCFG, 2) & ~(1 << 9);
  293                 kprintf("%s: set MCHCFG to %x04\n", __func__, reg & 0xffff);
  294                 pci_write_config(dev, AGP_INTEL_MCHCFG, reg, 2);
  295                 break;
  296         default: /* Intel Generic (maybe) */
  297                 reg = pci_read_config(dev, AGP_INTEL_NBXCFG, 4) & ~(1 << 9);
  298                 kprintf("%s: set NBXCFG to %08x\n", __func__, reg);
  299                 pci_write_config(dev, AGP_INTEL_NBXCFG, reg, 4);
  300         }
  301         pci_write_config(dev, AGP_INTEL_ATTBASE, 0, 4);
  302         AGP_SET_APERTURE(dev, sc->initial_aperture);
  303         agp_free_gatt(sc->gatt);
  304         agp_free_res(dev);
  305 
  306         return (0);
  307 }
  308 
  309 static int
  310 agp_intel_resume(device_t dev)
  311 {
  312         struct agp_intel_softc *sc;
  313         sc = device_get_softc(dev);
  314         
  315         AGP_SET_APERTURE(dev, sc->current_aperture);
  316         agp_intel_commit_gatt(dev);
  317         return (bus_generic_resume(dev));
  318 }
  319 
  320 static u_int32_t
  321 agp_intel_get_aperture(device_t dev)
  322 {
  323         struct agp_intel_softc *sc;
  324         u_int32_t apsize;
  325 
  326         sc = device_get_softc(dev);
  327 
  328         apsize = pci_read_config(dev, AGP_INTEL_APSIZE, 1) & sc->aperture_mask;
  329 
  330         /*
  331          * The size is determined by the number of low bits of
  332          * register APBASE which are forced to zero. The low 22 bits
  333          * are always forced to zero and each zero bit in the apsize
  334          * field just read forces the corresponding bit in the 27:22
  335          * to be zero. We calculate the aperture size accordingly.
  336          */
  337         return ((((apsize ^ sc->aperture_mask) << 22) | ((1 << 22) - 1)) + 1);
  338 }
  339 
  340 static int
  341 agp_intel_set_aperture(device_t dev, u_int32_t aperture)
  342 {
  343         struct agp_intel_softc *sc;
  344         u_int32_t apsize;
  345 
  346         sc = device_get_softc(dev);
  347 
  348         /*
  349          * Reverse the magic from get_aperture.
  350          */
  351         apsize = ((aperture - 1) >> 22) ^ sc->aperture_mask;
  352 
  353         /*
  354          * Double check for sanity.
  355          */
  356         if ((((apsize ^ sc->aperture_mask) << 22) | ((1 << 22) - 1)) + 1 != aperture)
  357                 return (EINVAL);
  358 
  359         sc->current_aperture = apsize;
  360 
  361         pci_write_config(dev, AGP_INTEL_APSIZE, apsize, 1);
  362 
  363         return (0);
  364 }
  365 
  366 static int
  367 agp_intel_bind_page(device_t dev, vm_offset_t offset, vm_offset_t physical)
  368 {
  369         struct agp_intel_softc *sc;
  370 
  371         sc = device_get_softc(dev);
  372 
  373         if (offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT))
  374                 return (EINVAL);
  375 
  376         sc->gatt->ag_virtual[offset >> AGP_PAGE_SHIFT] = physical | 0x17;
  377         return (0);
  378 }
  379 
  380 static int
  381 agp_intel_unbind_page(device_t dev, vm_offset_t offset)
  382 {
  383         struct agp_intel_softc *sc;
  384 
  385         sc = device_get_softc(dev);
  386 
  387         if (offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT))
  388                 return (EINVAL);
  389 
  390         sc->gatt->ag_virtual[offset >> AGP_PAGE_SHIFT] = 0;
  391         return (0);
  392 }
  393 
  394 static void
  395 agp_intel_flush_tlb(device_t dev)
  396 {
  397         u_int32_t val;
  398 
  399         val = pci_read_config(dev, AGP_INTEL_AGPCTRL, 4);
  400         pci_write_config(dev, AGP_INTEL_AGPCTRL, val & ~(1 << 7), 4);
  401         pci_write_config(dev, AGP_INTEL_AGPCTRL, val, 4);
  402 }
  403 
  404 static device_method_t agp_intel_methods[] = {
  405         /* Device interface */
  406         DEVMETHOD(device_probe,         agp_intel_probe),
  407         DEVMETHOD(device_attach,        agp_intel_attach),
  408         DEVMETHOD(device_detach,        agp_intel_detach),
  409         DEVMETHOD(device_shutdown,      bus_generic_shutdown),
  410         DEVMETHOD(device_suspend,       bus_generic_suspend),
  411         DEVMETHOD(device_resume,        agp_intel_resume),
  412 
  413         /* AGP interface */
  414         DEVMETHOD(agp_get_aperture,     agp_intel_get_aperture),
  415         DEVMETHOD(agp_set_aperture,     agp_intel_set_aperture),
  416         DEVMETHOD(agp_bind_page,        agp_intel_bind_page),
  417         DEVMETHOD(agp_unbind_page,      agp_intel_unbind_page),
  418         DEVMETHOD(agp_flush_tlb,        agp_intel_flush_tlb),
  419         DEVMETHOD(agp_enable,           agp_generic_enable),
  420         DEVMETHOD(agp_alloc_memory,     agp_generic_alloc_memory),
  421         DEVMETHOD(agp_free_memory,      agp_generic_free_memory),
  422         DEVMETHOD(agp_bind_memory,      agp_generic_bind_memory),
  423         DEVMETHOD(agp_unbind_memory,    agp_generic_unbind_memory),
  424 
  425         DEVMETHOD_END
  426 };
  427 
  428 static driver_t agp_intel_driver = {
  429         "agp",
  430         agp_intel_methods,
  431         sizeof(struct agp_intel_softc),
  432 };
  433 
  434 static devclass_t agp_devclass;
  435 
  436 DRIVER_MODULE(agp_intel, pci, agp_intel_driver, agp_devclass, NULL, NULL);
  437 MODULE_DEPEND(agp_intel, agp, 1, 1, 1);
  438 MODULE_DEPEND(agp_intel, pci, 1, 1, 1);

Cache object: 391090a71b08d432d6df5117e3f66150


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