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

Cache object: 2553b168b3f9cf990a6bec5200e3b0fe


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