[BACK]Return to agp_i810.c CVS log [TXT][DIR] Up to [local] / sys / dev / pci

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