root/dev/pci/agp_i810.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. agp_i810_attach
  2. agp_i810_get_aperture
  3. agp_i810_set_aperture
  4. agp_i810_bind_page
  5. agp_i810_unbind_page
  6. agp_i810_flush_tlb
  7. agp_i810_enable
  8. agp_i810_alloc_memory
  9. agp_i810_free_memory
  10. agp_i810_bind_memory
  11. agp_i810_unbind_memory
  12. agp_i810_write_gatt

    1 /*      $OpenBSD: agp_i810.c,v 1.15 2007/08/04 19:40:25 reyk Exp $      */
    2 /*      $NetBSD: agp_i810.c,v 1.15 2003/01/31 00:07:39 thorpej Exp $    */
    3 
    4 /*-
    5  * Copyright (c) 2000 Doug Rabson
    6  * Copyright (c) 2000 Ruslan Ermilov
    7  * All rights reserved.
    8  *
    9  * Redistribution and use in source and binary forms, with or without
   10  * modification, are permitted provided that the following conditions
   11  * are met:
   12  * 1. Redistributions of source code must retain the above copyright
   13  *    notice, this list of conditions and the following disclaimer.
   14  * 2. Redistributions in binary form must reproduce the above copyright
   15  *    notice, this list of conditions and the following disclaimer in the
   16  *    documentation and/or other materials provided with the distribution.
   17  *
   18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   28  * SUCH DAMAGE.
   29  *
   30  *      $FreeBSD: src/sys/pci/agp_i810.c,v 1.4 2001/07/05 21:28:47 jhb Exp $
   31  */
   32 
   33 
   34 #include <sys/param.h>
   35 #include <sys/systm.h>
   36 #include <sys/malloc.h>
   37 #include <sys/kernel.h>
   38 #include <sys/lock.h>
   39 #include <sys/proc.h>
   40 #include <sys/device.h>
   41 #include <sys/conf.h>
   42 #include <sys/agpio.h>
   43 
   44 #include <dev/pci/pcivar.h>
   45 #include <dev/pci/pcireg.h>
   46 #include <dev/pci/pcidevs.h>
   47 #include <dev/pci/agpvar.h>
   48 #include <dev/pci/agpreg.h>
   49 #include <dev/pci/vga_pcivar.h>
   50 
   51 #include <machine/bus.h>
   52 
   53 #define READ1(off)      bus_space_read_1(isc->bst, isc->bsh, off)
   54 #define READ4(off)      bus_space_read_4(isc->bst, isc->bsh, off)
   55 #define WRITE4(off,v)   bus_space_write_4(isc->bst, isc->bsh, off, v)
   56 #define WRITEGTT(off,v) bus_space_write_4(isc->gtt_bst, isc->gtt_bsh, off, v)
   57 
   58 #define WRITE_GATT(off, v)      agp_i810_write_gatt(isc, off, v)
   59 
   60 enum {
   61         CHIP_I810       = 0,    /* i810/i815 */
   62         CHIP_I830       = 1,    /* i830/i845 */
   63         CHIP_I855       = 2,    /* i852GM/i855GM/i865G */
   64         CHIP_I915       = 3,    /* i915G/i915GM */
   65         CHIP_I965       = 4     /* i965/i965GM */
   66 };
   67 
   68 struct agp_i810_softc {
   69         struct agp_gatt *gatt;
   70         int chiptype;                   /* i810-like or i830 */
   71         u_int32_t dcache_size;          /* i810 only */
   72         u_int32_t stolen;               /* number of i830/845 gtt entries
   73                                            for stolen memory */
   74         bus_space_tag_t bst;            /* bus_space tag */
   75         bus_space_handle_t bsh;         /* bus_space handle */
   76         bus_size_t bsz;                 /* bus_space size */
   77         bus_space_tag_t gtt_bst;        /* GATT bus_space tag */
   78         bus_space_handle_t gtt_bsh;     /* GATT bus_space handle */
   79         struct pci_attach_args bridge_pa;
   80 };
   81 
   82 u_int32_t agp_i810_get_aperture(struct vga_pci_softc *);
   83 int     agp_i810_set_aperture(struct vga_pci_softc *, u_int32_t);
   84 int     agp_i810_bind_page(struct vga_pci_softc *, off_t, bus_addr_t);
   85 int     agp_i810_unbind_page(struct vga_pci_softc *, off_t);
   86 void    agp_i810_flush_tlb(struct vga_pci_softc *);
   87 int     agp_i810_enable(struct vga_pci_softc *, u_int32_t mode);
   88 struct agp_memory *
   89         agp_i810_alloc_memory(struct vga_pci_softc *, int, vsize_t);
   90 int     agp_i810_free_memory(struct vga_pci_softc *, struct agp_memory *);
   91 int     agp_i810_bind_memory(struct vga_pci_softc *, struct agp_memory *,
   92             off_t);
   93 int     agp_i810_unbind_memory(struct vga_pci_softc *, struct agp_memory *);
   94 void    agp_i810_write_gatt(struct agp_i810_softc *, bus_size_t, u_int32_t);
   95 
   96 struct agp_methods agp_i810_methods = {
   97         agp_i810_get_aperture,
   98         agp_i810_set_aperture,
   99         agp_i810_bind_page,
  100         agp_i810_unbind_page,
  101         agp_i810_flush_tlb,
  102         agp_i810_enable,
  103         agp_i810_alloc_memory,
  104         agp_i810_free_memory,
  105         agp_i810_bind_memory,
  106         agp_i810_unbind_memory,
  107 };
  108 
  109 int
  110 agp_i810_attach(struct vga_pci_softc *sc, struct pci_attach_args *pa,
  111                 struct pci_attach_args *pchb_pa)
  112 {
  113         struct agp_i810_softc *isc;
  114         struct agp_gatt *gatt;
  115         bus_addr_t mmaddr, gmaddr;
  116         int error;
  117         u_int memtype = 0;
  118 
  119         isc = malloc(sizeof *isc, M_DEVBUF, M_NOWAIT);
  120         if (isc == NULL) {
  121                 printf(": can't allocate chipset-specific softc\n");
  122                 return (ENOMEM);
  123         }
  124         memset(isc, 0, sizeof *isc);
  125         sc->sc_chipc = isc;
  126         sc->sc_methods = &agp_i810_methods;
  127         memcpy(&isc->bridge_pa, pchb_pa, sizeof *pchb_pa);
  128 
  129         switch (PCI_PRODUCT(pa->pa_id)) {
  130         case PCI_PRODUCT_INTEL_82810_GC:
  131         case PCI_PRODUCT_INTEL_82810_DC100_GC:
  132         case PCI_PRODUCT_INTEL_82810E_GC:
  133         case PCI_PRODUCT_INTEL_82815_FULL_GRAPH:
  134                 isc->chiptype = CHIP_I810;
  135                 break;
  136         case PCI_PRODUCT_INTEL_82830MP_IV:
  137         case PCI_PRODUCT_INTEL_82845G_IGD:
  138                 isc->chiptype = CHIP_I830;
  139                 break;
  140         case PCI_PRODUCT_INTEL_82852GM_AGP:
  141         case PCI_PRODUCT_INTEL_82865_IGD:
  142                 isc->chiptype = CHIP_I855;
  143                 break;
  144         case PCI_PRODUCT_INTEL_82915G_IV:
  145         case PCI_PRODUCT_INTEL_82915GM_IGD:
  146         case PCI_PRODUCT_INTEL_82945G_IGD_1:
  147         case PCI_PRODUCT_INTEL_82945GM_IGD:
  148                 isc->chiptype = CHIP_I915;
  149                 break;
  150         case PCI_PRODUCT_INTEL_82965_IGD_1:
  151         case PCI_PRODUCT_INTEL_82965GM_IGD_1:
  152                 isc->chiptype = CHIP_I965;
  153                 break;
  154         }
  155 
  156         switch (isc->chiptype) {
  157         case CHIP_I915:
  158                 gmaddr = AGP_I915_GMADR;
  159                 mmaddr = AGP_I915_MMADR;
  160                 break;
  161         case CHIP_I965:
  162                 gmaddr = AGP_I965_GMADR;
  163                 mmaddr = AGP_I965_MMADR;
  164                 memtype = PCI_MAPREG_MEM_TYPE_64BIT;
  165                 break;
  166         default:
  167                 gmaddr = AGP_APBASE;
  168                 mmaddr = AGP_I810_MMADR;
  169                 break;
  170         }
  171 
  172         error = agp_map_aperture(sc, gmaddr, memtype);
  173         if (error != 0) {
  174                 printf(": can't map aperture\n");
  175                 free(isc, M_DEVBUF);
  176                 return (error);
  177         }
  178 
  179         error = pci_mapreg_map(pa, mmaddr, memtype, 0,
  180             &isc->bst, &isc->bsh, NULL, &isc->bsz, 0);
  181         if (error != 0) {
  182                 printf(": can't map mmadr registers\n");
  183                 return (error);
  184         }
  185 
  186         if (isc->chiptype == CHIP_I915) {
  187                 error = pci_mapreg_map(pa, AGP_I915_GTTADR, memtype,
  188                     0, &isc->gtt_bst, &isc->gtt_bsh, NULL, NULL, 0);
  189                 if (error != 0) {
  190                         printf(": can't map gatt registers\n");
  191                         agp_generic_detach(sc);
  192                         return (error);
  193                 }
  194         }
  195 
  196         gatt = malloc(sizeof(struct agp_gatt), M_DEVBUF, 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->sc_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_DEVBUF);
  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(isc->bridge_pa.pa_pc,
  235                     isc->bridge_pa.pa_tag, AGP_I830_GCC1);
  236                 gcc1 = (u_int16_t)(reg >> 16);
  237                 switch (gcc1 & AGP_I830_GCC1_GMS) {
  238                 case AGP_I830_GCC1_GMS_STOLEN_512:
  239                         isc->stolen = (512 - 132) * 1024 / 4096;
  240                         break;
  241                 case AGP_I830_GCC1_GMS_STOLEN_1024:
  242                         isc->stolen = (1024 - 132) * 1024 / 4096;
  243                         break;
  244                 case AGP_I830_GCC1_GMS_STOLEN_8192:
  245                         isc->stolen = (8192 - 132) * 1024 / 4096;
  246                         break;
  247                 default:
  248                         isc->stolen = 0;
  249                         printf(
  250                             ": unknown memory configuration, disabling\n");
  251                         agp_generic_detach(sc);
  252                         return (EINVAL);
  253                 }
  254 #ifdef DEBUG
  255                 if (isc->stolen > 0) {
  256                         printf(": detected %dk stolen memory",
  257                             isc->stolen * 4);
  258                 }
  259 #endif
  260 
  261                 /* GATT address is already in there, make sure it's enabled */
  262                 pgtblctl = READ4(AGP_I810_PGTBL_CTL);
  263                 pgtblctl |= 1;
  264                 WRITE4(AGP_I810_PGTBL_CTL, pgtblctl);
  265 
  266                 gatt->ag_physical = pgtblctl & ~1;
  267         } else if (isc->chiptype == CHIP_I915) {
  268                 /* The 915G automatically initializes the 256k gatt on boot. */
  269                 pcireg_t reg;
  270                 u_int32_t pgtblctl;
  271                 u_int16_t gcc1;
  272 
  273                 reg = pci_conf_read(isc->bridge_pa.pa_pc,
  274                     isc->bridge_pa.pa_tag, AGP_I855_GCC1);
  275                 gcc1 = (u_int16_t)(reg >> 16);
  276                 switch (gcc1 & AGP_I855_GCC1_GMS) {
  277                 case AGP_I855_GCC1_GMS_STOLEN_1M:
  278                         isc->stolen = (1024 - 260) * 1024 / 4096;
  279                         break;
  280                 case AGP_I855_GCC1_GMS_STOLEN_4M:
  281                         isc->stolen = (4096 - 260) * 1024 / 4096;
  282                         break;
  283                 case AGP_I855_GCC1_GMS_STOLEN_8M:
  284                         isc->stolen = (8192 - 260) * 1024 / 4096;
  285                         break;
  286                 case AGP_I855_GCC1_GMS_STOLEN_16M:
  287                         isc->stolen = (16384 - 260) * 1024 / 4096;
  288                         break;
  289                 case AGP_I855_GCC1_GMS_STOLEN_32M:
  290                         isc->stolen = (32768 - 260) * 1024 / 4096;
  291                         break;
  292                 case AGP_I915_GCC1_GMS_STOLEN_48M:
  293                         isc->stolen = (49152 - 260) * 1024 / 4096;
  294                         break;
  295                 case AGP_I915_GCC1_GMS_STOLEN_64M:
  296                         isc->stolen = (65536 - 260) * 1024 / 4096;
  297                         break;
  298                 default:
  299                         isc->stolen = 0;
  300                         printf(
  301                             ": unknown memory configuration, disabling\n");
  302                         agp_generic_detach(sc);
  303                         return (EINVAL);
  304                 }
  305 #ifdef DEBUG
  306                 if (isc->stolen > 0) {
  307                         printf(": detected %dk stolen memory",
  308                             isc->stolen * 4);
  309                 }
  310 #endif
  311 
  312                 /* GATT address is already in there, make sure it's enabled */
  313                 pgtblctl = READ4(AGP_I810_PGTBL_CTL);
  314                 pgtblctl |= 1;
  315                 WRITE4(AGP_I810_PGTBL_CTL, pgtblctl);
  316 
  317                 gatt->ag_physical = pgtblctl & ~1;
  318         } else if (isc->chiptype == CHIP_I965) {
  319                 pcireg_t reg;
  320                 u_int32_t pgtblctl;
  321                 u_int16_t gcc1;
  322                 u_int32_t gttsize;
  323 
  324                 switch (READ4(AGP_I810_PGTBL_CTL) &
  325                     AGP_I810_PGTBL_SIZE_MASK) {
  326                 case AGP_I810_PGTBL_SIZE_512KB:
  327                         gttsize = 512 + 4;
  328                         break;
  329                 case AGP_I810_PGTBL_SIZE_256KB:
  330                         gttsize = 256 + 4;
  331                         break;
  332                 case AGP_I810_PGTBL_SIZE_128KB:
  333                 default:
  334                         gttsize = 128 + 4;
  335                         break;
  336                 }
  337 
  338                 reg = pci_conf_read(isc->bridge_pa.pa_pc,
  339                     isc->bridge_pa.pa_tag, AGP_I855_GCC1);
  340                 gcc1 = (u_int16_t)(reg >> 16);
  341                 switch (gcc1 & AGP_I855_GCC1_GMS) {
  342                 case AGP_I855_GCC1_GMS_STOLEN_1M:
  343                         isc->stolen = (1024 - gttsize) * 1024 / 4096;
  344                         break;
  345                 case AGP_I855_GCC1_GMS_STOLEN_4M:
  346                         isc->stolen = (4096 - gttsize) * 1024 / 4096;
  347                         break;
  348                 case AGP_I855_GCC1_GMS_STOLEN_8M:
  349                         isc->stolen = (8192 - gttsize) * 1024 / 4096;
  350                         break;
  351                 case AGP_I855_GCC1_GMS_STOLEN_16M:
  352                         isc->stolen = (16384 - gttsize) * 1024 / 4096;
  353                         break;
  354                 case AGP_I855_GCC1_GMS_STOLEN_32M:
  355                         isc->stolen = (32768 - gttsize) * 1024 / 4096;
  356                         break;
  357                 case AGP_I915_GCC1_GMS_STOLEN_48M:
  358                         isc->stolen = (49152 - gttsize) * 1024 / 4096;
  359                         break;
  360                 case AGP_I915_GCC1_GMS_STOLEN_64M:
  361                         isc->stolen = (65536 - gttsize) * 1024 / 4096;
  362                         break;
  363                 case AGP_G33_GCC1_GMS_STOLEN_128M:
  364                         isc->stolen = (131072 - gttsize) * 1024 / 4096;
  365                         break;
  366                 case AGP_G33_GCC1_GMS_STOLEN_256M:
  367                         isc->stolen = (262144 - gttsize) * 1024 / 4096;
  368                         break;
  369                 default:
  370                         isc->stolen = 0;
  371                         printf(": unknown memory configuration 0x%x, "
  372                             "disabling\n", reg);
  373                         agp_generic_detach(sc);
  374                         return (EINVAL);
  375                 }
  376 #ifdef DEBUG
  377                 if (isc->stolen > 0) {
  378                         printf(": detected %dk stolen memory",
  379                             isc->stolen * 4);
  380                 }
  381 #endif
  382 
  383                 /* GATT address is already in there, make sure it's enabled */
  384                 pgtblctl = READ4(AGP_I810_PGTBL_CTL);
  385                 pgtblctl |= 1;
  386                 WRITE4(AGP_I810_PGTBL_CTL, pgtblctl);
  387 
  388                 gatt->ag_physical = pgtblctl & ~1;
  389         } else {        /* CHIP_I855 */
  390                 /* The 855GM automatically initializes the 128k gatt on boot. */
  391                 pcireg_t reg;
  392                 u_int32_t pgtblctl;
  393                 u_int16_t gcc1;
  394 
  395                 reg = pci_conf_read(isc->bridge_pa.pa_pc,
  396                     isc->bridge_pa.pa_tag, AGP_I855_GCC1);
  397                 gcc1 = (u_int16_t)(reg >> 16);
  398                 switch (gcc1 & AGP_I855_GCC1_GMS) {
  399                 case AGP_I855_GCC1_GMS_STOLEN_1M:
  400                         isc->stolen = (1024 - 132) * 1024 / 4096;
  401                         break;
  402                 case AGP_I855_GCC1_GMS_STOLEN_4M:
  403                         isc->stolen = (4096 - 132) * 1024 / 4096;
  404                         break;
  405                 case AGP_I855_GCC1_GMS_STOLEN_8M:
  406                         isc->stolen = (8192 - 132) * 1024 / 4096;
  407                         break;
  408                 case AGP_I855_GCC1_GMS_STOLEN_16M:
  409                         isc->stolen = (16384 - 132) * 1024 / 4096;
  410                         break;
  411                 case AGP_I855_GCC1_GMS_STOLEN_32M:
  412                         isc->stolen = (32768 - 132) * 1024 / 4096;
  413                         break;
  414                 default:
  415                         isc->stolen = 0;
  416                         printf(
  417                             ": unknown memory configuration, disabling\n");
  418                         agp_generic_detach(sc);
  419                         return (EINVAL);
  420                 }
  421 #ifdef DEBUG
  422                 if (isc->stolen > 0) {
  423                         printf(": detected %dk stolen memory",
  424                             isc->stolen * 4);
  425                 }
  426 #endif
  427 
  428                 /* GATT address is already in there, make sure it's enabled */
  429                 pgtblctl = READ4(AGP_I810_PGTBL_CTL);
  430                 pgtblctl |= 1;
  431                 WRITE4(AGP_I810_PGTBL_CTL, pgtblctl);
  432 
  433                 gatt->ag_physical = pgtblctl & ~1;
  434         }
  435 
  436         /*
  437          * Make sure the chipset can see everything.
  438          */
  439         agp_flush_cache();
  440 
  441         return (0);
  442 }
  443 
  444 u_int32_t
  445 agp_i810_get_aperture(struct vga_pci_softc *sc)
  446 {
  447         struct agp_i810_softc *isc = sc->sc_chipc;
  448         pcireg_t reg;
  449 
  450         if (isc->chiptype == CHIP_I810) {
  451                 u_int16_t miscc;
  452 
  453                 reg = pci_conf_read(isc->bridge_pa.pa_pc,
  454                     isc->bridge_pa.pa_tag, AGP_I810_SMRAM);
  455                 miscc = (u_int16_t)(reg >> 16);
  456                 if ((miscc & AGP_I810_MISCC_WINSIZE) ==
  457                     AGP_I810_MISCC_WINSIZE_32)
  458                         return (32 * 1024 * 1024);
  459                 else
  460                         return (64 * 1024 * 1024);
  461         } else if (isc->chiptype == CHIP_I830) {
  462                 u_int16_t gcc1;
  463 
  464                 reg = pci_conf_read(isc->bridge_pa.pa_pc,
  465                     isc->bridge_pa.pa_tag, AGP_I830_GCC0);
  466                 gcc1 = (u_int16_t)(reg >> 16);
  467                 if ((gcc1 & AGP_I830_GCC1_GMASIZE) == AGP_I830_GCC1_GMASIZE_64)
  468                         return (64 * 1024 * 1024);
  469                 else
  470                         return (128 * 1024 * 1024);
  471         } else if (isc->chiptype == CHIP_I915) {
  472                 reg = pci_conf_read(isc->bridge_pa.pa_pc,
  473                     isc->bridge_pa.pa_tag, AGP_I915_MSAC);
  474                 if ((reg & AGP_I915_MSAC_GMASIZE) == AGP_I915_MSAC_GMASIZE_128) {
  475                         return (128 * 1024 * 1024);
  476                 } else {
  477                         return (256 * 1024 * 1024);
  478                 }
  479         } else if (isc->chiptype == CHIP_I965) {
  480                 reg = pci_conf_read(isc->bridge_pa.pa_pc,
  481                     isc->bridge_pa.pa_tag, AGP_I965_MSAC);
  482                 switch (reg & AGP_I965_MSAC_GMASIZE) {
  483                 case AGP_I965_MSAC_GMASIZE_128:
  484                         return (128 * 1024 * 1024);
  485                 case AGP_I965_MSAC_GMASIZE_256:
  486                         return (256 * 1024 * 1024);
  487                 case AGP_I965_MSAC_GMASIZE_512:
  488                         return (512 * 1024 * 1024);
  489                 }
  490         }
  491 
  492         /* CHIP_I855 */
  493         return (128 * 1024 * 1024);
  494 }
  495 
  496 int
  497 agp_i810_set_aperture(struct vga_pci_softc *sc, u_int32_t aperture)
  498 {
  499         struct agp_i810_softc *isc = sc->sc_chipc;
  500         pcireg_t reg;
  501 
  502         if (isc->chiptype == CHIP_I810) {
  503                 u_int16_t miscc;
  504 
  505                 /*
  506                  * Double check for sanity.
  507                  */
  508                 if (aperture != (32 * 1024 * 1024) &&
  509                     aperture != (64 * 1024 * 1024)) {
  510                         printf("agp: bad aperture size %d\n", aperture);
  511                         return (EINVAL);
  512                 }
  513 
  514                 reg = pci_conf_read(isc->bridge_pa.pa_pc,
  515                     isc->bridge_pa.pa_tag, AGP_I810_SMRAM);
  516                 miscc = (u_int16_t)(reg >> 16);
  517                 miscc &= ~AGP_I810_MISCC_WINSIZE;
  518                 if (aperture == 32 * 1024 * 1024)
  519                         miscc |= AGP_I810_MISCC_WINSIZE_32;
  520                 else
  521                         miscc |= AGP_I810_MISCC_WINSIZE_64;
  522 
  523                 reg &= 0x0000ffff;
  524                 reg |= ((pcireg_t)miscc) << 16;
  525                 pci_conf_write(isc->bridge_pa.pa_pc,
  526                     isc->bridge_pa.pa_tag, AGP_I810_SMRAM, reg);
  527         } else if (isc->chiptype == CHIP_I830) {
  528                 u_int16_t gcc1;
  529 
  530                 if (aperture != (64 * 1024 * 1024) &&
  531                     aperture != (128 * 1024 * 1024)) {
  532                         printf("agp: bad aperture size %d\n", aperture);
  533                         return (EINVAL);
  534                 }
  535                 reg = pci_conf_read(isc->bridge_pa.pa_pc,
  536                     isc->bridge_pa.pa_tag, AGP_I830_GCC0);
  537                 gcc1 = (u_int16_t)(reg >> 16);
  538                 gcc1 &= ~AGP_I830_GCC1_GMASIZE;
  539                 if (aperture == 64 * 1024 * 1024)
  540                         gcc1 |= AGP_I830_GCC1_GMASIZE_64;
  541                 else
  542                         gcc1 |= AGP_I830_GCC1_GMASIZE_128;
  543 
  544                 reg &= 0x0000ffff;
  545                 reg |= ((pcireg_t)gcc1) << 16;
  546                 pci_conf_write(isc->bridge_pa.pa_pc,
  547                     isc->bridge_pa.pa_tag, AGP_I830_GCC0, reg);
  548         } else if (isc->chiptype == CHIP_I915) {
  549                 if (aperture != (128 * 1024 * 1024) &&
  550                     aperture != (256 * 1024 * 1024)) {
  551                         printf("agp: bad aperture size %d\n", aperture);
  552                         return (EINVAL);
  553                 }
  554                 reg = pci_conf_read(isc->bridge_pa.pa_pc,
  555                     isc->bridge_pa.pa_tag, AGP_I915_MSAC);
  556                 reg &= ~AGP_I915_MSAC_GMASIZE;
  557                 if (aperture == (128 * 1024 * 1024))
  558                         reg |= AGP_I915_MSAC_GMASIZE_128;
  559                 else
  560                         reg |= AGP_I915_MSAC_GMASIZE_256;
  561                 pci_conf_write(isc->bridge_pa.pa_pc,
  562                     isc->bridge_pa.pa_tag, AGP_I915_MSAC, reg);
  563         } else if (isc->chiptype == CHIP_I965) {
  564                 reg = pci_conf_read(isc->bridge_pa.pa_pc,
  565                     isc->bridge_pa.pa_tag, AGP_I965_MSAC);
  566                 reg &= ~AGP_I965_MSAC_GMASIZE;
  567                 switch (aperture) {
  568                 case (128 * 1024 * 1024):
  569                         reg |= AGP_I965_MSAC_GMASIZE_128;
  570                         break;
  571                 case (256 * 1024 * 1024):
  572                         reg |= AGP_I965_MSAC_GMASIZE_256;
  573                         break;
  574                 case (512 * 1024 * 1024):
  575                         reg |= AGP_I965_MSAC_GMASIZE_512;
  576                         break;
  577                 default:
  578                         printf("agp: bad aperture size %d\n", aperture);
  579                         return (EINVAL);
  580                 }
  581                 pci_conf_write(isc->bridge_pa.pa_pc,
  582                     isc->bridge_pa.pa_tag, AGP_I965_MSAC, reg);
  583         } else {        /* CHIP_I855 */
  584                 if (aperture != (128 * 1024 * 1024)) {
  585                         printf("agp: bad aperture size %d\n", aperture);
  586                         return (EINVAL);
  587                 }
  588         }
  589 
  590         return (0);
  591 }
  592 
  593 int
  594 agp_i810_bind_page(struct vga_pci_softc *sc, off_t offset, bus_addr_t physical)
  595 {
  596         struct agp_i810_softc *isc = sc->sc_chipc;
  597 
  598         if (offset < 0 || offset >= (isc->gatt->ag_entries << AGP_PAGE_SHIFT)) {
  599 #ifdef DEBUG
  600                 printf("agp: failed: offset 0x%08x, shift %d, entries %d\n",
  601                     (int)offset, AGP_PAGE_SHIFT,
  602                     isc->gatt->ag_entries);
  603 #endif
  604                 return (EINVAL);
  605         }
  606 
  607         if (isc->chiptype != CHIP_I810) {
  608                 if ((offset >> AGP_PAGE_SHIFT) < isc->stolen) {
  609 #ifdef DEBUG
  610                         printf("agp: trying to bind into stolen memory\n");
  611 #endif
  612                         return (EINVAL);
  613                 }
  614         }
  615 
  616         WRITE_GATT(offset, physical);
  617         return (0);
  618 }
  619 
  620 int
  621 agp_i810_unbind_page(struct vga_pci_softc *sc, off_t offset)
  622 {
  623         struct agp_i810_softc *isc = sc->sc_chipc;
  624 
  625         if (offset < 0 || offset >= (isc->gatt->ag_entries << AGP_PAGE_SHIFT))
  626                 return (EINVAL);
  627 
  628         if (isc->chiptype != CHIP_I810 ) {
  629                 if ((offset >> AGP_PAGE_SHIFT) < isc->stolen) {
  630 #ifdef DEBUG
  631                         printf("agp: trying to unbind from stolen memory\n");
  632 #endif
  633                         return (EINVAL);
  634                 }
  635         }
  636 
  637         WRITE_GATT(offset, 0);
  638         return (0);
  639 }
  640 
  641 /*
  642  * Writing via memory mapped registers already flushes all TLBs.
  643  */
  644 void
  645 agp_i810_flush_tlb(struct vga_pci_softc *sc)
  646 {
  647 }
  648 
  649 int
  650 agp_i810_enable(struct vga_pci_softc *sc, u_int32_t mode)
  651 {
  652         return (0);
  653 }
  654 
  655 struct agp_memory *
  656 agp_i810_alloc_memory(struct vga_pci_softc *sc, int type, vsize_t size)
  657 {
  658         struct agp_i810_softc *isc = sc->sc_chipc;
  659         struct agp_memory *mem;
  660         int error;
  661 
  662         if ((size & (AGP_PAGE_SIZE - 1)) != 0)
  663                 return 0;
  664 
  665         if (type == 1) {
  666                 /*
  667                  * Mapping local DRAM into GATT.
  668                  */
  669                 if (isc->chiptype != CHIP_I810 )
  670                         return (NULL);
  671                 if (size != isc->dcache_size)
  672                         return (NULL);
  673         } else if (type == 2) {
  674                 /*
  675                  * Bogus mapping of 1 or 4 pages for the hardware cursor.
  676                  */
  677                 if (size != AGP_PAGE_SIZE && size != 4 * AGP_PAGE_SIZE) {
  678                         printf("agp: trying to map %lu for hw cursor\n", size);
  679                         return (NULL);
  680                 }
  681         }
  682 
  683         mem = malloc(sizeof *mem, M_DEVBUF, M_WAITOK);
  684         bzero(mem, sizeof *mem);
  685         mem->am_id = sc->sc_nextid++;
  686         mem->am_size = size;
  687         mem->am_type = type;
  688 
  689         if (type == 2) {
  690                 /*
  691                  * Allocate and wire down the pages now so that we can
  692                  * get their physical address.
  693                  */
  694                 mem->am_dmaseg = malloc(sizeof *mem->am_dmaseg, M_DEVBUF,
  695                     M_WAITOK);
  696                 if (mem->am_dmaseg == NULL) {
  697                         free(mem, M_DEVBUF);
  698                         return (NULL);
  699                 }
  700                 if ((error = agp_alloc_dmamem(sc->sc_dmat, size, 0,
  701                     &mem->am_dmamap, &mem->am_virtual, &mem->am_physical,
  702                     mem->am_dmaseg, 1, &mem->am_nseg)) != 0) {
  703                         free(mem->am_dmaseg, M_DEVBUF);
  704                         free(mem, M_DEVBUF);
  705                         printf("agp: agp_alloc_dmamem(%d)\n", error);
  706                         return (NULL);
  707                 }
  708         } else if (type != 1) {
  709                 if ((error = bus_dmamap_create(sc->sc_dmat, size,
  710                     size / PAGE_SIZE + 1, size, 0, BUS_DMA_NOWAIT,
  711                     &mem->am_dmamap)) != 0) {
  712                         free(mem, M_DEVBUF);
  713                         printf("agp: bus_dmamap_create(%d)\n", error);
  714                         return (NULL);
  715                 }
  716         }
  717 
  718         TAILQ_INSERT_TAIL(&sc->sc_memory, mem, am_link);
  719         sc->sc_allocated += size;
  720 
  721         return (mem);
  722 }
  723 
  724 int
  725 agp_i810_free_memory(struct vga_pci_softc *sc, struct agp_memory *mem)
  726 {
  727         if (mem->am_is_bound)
  728                 return (EBUSY);
  729 
  730         if (mem->am_type == 2) {
  731                 agp_free_dmamem(sc->sc_dmat, mem->am_size, mem->am_dmamap,
  732                     mem->am_virtual, mem->am_dmaseg, mem->am_nseg);
  733                 free(mem->am_dmaseg, M_DEVBUF);
  734         }
  735 
  736         sc->sc_allocated -= mem->am_size;
  737         TAILQ_REMOVE(&sc->sc_memory, mem, am_link);
  738         free(mem, M_DEVBUF);
  739         return (0);
  740 }
  741 
  742 int
  743 agp_i810_bind_memory(struct vga_pci_softc *sc, struct agp_memory *mem,
  744                      off_t offset)
  745 {
  746         struct agp_i810_softc *isc = sc->sc_chipc;
  747         u_int32_t regval, i;
  748 
  749         /*
  750          * XXX evil hack: the PGTBL_CTL appearently gets overwritten by the
  751          * X server for mysterious reasons which leads to crashes if we write
  752          * to the GTT through the MMIO window.
  753          * Until the issue is solved, simply restore it.
  754          */
  755         regval = bus_space_read_4(isc->bst, isc->bsh, AGP_I810_PGTBL_CTL);
  756         if (regval != (isc->gatt->ag_physical | 1)) {
  757 #if DEBUG
  758                 printf("agp_i810_bind_memory: PGTBL_CTL is 0x%x - fixing\n",
  759                     regval);
  760 #endif
  761                 bus_space_write_4(isc->bst, isc->bsh, AGP_I810_PGTBL_CTL,
  762                     isc->gatt->ag_physical | 1);
  763         }
  764 
  765         if (mem->am_type == 2) {
  766                 for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) {
  767                         WRITE_GATT(offset + i, mem->am_physical + i);
  768                 }
  769                 mem->am_offset = offset;
  770                 mem->am_is_bound = 1;
  771                 return (0);
  772         }
  773 
  774         if (mem->am_type != 1)
  775                 return (agp_generic_bind_memory(sc, mem, offset));
  776 
  777         if (isc->chiptype != CHIP_I810)
  778                 return (EINVAL);
  779 
  780         for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) {
  781                 WRITE4(AGP_I810_GTT +
  782                     (u_int32_t)(offset >> AGP_PAGE_SHIFT) * 4, i | 3);
  783         }
  784         mem->am_is_bound = 1;
  785         return (0);
  786 }
  787 
  788 int
  789 agp_i810_unbind_memory(struct vga_pci_softc *sc, struct agp_memory *mem)
  790 {
  791         struct agp_i810_softc *isc = sc->sc_chipc;
  792         u_int32_t i;
  793 
  794         if (mem->am_type == 2) {
  795                 for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) {
  796                         WRITE_GATT(mem->am_offset + i, 0);
  797                 }
  798                 mem->am_offset = 0;
  799                 mem->am_is_bound = 0;
  800                 return (0);
  801         }
  802 
  803         if (mem->am_type != 1)
  804                 return (agp_generic_unbind_memory(sc, mem));
  805 
  806         if (isc->chiptype != CHIP_I810)
  807                 return (EINVAL);
  808 
  809         for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE)
  810                 WRITE4(AGP_I810_GTT + (i >> AGP_PAGE_SHIFT) * 4, 0);
  811         mem->am_is_bound = 0;
  812         return (0);
  813 }
  814 
  815 void
  816 agp_i810_write_gatt(struct agp_i810_softc *isc, bus_size_t off, u_int32_t v)
  817 {
  818         u_int32_t d;
  819 
  820 
  821         d = v | 1;
  822 
  823         if (isc->chiptype == CHIP_I915)
  824                 WRITEGTT((u_int32_t)((off) >> AGP_PAGE_SHIFT) * 4, v ? d : 0);
  825         else if (isc->chiptype == CHIP_I965) {
  826                 d |= (v & 0x0000000f00000000ULL) >> 28;
  827                 WRITE4(AGP_I965_GTT +
  828                     (u_int32_t)((off) >> AGP_PAGE_SHIFT) * 4, v ? d : 0);
  829         } else
  830                 WRITE4(AGP_I810_GTT +
  831                     (u_int32_t)((off) >> AGP_PAGE_SHIFT) * 4, v ? d : 0);
  832 }

/* [<][>][^][v][top][bottom][index][help] */