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/dev/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 /*      $NetBSD: agp_i810.c,v 1.22.2.1 2004/11/12 06:04:32 jmc Exp $    */
    2 
    3 /*-
    4  * Copyright (c) 2000 Doug Rabson
    5  * Copyright (c) 2000 Ruslan Ermilov
    6  * All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   27  * SUCH DAMAGE.
   28  *
   29  *      $FreeBSD: src/sys/pci/agp_i810.c,v 1.4 2001/07/05 21:28:47 jhb Exp $
   30  */
   31 
   32 #include <sys/cdefs.h>
   33 __KERNEL_RCSID(0, "$NetBSD: agp_i810.c,v 1.22.2.1 2004/11/12 06:04:32 jmc Exp $");
   34 
   35 #include <sys/param.h>
   36 #include <sys/systm.h>
   37 #include <sys/malloc.h>
   38 #include <sys/kernel.h>
   39 #include <sys/lock.h>
   40 #include <sys/proc.h>
   41 #include <sys/device.h>
   42 #include <sys/conf.h>
   43 
   44 #include <uvm/uvm_extern.h>
   45 
   46 #include <dev/pci/pcivar.h>
   47 #include <dev/pci/pcireg.h>
   48 #include <dev/pci/pcidevs.h>
   49 #include <dev/pci/agpvar.h>
   50 #include <dev/pci/agpreg.h>
   51 
   52 #include <sys/agpio.h>
   53 
   54 #include <machine/bus.h>
   55 
   56 #include "agp_intel.h"
   57 
   58 #define READ1(off)      bus_space_read_1(isc->bst, isc->bsh, off)
   59 #define READ4(off)      bus_space_read_4(isc->bst, isc->bsh, off)
   60 #define WRITE4(off,v)   bus_space_write_4(isc->bst, isc->bsh, off, v)
   61 
   62 #define CHIP_I810 0     /* i810/i815 */
   63 #define CHIP_I830 1     /* 830M/845G */
   64 #define CHIP_I855 2     /* 852GM/855GM/865G */
   65 
   66 struct agp_i810_softc {
   67         u_int32_t initial_aperture;     /* aperture size at startup */
   68         struct agp_gatt *gatt;
   69         int chiptype;                   /* i810-like or i830 */
   70         u_int32_t dcache_size;          /* i810 only */
   71         u_int32_t stolen;               /* number of i830/845 gtt entries
   72                                            for stolen memory */
   73         bus_space_tag_t bst;            /* bus_space tag */
   74         bus_space_handle_t bsh;         /* bus_space handle */
   75         struct pci_attach_args vga_pa;
   76 };
   77 
   78 static u_int32_t agp_i810_get_aperture(struct agp_softc *);
   79 static int agp_i810_set_aperture(struct agp_softc *, u_int32_t);
   80 static int agp_i810_bind_page(struct agp_softc *, off_t, bus_addr_t);
   81 static int agp_i810_unbind_page(struct agp_softc *, off_t);
   82 static void agp_i810_flush_tlb(struct agp_softc *);
   83 static int agp_i810_enable(struct agp_softc *, u_int32_t mode);
   84 static struct agp_memory *agp_i810_alloc_memory(struct agp_softc *, int,
   85                                                 vsize_t);
   86 static int agp_i810_free_memory(struct agp_softc *, struct agp_memory *);
   87 static int agp_i810_bind_memory(struct agp_softc *, struct agp_memory *, off_t);
   88 static int agp_i810_unbind_memory(struct agp_softc *, struct agp_memory *);
   89 
   90 struct agp_methods agp_i810_methods = {
   91         agp_i810_get_aperture,
   92         agp_i810_set_aperture,
   93         agp_i810_bind_page,
   94         agp_i810_unbind_page,
   95         agp_i810_flush_tlb,
   96         agp_i810_enable,
   97         agp_i810_alloc_memory,
   98         agp_i810_free_memory,
   99         agp_i810_bind_memory,
  100         agp_i810_unbind_memory,
  101 };
  102 
  103 /* XXXthorpej -- duplicated code (see arch/i386/pci/pchb.c) */
  104 static int
  105 agp_i810_vgamatch(struct pci_attach_args *pa)
  106 {
  107 
  108         if (PCI_CLASS(pa->pa_class) != PCI_CLASS_DISPLAY ||
  109             PCI_SUBCLASS(pa->pa_class) != PCI_SUBCLASS_DISPLAY_VGA)
  110                 return (0);
  111 
  112         switch (PCI_PRODUCT(pa->pa_id)) {
  113         case PCI_PRODUCT_INTEL_82810_GC:
  114         case PCI_PRODUCT_INTEL_82810_DC100_GC:
  115         case PCI_PRODUCT_INTEL_82810E_GC:
  116         case PCI_PRODUCT_INTEL_82815_FULL_GRAPH:
  117         case PCI_PRODUCT_INTEL_82830MP_IV:
  118         case PCI_PRODUCT_INTEL_82845G_IGD:
  119         case PCI_PRODUCT_INTEL_82855GM_IGD:
  120         case PCI_PRODUCT_INTEL_82865_IGD:
  121                 return (1);
  122         }
  123 
  124         return (0);
  125 }
  126 
  127 int
  128 agp_i810_attach(struct device *parent, struct device *self, void *aux)
  129 {
  130         struct agp_softc *sc = (void *)self;
  131         struct agp_i810_softc *isc;
  132         struct agp_gatt *gatt;
  133         int error;
  134 
  135         isc = malloc(sizeof *isc, M_AGP, M_NOWAIT|M_ZERO);
  136         if (isc == NULL) {
  137                 aprint_error(": can't allocate chipset-specific softc\n");
  138                 return ENOMEM;
  139         }
  140         sc->as_chipc = isc;
  141         sc->as_methods = &agp_i810_methods;
  142 
  143         if (pci_find_device(&isc->vga_pa, agp_i810_vgamatch) == 0) {
  144 #if NAGP_INTEL > 0
  145                 const struct pci_attach_args *pa = aux;
  146 
  147                 switch (PCI_PRODUCT(pa->pa_id)) {
  148                 case PCI_PRODUCT_INTEL_82840_HB:
  149                 case PCI_PRODUCT_INTEL_82865_HB:
  150                 case PCI_PRODUCT_INTEL_82845G_DRAM:
  151                 case PCI_PRODUCT_INTEL_82815_FULL_HUB:
  152                         return agp_intel_attach(parent, self, aux);
  153                 }
  154 #endif
  155                 aprint_error(": can't find internal VGA device config space\n");
  156                 free(isc, M_AGP);
  157                 return ENOENT;
  158         }
  159 
  160         /* XXXfvdl */
  161         sc->as_dmat = isc->vga_pa.pa_dmat;
  162 
  163         error = agp_map_aperture(&isc->vga_pa, sc);
  164         if (error != 0) {
  165                 aprint_error(": can't map aperture\n");
  166                 free(isc, M_AGP);
  167                 return error;
  168         }
  169 
  170         switch (PCI_PRODUCT(isc->vga_pa.pa_id)) {
  171         case PCI_PRODUCT_INTEL_82810_GC:
  172         case PCI_PRODUCT_INTEL_82810_DC100_GC:
  173         case PCI_PRODUCT_INTEL_82810E_GC:
  174         case PCI_PRODUCT_INTEL_82815_FULL_GRAPH:
  175                 isc->chiptype = CHIP_I810;
  176                 break;
  177         case PCI_PRODUCT_INTEL_82830MP_IV:
  178         case PCI_PRODUCT_INTEL_82845G_IGD:
  179                 isc->chiptype = CHIP_I830;
  180                 break;
  181         case PCI_PRODUCT_INTEL_82855GM_IGD:
  182         case PCI_PRODUCT_INTEL_82865_IGD:
  183                 isc->chiptype = CHIP_I855;
  184                 break;
  185         }
  186 
  187         error = pci_mapreg_map(&isc->vga_pa, AGP_I810_MMADR,
  188             PCI_MAPREG_TYPE_MEM, 0, &isc->bst, &isc->bsh, NULL, NULL);
  189         if (error != 0) {
  190                 aprint_error(": can't map mmadr registers\n");
  191                 return error;
  192         }
  193 
  194         isc->initial_aperture = AGP_GET_APERTURE(sc);
  195 
  196         gatt = malloc(sizeof(struct agp_gatt), M_AGP, M_NOWAIT);
  197         if (!gatt) {
  198                 agp_generic_detach(sc);
  199                 return ENOMEM;
  200         }
  201         isc->gatt = gatt;
  202 
  203         gatt->ag_entries = AGP_GET_APERTURE(sc) >> AGP_PAGE_SHIFT;
  204 
  205         if (isc->chiptype == CHIP_I810) {
  206                 int dummyseg;
  207                 /* Some i810s have on-chip memory called dcache */
  208                 if (READ1(AGP_I810_DRT) & AGP_I810_DRT_POPULATED)
  209                         isc->dcache_size = 4 * 1024 * 1024;
  210                 else
  211                         isc->dcache_size = 0;
  212 
  213                 /* According to the specs the gatt on the i810 must be 64k */
  214                 if (agp_alloc_dmamem(sc->as_dmat, 64 * 1024,
  215                     0, &gatt->ag_dmamap, (caddr_t *)&gatt->ag_virtual,
  216                     &gatt->ag_physical, &gatt->ag_dmaseg, 1, &dummyseg) != 0) {
  217                         free(gatt, M_AGP);
  218                         agp_generic_detach(sc);
  219                         return ENOMEM;
  220                 }
  221 
  222                 gatt->ag_size = gatt->ag_entries * sizeof(u_int32_t);
  223                 memset(gatt->ag_virtual, 0, gatt->ag_size);
  224                 
  225                 agp_flush_cache();
  226                 /* Install the GATT. */
  227                 WRITE4(AGP_I810_PGTBL_CTL, gatt->ag_physical | 1);
  228         } else if (isc->chiptype == CHIP_I830) {
  229                 /* The i830 automatically initializes the 128k gatt on boot. */
  230                 pcireg_t reg;
  231                 u_int32_t pgtblctl;
  232                 u_int16_t gcc1;
  233 
  234                 reg = pci_conf_read(sc->as_pc, sc->as_tag, AGP_I830_GCC0);
  235                 gcc1 = (u_int16_t)(reg >> 16);
  236                 switch (gcc1 & AGP_I830_GCC1_GMS) {
  237                 case AGP_I830_GCC1_GMS_STOLEN_512:
  238                         isc->stolen = (512 - 132) * 1024 / 4096;
  239                         break;
  240                 case AGP_I830_GCC1_GMS_STOLEN_1024: 
  241                         isc->stolen = (1024 - 132) * 1024 / 4096;
  242                         break;
  243                 case AGP_I830_GCC1_GMS_STOLEN_8192: 
  244                         isc->stolen = (8192 - 132) * 1024 / 4096;
  245                         break;
  246                 default:
  247                         isc->stolen = 0;
  248                         aprint_error(
  249                             ": unknown memory configuration, disabling\n");
  250                         agp_generic_detach(sc);
  251                         return EINVAL;
  252                 }
  253                 if (isc->stolen > 0) {
  254                         aprint_error(": detected %dk stolen memory\n%s",
  255                             isc->stolen * 4, sc->as_dev.dv_xname);
  256                 }
  257 
  258                 /* GATT address is already in there, make sure it's enabled */
  259                 pgtblctl = READ4(AGP_I810_PGTBL_CTL);
  260                 pgtblctl |= 1;
  261                 WRITE4(AGP_I810_PGTBL_CTL, pgtblctl);
  262 
  263                 gatt->ag_physical = pgtblctl & ~1;
  264         } else {        /* CHIP_I855 */
  265                 /* The 855GM automatically initializes the 128k gatt on boot. */
  266                 pcireg_t reg;
  267                 u_int32_t pgtblctl;
  268                 u_int16_t gcc1;
  269 
  270                 reg = pci_conf_read(sc->as_pc, sc->as_tag, AGP_I855_GCC1);
  271                 gcc1 = (u_int16_t)(reg >> 16);
  272                 switch (gcc1 & AGP_I855_GCC1_GMS) {
  273                 case AGP_I855_GCC1_GMS_STOLEN_1M:
  274                         isc->stolen = (1024 - 132) * 1024 / 4096;
  275                         break;
  276                 case AGP_I855_GCC1_GMS_STOLEN_4M:
  277                         isc->stolen = (4096 - 132) * 1024 / 4096;
  278                         break;
  279                 case AGP_I855_GCC1_GMS_STOLEN_8M:
  280                         isc->stolen = (8192 - 132) * 1024 / 4096;
  281                         break;
  282                 case AGP_I855_GCC1_GMS_STOLEN_16M:
  283                         isc->stolen = (16384 - 132) * 1024 / 4096;
  284                         break;
  285                 case AGP_I855_GCC1_GMS_STOLEN_32M:
  286                         isc->stolen = (32768 - 132) * 1024 / 4096;
  287                         break;
  288                 default:
  289                         isc->stolen = 0;
  290                         aprint_error(
  291                             ": unknown memory configuration, disabling\n");
  292                         agp_generic_detach(sc);
  293                         return EINVAL;
  294                 }
  295                 if (isc->stolen > 0) {
  296                         aprint_error(": detected %dk stolen memory\n%s",
  297                             isc->stolen * 4, sc->as_dev.dv_xname);
  298                 }
  299 
  300                 /* GATT address is already in there, make sure it's enabled */
  301                 pgtblctl = READ4(AGP_I810_PGTBL_CTL);
  302                 pgtblctl |= 1;
  303                 WRITE4(AGP_I810_PGTBL_CTL, pgtblctl);
  304 
  305                 gatt->ag_physical = pgtblctl & ~1;
  306         }
  307 
  308         /*
  309          * Make sure the chipset can see everything.
  310          */
  311         agp_flush_cache();
  312 
  313         return 0;
  314 }
  315 
  316 #if 0
  317 static int
  318 agp_i810_detach(struct agp_softc *sc)
  319 {
  320         int error;
  321         struct agp_i810_softc *isc = sc->as_chipc;
  322 
  323         error = agp_generic_detach(sc);
  324         if (error)
  325                 return error;
  326 
  327         /* Clear the GATT base. */
  328         if (sc->chiptype == CHIP_I810) {
  329                 WRITE4(AGP_I810_PGTBL_CTL, 0);
  330         } else {
  331                 unsigned int pgtblctl;
  332                 pgtblctl = READ4(AGP_I810_PGTBL_CTL);
  333                 pgtblctl &= ~1;
  334                 WRITE4(AGP_I810_PGTBL_CTL, pgtblctl);
  335         }
  336 
  337         /* Put the aperture back the way it started. */
  338         AGP_SET_APERTURE(sc, isc->initial_aperture);
  339 
  340         if (sc->chiptype == CHIP_I810) {
  341                 agp_free_dmamem(sc->as_dmat, gatt->ag_size, gatt->ag_dmamap,
  342                     (caddr_t)gatt->ag_virtual, &gatt->ag_dmaseg, 1);
  343         }
  344         free(sc->gatt, M_AGP);
  345 
  346         return 0;
  347 }
  348 #endif
  349 
  350 static u_int32_t
  351 agp_i810_get_aperture(struct agp_softc *sc)
  352 {
  353         struct agp_i810_softc *isc = sc->as_chipc;
  354         pcireg_t reg;
  355 
  356         if (isc->chiptype == CHIP_I810) {
  357                 u_int16_t miscc;
  358 
  359                 reg = pci_conf_read(sc->as_pc, sc->as_tag, AGP_I810_SMRAM);
  360                 miscc = (u_int16_t)(reg >> 16);
  361                 if ((miscc & AGP_I810_MISCC_WINSIZE) ==
  362                     AGP_I810_MISCC_WINSIZE_32)
  363                         return 32 * 1024 * 1024;
  364                 else
  365                         return 64 * 1024 * 1024;
  366         } else if (isc->chiptype == CHIP_I830) {
  367                 u_int16_t gcc1;
  368 
  369                 reg = pci_conf_read(sc->as_pc, sc->as_tag, AGP_I830_GCC0);
  370                 gcc1 = (u_int16_t)(reg >> 16);
  371                 if ((gcc1 & AGP_I830_GCC1_GMASIZE) == AGP_I830_GCC1_GMASIZE_64)
  372                         return 64 * 1024 * 1024;
  373                 else
  374                         return 128 * 1024 * 1024;
  375         } else {        /* CHIP_I855 */
  376                 return 128 * 1024 * 1024;
  377         }
  378 }
  379 
  380 static int
  381 agp_i810_set_aperture(struct agp_softc *sc, u_int32_t aperture)
  382 {
  383         struct agp_i810_softc *isc = sc->as_chipc;
  384         pcireg_t reg;
  385 
  386         if (isc->chiptype == CHIP_I810) {
  387                 u_int16_t miscc;
  388 
  389                 /*
  390                  * Double check for sanity.
  391                  */
  392                 if (aperture != (32 * 1024 * 1024) &&
  393                     aperture != (64 * 1024 * 1024)) {
  394                         printf("%s: bad aperture size %d\n",
  395                             sc->as_dev.dv_xname, aperture);
  396                         return EINVAL;
  397                 }
  398 
  399                 reg = pci_conf_read(sc->as_pc, sc->as_tag, AGP_I810_SMRAM);
  400                 miscc = (u_int16_t)(reg >> 16);
  401                 miscc &= ~AGP_I810_MISCC_WINSIZE;
  402                 if (aperture == 32 * 1024 * 1024)
  403                         miscc |= AGP_I810_MISCC_WINSIZE_32;
  404                 else
  405                         miscc |= AGP_I810_MISCC_WINSIZE_64;
  406 
  407                 reg &= 0x0000ffff;
  408                 reg |= ((pcireg_t)miscc) << 16;
  409                 pci_conf_write(sc->as_pc, sc->as_tag, AGP_I810_SMRAM, reg);
  410         } if (isc->chiptype == CHIP_I830) {
  411                 u_int16_t gcc1;
  412 
  413                 if (aperture != (64 * 1024 * 1024) &&
  414                     aperture != (128 * 1024 * 1024)) {
  415                         printf("%s: bad aperture size %d\n",
  416                             sc->as_dev.dv_xname, aperture);
  417                         return EINVAL;
  418                 }
  419                 reg = pci_conf_read(sc->as_pc, sc->as_tag, AGP_I830_GCC0);
  420                 gcc1 = (u_int16_t)(reg >> 16);
  421                 gcc1 &= ~AGP_I830_GCC1_GMASIZE;
  422                 if (aperture == 64 * 1024 * 1024)
  423                         gcc1 |= AGP_I830_GCC1_GMASIZE_64;
  424                 else
  425                         gcc1 |= AGP_I830_GCC1_GMASIZE_128;
  426 
  427                 reg &= 0x0000ffff;
  428                 reg |= ((pcireg_t)gcc1) << 16;
  429                 pci_conf_write(sc->as_pc, sc->as_tag, AGP_I830_GCC0, reg);
  430         } else {        /* CHIP_I855 */
  431                 if (aperture != 128 * 1024 * 1024) {
  432                         printf("%s: bad aperture size %d\n",
  433                             sc->as_dev.dv_xname, aperture);
  434                         return EINVAL;
  435                 }
  436         }
  437 
  438         return 0;
  439 }
  440 
  441 static int
  442 agp_i810_bind_page(struct agp_softc *sc, off_t offset, bus_addr_t physical)
  443 {
  444         struct agp_i810_softc *isc = sc->as_chipc;
  445 
  446         if (offset < 0 || offset >= (isc->gatt->ag_entries << AGP_PAGE_SHIFT)) {
  447 #ifdef DEBUG
  448                 printf("%s: failed: offset 0x%08x, shift %d, entries %d\n",
  449                     sc->as_dev.dv_xname, (int)offset, AGP_PAGE_SHIFT,
  450                     isc->gatt->ag_entries);
  451 #endif
  452                 return EINVAL;
  453         }
  454 
  455         if (isc->chiptype != CHIP_I830) {
  456                 if ((offset >> AGP_PAGE_SHIFT) < isc->stolen) {
  457 #ifdef DEBUG
  458                         printf("%s: trying to bind into stolen memory",
  459                             sc->as_dev.dv_xname);
  460 #endif
  461                         return EINVAL;
  462                 }
  463         }
  464 
  465         WRITE4(AGP_I810_GTT + (u_int32_t)(offset >> AGP_PAGE_SHIFT) * 4,
  466             physical | 1);
  467         return 0;
  468 }
  469 
  470 static int
  471 agp_i810_unbind_page(struct agp_softc *sc, off_t offset)
  472 {
  473         struct agp_i810_softc *isc = sc->as_chipc;
  474 
  475         if (offset < 0 || offset >= (isc->gatt->ag_entries << AGP_PAGE_SHIFT))
  476                 return EINVAL;
  477 
  478         if (isc->chiptype != CHIP_I810 ) {
  479                 if ((offset >> AGP_PAGE_SHIFT) < isc->stolen) {
  480 #ifdef DEBUG
  481                         printf("%s: trying to unbind from stolen memory",
  482                             sc->as_dev.dv_xname);
  483 #endif
  484                         return EINVAL;
  485                 }
  486         }
  487 
  488         WRITE4(AGP_I810_GTT + (u_int32_t)(offset >> AGP_PAGE_SHIFT) * 4, 0);
  489         return 0;
  490 }
  491 
  492 /*
  493  * Writing via memory mapped registers already flushes all TLBs.
  494  */
  495 static void
  496 agp_i810_flush_tlb(struct agp_softc *sc)
  497 {
  498 }
  499 
  500 static int
  501 agp_i810_enable(struct agp_softc *sc, u_int32_t mode)
  502 {
  503 
  504         return 0;
  505 }
  506 
  507 static struct agp_memory *
  508 agp_i810_alloc_memory(struct agp_softc *sc, int type, vsize_t size)
  509 {
  510         struct agp_i810_softc *isc = sc->as_chipc;
  511         struct agp_memory *mem;
  512 
  513         if ((size & (AGP_PAGE_SIZE - 1)) != 0)
  514                 return 0;
  515 
  516         if (sc->as_allocated + size > sc->as_maxmem)
  517                 return 0;
  518 
  519         if (type == 1) {
  520                 /*
  521                  * Mapping local DRAM into GATT.
  522                  */
  523                 if (isc->chiptype != CHIP_I810 )
  524                         return 0;
  525                 if (size != isc->dcache_size)
  526                         return 0;
  527         } else if (type == 2) {
  528                 /*
  529                  * Bogus mapping of a single page for the hardware cursor.
  530                  */
  531                 if (size != AGP_PAGE_SIZE)
  532                         return 0;
  533         }
  534 
  535         mem = malloc(sizeof *mem, M_AGP, M_WAITOK|M_ZERO);
  536         if (mem == NULL)
  537                 return NULL;
  538         mem->am_id = sc->as_nextid++;
  539         mem->am_size = size;
  540         mem->am_type = type;
  541 
  542         if (type == 2) {
  543                 /*
  544                  * Allocate and wire down the page now so that we can
  545                  * get its physical address.
  546                  */
  547                 mem->am_dmaseg = malloc(sizeof *mem->am_dmaseg, M_AGP,
  548                     M_WAITOK);
  549                 if (mem->am_dmaseg == NULL) {
  550                         free(mem, M_AGP);
  551                         return NULL;
  552                 }
  553                 if (agp_alloc_dmamem(sc->as_dmat, size, 0,
  554                     &mem->am_dmamap, &mem->am_virtual, &mem->am_physical,
  555                     mem->am_dmaseg, 1, &mem->am_nseg) != 0) {
  556                         free(mem->am_dmaseg, M_AGP);
  557                         free(mem, M_AGP);
  558                         return NULL;
  559                 }
  560         } else if (type != 1) {
  561                 if (bus_dmamap_create(sc->as_dmat, size, size / PAGE_SIZE + 1,
  562                                       size, 0, BUS_DMA_NOWAIT,
  563                                       &mem->am_dmamap) != 0) {
  564                         free(mem, M_AGP);
  565                         return NULL;
  566                 }
  567         }
  568 
  569         TAILQ_INSERT_TAIL(&sc->as_memory, mem, am_link);
  570         sc->as_allocated += size;
  571 
  572         return mem;
  573 }
  574 
  575 static int
  576 agp_i810_free_memory(struct agp_softc *sc, struct agp_memory *mem)
  577 {
  578         if (mem->am_is_bound)
  579                 return EBUSY;
  580 
  581         if (mem->am_type == 2) {
  582                 agp_free_dmamem(sc->as_dmat, mem->am_size, mem->am_dmamap,
  583                     mem->am_virtual, mem->am_dmaseg, mem->am_nseg);
  584                 free(mem->am_dmaseg, M_AGP);
  585         }
  586 
  587         sc->as_allocated -= mem->am_size;
  588         TAILQ_REMOVE(&sc->as_memory, mem, am_link);
  589         free(mem, M_AGP);
  590         return 0;
  591 }
  592 
  593 static int
  594 agp_i810_bind_memory(struct agp_softc *sc, struct agp_memory *mem,
  595                      off_t offset)
  596 {
  597         struct agp_i810_softc *isc = sc->as_chipc;
  598         u_int32_t regval, i;
  599 
  600         /*
  601          * XXX evil hack: the PGTBL_CTL appearently gets overwritten by the
  602          * X server for mysterious reasons which leads to crashes if we write
  603          * to the GTT through the MMIO window.
  604          * Until the issue is solved, simply restore it.
  605          */
  606         regval = bus_space_read_4(isc->bst, isc->bsh, AGP_I810_PGTBL_CTL);
  607         if (regval != (isc->gatt->ag_physical | 1)) {
  608                 printf("agp_i810_bind_memory: PGTBL_CTL is 0x%x - fixing\n",
  609                        regval);
  610                 bus_space_write_4(isc->bst, isc->bsh, AGP_I810_PGTBL_CTL,
  611                                   isc->gatt->ag_physical | 1);
  612         }
  613 
  614         if (mem->am_type == 2) {
  615                 WRITE4(AGP_I810_GTT + (u_int32_t)(offset >> AGP_PAGE_SHIFT) * 4,
  616                        mem->am_physical | 1);
  617                 mem->am_offset = offset;
  618                 mem->am_is_bound = 1;
  619                 return 0;
  620         }
  621 
  622         if (mem->am_type != 1)
  623                 return agp_generic_bind_memory(sc, mem, offset);
  624 
  625         if (isc->chiptype != CHIP_I810)
  626                 return EINVAL;
  627 
  628         for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) {
  629                 WRITE4(AGP_I810_GTT + (u_int32_t)(offset >> AGP_PAGE_SHIFT) * 4,
  630                        i | 3);
  631         }
  632         mem->am_is_bound = 1;
  633         return 0;
  634 }
  635 
  636 static int
  637 agp_i810_unbind_memory(struct agp_softc *sc, struct agp_memory *mem)
  638 {
  639         struct agp_i810_softc *isc = sc->as_chipc;
  640         u_int32_t i;
  641 
  642         if (mem->am_type == 2) {
  643                 WRITE4(AGP_I810_GTT +
  644                        (u_int32_t)(mem->am_offset >> AGP_PAGE_SHIFT) * 4,
  645                        0);
  646                 mem->am_offset = 0;
  647                 mem->am_is_bound = 0;
  648                 return 0;
  649         }
  650 
  651         if (mem->am_type != 1)
  652                 return agp_generic_unbind_memory(sc, mem);
  653 
  654         if (isc->chiptype != CHIP_I810)
  655                 return EINVAL;
  656 
  657         for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE)
  658                 WRITE4(AGP_I810_GTT + (i >> AGP_PAGE_SHIFT) * 4, 0);
  659         mem->am_is_bound = 0;
  660         return 0;
  661 }

Cache object: d025c31be398eb9b1da6f24388673944


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