Annotation of sys/dev/pci/agp_i810.c, Revision 1.1
1.1 ! nbrk 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: }
CVSweb