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_i810.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  * Copyright (c) 2000 Ruslan Ermilov
    4  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * 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 copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25  * SUCH DAMAGE.
   26  */
   27 
   28 /*
   29  * Fixes for 830/845G support: David Dawes <dawes@xfree86.org>
   30  * 852GM/855GM/865G support added by David Dawes <dawes@xfree86.org>
   31  */
   32 
   33 #include <sys/cdefs.h>
   34 __FBSDID("$FreeBSD$");
   35 
   36 #include "opt_bus.h"
   37 
   38 #include <sys/param.h>
   39 #include <sys/systm.h>
   40 #include <sys/malloc.h>
   41 #include <sys/kernel.h>
   42 #include <sys/module.h>
   43 #include <sys/bus.h>
   44 #include <sys/lock.h>
   45 #include <sys/mutex.h>
   46 #include <sys/proc.h>
   47 
   48 #include <dev/pci/pcivar.h>
   49 #include <dev/pci/pcireg.h>
   50 #include <pci/agppriv.h>
   51 #include <pci/agpreg.h>
   52 
   53 #include <vm/vm.h>
   54 #include <vm/vm_object.h>
   55 #include <vm/vm_page.h>
   56 #include <vm/vm_pageout.h>
   57 #include <vm/pmap.h>
   58 
   59 #include <machine/bus.h>
   60 #include <machine/resource.h>
   61 #include <machine/md_var.h>
   62 #include <sys/rman.h>
   63 
   64 MALLOC_DECLARE(M_AGP);
   65 
   66 enum {
   67         CHIP_I810,      /* i810/i815 */
   68         CHIP_I830,      /* 830M/845G */
   69         CHIP_I855,      /* 852GM/855GM/865G */
   70         CHIP_I915,      /* 915G/915GM */
   71         CHIP_I965,      /* G965 */
   72         CHIP_G33,       /* G33/Q33/Q35 */
   73         CHIP_G4X,       /* G45/Q45 */
   74 };
   75 
   76 /* The i810 through i855 have the registers at BAR 1, and the GATT gets
   77  * allocated by us.  The i915 has registers in BAR 0 and the GATT is at the
   78  * start of the stolen memory, and should only be accessed by the OS through
   79  * BAR 3.  The G965 has registers and GATT in the same BAR (0) -- first 512KB
   80  * is registers, second 512KB is GATT.
   81  */
   82 static struct resource_spec agp_i810_res_spec[] = {
   83         { SYS_RES_MEMORY, AGP_I810_MMADR, RF_ACTIVE | RF_SHAREABLE },
   84         { -1, 0 }
   85 };
   86 
   87 static struct resource_spec agp_i915_res_spec[] = {
   88         { SYS_RES_MEMORY, AGP_I915_MMADR, RF_ACTIVE | RF_SHAREABLE },
   89         { SYS_RES_MEMORY, AGP_I915_GTTADR, RF_ACTIVE | RF_SHAREABLE },
   90         { -1, 0 }
   91 };
   92 
   93 static struct resource_spec agp_i965_res_spec[] = {
   94         { SYS_RES_MEMORY, AGP_I965_GTTMMADR, RF_ACTIVE | RF_SHAREABLE },
   95         { -1, 0 }
   96 };
   97 
   98 struct agp_i810_softc {
   99         struct agp_softc agp;
  100         u_int32_t initial_aperture;     /* aperture size at startup */
  101         struct agp_gatt *gatt;
  102         int chiptype;                   /* i810-like or i830 */
  103         u_int32_t dcache_size;          /* i810 only */
  104         u_int32_t stolen;               /* number of i830/845 gtt entries for stolen memory */
  105         device_t bdev;                  /* bridge device */
  106 
  107         void *argb_cursor;              /* contigmalloc area for ARGB cursor */
  108 
  109         struct resource_spec * sc_res_spec;
  110         struct resource *sc_res[2];
  111 };
  112 
  113 /* For adding new devices, devid is the id of the graphics controller
  114  * (pci:0:2:0, for example).  The placeholder (usually at pci:0:2:1) for the
  115  * second head should never be added.  The bridge_offset is the offset to
  116  * subtract from devid to get the id of the hostb that the device is on.
  117  */
  118 static const struct agp_i810_match {
  119         int devid;
  120         int chiptype;
  121         int bridge_offset;
  122         char *name;
  123 } agp_i810_matches[] = {
  124         {0x71218086, CHIP_I810, 0x00010000,
  125             "Intel 82810 (i810 GMCH) SVGA controller"},
  126         {0x71238086, CHIP_I810, 0x00010000,
  127             "Intel 82810-DC100 (i810-DC100 GMCH) SVGA controller"},
  128         {0x71258086, CHIP_I810, 0x00010000,
  129             "Intel 82810E (i810E GMCH) SVGA controller"},
  130         {0x11328086, CHIP_I810, 0x00020000,
  131             "Intel 82815 (i815 GMCH) SVGA controller"},
  132         {0x35778086, CHIP_I830, 0x00020000,
  133             "Intel 82830M (830M GMCH) SVGA controller"},
  134         {0x25628086, CHIP_I830, 0x00020000,
  135             "Intel 82845M (845M GMCH) SVGA controller"},
  136         {0x35828086, CHIP_I855, 0x00020000,
  137             "Intel 82852/855GM SVGA controller"},
  138         {0x25728086, CHIP_I855, 0x00020000,
  139             "Intel 82865G (865G GMCH) SVGA controller"},
  140         {0x25828086, CHIP_I915, 0x00020000,
  141             "Intel 82915G (915G GMCH) SVGA controller"},
  142         {0x258A8086, CHIP_I915, 0x00020000,
  143             "Intel E7221 SVGA controller"},
  144         {0x25928086, CHIP_I915, 0x00020000,
  145             "Intel 82915GM (915GM GMCH) SVGA controller"},
  146         {0x27728086, CHIP_I915, 0x00020000,
  147             "Intel 82945G (945G GMCH) SVGA controller"},
  148         {0x27A28086, CHIP_I915, 0x00020000,
  149             "Intel 82945GM (945GM GMCH) SVGA controller"},
  150         {0x27AE8086, CHIP_I915, 0x00020000,
  151             "Intel 945GME SVGA controller"},
  152         {0x29728086, CHIP_I965, 0x00020000,
  153             "Intel 946GZ SVGA controller"},
  154         {0x29828086, CHIP_I965, 0x00020000,
  155             "Intel G965 SVGA controller"},
  156         {0x29928086, CHIP_I965, 0x00020000,
  157             "Intel Q965 SVGA controller"},
  158         {0x29A28086, CHIP_I965, 0x00020000,
  159             "Intel G965 SVGA controller"},
  160         {0x29B28086, CHIP_G33, 0x00020000,
  161             "Intel Q35 SVGA controller"},
  162         {0x29C28086, CHIP_G33, 0x00020000,
  163             "Intel G33 SVGA controller"},
  164         {0x29D28086, CHIP_G33, 0x00020000,
  165             "Intel Q33 SVGA controller"},
  166         {0x2A028086, CHIP_I965, 0x00020000,
  167             "Intel GM965 SVGA controller"},
  168         {0x2A128086, CHIP_I965, 0x00020000,
  169             "Intel GME965 SVGA controller"},
  170         {0x2A428086, CHIP_I965, 0x00020000,
  171             "Intel GM45 SVGA controller"},
  172         {0x2E028086, CHIP_G4X, 0x00020000,
  173             "Intel 4 Series SVGA controller"},
  174         {0x2E128086, CHIP_G4X, 0x00020000,
  175             "Intel Q45 SVGA controller"},
  176         {0x2E228086, CHIP_G4X, 0x00020000,
  177             "Intel G45 SVGA controller"},
  178         {0, 0, 0, NULL}
  179 };
  180 
  181 static const struct agp_i810_match*
  182 agp_i810_match(device_t dev)
  183 {
  184         int i, devid;
  185 
  186         if (pci_get_class(dev) != PCIC_DISPLAY
  187             || pci_get_subclass(dev) != PCIS_DISPLAY_VGA)
  188                 return NULL;
  189 
  190         devid = pci_get_devid(dev);
  191         for (i = 0; agp_i810_matches[i].devid != 0; i++) {
  192                 if (agp_i810_matches[i].devid == devid)
  193                     break;
  194         }
  195         if (agp_i810_matches[i].devid == 0)
  196                 return NULL;
  197         else
  198                 return &agp_i810_matches[i];
  199 }
  200 
  201 /*
  202  * Find bridge device.
  203  */
  204 static device_t
  205 agp_i810_find_bridge(device_t dev)
  206 {
  207         device_t *children, child;
  208         int nchildren, i;
  209         u_int32_t devid;
  210         const struct agp_i810_match *match;
  211   
  212         match = agp_i810_match(dev);
  213         devid = match->devid - match->bridge_offset;
  214 
  215         if (device_get_children(device_get_parent(device_get_parent(dev)),
  216             &children, &nchildren))
  217                 return 0;
  218 
  219         for (i = 0; i < nchildren; i++) {
  220                 child = children[i];
  221 
  222                 if (pci_get_devid(child) == devid) {
  223                         free(children, M_TEMP);
  224                         return child;
  225                 }
  226         }
  227         free(children, M_TEMP);
  228         return 0;
  229 }
  230 
  231 static void
  232 agp_i810_identify(driver_t *driver, device_t parent)
  233 {
  234 
  235         if (device_find_child(parent, "agp", -1) == NULL &&
  236             agp_i810_match(parent))
  237                 device_add_child(parent, "agp", -1);
  238 }
  239 
  240 static int
  241 agp_i810_probe(device_t dev)
  242 {
  243         device_t bdev;
  244         const struct agp_i810_match *match;
  245         u_int8_t smram;
  246         int gcc1, deven;
  247 
  248         if (resource_disabled("agp", device_get_unit(dev)))
  249                 return (ENXIO);
  250         match = agp_i810_match(dev);
  251         if (match == NULL)
  252                 return ENXIO;
  253 
  254         bdev = agp_i810_find_bridge(dev);
  255         if (!bdev) {
  256                 if (bootverbose)
  257                         printf("I810: can't find bridge device\n");
  258                 return ENXIO;
  259         }
  260 
  261         /*
  262          * checking whether internal graphics device has been activated.
  263          */
  264         switch (match->chiptype) {
  265         case CHIP_I810:
  266                 smram = pci_read_config(bdev, AGP_I810_SMRAM, 1);
  267                 if ((smram & AGP_I810_SMRAM_GMS) ==
  268                     AGP_I810_SMRAM_GMS_DISABLED) {
  269                         if (bootverbose)
  270                                 printf("I810: disabled, not probing\n");
  271                         return ENXIO;
  272                 }
  273                 break;
  274         case CHIP_I830:
  275         case CHIP_I855:
  276                 gcc1 = pci_read_config(bdev, AGP_I830_GCC1, 1);
  277                 if ((gcc1 & AGP_I830_GCC1_DEV2) ==
  278                     AGP_I830_GCC1_DEV2_DISABLED) {
  279                         if (bootverbose)
  280                                 printf("I830: disabled, not probing\n");
  281                         return ENXIO;
  282                 }
  283                 break;
  284         case CHIP_I915:
  285         case CHIP_I965:
  286         case CHIP_G33:
  287                 deven = pci_read_config(bdev, AGP_I915_DEVEN, 4);
  288                 if ((deven & AGP_I915_DEVEN_D2F0) ==
  289                     AGP_I915_DEVEN_D2F0_DISABLED) {
  290                         if (bootverbose)
  291                                 printf("I915: disabled, not probing\n");
  292                         return ENXIO;
  293                 }
  294                 break;
  295         }
  296 
  297         if (match->devid == 0x35828086) {
  298                 switch (pci_read_config(dev, AGP_I85X_CAPID, 1)) {
  299                 case AGP_I855_GME:
  300                         device_set_desc(dev,
  301                             "Intel 82855GME (855GME GMCH) SVGA controller");
  302                         break;
  303                 case AGP_I855_GM:
  304                         device_set_desc(dev,
  305                             "Intel 82855GM (855GM GMCH) SVGA controller");
  306                         break;
  307                 case AGP_I852_GME:
  308                         device_set_desc(dev,
  309                             "Intel 82852GME (852GME GMCH) SVGA controller");
  310                         break;
  311                 case AGP_I852_GM:
  312                         device_set_desc(dev,
  313                             "Intel 82852GM (852GM GMCH) SVGA controller");
  314                         break;
  315                 default:
  316                         device_set_desc(dev,
  317                             "Intel 8285xM (85xGM GMCH) SVGA controller");
  318                         break;
  319                 }
  320         } else {
  321                 device_set_desc(dev, match->name);
  322         }
  323 
  324         return BUS_PROBE_DEFAULT;
  325 }
  326 
  327 static void
  328 agp_i810_dump_regs(device_t dev)
  329 {
  330         struct agp_i810_softc *sc = device_get_softc(dev);
  331 
  332         device_printf(dev, "AGP_I810_PGTBL_CTL: %08x\n",
  333             bus_read_4(sc->sc_res[0], AGP_I810_PGTBL_CTL));
  334 
  335         switch (sc->chiptype) {
  336         case CHIP_I810:
  337                 device_printf(dev, "AGP_I810_MISCC: 0x%04x\n",
  338                     pci_read_config(sc->bdev, AGP_I810_MISCC, 2));
  339                 break;
  340         case CHIP_I830:
  341                 device_printf(dev, "AGP_I830_GCC1: 0x%02x\n",
  342                     pci_read_config(sc->bdev, AGP_I830_GCC1, 1));
  343                 break;
  344         case CHIP_I855:
  345                 device_printf(dev, "AGP_I855_GCC1: 0x%02x\n",
  346                     pci_read_config(sc->bdev, AGP_I855_GCC1, 1));
  347                 break;
  348         case CHIP_I915:
  349         case CHIP_I965:
  350         case CHIP_G33:
  351                 device_printf(dev, "AGP_I855_GCC1: 0x%02x\n",
  352                     pci_read_config(sc->bdev, AGP_I855_GCC1, 1));
  353                 device_printf(dev, "AGP_I915_MSAC: 0x%02x\n",
  354                     pci_read_config(sc->bdev, AGP_I915_MSAC, 1));
  355                 break;
  356         }
  357         device_printf(dev, "Aperture resource size: %d bytes\n",
  358             AGP_GET_APERTURE(dev));
  359 }
  360 
  361 static int
  362 agp_i810_attach(device_t dev)
  363 {
  364         struct agp_i810_softc *sc = device_get_softc(dev);
  365         struct agp_gatt *gatt;
  366         const struct agp_i810_match *match;
  367         int error;
  368 
  369         sc->bdev = agp_i810_find_bridge(dev);
  370         if (!sc->bdev)
  371                 return ENOENT;
  372 
  373         match = agp_i810_match(dev);
  374         sc->chiptype = match->chiptype;
  375 
  376         switch (sc->chiptype) {
  377         case CHIP_I810:
  378         case CHIP_I830:
  379         case CHIP_I855:
  380                 sc->sc_res_spec = agp_i810_res_spec;
  381                 agp_set_aperture_resource(dev, AGP_APBASE);
  382                 break;
  383         case CHIP_I915:
  384         case CHIP_G33:
  385                 sc->sc_res_spec = agp_i915_res_spec;
  386                 agp_set_aperture_resource(dev, AGP_I915_GMADR);
  387                 break;
  388         case CHIP_I965:
  389         case CHIP_G4X:
  390                 sc->sc_res_spec = agp_i965_res_spec;
  391                 agp_set_aperture_resource(dev, AGP_I915_GMADR);
  392                 break;
  393         }
  394 
  395         error = agp_generic_attach(dev);
  396         if (error)
  397                 return error;
  398 
  399         if (sc->chiptype != CHIP_I965 && sc->chiptype != CHIP_G33 &&
  400             ptoa((vm_paddr_t)Maxmem) > 0xfffffffful)
  401         {
  402                 device_printf(dev, "agp_i810.c does not support physical "
  403                     "memory above 4GB.\n");
  404                 return ENOENT;
  405         }
  406 
  407         if (bus_alloc_resources(dev, sc->sc_res_spec, sc->sc_res)) {
  408                 agp_generic_detach(dev);
  409                 return ENODEV;
  410         }
  411 
  412         sc->initial_aperture = AGP_GET_APERTURE(dev);
  413 
  414         gatt = malloc( sizeof(struct agp_gatt), M_AGP, M_NOWAIT);
  415         if (!gatt) {
  416                 bus_release_resources(dev, sc->sc_res_spec, sc->sc_res);
  417                 agp_generic_detach(dev);
  418                 return ENOMEM;
  419         }
  420         sc->gatt = gatt;
  421 
  422         gatt->ag_entries = AGP_GET_APERTURE(dev) >> AGP_PAGE_SHIFT;
  423 
  424         if ( sc->chiptype == CHIP_I810 ) {
  425                 /* Some i810s have on-chip memory called dcache */
  426                 if (bus_read_1(sc->sc_res[0], AGP_I810_DRT) &
  427                     AGP_I810_DRT_POPULATED)
  428                         sc->dcache_size = 4 * 1024 * 1024;
  429                 else
  430                         sc->dcache_size = 0;
  431 
  432                 /* According to the specs the gatt on the i810 must be 64k */
  433                 gatt->ag_virtual = contigmalloc( 64 * 1024, M_AGP, 0, 
  434                                         0, ~0, PAGE_SIZE, 0);
  435                 if (!gatt->ag_virtual) {
  436                         if (bootverbose)
  437                                 device_printf(dev, "contiguous allocation failed\n");
  438                         bus_release_resources(dev, sc->sc_res_spec,
  439                             sc->sc_res);
  440                         free(gatt, M_AGP);
  441                         agp_generic_detach(dev);
  442                         return ENOMEM;
  443                 }
  444                 bzero(gatt->ag_virtual, gatt->ag_entries * sizeof(u_int32_t));
  445         
  446                 gatt->ag_physical = vtophys((vm_offset_t) gatt->ag_virtual);
  447                 agp_flush_cache();
  448                 /* Install the GATT. */
  449                 bus_write_4(sc->sc_res[0], AGP_I810_PGTBL_CTL,
  450                     gatt->ag_physical | 1);
  451         } else if ( sc->chiptype == CHIP_I830 ) {
  452                 /* The i830 automatically initializes the 128k gatt on boot. */
  453                 unsigned int gcc1, pgtblctl;
  454                 
  455                 gcc1 = pci_read_config(sc->bdev, AGP_I830_GCC1, 1);
  456                 switch (gcc1 & AGP_I830_GCC1_GMS) {
  457                         case AGP_I830_GCC1_GMS_STOLEN_512:
  458                                 sc->stolen = (512 - 132) * 1024 / 4096;
  459                                 break;
  460                         case AGP_I830_GCC1_GMS_STOLEN_1024: 
  461                                 sc->stolen = (1024 - 132) * 1024 / 4096;
  462                                 break;
  463                         case AGP_I830_GCC1_GMS_STOLEN_8192: 
  464                                 sc->stolen = (8192 - 132) * 1024 / 4096;
  465                                 break;
  466                         default:
  467                                 sc->stolen = 0;
  468                                 device_printf(dev, "unknown memory configuration, disabling\n");
  469                                 bus_release_resources(dev, sc->sc_res_spec,
  470                                     sc->sc_res);
  471                                 free(gatt, M_AGP);
  472                                 agp_generic_detach(dev);
  473                                 return EINVAL;
  474                 }
  475                 if (sc->stolen > 0) {
  476                         device_printf(dev, "detected %dk stolen memory\n",
  477                             sc->stolen * 4);
  478                 }
  479                 device_printf(dev, "aperture size is %dM\n",
  480                     sc->initial_aperture / 1024 / 1024);
  481 
  482                 /* GATT address is already in there, make sure it's enabled */
  483                 pgtblctl = bus_read_4(sc->sc_res[0], AGP_I810_PGTBL_CTL);
  484                 pgtblctl |= 1;
  485                 bus_write_4(sc->sc_res[0], AGP_I810_PGTBL_CTL, pgtblctl);
  486 
  487                 gatt->ag_physical = pgtblctl & ~1;
  488         } else if (sc->chiptype == CHIP_I855 || sc->chiptype == CHIP_I915 ||
  489             sc->chiptype == CHIP_I965 || sc->chiptype == CHIP_G33 ||
  490             sc->chiptype == CHIP_G4X) {
  491                 unsigned int gcc1, pgtblctl, stolen, gtt_size;
  492 
  493                 /* Stolen memory is set up at the beginning of the aperture by
  494                  * the BIOS, consisting of the GATT followed by 4kb for the
  495                  * BIOS display.
  496                  */
  497                 switch (sc->chiptype) {
  498                 case CHIP_I855:
  499                         gtt_size = 128;
  500                         break;
  501                 case CHIP_I915:
  502                         gtt_size = 256;
  503                         break;
  504                 case CHIP_I965:
  505                         switch (bus_read_4(sc->sc_res[0], AGP_I810_PGTBL_CTL) &
  506                             AGP_I810_PGTBL_SIZE_MASK) {
  507                         case AGP_I810_PGTBL_SIZE_128KB:
  508                                 gtt_size = 128;
  509                                 break;
  510                         case AGP_I810_PGTBL_SIZE_256KB:
  511                                 gtt_size = 256;
  512                                 break;
  513                         case AGP_I810_PGTBL_SIZE_512KB:
  514                                 gtt_size = 512;
  515                                 break;
  516                         case AGP_I965_PGTBL_SIZE_1MB:
  517                                 gtt_size = 1024;
  518                                 break;
  519                         case AGP_I965_PGTBL_SIZE_2MB:
  520                                 gtt_size = 2048;
  521                                 break;
  522                         case AGP_I965_PGTBL_SIZE_1_5MB:
  523                                 gtt_size = 1024 + 512;
  524                                 break;
  525                         default:
  526                                 device_printf(dev, "Bad PGTBL size\n");
  527                                 bus_release_resources(dev, sc->sc_res_spec,
  528                                     sc->sc_res);
  529                                 free(gatt, M_AGP);
  530                                 agp_generic_detach(dev);
  531                                 return EINVAL;
  532                         }
  533                         break;
  534                 case CHIP_G33:
  535                         gcc1 = pci_read_config(sc->bdev, AGP_I855_GCC1, 2);
  536                         switch (gcc1 & AGP_G33_MGGC_GGMS_MASK) {
  537                         case AGP_G33_MGGC_GGMS_SIZE_1M:
  538                                 gtt_size = 1024;
  539                                 break;
  540                         case AGP_G33_MGGC_GGMS_SIZE_2M:
  541                                 gtt_size = 2048;
  542                                 break;
  543                         default:
  544                                 device_printf(dev, "Bad PGTBL size\n");
  545                                 bus_release_resources(dev, sc->sc_res_spec,
  546                                     sc->sc_res);
  547                                 free(gatt, M_AGP);
  548                                 agp_generic_detach(dev);
  549                                 return EINVAL;
  550                         }
  551                         break;
  552                 case CHIP_G4X:
  553                         gtt_size = 0;
  554                         break;
  555                 default:
  556                         device_printf(dev, "Bad chiptype\n");
  557                         bus_release_resources(dev, sc->sc_res_spec,
  558                             sc->sc_res);
  559                         free(gatt, M_AGP);
  560                         agp_generic_detach(dev);
  561                         return EINVAL;
  562                 }
  563 
  564                 /* GCC1 is called MGGC on i915+ */
  565                 gcc1 = pci_read_config(sc->bdev, AGP_I855_GCC1, 1);
  566                 switch (gcc1 & AGP_I855_GCC1_GMS) {
  567                 case AGP_I855_GCC1_GMS_STOLEN_1M:
  568                         stolen = 1024;
  569                         break;
  570                 case AGP_I855_GCC1_GMS_STOLEN_4M:
  571                         stolen = 4 * 1024;
  572                         break;
  573                 case AGP_I855_GCC1_GMS_STOLEN_8M:
  574                         stolen = 8 * 1024;
  575                         break;
  576                 case AGP_I855_GCC1_GMS_STOLEN_16M:
  577                         stolen = 16 * 1024;
  578                         break;
  579                 case AGP_I855_GCC1_GMS_STOLEN_32M:
  580                         stolen = 32 * 1024;
  581                         break;
  582                 case AGP_I915_GCC1_GMS_STOLEN_48M:
  583                         if (sc->chiptype == CHIP_I915 ||
  584                             sc->chiptype == CHIP_I965 ||
  585                             sc->chiptype == CHIP_G33 ||
  586                             sc->chiptype == CHIP_G4X) {
  587                                 stolen = 48 * 1024;
  588                         } else {
  589                                 stolen = 0;
  590                         }
  591                         break;
  592                 case AGP_I915_GCC1_GMS_STOLEN_64M:
  593                         if (sc->chiptype == CHIP_I915 ||
  594                             sc->chiptype == CHIP_I965 ||
  595                             sc->chiptype == CHIP_G33 ||
  596                             sc->chiptype == CHIP_G4X) {
  597                                 stolen = 64 * 1024;
  598                         } else {
  599                                 stolen = 0;
  600                         }
  601                         break;
  602                 case AGP_G33_GCC1_GMS_STOLEN_128M:
  603                         if (sc->chiptype == CHIP_I965 ||
  604                             sc->chiptype == CHIP_G33 ||
  605                             sc->chiptype == CHIP_G4X) {
  606                                 stolen = 128 * 1024;
  607                         } else {
  608                                 stolen = 0;
  609                         }
  610                         break;
  611                 case AGP_G33_GCC1_GMS_STOLEN_256M:
  612                         if (sc->chiptype == CHIP_I965 ||
  613                             sc->chiptype == CHIP_G33 ||
  614                             sc->chiptype == CHIP_G4X) {
  615                                 stolen = 256 * 1024;
  616                         } else {
  617                                 stolen = 0;
  618                         }
  619                         break;
  620                 case AGP_G4X_GCC1_GMS_STOLEN_96M:
  621                         if (sc->chiptype == CHIP_I965 ||
  622                             sc->chiptype == CHIP_G4X) {
  623                                 stolen = 96 * 1024;
  624                         } else {
  625                                 stolen = 0;
  626                         }
  627                         break;
  628                 case AGP_G4X_GCC1_GMS_STOLEN_160M:
  629                         if (sc->chiptype == CHIP_I965 ||
  630                             sc->chiptype == CHIP_G4X) {
  631                                 stolen = 160 * 1024;
  632                         } else {
  633                                 stolen = 0;
  634                         }
  635                         break;
  636                 case AGP_G4X_GCC1_GMS_STOLEN_224M:
  637                         if (sc->chiptype == CHIP_I965 ||
  638                             sc->chiptype == CHIP_G4X) {
  639                                 stolen = 224 * 1024;
  640                         } else {
  641                                 stolen = 0;
  642                         }
  643                         break;
  644                 case AGP_G4X_GCC1_GMS_STOLEN_352M:
  645                         if (sc->chiptype == CHIP_I965 ||
  646                             sc->chiptype == CHIP_G4X) {
  647                                 stolen = 352 * 1024;
  648                         } else {
  649                                 stolen = 0;
  650                         }
  651                         break;
  652                 default:
  653                         device_printf(dev, "unknown memory configuration, "
  654                             "disabling\n");
  655                         bus_release_resources(dev, sc->sc_res_spec,
  656                             sc->sc_res);
  657                         free(gatt, M_AGP);
  658                         agp_generic_detach(dev);
  659                         return EINVAL;
  660                 }
  661 
  662                 if (sc->chiptype != CHIP_G4X)
  663                     gtt_size += 4;
  664 
  665                 sc->stolen = (stolen - gtt_size) * 1024 / 4096;
  666                 if (sc->stolen > 0)
  667                         device_printf(dev, "detected %dk stolen memory\n", sc->stolen * 4);
  668                 device_printf(dev, "aperture size is %dM\n", sc->initial_aperture / 1024 / 1024);
  669 
  670                 /* GATT address is already in there, make sure it's enabled */
  671                 pgtblctl = bus_read_4(sc->sc_res[0], AGP_I810_PGTBL_CTL);
  672                 pgtblctl |= 1;
  673                 bus_write_4(sc->sc_res[0], AGP_I810_PGTBL_CTL, pgtblctl);
  674 
  675                 gatt->ag_physical = pgtblctl & ~1;
  676         }
  677 
  678         if (0)
  679                 agp_i810_dump_regs(dev);
  680 
  681         return 0;
  682 }
  683 
  684 static int
  685 agp_i810_detach(device_t dev)
  686 {
  687         struct agp_i810_softc *sc = device_get_softc(dev);
  688 
  689         agp_free_cdev(dev);
  690 
  691         /* Clear the GATT base. */
  692         if ( sc->chiptype == CHIP_I810 ) {
  693                 bus_write_4(sc->sc_res[0], AGP_I810_PGTBL_CTL, 0);
  694         } else {
  695                 unsigned int pgtblctl;
  696                 pgtblctl = bus_read_4(sc->sc_res[0], AGP_I810_PGTBL_CTL);
  697                 pgtblctl &= ~1;
  698                 bus_write_4(sc->sc_res[0], AGP_I810_PGTBL_CTL, pgtblctl);
  699         }
  700 
  701         /* Put the aperture back the way it started. */
  702         AGP_SET_APERTURE(dev, sc->initial_aperture);
  703 
  704         if ( sc->chiptype == CHIP_I810 ) {
  705                 contigfree(sc->gatt->ag_virtual, 64 * 1024, M_AGP);
  706         }
  707         free(sc->gatt, M_AGP);
  708 
  709         bus_release_resources(dev, sc->sc_res_spec, sc->sc_res);
  710         agp_free_res(dev);
  711 
  712         return 0;
  713 }
  714 
  715 static int
  716 agp_i810_resume(device_t dev)
  717 {
  718         struct agp_i810_softc *sc;
  719         sc = device_get_softc(dev);
  720 
  721         AGP_SET_APERTURE(dev, sc->initial_aperture);
  722 
  723         /* Install the GATT. */
  724         bus_write_4(sc->sc_res[0], AGP_I810_PGTBL_CTL,
  725         sc->gatt->ag_physical | 1);
  726 
  727         return (bus_generic_resume(dev));
  728 }
  729 
  730 /**
  731  * Sets the PCI resource size of the aperture on i830-class and below chipsets,
  732  * while returning failure on later chipsets when an actual change is
  733  * requested.
  734  *
  735  * This whole function is likely bogus, as the kernel would probably need to
  736  * reconfigure the placement of the AGP aperture if a larger size is requested,
  737  * which doesn't happen currently.
  738  */
  739 static int
  740 agp_i810_set_aperture(device_t dev, u_int32_t aperture)
  741 {
  742         struct agp_i810_softc *sc = device_get_softc(dev);
  743         u_int16_t miscc, gcc1;
  744 
  745         switch (sc->chiptype) {
  746         case CHIP_I810:
  747                 /*
  748                  * Double check for sanity.
  749                  */
  750                 if (aperture != 32 * 1024 * 1024 && aperture != 64 * 1024 * 1024) {
  751                         device_printf(dev, "bad aperture size %d\n", aperture);
  752                         return EINVAL;
  753                 }
  754 
  755                 miscc = pci_read_config(sc->bdev, AGP_I810_MISCC, 2);
  756                 miscc &= ~AGP_I810_MISCC_WINSIZE;
  757                 if (aperture == 32 * 1024 * 1024)
  758                         miscc |= AGP_I810_MISCC_WINSIZE_32;
  759                 else
  760                         miscc |= AGP_I810_MISCC_WINSIZE_64;
  761         
  762                 pci_write_config(sc->bdev, AGP_I810_MISCC, miscc, 2);
  763                 break;
  764         case CHIP_I830:
  765                 if (aperture != 64 * 1024 * 1024 &&
  766                     aperture != 128 * 1024 * 1024) {
  767                         device_printf(dev, "bad aperture size %d\n", aperture);
  768                         return EINVAL;
  769                 }
  770                 gcc1 = pci_read_config(sc->bdev, AGP_I830_GCC1, 2);
  771                 gcc1 &= ~AGP_I830_GCC1_GMASIZE;
  772                 if (aperture == 64 * 1024 * 1024)
  773                         gcc1 |= AGP_I830_GCC1_GMASIZE_64;
  774                 else
  775                         gcc1 |= AGP_I830_GCC1_GMASIZE_128;
  776 
  777                 pci_write_config(sc->bdev, AGP_I830_GCC1, gcc1, 2);
  778                 break;
  779         case CHIP_I855:
  780         case CHIP_I915:
  781         case CHIP_I965:
  782         case CHIP_G33:
  783                 return agp_generic_set_aperture(dev, aperture);
  784         }
  785 
  786         return 0;
  787 }
  788 
  789 /**
  790  * Writes a GTT entry mapping the page at the given offset from the beginning
  791  * of the aperture to the given physical address.
  792  */
  793 static void
  794 agp_i810_write_gtt_entry(device_t dev, int offset, vm_offset_t physical,
  795     int enabled)
  796 {
  797         struct agp_i810_softc *sc = device_get_softc(dev);
  798         u_int32_t pte;
  799 
  800         pte = (u_int32_t)physical | 1;
  801         if (sc->chiptype == CHIP_I965 || sc->chiptype == CHIP_G33) {
  802                 pte |= (physical & 0x0000000f00000000ull) >> 28;
  803         } else {
  804                 /* If we do actually have memory above 4GB on an older system,
  805                  * crash cleanly rather than scribble on system memory,
  806                  * so we know we need to fix it.
  807                  */
  808                 KASSERT((pte & 0x0000000f00000000ull) == 0,
  809                     (">4GB physical address in agp"));
  810         }
  811 
  812         switch (sc->chiptype) {
  813         case CHIP_I810:
  814         case CHIP_I830:
  815         case CHIP_I855:
  816                 bus_write_4(sc->sc_res[0],
  817                     AGP_I810_GTT + (offset >> AGP_PAGE_SHIFT) * 4, pte);
  818                 break;
  819         case CHIP_I915:
  820         case CHIP_G33:
  821                 bus_write_4(sc->sc_res[1],
  822                     (offset >> AGP_PAGE_SHIFT) * 4, pte);
  823                 break;
  824         case CHIP_I965:
  825                 bus_write_4(sc->sc_res[0],
  826                     (offset >> AGP_PAGE_SHIFT) * 4 + (512 * 1024), pte);
  827                 break;
  828         }
  829 }
  830 
  831 static int
  832 agp_i810_bind_page(device_t dev, int offset, vm_offset_t physical)
  833 {
  834         struct agp_i810_softc *sc = device_get_softc(dev);
  835 
  836         if (offset < 0 || offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT)) {
  837                 device_printf(dev, "failed: offset is 0x%08x, shift is %d, entries is %d\n", offset, AGP_PAGE_SHIFT, sc->gatt->ag_entries);
  838                 return EINVAL;
  839         }
  840 
  841         if ( sc->chiptype != CHIP_I810 ) {
  842                 if ( (offset >> AGP_PAGE_SHIFT) < sc->stolen ) {
  843                         device_printf(dev, "trying to bind into stolen memory");
  844                         return EINVAL;
  845                 }
  846         }
  847 
  848         agp_i810_write_gtt_entry(dev, offset, physical, 1);
  849 
  850         return 0;
  851 }
  852 
  853 static int
  854 agp_i810_unbind_page(device_t dev, int offset)
  855 {
  856         struct agp_i810_softc *sc = device_get_softc(dev);
  857 
  858         if (offset < 0 || offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT))
  859                 return EINVAL;
  860 
  861         if ( sc->chiptype != CHIP_I810 ) {
  862                 if ( (offset >> AGP_PAGE_SHIFT) < sc->stolen ) {
  863                         device_printf(dev, "trying to unbind from stolen memory");
  864                         return EINVAL;
  865                 }
  866         }
  867 
  868         agp_i810_write_gtt_entry(dev, offset, 0, 0);
  869 
  870         return 0;
  871 }
  872 
  873 /*
  874  * Writing via memory mapped registers already flushes all TLBs.
  875  */
  876 static void
  877 agp_i810_flush_tlb(device_t dev)
  878 {
  879 }
  880 
  881 static int
  882 agp_i810_enable(device_t dev, u_int32_t mode)
  883 {
  884 
  885         return 0;
  886 }
  887 
  888 static struct agp_memory *
  889 agp_i810_alloc_memory(device_t dev, int type, vm_size_t size)
  890 {
  891         struct agp_i810_softc *sc = device_get_softc(dev);
  892         struct agp_memory *mem;
  893 
  894         if ((size & (AGP_PAGE_SIZE - 1)) != 0)
  895                 return 0;
  896 
  897         if (sc->agp.as_allocated + size > sc->agp.as_maxmem)
  898                 return 0;
  899 
  900         if (type == 1) {
  901                 /*
  902                  * Mapping local DRAM into GATT.
  903                  */
  904                 if ( sc->chiptype != CHIP_I810 )
  905                         return 0;
  906                 if (size != sc->dcache_size)
  907                         return 0;
  908         } else if (type == 2) {
  909                 /*
  910                  * Type 2 is the contiguous physical memory type, that hands
  911                  * back a physical address.  This is used for cursors on i810.
  912                  * Hand back as many single pages with physical as the user
  913                  * wants, but only allow one larger allocation (ARGB cursor)
  914                  * for simplicity.
  915                  */
  916                 if (size != AGP_PAGE_SIZE) {
  917                         if (sc->argb_cursor != NULL)
  918                                 return 0;
  919 
  920                         /* Allocate memory for ARGB cursor, if we can. */
  921                         sc->argb_cursor = contigmalloc(size, M_AGP,
  922                            0, 0, ~0, PAGE_SIZE, 0);
  923                         if (sc->argb_cursor == NULL)
  924                                 return 0;
  925                 }
  926         }
  927 
  928         mem = malloc(sizeof *mem, M_AGP, M_WAITOK);
  929         mem->am_id = sc->agp.as_nextid++;
  930         mem->am_size = size;
  931         mem->am_type = type;
  932         if (type != 1 && (type != 2 || size == AGP_PAGE_SIZE))
  933                 mem->am_obj = vm_object_allocate(OBJT_DEFAULT,
  934                                                  atop(round_page(size)));
  935         else
  936                 mem->am_obj = 0;
  937 
  938         if (type == 2) {
  939                 if (size == AGP_PAGE_SIZE) {
  940                         /*
  941                          * Allocate and wire down the page now so that we can
  942                          * get its physical address.
  943                          */
  944                         vm_page_t m;
  945         
  946                         VM_OBJECT_LOCK(mem->am_obj);
  947                         m = vm_page_grab(mem->am_obj, 0, VM_ALLOC_NOBUSY |
  948                             VM_ALLOC_WIRED | VM_ALLOC_ZERO | VM_ALLOC_RETRY);
  949                         VM_OBJECT_UNLOCK(mem->am_obj);
  950                         mem->am_physical = VM_PAGE_TO_PHYS(m);
  951                 } else {
  952                         /* Our allocation is already nicely wired down for us.
  953                          * Just grab the physical address.
  954                          */
  955                         mem->am_physical = vtophys(sc->argb_cursor);
  956                 }
  957         } else {
  958                 mem->am_physical = 0;
  959         }
  960 
  961         mem->am_offset = 0;
  962         mem->am_is_bound = 0;
  963         TAILQ_INSERT_TAIL(&sc->agp.as_memory, mem, am_link);
  964         sc->agp.as_allocated += size;
  965 
  966         return mem;
  967 }
  968 
  969 static int
  970 agp_i810_free_memory(device_t dev, struct agp_memory *mem)
  971 {
  972         struct agp_i810_softc *sc = device_get_softc(dev);
  973 
  974         if (mem->am_is_bound)
  975                 return EBUSY;
  976 
  977         if (mem->am_type == 2) {
  978                 if (mem->am_size == AGP_PAGE_SIZE) {
  979                         /*
  980                          * Unwire the page which we wired in alloc_memory.
  981                          */
  982                         vm_page_t m;
  983         
  984                         VM_OBJECT_LOCK(mem->am_obj);
  985                         m = vm_page_lookup(mem->am_obj, 0);
  986                         VM_OBJECT_UNLOCK(mem->am_obj);
  987                         vm_page_lock_queues();
  988                         vm_page_unwire(m, 0);
  989                         vm_page_unlock_queues();
  990                 } else {
  991                         contigfree(sc->argb_cursor, mem->am_size, M_AGP);
  992                         sc->argb_cursor = NULL;
  993                 }
  994         }
  995 
  996         sc->agp.as_allocated -= mem->am_size;
  997         TAILQ_REMOVE(&sc->agp.as_memory, mem, am_link);
  998         if (mem->am_obj)
  999                 vm_object_deallocate(mem->am_obj);
 1000         free(mem, M_AGP);
 1001         return 0;
 1002 }
 1003 
 1004 static int
 1005 agp_i810_bind_memory(device_t dev, struct agp_memory *mem,
 1006                      vm_offset_t offset)
 1007 {
 1008         struct agp_i810_softc *sc = device_get_softc(dev);
 1009         vm_offset_t i;
 1010 
 1011         /* Do some sanity checks first. */
 1012         if (offset < 0 || (offset & (AGP_PAGE_SIZE - 1)) != 0 ||
 1013             offset + mem->am_size > AGP_GET_APERTURE(dev)) {
 1014                 device_printf(dev, "binding memory at bad offset %#x\n",
 1015                     (int)offset);
 1016                 return EINVAL;
 1017         }
 1018 
 1019         if (mem->am_type == 2 && mem->am_size != AGP_PAGE_SIZE) {
 1020                 mtx_lock(&sc->agp.as_lock);
 1021                 if (mem->am_is_bound) {
 1022                         mtx_unlock(&sc->agp.as_lock);
 1023                         return EINVAL;
 1024                 }
 1025                 /* The memory's already wired down, just stick it in the GTT. */
 1026                 for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) {
 1027                         agp_i810_write_gtt_entry(dev, offset + i,
 1028                             mem->am_physical + i, 1);
 1029                 }
 1030                 agp_flush_cache();
 1031                 mem->am_offset = offset;
 1032                 mem->am_is_bound = 1;
 1033                 mtx_unlock(&sc->agp.as_lock);
 1034                 return 0;
 1035         }
 1036 
 1037         if (mem->am_type != 1)
 1038                 return agp_generic_bind_memory(dev, mem, offset);
 1039 
 1040         if ( sc->chiptype != CHIP_I810 )
 1041                 return EINVAL;
 1042 
 1043         for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) {
 1044                 bus_write_4(sc->sc_res[0],
 1045                     AGP_I810_GTT + (i >> AGP_PAGE_SHIFT) * 4, i | 3);
 1046         }
 1047 
 1048         return 0;
 1049 }
 1050 
 1051 static int
 1052 agp_i810_unbind_memory(device_t dev, struct agp_memory *mem)
 1053 {
 1054         struct agp_i810_softc *sc = device_get_softc(dev);
 1055         vm_offset_t i;
 1056 
 1057         if (mem->am_type == 2 && mem->am_size != AGP_PAGE_SIZE) {
 1058                 mtx_lock(&sc->agp.as_lock);
 1059                 if (!mem->am_is_bound) {
 1060                         mtx_unlock(&sc->agp.as_lock);
 1061                         return EINVAL;
 1062                 }
 1063 
 1064                 for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) {
 1065                         agp_i810_write_gtt_entry(dev, mem->am_offset + i,
 1066                             0, 0);
 1067                 }
 1068                 agp_flush_cache();
 1069                 mem->am_is_bound = 0;
 1070                 mtx_unlock(&sc->agp.as_lock);
 1071                 return 0;
 1072         }
 1073 
 1074         if (mem->am_type != 1)
 1075                 return agp_generic_unbind_memory(dev, mem);
 1076 
 1077         if ( sc->chiptype != CHIP_I810 )
 1078                 return EINVAL;
 1079 
 1080         for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) {
 1081                 bus_write_4(sc->sc_res[0],
 1082                     AGP_I810_GTT + (i >> AGP_PAGE_SHIFT) * 4, 0);
 1083         }
 1084 
 1085         return 0;
 1086 }
 1087 
 1088 static device_method_t agp_i810_methods[] = {
 1089         /* Device interface */
 1090         DEVMETHOD(device_identify,      agp_i810_identify),
 1091         DEVMETHOD(device_probe,         agp_i810_probe),
 1092         DEVMETHOD(device_attach,        agp_i810_attach),
 1093         DEVMETHOD(device_detach,        agp_i810_detach),
 1094         DEVMETHOD(device_suspend,       bus_generic_suspend),
 1095         DEVMETHOD(device_resume,        agp_i810_resume),
 1096 
 1097         /* AGP interface */
 1098         DEVMETHOD(agp_get_aperture,     agp_generic_get_aperture),
 1099         DEVMETHOD(agp_set_aperture,     agp_i810_set_aperture),
 1100         DEVMETHOD(agp_bind_page,        agp_i810_bind_page),
 1101         DEVMETHOD(agp_unbind_page,      agp_i810_unbind_page),
 1102         DEVMETHOD(agp_flush_tlb,        agp_i810_flush_tlb),
 1103         DEVMETHOD(agp_enable,           agp_i810_enable),
 1104         DEVMETHOD(agp_alloc_memory,     agp_i810_alloc_memory),
 1105         DEVMETHOD(agp_free_memory,      agp_i810_free_memory),
 1106         DEVMETHOD(agp_bind_memory,      agp_i810_bind_memory),
 1107         DEVMETHOD(agp_unbind_memory,    agp_i810_unbind_memory),
 1108 
 1109         { 0, 0 }
 1110 };
 1111 
 1112 static driver_t agp_i810_driver = {
 1113         "agp",
 1114         agp_i810_methods,
 1115         sizeof(struct agp_i810_softc),
 1116 };
 1117 
 1118 static devclass_t agp_devclass;
 1119 
 1120 DRIVER_MODULE(agp_i810, vgapci, agp_i810_driver, agp_devclass, 0, 0);
 1121 MODULE_DEPEND(agp_i810, agp, 1, 1, 1);
 1122 MODULE_DEPEND(agp_i810, pci, 1, 1, 1);

Cache object: 8f7fbb35a98beeb530b3b2b5c57d6417


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