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

Cache object: 15fac2c135464486423ac62649c4ee00


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