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  *      $FreeBSD: releng/5.1/sys/pci/agp_i810.c 113506 2003-04-15 06:37:30Z mdodd $
   28  */
   29 
   30 /*
   31  * Fixes for 830/845G support: David Dawes <dawes@xfree86.org>
   32  * 852GM/855GM/865G support added by David Dawes <dawes@xfree86.org>
   33  */
   34 
   35 #include "opt_bus.h"
   36 
   37 #include <sys/param.h>
   38 #include <sys/systm.h>
   39 #include <sys/malloc.h>
   40 #include <sys/kernel.h>
   41 #include <sys/bus.h>
   42 #include <sys/lock.h>
   43 #include <sys/lockmgr.h>
   44 #include <sys/mutex.h>
   45 #include <sys/proc.h>
   46 
   47 #include <pci/pcivar.h>
   48 #include <pci/pcireg.h>
   49 #include <pci/agppriv.h>
   50 #include <pci/agpreg.h>
   51 
   52 #include <vm/vm.h>
   53 #include <vm/vm_object.h>
   54 #include <vm/vm_page.h>
   55 #include <vm/vm_pageout.h>
   56 #include <vm/pmap.h>
   57 
   58 #include <machine/bus.h>
   59 #include <machine/resource.h>
   60 #include <sys/rman.h>
   61 
   62 MALLOC_DECLARE(M_AGP);
   63 
   64 #define READ1(off)      bus_space_read_1(sc->bst, sc->bsh, off)
   65 #define READ4(off)      bus_space_read_4(sc->bst, sc->bsh, off)
   66 #define WRITE4(off,v)   bus_space_write_4(sc->bst, sc->bsh, off, v)
   67 
   68 #define CHIP_I810 0     /* i810/i815 */
   69 #define CHIP_I830 1     /* 830M/845G */
   70 #define CHIP_I855 2     /* 852GM/855GM/865G */
   71 
   72 struct agp_i810_softc {
   73         struct agp_softc agp;
   74         u_int32_t initial_aperture;     /* aperture size at startup */
   75         struct agp_gatt *gatt;
   76         int chiptype;                   /* i810-like or i830 */
   77         u_int32_t dcache_size;          /* i810 only */
   78         u_int32_t stolen;               /* number of i830/845 gtt entries for stolen memory */
   79         device_t bdev;                  /* bridge device */
   80         struct resource *regs;          /* memory mapped GC registers */
   81         bus_space_tag_t bst;            /* bus_space tag */
   82         bus_space_handle_t bsh;         /* bus_space handle */
   83 };
   84 
   85 static const char*
   86 agp_i810_match(device_t dev)
   87 {
   88         if (pci_get_class(dev) != PCIC_DISPLAY
   89             || pci_get_subclass(dev) != PCIS_DISPLAY_VGA)
   90                 return NULL;
   91 
   92         switch (pci_get_devid(dev)) {
   93         case 0x71218086:
   94                 return ("Intel 82810 (i810 GMCH) SVGA controller");
   95 
   96         case 0x71238086:
   97                 return ("Intel 82810-DC100 (i810-DC100 GMCH) SVGA controller");
   98 
   99         case 0x71258086:
  100                 return ("Intel 82810E (i810E GMCH) SVGA controller");
  101 
  102         case 0x11328086:
  103                 return ("Intel 82815 (i815 GMCH) SVGA controller");
  104 
  105         case 0x35778086:
  106                 return ("Intel 82830M (830M GMCH) SVGA controller");
  107 
  108         case 0x25628086:
  109                 return ("Intel 82845G (845G GMCH) SVGA controller");
  110 
  111         case 0x35828086:
  112                 switch (pci_read_config(dev, AGP_I85X_CAPID, 1)) {
  113                 case AGP_I855_GME:
  114                         return ("Intel 82855GME (855GME GMCH) SVGA controller");
  115 
  116                 case AGP_I855_GM:
  117                         return ("Intel 82855GM (855GM GMCH) SVGA controller");
  118 
  119                 case AGP_I852_GME:
  120                         return ("Intel 82852GME (852GME GMCH) SVGA controller");
  121 
  122                 case AGP_I852_GM:
  123                         return ("Intel 82852GM (852GM GMCH) SVGA controller");
  124 
  125                 default:
  126                         return ("Intel 8285xM (85xGM GMCH) SVGA controller");
  127                 }
  128 
  129         case 0x25728086:
  130                 return ("Intel 82865G (865G GMCH) SVGA controller");
  131         };
  132 
  133         return NULL;
  134 }
  135 
  136 /*
  137  * Find bridge device.
  138  */
  139 static device_t
  140 agp_i810_find_bridge(device_t dev)
  141 {
  142         device_t *children, child;
  143         int nchildren, i;
  144         u_int32_t devid;
  145 
  146         /*
  147          * Calculate bridge device's ID.
  148          */
  149         devid = pci_get_devid(dev);
  150         switch (devid) {
  151         case 0x71218086:
  152         case 0x71238086:
  153         case 0x71258086:
  154                 devid -= 0x10000;
  155                 break;
  156 
  157         case 0x11328086:
  158         case 0x35778086:
  159         case 0x25628086:
  160         case 0x35828086:
  161         case 0x25728086:
  162                 devid -= 0x20000;
  163                 break;
  164         };
  165         if (device_get_children(device_get_parent(dev), &children, &nchildren))
  166                 return 0;
  167 
  168         for (i = 0; i < nchildren; i++) {
  169                 child = children[i];
  170 
  171                 if (pci_get_devid(child) == devid) {
  172                         free(children, M_TEMP);
  173                         return child;
  174                 }
  175         }
  176         free(children, M_TEMP);
  177         return 0;
  178 }
  179 
  180 static int
  181 agp_i810_probe(device_t dev)
  182 {
  183         const char *desc;
  184 
  185         desc = agp_i810_match(dev);
  186         if (desc) {
  187                 device_t bdev;
  188                 u_int8_t smram;
  189                 int devid = pci_get_devid(dev);
  190 
  191                 bdev = agp_i810_find_bridge(dev);
  192                 if (!bdev) {
  193                         if (bootverbose)
  194                                 printf("I810: can't find bridge device\n");
  195                         return ENXIO;
  196                 }
  197 
  198                 /*
  199                  * checking whether internal graphics device has been activated.
  200                  */
  201                 if ( (devid == 0x71218086 ) ||
  202                      (devid == 0x71238086 ) ||
  203                      (devid == 0x71258086 ) ||
  204                      (devid == 0x11328086 ) ) {
  205                         smram = pci_read_config(bdev, AGP_I810_SMRAM, 1);
  206                         if ((smram & AGP_I810_SMRAM_GMS)
  207                             == AGP_I810_SMRAM_GMS_DISABLED) {
  208                                 if (bootverbose)
  209                                         printf("I810: disabled, not probing\n");
  210                                 return ENXIO;
  211                         }
  212                 } else {        /* I830MG */
  213                         unsigned int gcc1;
  214                         gcc1 = pci_read_config(bdev, AGP_I830_GCC1, 1);
  215                         if ((gcc1 & AGP_I830_GCC1_DEV2) == AGP_I830_GCC1_DEV2_DISABLED) {
  216                                 if (bootverbose)
  217                                         printf("I830: disabled, not probing\n");
  218                                 return ENXIO;
  219                         }
  220                 }
  221 
  222                 device_verbose(dev);
  223                 device_set_desc(dev, desc);
  224                 return 0;
  225         }
  226 
  227         return ENXIO;
  228 }
  229 
  230 static int
  231 agp_i810_attach(device_t dev)
  232 {
  233         struct agp_i810_softc *sc = device_get_softc(dev);
  234         struct agp_gatt *gatt;
  235         int error, rid;
  236 
  237         sc->bdev = agp_i810_find_bridge(dev);
  238         if (!sc->bdev)
  239                 return ENOENT;
  240 
  241         error = agp_generic_attach(dev);
  242         if (error)
  243                 return error;
  244 
  245         switch (pci_get_devid(dev)) {
  246         case 0x71218086:
  247         case 0x71238086:
  248         case 0x71258086:
  249         case 0x11328086:
  250                 sc->chiptype = CHIP_I810;
  251                 break;
  252         case 0x35778086:
  253         case 0x25628086:
  254                 sc->chiptype = CHIP_I830;
  255                 break;
  256         case 0x35828086:
  257         case 0x25728086:
  258                 sc->chiptype = CHIP_I855;
  259                 break;
  260         };
  261 
  262         /* Same for i810 and i830 */
  263         rid = AGP_I810_MMADR;
  264         sc->regs = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid,
  265                                       0, ~0, 1, RF_ACTIVE);
  266         if (!sc->regs) {
  267                 agp_generic_detach(dev);
  268                 return ENOMEM;
  269         }
  270         sc->bst = rman_get_bustag(sc->regs);
  271         sc->bsh = rman_get_bushandle(sc->regs);
  272 
  273         sc->initial_aperture = AGP_GET_APERTURE(dev);
  274 
  275         gatt = malloc( sizeof(struct agp_gatt), M_AGP, M_NOWAIT);
  276         if (!gatt) {
  277                 agp_generic_detach(dev);
  278                 return ENOMEM;
  279         }
  280         sc->gatt = gatt;
  281 
  282         gatt->ag_entries = AGP_GET_APERTURE(dev) >> AGP_PAGE_SHIFT;
  283 
  284         if ( sc->chiptype == CHIP_I810 ) {
  285                 /* Some i810s have on-chip memory called dcache */
  286                 if (READ1(AGP_I810_DRT) & AGP_I810_DRT_POPULATED)
  287                         sc->dcache_size = 4 * 1024 * 1024;
  288                 else
  289                         sc->dcache_size = 0;
  290 
  291                 /* According to the specs the gatt on the i810 must be 64k */
  292                 gatt->ag_virtual = contigmalloc( 64 * 1024, M_AGP, 0, 
  293                                         0, ~0, PAGE_SIZE, 0);
  294                 if (!gatt->ag_virtual) {
  295                         if (bootverbose)
  296                                 device_printf(dev, "contiguous allocation failed\n");
  297                         free(gatt, M_AGP);
  298                         agp_generic_detach(dev);
  299                         return ENOMEM;
  300                 }
  301                 bzero(gatt->ag_virtual, gatt->ag_entries * sizeof(u_int32_t));
  302         
  303                 gatt->ag_physical = vtophys((vm_offset_t) gatt->ag_virtual);
  304                 agp_flush_cache();
  305                 /* Install the GATT. */
  306                 WRITE4(AGP_I810_PGTBL_CTL, gatt->ag_physical | 1);
  307         } else if ( sc->chiptype == CHIP_I830 ) {
  308                 /* The i830 automatically initializes the 128k gatt on boot. */
  309                 unsigned int gcc1, pgtblctl;
  310                 
  311                 gcc1 = pci_read_config(sc->bdev, AGP_I830_GCC1, 1);
  312                 switch (gcc1 & AGP_I830_GCC1_GMS) {
  313                         case AGP_I830_GCC1_GMS_STOLEN_512:
  314                                 sc->stolen = (512 - 132) * 1024 / 4096;
  315                                 break;
  316                         case AGP_I830_GCC1_GMS_STOLEN_1024: 
  317                                 sc->stolen = (1024 - 132) * 1024 / 4096;
  318                                 break;
  319                         case AGP_I830_GCC1_GMS_STOLEN_8192: 
  320                                 sc->stolen = (8192 - 132) * 1024 / 4096;
  321                                 break;
  322                         default:
  323                                 sc->stolen = 0;
  324                                 device_printf(dev, "unknown memory configuration, disabling\n");
  325                                 agp_generic_detach(dev);
  326                                 return EINVAL;
  327                 }
  328                 if (sc->stolen > 0)
  329                         device_printf(dev, "detected %dk stolen memory\n", sc->stolen * 4);
  330                 device_printf(dev, "aperture size is %dM\n", sc->initial_aperture / 1024 / 1024);
  331 
  332                 /* GATT address is already in there, make sure it's enabled */
  333                 pgtblctl = READ4(AGP_I810_PGTBL_CTL);
  334                 pgtblctl |= 1;
  335                 WRITE4(AGP_I810_PGTBL_CTL, pgtblctl);
  336 
  337                 gatt->ag_physical = pgtblctl & ~1;
  338         } else {        /* CHIP_I855 */
  339                 /* The 855GM automatically initializes the 128k gatt on boot. */
  340                 unsigned int gcc1, pgtblctl;
  341                 
  342                 gcc1 = pci_read_config(sc->bdev, AGP_I855_GCC1, 1);
  343                 switch (gcc1 & AGP_I855_GCC1_GMS) {
  344                         case AGP_I855_GCC1_GMS_STOLEN_1M:
  345                                 sc->stolen = (1024 - 132) * 1024 / 4096;
  346                                 break;
  347                         case AGP_I855_GCC1_GMS_STOLEN_4M: 
  348                                 sc->stolen = (4096 - 132) * 1024 / 4096;
  349                                 break;
  350                         case AGP_I855_GCC1_GMS_STOLEN_8M: 
  351                                 sc->stolen = (8192 - 132) * 1024 / 4096;
  352                                 break;
  353                         case AGP_I855_GCC1_GMS_STOLEN_16M: 
  354                                 sc->stolen = (16384 - 132) * 1024 / 4096;
  355                                 break;
  356                         case AGP_I855_GCC1_GMS_STOLEN_32M: 
  357                                 sc->stolen = (32768 - 132) * 1024 / 4096;
  358                                 break;
  359                         default:
  360                                 sc->stolen = 0;
  361                                 device_printf(dev, "unknown memory configuration, disabling\n");
  362                                 agp_generic_detach(dev);
  363                                 return EINVAL;
  364                 }
  365                 if (sc->stolen > 0)
  366                         device_printf(dev, "detected %dk stolen memory\n", sc->stolen * 4);
  367                 device_printf(dev, "aperture size is %dM\n", sc->initial_aperture / 1024 / 1024);
  368 
  369                 /* GATT address is already in there, make sure it's enabled */
  370                 pgtblctl = READ4(AGP_I810_PGTBL_CTL);
  371                 pgtblctl |= 1;
  372                 WRITE4(AGP_I810_PGTBL_CTL, pgtblctl);
  373 
  374                 gatt->ag_physical = pgtblctl & ~1;
  375         }
  376 
  377         return 0;
  378 }
  379 
  380 static int
  381 agp_i810_detach(device_t dev)
  382 {
  383         struct agp_i810_softc *sc = device_get_softc(dev);
  384         int error;
  385 
  386         error = agp_generic_detach(dev);
  387         if (error)
  388                 return error;
  389 
  390         /* Clear the GATT base. */
  391         if ( sc->chiptype == CHIP_I810 ) {
  392                 WRITE4(AGP_I810_PGTBL_CTL, 0);
  393         } else {
  394                 unsigned int pgtblctl;
  395                 pgtblctl = READ4(AGP_I810_PGTBL_CTL);
  396                 pgtblctl &= ~1;
  397                 WRITE4(AGP_I810_PGTBL_CTL, pgtblctl);
  398         }
  399 
  400         /* Put the aperture back the way it started. */
  401         AGP_SET_APERTURE(dev, sc->initial_aperture);
  402 
  403         if ( sc->chiptype == CHIP_I810 ) {
  404                 contigfree(sc->gatt->ag_virtual, 64 * 1024, M_AGP);
  405         }
  406         free(sc->gatt, M_AGP);
  407 
  408         bus_release_resource(dev, SYS_RES_MEMORY,
  409                              AGP_I810_MMADR, sc->regs);
  410 
  411         return 0;
  412 }
  413 
  414 static u_int32_t
  415 agp_i810_get_aperture(device_t dev)
  416 {
  417         struct agp_i810_softc *sc = device_get_softc(dev);
  418 
  419         if ( sc->chiptype == CHIP_I810 ) {
  420                 u_int16_t miscc;
  421                 miscc = pci_read_config(sc->bdev, AGP_I810_MISCC, 2);
  422                 if ((miscc & AGP_I810_MISCC_WINSIZE) == AGP_I810_MISCC_WINSIZE_32)
  423                         return 32 * 1024 * 1024;
  424                 else
  425                         return 64 * 1024 * 1024;
  426         } else if ( sc->chiptype == CHIP_I830 ) {
  427                 unsigned int gcc1;
  428 
  429                 gcc1 = pci_read_config(sc->bdev, AGP_I830_GCC1, 2);
  430                 if ((gcc1 & AGP_I830_GCC1_GMASIZE) == AGP_I830_GCC1_GMASIZE_64)
  431                         return 64 * 1024 * 1024;
  432                 else
  433                         return 128 * 1024 * 1024;
  434         } else { /* CHIP_I855 */
  435                 return 128 * 1024 * 1024;
  436         }
  437 }
  438 
  439 static int
  440 agp_i810_set_aperture(device_t dev, u_int32_t aperture)
  441 {
  442         struct agp_i810_softc *sc = device_get_softc(dev);
  443         u_int16_t miscc;
  444 
  445         if ( sc->chiptype == CHIP_I810 ) {
  446                 /*
  447                  * Double check for sanity.
  448                  */
  449                 if (aperture != 32 * 1024 * 1024 && aperture != 64 * 1024 * 1024) {
  450                         device_printf(dev, "bad aperture size %d\n", aperture);
  451                         return EINVAL;
  452                 }
  453         
  454                 miscc = pci_read_config(sc->bdev, AGP_I810_MISCC, 2);
  455                 miscc &= ~AGP_I810_MISCC_WINSIZE;
  456                 if (aperture == 32 * 1024 * 1024)
  457                         miscc |= AGP_I810_MISCC_WINSIZE_32;
  458                 else
  459                         miscc |= AGP_I810_MISCC_WINSIZE_64;
  460         
  461                 pci_write_config(sc->bdev, AGP_I810_MISCC, miscc, 2);
  462         } else if ( sc->chiptype == CHIP_I830 ) {
  463                 unsigned int gcc1;
  464 
  465                 if (aperture != 64 * 1024 * 1024 && aperture != 128 * 1024 * 1024) {
  466                         device_printf(dev, "bad aperture size %d\n", aperture);
  467                         return EINVAL;
  468                 }
  469                 gcc1 = pci_read_config(sc->bdev, AGP_I830_GCC1, 2);
  470                 gcc1 &= ~AGP_I830_GCC1_GMASIZE;
  471                 if (aperture == 64 * 1024 * 1024)
  472                         gcc1 |= AGP_I830_GCC1_GMASIZE_64;
  473                 else
  474                         gcc1 |= AGP_I830_GCC1_GMASIZE_128;
  475 
  476                 pci_write_config(sc->bdev, AGP_I830_GCC1, gcc1, 2);
  477         } else {        /* CHIP_I855 */
  478                 if (aperture != 128 * 1024 * 1024) {
  479                         device_printf(dev, "bad aperture size %d\n", aperture);
  480                         return EINVAL;
  481                 }
  482         }
  483 
  484         return 0;
  485 }
  486 
  487 static int
  488 agp_i810_bind_page(device_t dev, int offset, vm_offset_t physical)
  489 {
  490         struct agp_i810_softc *sc = device_get_softc(dev);
  491 
  492         if (offset < 0 || offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT)) {
  493                 device_printf(dev, "failed: offset is 0x%08x, shift is %d, entries is %d\n", offset, AGP_PAGE_SHIFT, sc->gatt->ag_entries);
  494                 return EINVAL;
  495         }
  496 
  497         if ( sc->chiptype != CHIP_I810 ) {
  498                 if ( (offset >> AGP_PAGE_SHIFT) < sc->stolen ) {
  499                         device_printf(dev, "trying to bind into stolen memory");
  500                         return EINVAL;
  501                 }
  502         }
  503 
  504         WRITE4(AGP_I810_GTT + (offset >> AGP_PAGE_SHIFT) * 4, physical | 1);
  505         return 0;
  506 }
  507 
  508 static int
  509 agp_i810_unbind_page(device_t dev, int offset)
  510 {
  511         struct agp_i810_softc *sc = device_get_softc(dev);
  512 
  513         if (offset < 0 || offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT))
  514                 return EINVAL;
  515 
  516         if ( sc->chiptype != CHIP_I810 ) {
  517                 if ( (offset >> AGP_PAGE_SHIFT) < sc->stolen ) {
  518                         device_printf(dev, "trying to unbind from stolen memory");
  519                         return EINVAL;
  520                 }
  521         }
  522 
  523         WRITE4(AGP_I810_GTT + (offset >> AGP_PAGE_SHIFT) * 4, 0);
  524         return 0;
  525 }
  526 
  527 /*
  528  * Writing via memory mapped registers already flushes all TLBs.
  529  */
  530 static void
  531 agp_i810_flush_tlb(device_t dev)
  532 {
  533 }
  534 
  535 static int
  536 agp_i810_enable(device_t dev, u_int32_t mode)
  537 {
  538 
  539         return 0;
  540 }
  541 
  542 static struct agp_memory *
  543 agp_i810_alloc_memory(device_t dev, int type, vm_size_t size)
  544 {
  545         struct agp_i810_softc *sc = device_get_softc(dev);
  546         struct agp_memory *mem;
  547 
  548         if ((size & (AGP_PAGE_SIZE - 1)) != 0)
  549                 return 0;
  550 
  551         if (sc->agp.as_allocated + size > sc->agp.as_maxmem)
  552                 return 0;
  553 
  554         if (type == 1) {
  555                 /*
  556                  * Mapping local DRAM into GATT.
  557                  */
  558                 if ( sc->chiptype != CHIP_I810 )
  559                         return 0;
  560                 if (size != sc->dcache_size)
  561                         return 0;
  562         } else if (type == 2) {
  563                 /*
  564                  * Bogus mapping of a single page for the hardware cursor.
  565                  */
  566                 if (size != AGP_PAGE_SIZE)
  567                         return 0;
  568         }
  569 
  570         mem = malloc(sizeof *mem, M_AGP, M_WAITOK);
  571         mem->am_id = sc->agp.as_nextid++;
  572         mem->am_size = size;
  573         mem->am_type = type;
  574         if (type != 1)
  575                 mem->am_obj = vm_object_allocate(OBJT_DEFAULT,
  576                                                  atop(round_page(size)));
  577         else
  578                 mem->am_obj = 0;
  579 
  580         if (type == 2) {
  581                 /*
  582                  * Allocate and wire down the page now so that we can
  583                  * get its physical address.
  584                  */
  585                 vm_page_t m;
  586                 m = vm_page_grab(mem->am_obj, 0,
  587                     VM_ALLOC_WIRED | VM_ALLOC_ZERO | VM_ALLOC_RETRY);
  588                 if ((m->flags & PG_ZERO) == 0)
  589                         pmap_zero_page(m);
  590                 vm_page_lock_queues();
  591                 mem->am_physical = VM_PAGE_TO_PHYS(m);
  592                 vm_page_wakeup(m);
  593                 vm_page_unlock_queues();
  594         } else {
  595                 mem->am_physical = 0;
  596         }
  597 
  598         mem->am_offset = 0;
  599         mem->am_is_bound = 0;
  600         TAILQ_INSERT_TAIL(&sc->agp.as_memory, mem, am_link);
  601         sc->agp.as_allocated += size;
  602 
  603         return mem;
  604 }
  605 
  606 static int
  607 agp_i810_free_memory(device_t dev, struct agp_memory *mem)
  608 {
  609         struct agp_i810_softc *sc = device_get_softc(dev);
  610 
  611         if (mem->am_is_bound)
  612                 return EBUSY;
  613 
  614         if (mem->am_type == 2) {
  615                 /*
  616                  * Unwire the page which we wired in alloc_memory.
  617                  */
  618                 vm_page_t m = vm_page_lookup(mem->am_obj, 0);
  619                 vm_page_lock_queues();
  620                 vm_page_unwire(m, 0);
  621                 vm_page_unlock_queues();
  622         }
  623 
  624         sc->agp.as_allocated -= mem->am_size;
  625         TAILQ_REMOVE(&sc->agp.as_memory, mem, am_link);
  626         if (mem->am_obj)
  627                 vm_object_deallocate(mem->am_obj);
  628         free(mem, M_AGP);
  629         return 0;
  630 }
  631 
  632 static int
  633 agp_i810_bind_memory(device_t dev, struct agp_memory *mem,
  634                      vm_offset_t offset)
  635 {
  636         struct agp_i810_softc *sc = device_get_softc(dev);
  637         vm_offset_t i;
  638 
  639         if (mem->am_type != 1)
  640                 return agp_generic_bind_memory(dev, mem, offset);
  641 
  642         if ( sc->chiptype != CHIP_I810 )
  643                 return EINVAL;
  644 
  645         for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) {
  646                 WRITE4(AGP_I810_GTT + (offset >> AGP_PAGE_SHIFT) * 4,
  647                        i | 3);
  648         }
  649 
  650         return 0;
  651 }
  652 
  653 static int
  654 agp_i810_unbind_memory(device_t dev, struct agp_memory *mem)
  655 {
  656         struct agp_i810_softc *sc = device_get_softc(dev);
  657         vm_offset_t i;
  658 
  659         if (mem->am_type != 1)
  660                 return agp_generic_unbind_memory(dev, mem);
  661 
  662         if ( sc->chiptype != CHIP_I810 )
  663                 return EINVAL;
  664 
  665         for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE)
  666                 WRITE4(AGP_I810_GTT + (i >> AGP_PAGE_SHIFT) * 4, 0);
  667 
  668         return 0;
  669 }
  670 
  671 static device_method_t agp_i810_methods[] = {
  672         /* Device interface */
  673         DEVMETHOD(device_probe,         agp_i810_probe),
  674         DEVMETHOD(device_attach,        agp_i810_attach),
  675         DEVMETHOD(device_detach,        agp_i810_detach),
  676         DEVMETHOD(device_shutdown,      bus_generic_shutdown),
  677         DEVMETHOD(device_suspend,       bus_generic_suspend),
  678         DEVMETHOD(device_resume,        bus_generic_resume),
  679 
  680         /* AGP interface */
  681         DEVMETHOD(agp_get_aperture,     agp_i810_get_aperture),
  682         DEVMETHOD(agp_set_aperture,     agp_i810_set_aperture),
  683         DEVMETHOD(agp_bind_page,        agp_i810_bind_page),
  684         DEVMETHOD(agp_unbind_page,      agp_i810_unbind_page),
  685         DEVMETHOD(agp_flush_tlb,        agp_i810_flush_tlb),
  686         DEVMETHOD(agp_enable,           agp_i810_enable),
  687         DEVMETHOD(agp_alloc_memory,     agp_i810_alloc_memory),
  688         DEVMETHOD(agp_free_memory,      agp_i810_free_memory),
  689         DEVMETHOD(agp_bind_memory,      agp_i810_bind_memory),
  690         DEVMETHOD(agp_unbind_memory,    agp_i810_unbind_memory),
  691 
  692         { 0, 0 }
  693 };
  694 
  695 static driver_t agp_i810_driver = {
  696         "agp",
  697         agp_i810_methods,
  698         sizeof(struct agp_i810_softc),
  699 };
  700 
  701 static devclass_t agp_devclass;
  702 
  703 DRIVER_MODULE(agp_i810, pci, agp_i810_driver, agp_devclass, 0, 0);
  704 MODULE_DEPEND(agp_i810, agp, 1, 1, 1);
  705 MODULE_DEPEND(agp_i810, pci, 1, 1, 1);

Cache object: 815505e4e859eea68d89054ade40da84


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