| File: | dev/pci/agp_i810.c |
| Warning: | line 255, 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; |
Value stored to 'mmaddr' is never read | |
| 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; |
| 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 | } |