| File: | dev/pci/agp_i810.c | 
| Warning: | line 264, column 3 Value stored to 'mmaddr' is never read | 
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* $OpenBSD: agp_i810.c,v 1.95 2022/03/11 18:00:45 mpi Exp $ */ | 
| 2 | |
| 3 | /*- | 
| 4 | * Copyright (c) 2000 Doug Rabson | 
| 5 | * Copyright (c) 2000 Ruslan Ermilov | 
| 6 | * All rights reserved. | 
| 7 | * | 
| 8 | * Redistribution and use in source and binary forms, with or without | 
| 9 | * modification, are permitted provided that the following conditions | 
| 10 | * are met: | 
| 11 | * 1. Redistributions of source code must retain the above copyright | 
| 12 | * notice, this list of conditions and the following disclaimer. | 
| 13 | * 2. Redistributions in binary form must reproduce the above copyright | 
| 14 | * notice, this list of conditions and the following disclaimer in the | 
| 15 | * documentation and/or other materials provided with the distribution. | 
| 16 | * | 
| 17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | 
| 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 
| 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 
| 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | 
| 21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 
| 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | 
| 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 
| 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | 
| 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | 
| 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 
| 27 | * SUCH DAMAGE. | 
| 28 | * | 
| 29 | */ | 
| 30 | |
| 31 | #include "acpi.h" | 
| 32 | #include "drm.h" | 
| 33 | #include "vga.h" | 
| 34 | |
| 35 | #include <sys/param.h> | 
| 36 | #include <sys/systm.h> | 
| 37 | #include <sys/malloc.h> | 
| 38 | #include <sys/device.h> | 
| 39 | #include <sys/rwlock.h> | 
| 40 | |
| 41 | #include <dev/pci/pcivar.h> | 
| 42 | #include <dev/pci/pcireg.h> | 
| 43 | #include <dev/pci/pcidevs.h> | 
| 44 | #include <dev/pci/agpvar.h> | 
| 45 | #include <dev/pci/agpreg.h> | 
| 46 | #include <dev/pci/drm/i915/i915_drv.h> | 
| 47 | |
| 48 | #include <machine/bus.h> | 
| 49 | |
| 50 | #define READ1(off)((isc->map->bst)->read_1((isc->map->bsh), (off ))) bus_space_read_1(isc->map->bst, isc->map->bsh, off)((isc->map->bst)->read_1((isc->map->bsh), (off ))) | 
| 51 | #define READ4(off)((isc->map->bst)->read_4((isc->map->bsh), (off ))) bus_space_read_4(isc->map->bst, isc->map->bsh, off)((isc->map->bst)->read_4((isc->map->bsh), (off ))) | 
| 52 | #define WRITE4(off,v)((isc->map->bst)->write_4((isc->map->bsh), (off ), (v))) bus_space_write_4(isc->map->bst, isc->map->bsh, off, v)((isc->map->bst)->write_4((isc->map->bsh), (off ), (v))) | 
| 53 | |
| 54 | /* | 
| 55 | * Intel IGP gtt bits. | 
| 56 | */ | 
| 57 | /* PTE is enabled */ | 
| 58 | #define INTEL_ENABLED0x1 0x1 | 
| 59 | /* I810/I815 only, memory is in dcache */ | 
| 60 | #define INTEL_LOCAL0x2 0x2 | 
| 61 | /* Memory is snooped, must not be accessed through gtt from the cpu. */ | 
| 62 | #define INTEL_COHERENT0x6 0x6 | 
| 63 | |
| 64 | enum { | 
| 65 | CHIP_NONE = 0, /* not integrated graphics */ | 
| 66 | CHIP_I810 = 1, /* i810/i815 */ | 
| 67 | CHIP_I830 = 2, /* i830/i845 */ | 
| 68 | CHIP_I855 = 3, /* i852GM/i855GM/i865G */ | 
| 69 | CHIP_I915 = 4, /* i915G/i915GM */ | 
| 70 | CHIP_I965 = 5, /* i965/i965GM */ | 
| 71 | CHIP_G33 = 6, /* G33/Q33/Q35 */ | 
| 72 | CHIP_G4X = 7, /* G4X */ | 
| 73 | CHIP_PINEVIEW = 8, /* Pineview/Pineview M */ | 
| 74 | CHIP_IRONLAKE = 9, /* Clarkdale/Arrandale */ | 
| 75 | }; | 
| 76 | |
| 77 | struct agp_i810_softc { | 
| 78 | struct device dev; | 
| 79 | bus_dma_segment_t scrib_seg; | 
| 80 | struct agp_softc *agpdev; | 
| 81 | struct agp_gatt *gatt; | 
| 82 | struct vga_pci_bar *map; | 
| 83 | bus_space_tag_t gtt_bst; | 
| 84 | bus_space_handle_t gtt_bsh; | 
| 85 | bus_size_t gtt_size; | 
| 86 | bus_dmamap_t scrib_dmamap; | 
| 87 | bus_addr_t isc_apaddr; | 
| 88 | bus_size_t isc_apsize; /* current aperture size */ | 
| 89 | int chiptype; /* i810-like or i830 */ | 
| 90 | u_int32_t dcache_size; /* i810 only */ | 
| 91 | u_int32_t stolen; /* number of i830/845 gtt | 
| 92 | entries for stolen memory */ | 
| 93 | }; | 
| 94 | |
| 95 | void agp_i810_attach(struct device *, struct device *, void *); | 
| 96 | int agp_i810_activate(struct device *, int); | 
| 97 | void agp_i810_configure(struct agp_i810_softc *); | 
| 98 | int agp_i810_probe(struct device *, void *, void *); | 
| 99 | int agp_i810_get_chiptype(struct pci_attach_args *); | 
| 100 | void agp_i810_bind_page(void *, bus_size_t, paddr_t, int); | 
| 101 | void agp_i810_unbind_page(void *, bus_size_t); | 
| 102 | void agp_i810_flush_tlb(void *); | 
| 103 | int agp_i810_enable(void *, u_int32_t mode); | 
| 104 | void intagp_write_gtt(struct agp_i810_softc *, bus_size_t, paddr_t); | 
| 105 | int intagp_gmch_match(struct pci_attach_args *); | 
| 106 | |
| 107 | extern void intagp_dma_sync(bus_dma_tag_t, bus_dmamap_t, | 
| 108 | bus_addr_t, bus_size_t, int); | 
| 109 | |
| 110 | const struct cfattach intagp_ca = { | 
| 111 | sizeof(struct agp_i810_softc), agp_i810_probe, agp_i810_attach, | 
| 112 | NULL((void *)0), agp_i810_activate, | 
| 113 | }; | 
| 114 | |
| 115 | struct cfdriver intagp_cd = { | 
| 116 | NULL((void *)0), "intagp", DV_DULL | 
| 117 | }; | 
| 118 | |
| 119 | struct agp_methods agp_i810_methods = { | 
| 120 | agp_i810_bind_page, | 
| 121 | agp_i810_unbind_page, | 
| 122 | agp_i810_flush_tlb, | 
| 123 | agp_i810_enable, | 
| 124 | }; | 
| 125 | |
| 126 | int | 
| 127 | agp_i810_get_chiptype(struct pci_attach_args *pa) | 
| 128 | { | 
| 129 | switch (PCI_PRODUCT(pa->pa_id)(((pa->pa_id) >> 16) & 0xffff)) { | 
| 130 | case PCI_PRODUCT_INTEL_82810_IGD0x7121: | 
| 131 | case PCI_PRODUCT_INTEL_82810_DC100_IGD0x7123: | 
| 132 | case PCI_PRODUCT_INTEL_82810E_IGD0x7125: | 
| 133 | case PCI_PRODUCT_INTEL_82815_IGD0x1132: | 
| 134 | return (CHIP_I810); | 
| 135 | break; | 
| 136 | case PCI_PRODUCT_INTEL_82830M_IGD0x3577: | 
| 137 | case PCI_PRODUCT_INTEL_82845G_IGD0x2562: | 
| 138 | return (CHIP_I830); | 
| 139 | break; | 
| 140 | case PCI_PRODUCT_INTEL_82854_IGD0x358e: | 
| 141 | case PCI_PRODUCT_INTEL_82855GM_IGD0x3582: | 
| 142 | case PCI_PRODUCT_INTEL_82865G_IGD0x2572: | 
| 143 | return (CHIP_I855); | 
| 144 | break; | 
| 145 | case PCI_PRODUCT_INTEL_E7221_IGD0x258a: | 
| 146 | case PCI_PRODUCT_INTEL_82915G_IGD_10x2582: | 
| 147 | case PCI_PRODUCT_INTEL_82915G_IGD_20x2782: | 
| 148 | case PCI_PRODUCT_INTEL_82915GM_IGD_10x2592: | 
| 149 | case PCI_PRODUCT_INTEL_82915GM_IGD_20x2792: | 
| 150 | case PCI_PRODUCT_INTEL_82945G_IGD_10x2772: | 
| 151 | case PCI_PRODUCT_INTEL_82945G_IGD_20x2776: | 
| 152 | case PCI_PRODUCT_INTEL_82945GM_IGD_10x27a2: | 
| 153 | case PCI_PRODUCT_INTEL_82945GM_IGD_20x27a6: | 
| 154 | case PCI_PRODUCT_INTEL_82945GME_IGD_10x27ae: | 
| 155 | return (CHIP_I915); | 
| 156 | break; | 
| 157 | case PCI_PRODUCT_INTEL_82946GZ_IGD_10x2972: | 
| 158 | case PCI_PRODUCT_INTEL_82946GZ_IGD_20x2973: | 
| 159 | case PCI_PRODUCT_INTEL_82Q965_IGD_10x2992: | 
| 160 | case PCI_PRODUCT_INTEL_82Q965_IGD_20x2993: | 
| 161 | case PCI_PRODUCT_INTEL_82G965_IGD_10x29a2: | 
| 162 | case PCI_PRODUCT_INTEL_82G965_IGD_20x29a3: | 
| 163 | case PCI_PRODUCT_INTEL_82GM965_IGD_10x2a02: | 
| 164 | case PCI_PRODUCT_INTEL_82GM965_IGD_20x2a03: | 
| 165 | case PCI_PRODUCT_INTEL_82GME965_IGD_10x2a12: | 
| 166 | case PCI_PRODUCT_INTEL_82GME965_IGD_20x2a13: | 
| 167 | case PCI_PRODUCT_INTEL_82G35_IGD_10x2982: | 
| 168 | case PCI_PRODUCT_INTEL_82G35_IGD_20x2983: | 
| 169 | return (CHIP_I965); | 
| 170 | break; | 
| 171 | case PCI_PRODUCT_INTEL_82G33_IGD_10x29c2: | 
| 172 | case PCI_PRODUCT_INTEL_82G33_IGD_20x29c3: | 
| 173 | case PCI_PRODUCT_INTEL_82Q35_IGD_10x29b2: | 
| 174 | case PCI_PRODUCT_INTEL_82Q35_IGD_20x29b3: | 
| 175 | case PCI_PRODUCT_INTEL_82Q33_IGD_10x29d2: | 
| 176 | case PCI_PRODUCT_INTEL_82Q33_IGD_20x29d3: | 
| 177 | return (CHIP_G33); | 
| 178 | break; | 
| 179 | case PCI_PRODUCT_INTEL_82GM45_IGD_10x2a42: | 
| 180 | case PCI_PRODUCT_INTEL_4SERIES_IGD0x2e02: | 
| 181 | case PCI_PRODUCT_INTEL_82Q45_IGD_10x2e12: | 
| 182 | case PCI_PRODUCT_INTEL_82G45_IGD_10x2e22: | 
| 183 | case PCI_PRODUCT_INTEL_82G41_IGD_10x2e32: | 
| 184 | case PCI_PRODUCT_INTEL_82B43_IGD_10x2e42: | 
| 185 | case PCI_PRODUCT_INTEL_82B43_IGD_20x2e92: | 
| 186 | return (CHIP_G4X); | 
| 187 | break; | 
| 188 | case PCI_PRODUCT_INTEL_PINEVIEW_IGC_10xa001: | 
| 189 | case PCI_PRODUCT_INTEL_PINEVIEW_M_IGC_10xa011: | 
| 190 | return (CHIP_PINEVIEW); | 
| 191 | break; | 
| 192 | case PCI_PRODUCT_INTEL_CLARKDALE_IGD0x0042: | 
| 193 | case PCI_PRODUCT_INTEL_ARRANDALE_IGD0x0046: | 
| 194 | return (CHIP_IRONLAKE); | 
| 195 | break; | 
| 196 | } | 
| 197 | |
| 198 | return (CHIP_NONE); | 
| 199 | } | 
| 200 | |
| 201 | /* | 
| 202 | * We're intel IGD, bus 0 function 0 dev 0 should be the GMCH, so it should | 
| 203 | * be Intel | 
| 204 | */ | 
| 205 | int | 
| 206 | intagp_gmch_match(struct pci_attach_args *pa) | 
| 207 | { | 
| 208 | if (pa->pa_bus == 0 && pa->pa_device == 0 && pa->pa_function == 0 && | 
| 209 | PCI_VENDOR(pa->pa_id)(((pa->pa_id) >> 0) & 0xffff) == PCI_VENDOR_INTEL0x8086 && | 
| 210 | PCI_CLASS(pa->pa_class)(((pa->pa_class) >> 24) & 0xff) == PCI_CLASS_BRIDGE0x06 && | 
| 211 | PCI_SUBCLASS(pa->pa_class)(((pa->pa_class) >> 16) & 0xff) == PCI_SUBCLASS_BRIDGE_HOST0x00) | 
| 212 | return (1); | 
| 213 | return (0); | 
| 214 | } | 
| 215 | |
| 216 | int | 
| 217 | agp_i810_probe(struct device *parent, void *match, void *aux) | 
| 218 | { | 
| 219 | struct pci_attach_args *pa = aux; | 
| 220 | |
| 221 | if (PCI_CLASS(pa->pa_class)(((pa->pa_class) >> 24) & 0xff) != PCI_CLASS_DISPLAY0x03 || | 
| 222 | PCI_SUBCLASS(pa->pa_class)(((pa->pa_class) >> 16) & 0xff) != PCI_SUBCLASS_DISPLAY_VGA0x00) | 
| 223 | return (0); | 
| 224 | |
| 225 | return (agp_i810_get_chiptype(pa) != CHIP_NONE); | 
| 226 | } | 
| 227 | |
| 228 | void | 
| 229 | agp_i810_attach(struct device *parent, struct device *self, void *aux) | 
| 230 | { | 
| 231 | struct agp_i810_softc *isc = (struct agp_i810_softc *)self; | 
| 232 | struct agp_gatt *gatt; | 
| 233 | struct pci_attach_args *pa = aux, bpa; | 
| 234 | struct inteldrm_softc *psc = (struct inteldrm_softc *)parent; | 
| 235 | bus_addr_t mmaddr, gmaddr, tmp; | 
| 236 | bus_size_t gtt_off = 0; | 
| 237 | pcireg_t memtype, reg; | 
| 238 | u_int32_t stolen; | 
| 239 | u_int16_t gcc1; | 
| 240 | |
| 241 | isc->chiptype = agp_i810_get_chiptype(pa); | 
| 242 | |
| 243 | switch (isc->chiptype) { | 
| 244 | case CHIP_I915: | 
| 245 | case CHIP_G33: | 
| 246 | case CHIP_PINEVIEW: | 
| 247 | gmaddr = AGP_I915_GMADR0x18; | 
| 248 | mmaddr = AGP_I915_MMADR0x10; | 
| 249 | memtype = PCI_MAPREG_TYPE_MEM0x00000000; | 
| 250 | break; | 
| 251 | case CHIP_I965: | 
| 252 | case CHIP_G4X: | 
| 253 | case CHIP_IRONLAKE: | 
| 254 | gmaddr = AGP_I965_GMADR0x18; | 
| 255 | mmaddr = AGP_I965_MMADR0x10; | 
| 256 | memtype = PCI_MAPREG_TYPE_MEM0x00000000 | PCI_MAPREG_MEM_TYPE_64BIT0x00000004; | 
| 257 | if (isc->chiptype == CHIP_I965) | 
| 258 | gtt_off = AGP_I965_GTT0x80000; | 
| 259 | else | 
| 260 | gtt_off = AGP_G4X_GTT0x200000; | 
| 261 | break; | 
| 262 | default: | 
| 263 | gmaddr = AGP_APBASE0x10; | 
| 264 | mmaddr = AGP_I810_MMADR0x14; | 
| Value stored to 'mmaddr' is never read | |
| 265 | memtype = PCI_MAPREG_TYPE_MEM0x00000000; | 
| 266 | gtt_off = AGP_I810_GTT0x10000; | 
| 267 | break; | 
| 268 | } | 
| 269 | |
| 270 | if (pci_mapreg_info(pa->pa_pc, pa->pa_tag, gmaddr, memtype, | 
| 271 | &isc->isc_apaddr, &isc->isc_apsize, NULL((void *)0)) != 0) { | 
| 272 | printf("can't get aperture info\n"); | 
| 273 | return; | 
| 274 | } | 
| 275 | |
| 276 | isc->map = psc->vga_regs; | 
| 277 | |
| 278 | if (isc->chiptype == CHIP_I915 || isc->chiptype == CHIP_G33 || | 
| 279 | isc->chiptype == CHIP_PINEVIEW) { | 
| 280 | if (pci_mapreg_map(pa, AGP_I915_GTTADR0x1C, memtype, | 
| 281 | BUS_SPACE_MAP_LINEAR0x0002, &isc->gtt_bst, &isc->gtt_bsh, | 
| 282 | NULL((void *)0), &isc->gtt_size, 0)) { | 
| 283 | printf("can't map gatt registers\n"); | 
| 284 | goto out; | 
| 285 | } | 
| 286 | } else if (gtt_off >= isc->map->size) { | 
| 287 | isc->gtt_bst = isc->map->bst; | 
| 288 | isc->gtt_size = (isc->isc_apsize >> AGP_PAGE_SHIFT12) * 4; | 
| 289 | if (bus_space_map(isc->gtt_bst, isc->map->base + gtt_off, | 
| 290 | isc->gtt_size, BUS_SPACE_MAP_LINEAR0x0002, &isc->gtt_bsh)) { | 
| 291 | printf("can't map gatt registers\n"); | 
| 292 | isc->gtt_size = 0; | 
| 293 | goto out; | 
| 294 | } | 
| 295 | } else { | 
| 296 | isc->gtt_bst = isc->map->bst; | 
| 297 | if (bus_space_subregion(isc->map->bst, isc->map->bsh, gtt_off, | 
| 298 | (isc->isc_apsize >> AGP_PAGE_SHIFT12) * 4, &isc->gtt_bsh)) { | 
| 299 | printf("can't map gatt registers\n"); | 
| 300 | goto out; | 
| 301 | } | 
| 302 | } | 
| 303 | |
| 304 | gatt = malloc(sizeof(*gatt), M_AGP144, M_NOWAIT0x0002 | M_ZERO0x0008); | 
| 305 | if (gatt == NULL((void *)0)) { | 
| 306 | printf("can't alloc gatt\n"); | 
| 307 | goto out; | 
| 308 | } | 
| 309 | isc->gatt = gatt; | 
| 310 | |
| 311 | gatt->ag_entries = isc->isc_apsize >> AGP_PAGE_SHIFT12; | 
| 312 | |
| 313 | /* | 
| 314 | * Find the GMCH, some of the registers we need to read for | 
| 315 | * configuration purposes are on there. it's always at | 
| 316 | * 0/0/0 (bus/dev/func). | 
| 317 | */ | 
| 318 | if (pci_find_device(&bpa, intagp_gmch_match) == 0) { | 
| 319 | printf("can't find GMCH\n"); | 
| 320 | goto out; | 
| 321 | } | 
| 322 | |
| 323 | switch (isc->chiptype) { | 
| 324 | case CHIP_I810: | 
| 325 | /* Some i810s have on-chip memory called dcache */ | 
| 326 | if (READ1(AGP_I810_DRT)((isc->map->bst)->read_1((isc->map->bsh), (0x3000 ))) & AGP_I810_DRT_POPULATED0x01) | 
| 327 | isc->dcache_size = 4 * 1024 * 1024; | 
| 328 | else | 
| 329 | isc->dcache_size = 0; | 
| 330 | |
| 331 | /* According to the specs the gatt on the i810 must be 64k */ | 
| 332 | if (agp_alloc_dmamem(pa->pa_dmat, 64 * 1024, &gatt->ag_dmamap, | 
| 333 | &gatt->ag_physical, &gatt->ag_dmaseg) != 0) { | 
| 334 | goto out; | 
| 335 | } | 
| 336 | gatt->ag_size = gatt->ag_entries * sizeof(u_int32_t); | 
| 337 | |
| 338 | if (bus_dmamem_map(pa->pa_dmat, &gatt->ag_dmaseg, 1, 64 * 1024,(*(pa->pa_dmat)->_dmamem_map)((pa->pa_dmat), (&gatt ->ag_dmaseg), (1), (64 * 1024), ((caddr_t *)&gatt-> ag_virtual), (0x0001)) | 
| 339 | (caddr_t *)&gatt->ag_virtual, BUS_DMA_NOWAIT)(*(pa->pa_dmat)->_dmamem_map)((pa->pa_dmat), (&gatt ->ag_dmaseg), (1), (64 * 1024), ((caddr_t *)&gatt-> ag_virtual), (0x0001)) != 0) | 
| 340 | goto out; | 
| 341 | break; | 
| 342 | |
| 343 | case CHIP_I830: | 
| 344 | /* The i830 automatically initializes the 128k gatt on boot. */ | 
| 345 | |
| 346 | reg = pci_conf_read(bpa.pa_pc, bpa.pa_tag, AGP_I830_GCC00x50); | 
| 347 | gcc1 = (u_int16_t)(reg >> 16); | 
| 348 | switch (gcc1 & AGP_I830_GCC1_GMS0xf0) { | 
| 349 | case AGP_I830_GCC1_GMS_STOLEN_5120x20: | 
| 350 | isc->stolen = (512 - 132) * 1024 / 4096; | 
| 351 | break; | 
| 352 | case AGP_I830_GCC1_GMS_STOLEN_10240x30: | 
| 353 | isc->stolen = (1024 - 132) * 1024 / 4096; | 
| 354 | break; | 
| 355 | case AGP_I830_GCC1_GMS_STOLEN_81920x40: | 
| 356 | isc->stolen = (8192 - 132) * 1024 / 4096; | 
| 357 | break; | 
| 358 | default: | 
| 359 | isc->stolen = 0; | 
| 360 | printf("unknown memory configuration, disabling\n"); | 
| 361 | goto out; | 
| 362 | } | 
| 363 | #ifdef DEBUG | 
| 364 | if (isc->stolen > 0) { | 
| 365 | printf(": detected %dk stolen memory", | 
| 366 | isc->stolen * 4); | 
| 367 | } else | 
| 368 | printf(": no preallocated video memory\n"); | 
| 369 | #endif | 
| 370 | |
| 371 | /* XXX */ | 
| 372 | isc->stolen = 0; | 
| 373 | |
| 374 | /* GATT address is already in there, make sure it's enabled */ | 
| 375 | gatt->ag_physical = READ4(AGP_I810_PGTBL_CTL)((isc->map->bst)->read_4((isc->map->bsh), (0x2020 ))) & ~1; | 
| 376 | break; | 
| 377 | |
| 378 | case CHIP_I855: | 
| 379 | /* FALLTHROUGH */ | 
| 380 | case CHIP_I915: | 
| 381 | /* FALLTHROUGH */ | 
| 382 | case CHIP_I965: | 
| 383 | /* FALLTHROUGH */ | 
| 384 | case CHIP_G33: | 
| 385 | /* FALLTHROUGH */ | 
| 386 | case CHIP_G4X: | 
| 387 | case CHIP_PINEVIEW: | 
| 388 | case CHIP_IRONLAKE: | 
| 389 | |
| 390 | /* Stolen memory is set up at the beginning of the aperture by | 
| 391 | * the BIOS, consisting of the GATT followed by 4kb for the | 
| 392 | * BIOS display. | 
| 393 | */ | 
| 394 | |
| 395 | reg = pci_conf_read(bpa.pa_pc, bpa.pa_tag, AGP_I855_GCC10x50); | 
| 396 | gcc1 = (u_int16_t)(reg >> 16); | 
| 397 | switch (isc->chiptype) { | 
| 398 | case CHIP_I855: | 
| 399 | /* The 855GM automatically initializes the 128k gatt on boot. */ | 
| 400 | stolen = 128 + 4; | 
| 401 | break; | 
| 402 | case CHIP_I915: | 
| 403 | /* The 915G automatically initializes the 256k gatt on boot. */ | 
| 404 | stolen = 256 + 4; | 
| 405 | break; | 
| 406 | case CHIP_I965: | 
| 407 | switch (READ4(AGP_I810_PGTBL_CTL)((isc->map->bst)->read_4((isc->map->bsh), (0x2020 ))) & | 
| 408 | AGP_I810_PGTBL_SIZE_MASK0x0000000e) { | 
| 409 | case AGP_I810_PGTBL_SIZE_512KB(0 << 1): | 
| 410 | stolen = 512 + 4; | 
| 411 | break; | 
| 412 | case AGP_I810_PGTBL_SIZE_256KB(1 << 1): | 
| 413 | stolen = 256 + 4; | 
| 414 | break; | 
| 415 | case AGP_I810_PGTBL_SIZE_128KB(2 << 1): | 
| 416 | default: | 
| 417 | stolen = 128 + 4; | 
| 418 | break; | 
| 419 | } | 
| 420 | break; | 
| 421 | case CHIP_G33: | 
| 422 | switch (gcc1 & AGP_G33_PGTBL_SIZE_MASK(3U << 8)) { | 
| 423 | case AGP_G33_PGTBL_SIZE_2M(2U << 8): | 
| 424 | stolen = 2048 + 4; | 
| 425 | break; | 
| 426 | case AGP_G33_PGTBL_SIZE_1M(1U << 8): | 
| 427 | default: | 
| 428 | stolen = 1024 + 4; | 
| 429 | break; | 
| 430 | } | 
| 431 | break; | 
| 432 | case CHIP_G4X: | 
| 433 | case CHIP_PINEVIEW: | 
| 434 | case CHIP_IRONLAKE: | 
| 435 | /* | 
| 436 | * GTT stolen is separate from graphics stolen on | 
| 437 | * 4 series hardware. so ignore it in stolen gtt entries | 
| 438 | * counting. However, 4Kb of stolen memory isn't mapped | 
| 439 | * to the GTT. | 
| 440 | */ | 
| 441 | stolen = 4; | 
| 442 | break; | 
| 443 | default: | 
| 444 | printf("bad chiptype\n"); | 
| 445 | goto out; | 
| 446 | } | 
| 447 | |
| 448 | switch (gcc1 & AGP_I855_GCC1_GMS0xf0) { | 
| 449 | case AGP_I855_GCC1_GMS_STOLEN_1M0x10: | 
| 450 | isc->stolen = (1024 - stolen) * 1024 / 4096; | 
| 451 | break; | 
| 452 | case AGP_I855_GCC1_GMS_STOLEN_4M0x20: | 
| 453 | isc->stolen = (4096 - stolen) * 1024 / 4096; | 
| 454 | break; | 
| 455 | case AGP_I855_GCC1_GMS_STOLEN_8M0x30: | 
| 456 | isc->stolen = (8192 - stolen) * 1024 / 4096; | 
| 457 | break; | 
| 458 | case AGP_I855_GCC1_GMS_STOLEN_16M0x40: | 
| 459 | isc->stolen = (16384 - stolen) * 1024 / 4096; | 
| 460 | break; | 
| 461 | case AGP_I855_GCC1_GMS_STOLEN_32M0x50: | 
| 462 | isc->stolen = (32768 - stolen) * 1024 / 4096; | 
| 463 | break; | 
| 464 | case AGP_I915_GCC1_GMS_STOLEN_48M0x60: | 
| 465 | isc->stolen = (49152 - stolen) * 1024 / 4096; | 
| 466 | break; | 
| 467 | case AGP_I915_GCC1_GMS_STOLEN_64M0x70: | 
| 468 | isc->stolen = (65536 - stolen) * 1024 / 4096; | 
| 469 | break; | 
| 470 | case AGP_G33_GCC1_GMS_STOLEN_128M0x80: | 
| 471 | isc->stolen = (131072 - stolen) * 1024 / 4096; | 
| 472 | break; | 
| 473 | case AGP_G33_GCC1_GMS_STOLEN_256M0x90: | 
| 474 | isc->stolen = (262144 - stolen) * 1024 / 4096; | 
| 475 | break; | 
| 476 | case AGP_INTEL_GMCH_GMS_STOLEN_96M0xa0: | 
| 477 | isc->stolen = (98304 - stolen) * 1024 / 4096; | 
| 478 | break; | 
| 479 | case AGP_INTEL_GMCH_GMS_STOLEN_160M0xb0: | 
| 480 | isc->stolen = (163840 - stolen) * 1024 / 4096; | 
| 481 | break; | 
| 482 | case AGP_INTEL_GMCH_GMS_STOLEN_224M0xc0: | 
| 483 | isc->stolen = (229376 - stolen) * 1024 / 4096; | 
| 484 | break; | 
| 485 | case AGP_INTEL_GMCH_GMS_STOLEN_352M0xd0: | 
| 486 | isc->stolen = (360448 - stolen) * 1024 / 4096; | 
| 487 | break; | 
| 488 | default: | 
| 489 | isc->stolen = 0; | 
| 490 | printf("unknown memory configuration, disabling\n"); | 
| 491 | goto out; | 
| 492 | } | 
| 493 | #ifdef DEBUG | 
| 494 | if (isc->stolen > 0) { | 
| 495 | printf(": detected %dk stolen memory", | 
| 496 | isc->stolen * 4); | 
| 497 | } else | 
| 498 | printf(": no preallocated video memory\n"); | 
| 499 | #endif | 
| 500 | |
| 501 | /* XXX */ | 
| 502 | isc->stolen = 0; | 
| 503 | |
| 504 | /* GATT address is already in there, make sure it's enabled */ | 
| 505 | gatt->ag_physical = READ4(AGP_I810_PGTBL_CTL)((isc->map->bst)->read_4((isc->map->bsh), (0x2020 ))) & ~1; | 
| 506 | break; | 
| 507 | |
| 508 | default: | 
| 509 | printf(": unknown initialisation\n"); | 
| 510 | return; | 
| 511 | } | 
| 512 | /* Intel recommends that you have a fake page bound to the gtt always */ | 
| 513 | if (agp_alloc_dmamem(pa->pa_dmat, AGP_PAGE_SIZE4096, &isc->scrib_dmamap, | 
| 514 | &tmp, &isc->scrib_seg) != 0) { | 
| 515 | printf(": can't get scribble page\n"); | 
| 516 | return; | 
| 517 | } | 
| 518 | agp_i810_configure(isc); | 
| 519 | |
| 520 | isc->agpdev = (struct agp_softc *)agp_attach_bus(pa, &agp_i810_methods, | 
| 521 | isc->isc_apaddr, isc->isc_apsize, &isc->dev); | 
| 522 | isc->agpdev->sc_stolen_entries = isc->stolen; | 
| 523 | return; | 
| 524 | out: | 
| 525 | |
| 526 | if (isc->gatt) { | 
| 527 | if (isc->gatt->ag_size != 0) | 
| 528 | agp_free_dmamem(pa->pa_dmat, isc->gatt->ag_size, | 
| 529 | isc->gatt->ag_dmamap, &isc->gatt->ag_dmaseg); | 
| 530 | free(isc->gatt, M_AGP144, sizeof (*isc->gatt)); | 
| 531 | } | 
| 532 | if (isc->gtt_size != 0) | 
| 533 | bus_space_unmap(isc->gtt_bst, isc->gtt_bsh, isc->gtt_size); | 
| 534 | } | 
| 535 | |
| 536 | int | 
| 537 | agp_i810_activate(struct device *arg, int act) | 
| 538 | { | 
| 539 | struct agp_i810_softc *isc = (struct agp_i810_softc *)arg; | 
| 540 | |
| 541 | /* | 
| 542 | * Anything kept in agp over a suspend/resume cycle (and thus by X | 
| 543 | * over a vt switch cycle) is undefined upon resume. | 
| 544 | */ | 
| 545 | switch (act) { | 
| 546 | case DVACT_RESUME4: | 
| 547 | agp_i810_configure(isc); | 
| 548 | break; | 
| 549 | } | 
| 550 | |
| 551 | return (0); | 
| 552 | } | 
| 553 | |
| 554 | void | 
| 555 | agp_i810_configure(struct agp_i810_softc *isc) | 
| 556 | { | 
| 557 | bus_addr_t tmp; | 
| 558 | |
| 559 | tmp = isc->isc_apaddr; | 
| 560 | if (isc->chiptype == CHIP_I810) { | 
| 561 | tmp += isc->dcache_size; | 
| 562 | } else { | 
| 563 | tmp += isc->stolen << AGP_PAGE_SHIFT12; | 
| 564 | } | 
| 565 | |
| 566 | agp_flush_cache(); | 
| 567 | /* Install the GATT. */ | 
| 568 | WRITE4(AGP_I810_PGTBL_CTL, isc->gatt->ag_physical | 1)((isc->map->bst)->write_4((isc->map->bsh), (0x2020 ), (isc->gatt->ag_physical | 1))); | 
| 569 | |
| 570 | /* initialise all gtt entries to point to scribble page */ | 
| 571 | for (; tmp < (isc->isc_apaddr + isc->isc_apsize); | 
| 572 | tmp += AGP_PAGE_SIZE4096) | 
| 573 | agp_i810_unbind_page(isc, tmp); | 
| 574 | /* XXX we'll need to restore the GTT contents when we go kms */ | 
| 575 | |
| 576 | /* | 
| 577 | * Make sure the chipset can see everything. | 
| 578 | */ | 
| 579 | agp_flush_cache(); | 
| 580 | } | 
| 581 | |
| 582 | void | 
| 583 | agp_i810_bind_page(void *sc, bus_addr_t offset, paddr_t physical, int flags) | 
| 584 | { | 
| 585 | struct agp_i810_softc *isc = sc; | 
| 586 | |
| 587 | /* | 
| 588 | * COHERENT mappings mean set the snoop bit. this should never be | 
| 589 | * accessed by the gpu through the gtt. | 
| 590 | */ | 
| 591 | if (flags & BUS_DMA_COHERENT0x0004) | 
| 592 | physical |= INTEL_COHERENT0x6; | 
| 593 | |
| 594 | intagp_write_gtt(isc, offset - isc->isc_apaddr, physical); | 
| 595 | } | 
| 596 | |
| 597 | void | 
| 598 | agp_i810_unbind_page(void *sc, bus_size_t offset) | 
| 599 | { | 
| 600 | struct agp_i810_softc *isc = sc; | 
| 601 | |
| 602 | intagp_write_gtt(isc, offset - isc->isc_apaddr, | 
| 603 | isc->scrib_dmamap->dm_segs[0].ds_addr); | 
| 604 | } | 
| 605 | |
| 606 | /* | 
| 607 | * Writing via memory mapped registers already flushes all TLBs. | 
| 608 | */ | 
| 609 | void | 
| 610 | agp_i810_flush_tlb(void *sc) | 
| 611 | { | 
| 612 | } | 
| 613 | |
| 614 | int | 
| 615 | agp_i810_enable(void *sc, u_int32_t mode) | 
| 616 | { | 
| 617 | return (0); | 
| 618 | } | 
| 619 | |
| 620 | void | 
| 621 | intagp_write_gtt(struct agp_i810_softc *isc, bus_size_t off, paddr_t v) | 
| 622 | { | 
| 623 | u_int32_t pte = 0; | 
| 624 | bus_size_t wroff; | 
| 625 | |
| 626 | if (isc->chiptype != CHIP_I810 && | 
| 627 | (off >> AGP_PAGE_SHIFT12) < isc->stolen) { | 
| 628 | printf("intagp: binding into stolen memory! (0x%lx)\n", | 
| 629 | (off >> AGP_PAGE_SHIFT12)); | 
| 630 | } | 
| 631 | |
| 632 | if (v != 0) { | 
| 633 | pte = v | INTEL_ENABLED0x1; | 
| 634 | /* 965+ can do 36-bit addressing, add in the extra bits */ | 
| 635 | switch (isc->chiptype) { | 
| 636 | case CHIP_I965: | 
| 637 | case CHIP_G4X: | 
| 638 | case CHIP_PINEVIEW: | 
| 639 | case CHIP_G33: | 
| 640 | case CHIP_IRONLAKE: | 
| 641 | pte |= (v & 0x0000000f00000000ULL) >> 28; | 
| 642 | break; | 
| 643 | } | 
| 644 | } | 
| 645 | |
| 646 | wroff = (off >> AGP_PAGE_SHIFT12) * 4; | 
| 647 | bus_space_write_4(isc->gtt_bst, isc->gtt_bsh, wroff, pte)((isc->gtt_bst)->write_4((isc->gtt_bsh), (wroff), (pte ))); | 
| 648 | } |