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: releng/6.2/sys/pci/agp_i810.c 159884 2006-06-23 17:10:25Z anholt $");
   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 <sys/rman.h>
   62 
   63 MALLOC_DECLARE(M_AGP);
   64 
   65 #define READ1(off)      bus_space_read_1(sc->bst, sc->bsh, off)
   66 #define READ4(off)      bus_space_read_4(sc->bst, sc->bsh, off)
   67 #define WRITE4(off,v)   bus_space_write_4(sc->bst, sc->bsh, off, v)
   68 #define WRITEGTT(off,v) bus_space_write_4(sc->gtt_bst, sc->gtt_bsh, off, v)
   69 
   70 #define CHIP_I810 0     /* i810/i815 */
   71 #define CHIP_I830 1     /* 830M/845G */
   72 #define CHIP_I855 2     /* 852GM/855GM/865G */
   73 #define CHIP_I915 3     /* 915G/915GM */
   74 
   75 struct agp_i810_softc {
   76         struct agp_softc agp;
   77         u_int32_t initial_aperture;     /* aperture size at startup */
   78         struct agp_gatt *gatt;
   79         int chiptype;                   /* i810-like or i830 */
   80         u_int32_t dcache_size;          /* i810 only */
   81         u_int32_t stolen;               /* number of i830/845 gtt entries for stolen memory */
   82         device_t bdev;                  /* bridge device */
   83 
   84         struct resource *regs;          /* memory mapped GC registers */
   85         bus_space_tag_t bst;            /* bus_space tag */
   86         bus_space_handle_t bsh;         /* bus_space handle */
   87 
   88         struct resource *gtt;           /* memory mapped GATT entries */
   89         bus_space_tag_t gtt_bst;        /* bus_space tag */
   90         bus_space_handle_t gtt_bsh;     /* bus_space handle */
   91 
   92         void *argb_cursor;              /* contigmalloc area for ARGB cursor */
   93 };
   94 
   95 static const char*
   96 agp_i810_match(device_t dev)
   97 {
   98         if (pci_get_class(dev) != PCIC_DISPLAY
   99             || pci_get_subclass(dev) != PCIS_DISPLAY_VGA)
  100                 return NULL;
  101 
  102         switch (pci_get_devid(dev)) {
  103         case 0x71218086:
  104                 return ("Intel 82810 (i810 GMCH) SVGA controller");
  105 
  106         case 0x71238086:
  107                 return ("Intel 82810-DC100 (i810-DC100 GMCH) SVGA controller");
  108 
  109         case 0x71258086:
  110                 return ("Intel 82810E (i810E GMCH) SVGA controller");
  111 
  112         case 0x11328086:
  113                 return ("Intel 82815 (i815 GMCH) SVGA controller");
  114 
  115         case 0x35778086:
  116                 return ("Intel 82830M (830M GMCH) SVGA controller");
  117 
  118         case 0x25628086:
  119                 return ("Intel 82845G (845G GMCH) SVGA controller");
  120 
  121         case 0x35828086:
  122                 switch (pci_read_config(dev, AGP_I85X_CAPID, 1)) {
  123                 case AGP_I855_GME:
  124                         return ("Intel 82855GME (855GME GMCH) SVGA controller");
  125 
  126                 case AGP_I855_GM:
  127                         return ("Intel 82855GM (855GM GMCH) SVGA controller");
  128 
  129                 case AGP_I852_GME:
  130                         return ("Intel 82852GME (852GME GMCH) SVGA controller");
  131 
  132                 case AGP_I852_GM:
  133                         return ("Intel 82852GM (852GM GMCH) SVGA controller");
  134 
  135                 default:
  136                         return ("Intel 8285xM (85xGM GMCH) SVGA controller");
  137                 }
  138 
  139         case 0x25728086:
  140                 return ("Intel 82865G (865G GMCH) SVGA controller");
  141 
  142         case 0x25828086:
  143                 return ("Intel 82915G (915G GMCH) SVGA controller");
  144 
  145         case 0x25928086:
  146                 return ("Intel 82915GM (915GM GMCH) SVGA controller");
  147         };
  148 
  149         return NULL;
  150 }
  151 
  152 /*
  153  * Find bridge device.
  154  */
  155 static device_t
  156 agp_i810_find_bridge(device_t dev)
  157 {
  158         device_t *children, child;
  159         int nchildren, i;
  160         u_int32_t devid;
  161 
  162         /*
  163          * Calculate bridge device's ID.
  164          */
  165         devid = pci_get_devid(dev);
  166         switch (devid) {
  167         case 0x71218086:
  168         case 0x71238086:
  169         case 0x71258086:
  170                 devid -= 0x10000;
  171                 break;
  172 
  173         case 0x11328086:
  174         case 0x35778086:
  175         case 0x25628086:
  176         case 0x35828086:
  177         case 0x25728086:
  178         case 0x25828086:
  179         case 0x25928086:
  180                 devid -= 0x20000;
  181                 break;
  182         };
  183         if (device_get_children(device_get_parent(dev), &children, &nchildren))
  184                 return 0;
  185 
  186         for (i = 0; i < nchildren; i++) {
  187                 child = children[i];
  188 
  189                 if (pci_get_devid(child) == devid) {
  190                         free(children, M_TEMP);
  191                         return child;
  192                 }
  193         }
  194         free(children, M_TEMP);
  195         return 0;
  196 }
  197 
  198 static int
  199 agp_i810_probe(device_t dev)
  200 {
  201         const char *desc;
  202 
  203         if (resource_disabled("agp", device_get_unit(dev)))
  204                 return (ENXIO);
  205         desc = agp_i810_match(dev);
  206         if (desc) {
  207                 device_t bdev;
  208                 u_int8_t smram;
  209                 unsigned int gcc1;
  210                 int devid = pci_get_devid(dev);
  211 
  212                 bdev = agp_i810_find_bridge(dev);
  213                 if (!bdev) {
  214                         if (bootverbose)
  215                                 printf("I810: can't find bridge device\n");
  216                         return ENXIO;
  217                 }
  218 
  219                 /*
  220                  * checking whether internal graphics device has been activated.
  221                  */
  222                 switch (devid) {
  223                         /* i810 */
  224                 case 0x71218086:
  225                 case 0x71238086:
  226                 case 0x71258086:
  227                 case 0x11328086:
  228                         smram = pci_read_config(bdev, AGP_I810_SMRAM, 1);
  229                         if ((smram & AGP_I810_SMRAM_GMS)
  230                             == AGP_I810_SMRAM_GMS_DISABLED) {
  231                                 if (bootverbose)
  232                                         printf("I810: disabled, not probing\n");
  233                                 return ENXIO;
  234                         }
  235                         break;
  236 
  237                         /* i830 */
  238                 case 0x35778086:
  239                 case 0x35828086:
  240                 case 0x25628086:
  241                 case 0x25728086:
  242                         gcc1 = pci_read_config(bdev, AGP_I830_GCC1, 1);
  243                         if ((gcc1 & AGP_I830_GCC1_DEV2) == AGP_I830_GCC1_DEV2_DISABLED) {
  244                                 if (bootverbose)
  245                                         printf("I830: disabled, not probing\n");
  246                                 return ENXIO;
  247                         }
  248                         break;
  249 
  250                         /* i915 */
  251                 case 0x25828086:
  252                 case 0x25928086:
  253                         gcc1 = pci_read_config(bdev, AGP_I915_DEVEN, 4);
  254                         if ((gcc1 & AGP_I915_DEVEN_D2F0) ==
  255                             AGP_I915_DEVEN_D2F0_DISABLED) {
  256                                 if (bootverbose)
  257                                         printf("I915: disabled, not probing\n");
  258                                 return ENXIO;
  259                         }
  260                         break;
  261 
  262                 default:
  263                         return ENXIO;
  264                 }
  265 
  266                 device_verbose(dev);
  267                 device_set_desc(dev, desc);
  268                 return BUS_PROBE_DEFAULT;
  269         }
  270 
  271         return ENXIO;
  272 }
  273 
  274 static int
  275 agp_i810_attach(device_t dev)
  276 {
  277         struct agp_i810_softc *sc = device_get_softc(dev);
  278         struct agp_gatt *gatt;
  279         int error, rid;
  280 
  281         sc->bdev = agp_i810_find_bridge(dev);
  282         if (!sc->bdev)
  283                 return ENOENT;
  284 
  285         error = agp_generic_attach(dev);
  286         if (error)
  287                 return error;
  288 
  289         switch (pci_get_devid(dev)) {
  290         case 0x71218086:
  291         case 0x71238086:
  292         case 0x71258086:
  293         case 0x11328086:
  294                 sc->chiptype = CHIP_I810;
  295                 break;
  296         case 0x35778086:
  297         case 0x25628086:
  298                 sc->chiptype = CHIP_I830;
  299                 break;
  300         case 0x35828086:
  301         case 0x25728086:
  302                 sc->chiptype = CHIP_I855;
  303                 break;
  304         case 0x25828086:
  305         case 0x25928086:
  306                 sc->chiptype = CHIP_I915;
  307                 break;
  308         };
  309 
  310         /* Same for i810 and i830 */
  311         if (sc->chiptype == CHIP_I915)
  312                 rid = AGP_I915_MMADR;
  313         else
  314                 rid = AGP_I810_MMADR;
  315 
  316         sc->regs = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
  317                                           RF_ACTIVE);
  318         if (!sc->regs) {
  319                 agp_generic_detach(dev);
  320                 return ENODEV;
  321         }
  322         sc->bst = rman_get_bustag(sc->regs);
  323         sc->bsh = rman_get_bushandle(sc->regs);
  324 
  325         if (sc->chiptype == CHIP_I915) {
  326                 rid = AGP_I915_GTTADR;
  327                 sc->gtt = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
  328                                                  RF_ACTIVE);
  329                 if (!sc->gtt) {
  330                         bus_release_resource(dev, SYS_RES_MEMORY,
  331                                              AGP_I810_MMADR, sc->regs);
  332                         agp_generic_detach(dev);
  333                         return ENODEV;
  334                 }
  335                 sc->gtt_bst = rman_get_bustag(sc->gtt);
  336                 sc->gtt_bsh = rman_get_bushandle(sc->gtt);
  337         }
  338 
  339         sc->initial_aperture = AGP_GET_APERTURE(dev);
  340 
  341         gatt = malloc( sizeof(struct agp_gatt), M_AGP, M_NOWAIT);
  342         if (!gatt) {
  343                 agp_generic_detach(dev);
  344                 return ENOMEM;
  345         }
  346         sc->gatt = gatt;
  347 
  348         gatt->ag_entries = AGP_GET_APERTURE(dev) >> AGP_PAGE_SHIFT;
  349 
  350         if ( sc->chiptype == CHIP_I810 ) {
  351                 /* Some i810s have on-chip memory called dcache */
  352                 if (READ1(AGP_I810_DRT) & AGP_I810_DRT_POPULATED)
  353                         sc->dcache_size = 4 * 1024 * 1024;
  354                 else
  355                         sc->dcache_size = 0;
  356 
  357                 /* According to the specs the gatt on the i810 must be 64k */
  358                 gatt->ag_virtual = contigmalloc( 64 * 1024, M_AGP, 0, 
  359                                         0, ~0, PAGE_SIZE, 0);
  360                 if (!gatt->ag_virtual) {
  361                         if (bootverbose)
  362                                 device_printf(dev, "contiguous allocation failed\n");
  363                         free(gatt, M_AGP);
  364                         agp_generic_detach(dev);
  365                         return ENOMEM;
  366                 }
  367                 bzero(gatt->ag_virtual, gatt->ag_entries * sizeof(u_int32_t));
  368         
  369                 gatt->ag_physical = vtophys((vm_offset_t) gatt->ag_virtual);
  370                 agp_flush_cache();
  371                 /* Install the GATT. */
  372                 WRITE4(AGP_I810_PGTBL_CTL, gatt->ag_physical | 1);
  373         } else if ( sc->chiptype == CHIP_I830 ) {
  374                 /* The i830 automatically initializes the 128k gatt on boot. */
  375                 unsigned int gcc1, pgtblctl;
  376                 
  377                 gcc1 = pci_read_config(sc->bdev, AGP_I830_GCC1, 1);
  378                 switch (gcc1 & AGP_I830_GCC1_GMS) {
  379                         case AGP_I830_GCC1_GMS_STOLEN_512:
  380                                 sc->stolen = (512 - 132) * 1024 / 4096;
  381                                 break;
  382                         case AGP_I830_GCC1_GMS_STOLEN_1024: 
  383                                 sc->stolen = (1024 - 132) * 1024 / 4096;
  384                                 break;
  385                         case AGP_I830_GCC1_GMS_STOLEN_8192: 
  386                                 sc->stolen = (8192 - 132) * 1024 / 4096;
  387                                 break;
  388                         default:
  389                                 sc->stolen = 0;
  390                                 device_printf(dev, "unknown memory configuration, disabling\n");
  391                                 agp_generic_detach(dev);
  392                                 return EINVAL;
  393                 }
  394                 if (sc->stolen > 0)
  395                         device_printf(dev, "detected %dk stolen memory\n", sc->stolen * 4);
  396                 device_printf(dev, "aperture size is %dM\n", sc->initial_aperture / 1024 / 1024);
  397 
  398                 /* GATT address is already in there, make sure it's enabled */
  399                 pgtblctl = READ4(AGP_I810_PGTBL_CTL);
  400                 pgtblctl |= 1;
  401                 WRITE4(AGP_I810_PGTBL_CTL, pgtblctl);
  402 
  403                 gatt->ag_physical = pgtblctl & ~1;
  404         } else if (sc->chiptype == CHIP_I855 || sc->chiptype == CHIP_I915) {    /* CHIP_I855 */
  405                 unsigned int gcc1, pgtblctl, stolen;
  406 
  407                 /* Stolen memory is set up at the beginning of the aperture by
  408                  * the BIOS, consisting of the GATT followed by 4kb for the BIOS
  409                  * display.
  410                  */
  411                 if (sc->chiptype == CHIP_I855)
  412                         stolen = 132;
  413                 else
  414                         stolen = 260;
  415 
  416                 gcc1 = pci_read_config(sc->bdev, AGP_I855_GCC1, 1);
  417                 switch (gcc1 & AGP_I855_GCC1_GMS) {
  418                         case AGP_I855_GCC1_GMS_STOLEN_1M:
  419                                 sc->stolen = (1024 - stolen) * 1024 / 4096;
  420                                 break;
  421                         case AGP_I855_GCC1_GMS_STOLEN_4M: 
  422                                 sc->stolen = (4096 - stolen) * 1024 / 4096;
  423                                 break;
  424                         case AGP_I855_GCC1_GMS_STOLEN_8M: 
  425                                 sc->stolen = (8192 - stolen) * 1024 / 4096;
  426                                 break;
  427                         case AGP_I855_GCC1_GMS_STOLEN_16M: 
  428                                 sc->stolen = (16384 - stolen) * 1024 / 4096;
  429                                 break;
  430                         case AGP_I855_GCC1_GMS_STOLEN_32M: 
  431                                 sc->stolen = (32768 - stolen) * 1024 / 4096;
  432                                 break;
  433                         case AGP_I915_GCC1_GMS_STOLEN_48M: 
  434                                 sc->stolen = (49152 - stolen) * 1024 / 4096;
  435                                 break;
  436                         case AGP_I915_GCC1_GMS_STOLEN_64M: 
  437                                 sc->stolen = (65536 - stolen) * 1024 / 4096;
  438                                 break;
  439                         default:
  440                                 sc->stolen = 0;
  441                                 device_printf(dev, "unknown memory configuration, disabling\n");
  442                                 agp_generic_detach(dev);
  443                                 return EINVAL;
  444                 }
  445                 if (sc->stolen > 0)
  446                         device_printf(dev, "detected %dk stolen memory\n", sc->stolen * 4);
  447                 device_printf(dev, "aperture size is %dM\n", sc->initial_aperture / 1024 / 1024);
  448 
  449                 /* GATT address is already in there, make sure it's enabled */
  450                 pgtblctl = READ4(AGP_I810_PGTBL_CTL);
  451                 pgtblctl |= 1;
  452                 WRITE4(AGP_I810_PGTBL_CTL, pgtblctl);
  453 
  454                 gatt->ag_physical = pgtblctl & ~1;
  455         }
  456 
  457         /* Add a device for the drm to attach to */
  458         if (!device_add_child( dev, "drmsub", -1 ))
  459                 printf("out of memory...\n");
  460 
  461         return bus_generic_attach(dev);
  462 }
  463 
  464 static int
  465 agp_i810_detach(device_t dev)
  466 {
  467         struct agp_i810_softc *sc = device_get_softc(dev);
  468         int error;
  469         device_t child;
  470 
  471         error = agp_generic_detach(dev);
  472         if (error)
  473                 return error;
  474 
  475         /* Clear the GATT base. */
  476         if ( sc->chiptype == CHIP_I810 ) {
  477                 WRITE4(AGP_I810_PGTBL_CTL, 0);
  478         } else {
  479                 unsigned int pgtblctl;
  480                 pgtblctl = READ4(AGP_I810_PGTBL_CTL);
  481                 pgtblctl &= ~1;
  482                 WRITE4(AGP_I810_PGTBL_CTL, pgtblctl);
  483         }
  484 
  485         /* Put the aperture back the way it started. */
  486         AGP_SET_APERTURE(dev, sc->initial_aperture);
  487 
  488         if ( sc->chiptype == CHIP_I810 ) {
  489                 contigfree(sc->gatt->ag_virtual, 64 * 1024, M_AGP);
  490         }
  491         free(sc->gatt, M_AGP);
  492 
  493         if (sc->chiptype == CHIP_I915) {
  494                 bus_release_resource(dev, SYS_RES_MEMORY, AGP_I915_GTTADR,
  495                                      sc->gtt);
  496                 bus_release_resource(dev, SYS_RES_MEMORY, AGP_I915_MMADR,
  497                                      sc->regs);
  498         } else {
  499                 bus_release_resource(dev, SYS_RES_MEMORY, AGP_I810_MMADR,
  500                                      sc->regs);
  501         }
  502 
  503         child = device_find_child( dev, "drmsub", 0 );
  504         if (child)
  505            device_delete_child( dev, child );
  506 
  507         return 0;
  508 }
  509 
  510 static u_int32_t
  511 agp_i810_get_aperture(device_t dev)
  512 {
  513         struct agp_i810_softc *sc = device_get_softc(dev);
  514         uint32_t temp;
  515         u_int16_t miscc;
  516 
  517         switch (sc->chiptype) {
  518         case CHIP_I810:
  519                 miscc = pci_read_config(sc->bdev, AGP_I810_MISCC, 2);
  520                 if ((miscc & AGP_I810_MISCC_WINSIZE) == AGP_I810_MISCC_WINSIZE_32)
  521                         return 32 * 1024 * 1024;
  522                 else
  523                         return 64 * 1024 * 1024;
  524         case CHIP_I830:
  525                 temp = pci_read_config(sc->bdev, AGP_I830_GCC1, 2);
  526                 if ((temp & AGP_I830_GCC1_GMASIZE) == AGP_I830_GCC1_GMASIZE_64)
  527                         return 64 * 1024 * 1024;
  528                 else
  529                         return 128 * 1024 * 1024;
  530         case CHIP_I855:
  531                 return 128 * 1024 * 1024;
  532         case CHIP_I915:
  533                 temp = pci_read_config(dev, AGP_I915_MSAC, 1);
  534                 if ((temp & AGP_I915_MSAC_GMASIZE) ==
  535                     AGP_I915_MSAC_GMASIZE_128) {
  536                         return 128 * 1024 * 1024;
  537                 } else {
  538                         return 256 * 1024 * 1024;
  539                 }
  540         }
  541 
  542         return 0;
  543 }
  544 
  545 static int
  546 agp_i810_set_aperture(device_t dev, u_int32_t aperture)
  547 {
  548         struct agp_i810_softc *sc = device_get_softc(dev);
  549         u_int16_t miscc, gcc1;
  550         u_int32_t temp;
  551 
  552         switch (sc->chiptype) {
  553         case CHIP_I810:
  554                 /*
  555                  * Double check for sanity.
  556                  */
  557                 if (aperture != 32 * 1024 * 1024 && aperture != 64 * 1024 * 1024) {
  558                         device_printf(dev, "bad aperture size %d\n", aperture);
  559                         return EINVAL;
  560                 }
  561 
  562                 miscc = pci_read_config(sc->bdev, AGP_I810_MISCC, 2);
  563                 miscc &= ~AGP_I810_MISCC_WINSIZE;
  564                 if (aperture == 32 * 1024 * 1024)
  565                         miscc |= AGP_I810_MISCC_WINSIZE_32;
  566                 else
  567                         miscc |= AGP_I810_MISCC_WINSIZE_64;
  568         
  569                 pci_write_config(sc->bdev, AGP_I810_MISCC, miscc, 2);
  570                 break;
  571         case CHIP_I830:
  572                 if (aperture != 64 * 1024 * 1024 &&
  573                     aperture != 128 * 1024 * 1024) {
  574                         device_printf(dev, "bad aperture size %d\n", aperture);
  575                         return EINVAL;
  576                 }
  577                 gcc1 = pci_read_config(sc->bdev, AGP_I830_GCC1, 2);
  578                 gcc1 &= ~AGP_I830_GCC1_GMASIZE;
  579                 if (aperture == 64 * 1024 * 1024)
  580                         gcc1 |= AGP_I830_GCC1_GMASIZE_64;
  581                 else
  582                         gcc1 |= AGP_I830_GCC1_GMASIZE_128;
  583 
  584                 pci_write_config(sc->bdev, AGP_I830_GCC1, gcc1, 2);
  585                 break;
  586         case CHIP_I855:
  587                 if (aperture != 128 * 1024 * 1024) {
  588                         device_printf(dev, "bad aperture size %d\n", aperture);
  589                         return EINVAL;
  590                 }
  591                 break;
  592         case CHIP_I915:
  593                 temp = pci_read_config(dev, AGP_I915_MSAC, 1);
  594                 temp &= ~AGP_I915_MSAC_GMASIZE;
  595 
  596                 switch (aperture) {
  597                 case 128 * 1024 * 1024:
  598                         temp |= AGP_I915_MSAC_GMASIZE_128;
  599                         break;
  600                 case 256 * 1024 * 1024:
  601                         temp |= AGP_I915_MSAC_GMASIZE_256;
  602                         break;
  603                 default:
  604                         device_printf(dev, "bad aperture size %d\n", aperture);
  605                         return EINVAL;
  606                 }
  607 
  608                 pci_write_config(dev, AGP_I915_MSAC, temp, 1);
  609                 break;
  610         }
  611 
  612         return 0;
  613 }
  614 
  615 static int
  616 agp_i810_bind_page(device_t dev, int offset, vm_offset_t physical)
  617 {
  618         struct agp_i810_softc *sc = device_get_softc(dev);
  619 
  620         if (offset < 0 || offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT)) {
  621                 device_printf(dev, "failed: offset is 0x%08x, shift is %d, entries is %d\n", offset, AGP_PAGE_SHIFT, sc->gatt->ag_entries);
  622                 return EINVAL;
  623         }
  624 
  625         if ( sc->chiptype != CHIP_I810 ) {
  626                 if ( (offset >> AGP_PAGE_SHIFT) < sc->stolen ) {
  627                         device_printf(dev, "trying to bind into stolen memory");
  628                         return EINVAL;
  629                 }
  630         }
  631 
  632         if (sc->chiptype == CHIP_I915) {
  633                 WRITEGTT((offset >> AGP_PAGE_SHIFT) * 4, physical | 1);
  634         } else {
  635                 WRITE4(AGP_I810_GTT + (offset >> AGP_PAGE_SHIFT) * 4, physical | 1);
  636         }
  637 
  638         return 0;
  639 }
  640 
  641 static int
  642 agp_i810_unbind_page(device_t dev, int offset)
  643 {
  644         struct agp_i810_softc *sc = device_get_softc(dev);
  645 
  646         if (offset < 0 || offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT))
  647                 return EINVAL;
  648 
  649         if ( sc->chiptype != CHIP_I810 ) {
  650                 if ( (offset >> AGP_PAGE_SHIFT) < sc->stolen ) {
  651                         device_printf(dev, "trying to unbind from stolen memory");
  652                         return EINVAL;
  653                 }
  654         }
  655 
  656         if (sc->chiptype == CHIP_I915) {
  657                 WRITEGTT((offset >> AGP_PAGE_SHIFT) * 4, 0);
  658         } else {
  659                 WRITE4(AGP_I810_GTT + (offset >> AGP_PAGE_SHIFT) * 4, 0);
  660         }
  661         
  662         return 0;
  663 }
  664 
  665 /*
  666  * Writing via memory mapped registers already flushes all TLBs.
  667  */
  668 static void
  669 agp_i810_flush_tlb(device_t dev)
  670 {
  671 }
  672 
  673 static int
  674 agp_i810_enable(device_t dev, u_int32_t mode)
  675 {
  676 
  677         return 0;
  678 }
  679 
  680 static struct agp_memory *
  681 agp_i810_alloc_memory(device_t dev, int type, vm_size_t size)
  682 {
  683         struct agp_i810_softc *sc = device_get_softc(dev);
  684         struct agp_memory *mem;
  685 
  686         if ((size & (AGP_PAGE_SIZE - 1)) != 0)
  687                 return 0;
  688 
  689         if (sc->agp.as_allocated + size > sc->agp.as_maxmem)
  690                 return 0;
  691 
  692         if (type == 1) {
  693                 /*
  694                  * Mapping local DRAM into GATT.
  695                  */
  696                 if ( sc->chiptype != CHIP_I810 )
  697                         return 0;
  698                 if (size != sc->dcache_size)
  699                         return 0;
  700         } else if (type == 2) {
  701                 /*
  702                  * Type 2 is the contiguous physical memory type, that hands
  703                  * back a physical address.  This is used for cursors on i810.
  704                  * Hand back as many single pages with physical as the user
  705                  * wants, but only allow one larger allocation (ARGB cursor)
  706                  * for simplicity.
  707                  */
  708                 if (size != AGP_PAGE_SIZE) {
  709                         if (sc->argb_cursor != NULL)
  710                                 return 0;
  711 
  712                         /* Allocate memory for ARGB cursor, if we can. */
  713                         sc->argb_cursor = contigmalloc(size, M_AGP,
  714                            0, 0, ~0, PAGE_SIZE, 0);
  715                         if (sc->argb_cursor == NULL)
  716                                 return 0;
  717                 }
  718         }
  719 
  720         mem = malloc(sizeof *mem, M_AGP, M_WAITOK);
  721         mem->am_id = sc->agp.as_nextid++;
  722         mem->am_size = size;
  723         mem->am_type = type;
  724         if (type != 1 && (type != 2 || size == AGP_PAGE_SIZE))
  725                 mem->am_obj = vm_object_allocate(OBJT_DEFAULT,
  726                                                  atop(round_page(size)));
  727         else
  728                 mem->am_obj = 0;
  729 
  730         if (type == 2) {
  731                 if (size == AGP_PAGE_SIZE) {
  732                         /*
  733                          * Allocate and wire down the page now so that we can
  734                          * get its physical address.
  735                          */
  736                         vm_page_t m;
  737         
  738                         VM_OBJECT_LOCK(mem->am_obj);
  739                         m = vm_page_grab(mem->am_obj, 0, VM_ALLOC_NOBUSY |
  740                             VM_ALLOC_WIRED | VM_ALLOC_ZERO | VM_ALLOC_RETRY);
  741                         VM_OBJECT_UNLOCK(mem->am_obj);
  742                         mem->am_physical = VM_PAGE_TO_PHYS(m);
  743                 } else {
  744                         /* Our allocation is already nicely wired down for us.
  745                          * Just grab the physical address.
  746                          */
  747                         mem->am_physical = vtophys(sc->argb_cursor);
  748                 }
  749         } else {
  750                 mem->am_physical = 0;
  751         }
  752 
  753         mem->am_offset = 0;
  754         mem->am_is_bound = 0;
  755         TAILQ_INSERT_TAIL(&sc->agp.as_memory, mem, am_link);
  756         sc->agp.as_allocated += size;
  757 
  758         return mem;
  759 }
  760 
  761 static int
  762 agp_i810_free_memory(device_t dev, struct agp_memory *mem)
  763 {
  764         struct agp_i810_softc *sc = device_get_softc(dev);
  765 
  766         if (mem->am_is_bound)
  767                 return EBUSY;
  768 
  769         if (mem->am_type == 2) {
  770                 if (mem->am_size == AGP_PAGE_SIZE) {
  771                         /*
  772                          * Unwire the page which we wired in alloc_memory.
  773                          */
  774                         vm_page_t m;
  775         
  776                         VM_OBJECT_LOCK(mem->am_obj);
  777                         m = vm_page_lookup(mem->am_obj, 0);
  778                         VM_OBJECT_UNLOCK(mem->am_obj);
  779                         vm_page_lock_queues();
  780                         vm_page_unwire(m, 0);
  781                         vm_page_unlock_queues();
  782                 } else {
  783                         contigfree(sc->argb_cursor, mem->am_size, M_AGP);
  784                         sc->argb_cursor = NULL;
  785                 }
  786         }
  787 
  788         sc->agp.as_allocated -= mem->am_size;
  789         TAILQ_REMOVE(&sc->agp.as_memory, mem, am_link);
  790         if (mem->am_obj)
  791                 vm_object_deallocate(mem->am_obj);
  792         free(mem, M_AGP);
  793         return 0;
  794 }
  795 
  796 static int
  797 agp_i810_bind_memory(device_t dev, struct agp_memory *mem,
  798                      vm_offset_t offset)
  799 {
  800         struct agp_i810_softc *sc = device_get_softc(dev);
  801         vm_offset_t i;
  802 
  803         /* Do some sanity checks first. */
  804         if (offset < 0 || (offset & (AGP_PAGE_SIZE - 1)) != 0 ||
  805             offset + mem->am_size > AGP_GET_APERTURE(dev)) {
  806                 device_printf(dev, "binding memory at bad offset %#x\n",
  807                     (int)offset);
  808                 return EINVAL;
  809         }
  810 
  811         if (mem->am_type == 2 && mem->am_size != AGP_PAGE_SIZE) {
  812                 mtx_lock(&sc->agp.as_lock);
  813                 if (mem->am_is_bound) {
  814                         mtx_unlock(&sc->agp.as_lock);
  815                         return EINVAL;
  816                 }
  817                 /* The memory's already wired down, just stick it in the GTT. */
  818                 for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) {
  819                         u_int32_t physical = mem->am_physical + i;
  820 
  821                         if (sc->chiptype == CHIP_I915) {
  822                                 WRITEGTT(((offset + i) >> AGP_PAGE_SHIFT) * 4,
  823                                     physical | 1);
  824                         } else {
  825                                 WRITE4(AGP_I810_GTT +
  826                                     ((offset + i) >> AGP_PAGE_SHIFT) * 4,
  827                                     physical | 1);
  828                         }
  829                 }
  830                 agp_flush_cache();
  831                 mem->am_offset = offset;
  832                 mem->am_is_bound = 1;
  833                 mtx_unlock(&sc->agp.as_lock);
  834                 return 0;
  835         }
  836 
  837         if (mem->am_type != 1)
  838                 return agp_generic_bind_memory(dev, mem, offset);
  839 
  840         if ( sc->chiptype != CHIP_I810 )
  841                 return EINVAL;
  842 
  843         for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) {
  844                 WRITE4(AGP_I810_GTT + (offset >> AGP_PAGE_SHIFT) * 4,
  845                        i | 3);
  846         }
  847 
  848         return 0;
  849 }
  850 
  851 static int
  852 agp_i810_unbind_memory(device_t dev, struct agp_memory *mem)
  853 {
  854         struct agp_i810_softc *sc = device_get_softc(dev);
  855         vm_offset_t i;
  856 
  857         if (mem->am_type == 2 && mem->am_size != AGP_PAGE_SIZE) {
  858                 mtx_lock(&sc->agp.as_lock);
  859                 if (!mem->am_is_bound) {
  860                         mtx_unlock(&sc->agp.as_lock);
  861                         return EINVAL;
  862                 }
  863 
  864                 for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) {
  865                         vm_offset_t offset = mem->am_offset;
  866 
  867                         if (sc->chiptype == CHIP_I915) {
  868                                 WRITEGTT(((offset + i) >> AGP_PAGE_SHIFT) * 4,
  869                                     0);
  870                         } else {
  871                                 WRITE4(AGP_I810_GTT +
  872                                     ((offset + i) >> AGP_PAGE_SHIFT) * 4, 0);
  873                         }
  874                 }
  875                 agp_flush_cache();
  876                 mem->am_is_bound = 0;
  877                 mtx_unlock(&sc->agp.as_lock);
  878                 return 0;
  879         }
  880 
  881         if (mem->am_type != 1)
  882                 return agp_generic_unbind_memory(dev, mem);
  883 
  884         if ( sc->chiptype != CHIP_I810 )
  885                 return EINVAL;
  886 
  887         for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE)
  888                 WRITE4(AGP_I810_GTT + (i >> AGP_PAGE_SHIFT) * 4, 0);
  889 
  890         return 0;
  891 }
  892 
  893 static int
  894 agp_i810_print_child(device_t dev, device_t child)
  895 {
  896         int retval = 0;
  897 
  898         retval += bus_print_child_header(dev, child);
  899         retval += printf(": (child of agp_i810.c)");
  900         retval += bus_print_child_footer(dev, child);
  901 
  902         return retval;
  903 }
  904 
  905 static device_method_t agp_i810_methods[] = {
  906         /* Device interface */
  907         DEVMETHOD(device_probe,         agp_i810_probe),
  908         DEVMETHOD(device_attach,        agp_i810_attach),
  909         DEVMETHOD(device_detach,        agp_i810_detach),
  910         DEVMETHOD(device_shutdown,      bus_generic_shutdown),
  911         DEVMETHOD(device_suspend,       bus_generic_suspend),
  912         DEVMETHOD(device_resume,        bus_generic_resume),
  913 
  914         /* AGP interface */
  915         DEVMETHOD(agp_get_aperture,     agp_i810_get_aperture),
  916         DEVMETHOD(agp_set_aperture,     agp_i810_set_aperture),
  917         DEVMETHOD(agp_bind_page,        agp_i810_bind_page),
  918         DEVMETHOD(agp_unbind_page,      agp_i810_unbind_page),
  919         DEVMETHOD(agp_flush_tlb,        agp_i810_flush_tlb),
  920         DEVMETHOD(agp_enable,           agp_i810_enable),
  921         DEVMETHOD(agp_alloc_memory,     agp_i810_alloc_memory),
  922         DEVMETHOD(agp_free_memory,      agp_i810_free_memory),
  923         DEVMETHOD(agp_bind_memory,      agp_i810_bind_memory),
  924         DEVMETHOD(agp_unbind_memory,    agp_i810_unbind_memory),
  925 
  926         /* bus methods */
  927         DEVMETHOD(bus_print_child,      agp_i810_print_child),
  928         DEVMETHOD(bus_alloc_resource,   bus_generic_alloc_resource),
  929         DEVMETHOD(bus_release_resource, bus_generic_release_resource),
  930         DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
  931         DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
  932         DEVMETHOD(bus_setup_intr,       bus_generic_setup_intr),
  933         DEVMETHOD(bus_teardown_intr,    bus_generic_teardown_intr),
  934         { 0, 0 }
  935 };
  936 
  937 static driver_t agp_i810_driver = {
  938         "agp",
  939         agp_i810_methods,
  940         sizeof(struct agp_i810_softc),
  941 };
  942 
  943 static devclass_t agp_devclass;
  944 
  945 DRIVER_MODULE(agp_i810, pci, agp_i810_driver, agp_devclass, 0, 0);
  946 MODULE_DEPEND(agp_i810, agp, 1, 1, 1);
  947 MODULE_DEPEND(agp_i810, pci, 1, 1, 1);

Cache object: 59a8840eecfe92d270badc34aab49fd8


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