Line data Source code
1 : /* $OpenBSD: agp_i810.c,v 1.93 2015/12/19 16:07:20 kettenis 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) bus_space_read_1(isc->map->bst, isc->map->bsh, off)
51 : #define READ4(off) bus_space_read_4(isc->map->bst, isc->map->bsh, off)
52 : #define WRITE4(off,v) bus_space_write_4(isc->map->bst, isc->map->bsh, off, v)
53 :
54 : /*
55 : * Intel IGP gtt bits.
56 : */
57 : /* PTE is enabled */
58 : #define INTEL_ENABLED 0x1
59 : /* I810/I815 only, memory is in dcache */
60 : #define INTEL_LOCAL 0x2
61 : /* Memory is snooped, must not be accessed through gtt from the cpu. */
62 : #define INTEL_COHERENT 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 : struct cfattach intagp_ca = {
111 : sizeof(struct agp_i810_softc), agp_i810_probe, agp_i810_attach,
112 : NULL, agp_i810_activate,
113 : };
114 :
115 : struct cfdriver intagp_cd = {
116 : NULL, "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 0 : agp_i810_get_chiptype(struct pci_attach_args *pa)
128 : {
129 0 : switch (PCI_PRODUCT(pa->pa_id)) {
130 : case PCI_PRODUCT_INTEL_82810_IGD:
131 : case PCI_PRODUCT_INTEL_82810_DC100_IGD:
132 : case PCI_PRODUCT_INTEL_82810E_IGD:
133 : case PCI_PRODUCT_INTEL_82815_IGD:
134 0 : return (CHIP_I810);
135 : break;
136 : case PCI_PRODUCT_INTEL_82830M_IGD:
137 : case PCI_PRODUCT_INTEL_82845G_IGD:
138 0 : return (CHIP_I830);
139 : break;
140 : case PCI_PRODUCT_INTEL_82854_IGD:
141 : case PCI_PRODUCT_INTEL_82855GM_IGD:
142 : case PCI_PRODUCT_INTEL_82865G_IGD:
143 0 : return (CHIP_I855);
144 : break;
145 : case PCI_PRODUCT_INTEL_E7221_IGD:
146 : case PCI_PRODUCT_INTEL_82915G_IGD_1:
147 : case PCI_PRODUCT_INTEL_82915G_IGD_2:
148 : case PCI_PRODUCT_INTEL_82915GM_IGD_1:
149 : case PCI_PRODUCT_INTEL_82915GM_IGD_2:
150 : case PCI_PRODUCT_INTEL_82945G_IGD_1:
151 : case PCI_PRODUCT_INTEL_82945G_IGD_2:
152 : case PCI_PRODUCT_INTEL_82945GM_IGD_1:
153 : case PCI_PRODUCT_INTEL_82945GM_IGD_2:
154 : case PCI_PRODUCT_INTEL_82945GME_IGD_1:
155 0 : return (CHIP_I915);
156 : break;
157 : case PCI_PRODUCT_INTEL_82946GZ_IGD_1:
158 : case PCI_PRODUCT_INTEL_82946GZ_IGD_2:
159 : case PCI_PRODUCT_INTEL_82Q965_IGD_1:
160 : case PCI_PRODUCT_INTEL_82Q965_IGD_2:
161 : case PCI_PRODUCT_INTEL_82G965_IGD_1:
162 : case PCI_PRODUCT_INTEL_82G965_IGD_2:
163 : case PCI_PRODUCT_INTEL_82GM965_IGD_1:
164 : case PCI_PRODUCT_INTEL_82GM965_IGD_2:
165 : case PCI_PRODUCT_INTEL_82GME965_IGD_1:
166 : case PCI_PRODUCT_INTEL_82GME965_IGD_2:
167 : case PCI_PRODUCT_INTEL_82G35_IGD_1:
168 : case PCI_PRODUCT_INTEL_82G35_IGD_2:
169 0 : return (CHIP_I965);
170 : break;
171 : case PCI_PRODUCT_INTEL_82G33_IGD_1:
172 : case PCI_PRODUCT_INTEL_82G33_IGD_2:
173 : case PCI_PRODUCT_INTEL_82Q35_IGD_1:
174 : case PCI_PRODUCT_INTEL_82Q35_IGD_2:
175 : case PCI_PRODUCT_INTEL_82Q33_IGD_1:
176 : case PCI_PRODUCT_INTEL_82Q33_IGD_2:
177 0 : return (CHIP_G33);
178 : break;
179 : case PCI_PRODUCT_INTEL_82GM45_IGD_1:
180 : case PCI_PRODUCT_INTEL_4SERIES_IGD:
181 : case PCI_PRODUCT_INTEL_82Q45_IGD_1:
182 : case PCI_PRODUCT_INTEL_82G45_IGD_1:
183 : case PCI_PRODUCT_INTEL_82G41_IGD_1:
184 : case PCI_PRODUCT_INTEL_82B43_IGD_1:
185 : case PCI_PRODUCT_INTEL_82B43_IGD_2:
186 0 : return (CHIP_G4X);
187 : break;
188 : case PCI_PRODUCT_INTEL_PINEVIEW_IGC_1:
189 : case PCI_PRODUCT_INTEL_PINEVIEW_M_IGC_1:
190 0 : return (CHIP_PINEVIEW);
191 : break;
192 : case PCI_PRODUCT_INTEL_CLARKDALE_IGD:
193 : case PCI_PRODUCT_INTEL_ARRANDALE_IGD:
194 0 : return (CHIP_IRONLAKE);
195 : break;
196 : }
197 :
198 0 : return (CHIP_NONE);
199 0 : }
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 0 : intagp_gmch_match(struct pci_attach_args *pa)
207 : {
208 0 : if (pa->pa_bus == 0 && pa->pa_device == 0 && pa->pa_function == 0 &&
209 0 : PCI_VENDOR(pa->pa_id) == PCI_VENDOR_INTEL &&
210 0 : PCI_CLASS(pa->pa_class) == PCI_CLASS_BRIDGE &&
211 0 : PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_BRIDGE_HOST)
212 0 : return (1);
213 0 : return (0);
214 0 : }
215 :
216 : int
217 0 : agp_i810_probe(struct device *parent, void *match, void *aux)
218 : {
219 0 : struct pci_attach_args *pa = aux;
220 :
221 0 : if (PCI_CLASS(pa->pa_class) != PCI_CLASS_DISPLAY ||
222 0 : PCI_SUBCLASS(pa->pa_class) != PCI_SUBCLASS_DISPLAY_VGA)
223 0 : return (0);
224 :
225 0 : return (agp_i810_get_chiptype(pa) != CHIP_NONE);
226 0 : }
227 :
228 : void
229 0 : agp_i810_attach(struct device *parent, struct device *self, void *aux)
230 : {
231 0 : struct agp_i810_softc *isc = (struct agp_i810_softc *)self;
232 : struct agp_gatt *gatt;
233 0 : struct pci_attach_args *pa = aux, bpa;
234 0 : struct inteldrm_softc *psc = (struct inteldrm_softc *)parent;
235 0 : 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 0 : isc->chiptype = agp_i810_get_chiptype(pa);
242 :
243 0 : switch (isc->chiptype) {
244 : case CHIP_I915:
245 : case CHIP_G33:
246 : case CHIP_PINEVIEW:
247 : gmaddr = AGP_I915_GMADR;
248 : mmaddr = AGP_I915_MMADR;
249 : memtype = PCI_MAPREG_TYPE_MEM;
250 0 : break;
251 : case CHIP_I965:
252 : case CHIP_G4X:
253 : case CHIP_IRONLAKE:
254 : gmaddr = AGP_I965_GMADR;
255 : mmaddr = AGP_I965_MMADR;
256 : memtype = PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT;
257 0 : if (isc->chiptype == CHIP_I965)
258 0 : gtt_off = AGP_I965_GTT;
259 : else
260 : gtt_off = AGP_G4X_GTT;
261 : break;
262 : default:
263 : gmaddr = AGP_APBASE;
264 : mmaddr = AGP_I810_MMADR;
265 : memtype = PCI_MAPREG_TYPE_MEM;
266 : gtt_off = AGP_I810_GTT;
267 0 : break;
268 : }
269 :
270 0 : if (pci_mapreg_info(pa->pa_pc, pa->pa_tag, gmaddr, memtype,
271 0 : &isc->isc_apaddr, &isc->isc_apsize, NULL) != 0) {
272 0 : printf("can't get aperture info\n");
273 0 : return;
274 : }
275 :
276 0 : isc->map = psc->regs;
277 :
278 0 : if (isc->chiptype == CHIP_I915 || isc->chiptype == CHIP_G33 ||
279 0 : isc->chiptype == CHIP_PINEVIEW) {
280 0 : if (pci_mapreg_map(pa, AGP_I915_GTTADR, memtype,
281 0 : BUS_SPACE_MAP_LINEAR, &isc->gtt_bst, &isc->gtt_bsh,
282 0 : NULL, &isc->gtt_size, 0)) {
283 0 : printf("can't map gatt registers\n");
284 0 : goto out;
285 : }
286 0 : } else if (gtt_off >= isc->map->size) {
287 : isc->gtt_bst = isc->map->bst;
288 0 : isc->gtt_size = (isc->isc_apsize >> AGP_PAGE_SHIFT) * 4;
289 0 : if (bus_space_map(isc->gtt_bst, isc->map->base + gtt_off,
290 0 : isc->gtt_size, BUS_SPACE_MAP_LINEAR, &isc->gtt_bsh)) {
291 0 : printf("can't map gatt registers\n");
292 0 : isc->gtt_size = 0;
293 0 : goto out;
294 : }
295 : } else {
296 : isc->gtt_bst = isc->map->bst;
297 0 : if (bus_space_subregion(isc->map->bst, isc->map->bsh, gtt_off,
298 0 : (isc->isc_apsize >> AGP_PAGE_SHIFT) * 4, &isc->gtt_bsh)) {
299 0 : printf("can't map gatt registers\n");
300 0 : goto out;
301 : }
302 : }
303 :
304 0 : gatt = malloc(sizeof(*gatt), M_AGP, M_NOWAIT | M_ZERO);
305 0 : if (gatt == NULL) {
306 0 : printf("can't alloc gatt\n");
307 0 : goto out;
308 : }
309 0 : isc->gatt = gatt;
310 :
311 0 : gatt->ag_entries = isc->isc_apsize >> AGP_PAGE_SHIFT;
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 0 : if (pci_find_device(&bpa, intagp_gmch_match) == 0) {
319 0 : printf("can't find GMCH\n");
320 0 : goto out;
321 : }
322 :
323 0 : switch (isc->chiptype) {
324 : case CHIP_I810:
325 : /* Some i810s have on-chip memory called dcache */
326 0 : if (READ1(AGP_I810_DRT) & AGP_I810_DRT_POPULATED)
327 0 : isc->dcache_size = 4 * 1024 * 1024;
328 : else
329 0 : isc->dcache_size = 0;
330 :
331 : /* According to the specs the gatt on the i810 must be 64k */
332 0 : if (agp_alloc_dmamem(pa->pa_dmat, 64 * 1024, &gatt->ag_dmamap,
333 0 : &gatt->ag_physical, &gatt->ag_dmaseg) != 0) {
334 : goto out;
335 : }
336 0 : gatt->ag_size = gatt->ag_entries * sizeof(u_int32_t);
337 :
338 0 : if (bus_dmamem_map(pa->pa_dmat, &gatt->ag_dmaseg, 1, 64 * 1024,
339 0 : (caddr_t *)&gatt->ag_virtual, BUS_DMA_NOWAIT) != 0)
340 : goto out;
341 : break;
342 :
343 : case CHIP_I830:
344 : /* The i830 automatically initializes the 128k gatt on boot. */
345 :
346 0 : reg = pci_conf_read(bpa.pa_pc, bpa.pa_tag, AGP_I830_GCC0);
347 0 : gcc1 = (u_int16_t)(reg >> 16);
348 0 : switch (gcc1 & AGP_I830_GCC1_GMS) {
349 : case AGP_I830_GCC1_GMS_STOLEN_512:
350 0 : isc->stolen = (512 - 132) * 1024 / 4096;
351 0 : break;
352 : case AGP_I830_GCC1_GMS_STOLEN_1024:
353 0 : isc->stolen = (1024 - 132) * 1024 / 4096;
354 0 : break;
355 : case AGP_I830_GCC1_GMS_STOLEN_8192:
356 0 : isc->stolen = (8192 - 132) * 1024 / 4096;
357 0 : break;
358 : default:
359 0 : isc->stolen = 0;
360 0 : printf("unknown memory configuration, disabling\n");
361 0 : 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 0 : isc->stolen = 0;
373 :
374 : /* GATT address is already in there, make sure it's enabled */
375 0 : gatt->ag_physical = READ4(AGP_I810_PGTBL_CTL) & ~1;
376 0 : 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 0 : reg = pci_conf_read(bpa.pa_pc, bpa.pa_tag, AGP_I855_GCC1);
396 0 : gcc1 = (u_int16_t)(reg >> 16);
397 0 : switch (isc->chiptype) {
398 : case CHIP_I855:
399 : /* The 855GM automatically initializes the 128k gatt on boot. */
400 : stolen = 128 + 4;
401 0 : break;
402 : case CHIP_I915:
403 : /* The 915G automatically initializes the 256k gatt on boot. */
404 : stolen = 256 + 4;
405 0 : break;
406 : case CHIP_I965:
407 0 : switch (READ4(AGP_I810_PGTBL_CTL) &
408 : AGP_I810_PGTBL_SIZE_MASK) {
409 : case AGP_I810_PGTBL_SIZE_512KB:
410 : stolen = 512 + 4;
411 0 : break;
412 : case AGP_I810_PGTBL_SIZE_256KB:
413 : stolen = 256 + 4;
414 0 : break;
415 : case AGP_I810_PGTBL_SIZE_128KB:
416 : default:
417 : stolen = 128 + 4;
418 0 : break;
419 : }
420 : break;
421 : case CHIP_G33:
422 0 : switch (gcc1 & AGP_G33_PGTBL_SIZE_MASK) {
423 : case AGP_G33_PGTBL_SIZE_2M:
424 : stolen = 2048 + 4;
425 0 : break;
426 : case AGP_G33_PGTBL_SIZE_1M:
427 : default:
428 : stolen = 1024 + 4;
429 0 : 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 0 : break;
443 : default:
444 0 : printf("bad chiptype\n");
445 0 : goto out;
446 : }
447 :
448 0 : switch (gcc1 & AGP_I855_GCC1_GMS) {
449 : case AGP_I855_GCC1_GMS_STOLEN_1M:
450 0 : isc->stolen = (1024 - stolen) * 1024 / 4096;
451 0 : break;
452 : case AGP_I855_GCC1_GMS_STOLEN_4M:
453 0 : isc->stolen = (4096 - stolen) * 1024 / 4096;
454 0 : break;
455 : case AGP_I855_GCC1_GMS_STOLEN_8M:
456 0 : isc->stolen = (8192 - stolen) * 1024 / 4096;
457 0 : break;
458 : case AGP_I855_GCC1_GMS_STOLEN_16M:
459 0 : isc->stolen = (16384 - stolen) * 1024 / 4096;
460 0 : break;
461 : case AGP_I855_GCC1_GMS_STOLEN_32M:
462 0 : isc->stolen = (32768 - stolen) * 1024 / 4096;
463 0 : break;
464 : case AGP_I915_GCC1_GMS_STOLEN_48M:
465 0 : isc->stolen = (49152 - stolen) * 1024 / 4096;
466 0 : break;
467 : case AGP_I915_GCC1_GMS_STOLEN_64M:
468 0 : isc->stolen = (65536 - stolen) * 1024 / 4096;
469 0 : break;
470 : case AGP_G33_GCC1_GMS_STOLEN_128M:
471 0 : isc->stolen = (131072 - stolen) * 1024 / 4096;
472 0 : break;
473 : case AGP_G33_GCC1_GMS_STOLEN_256M:
474 0 : isc->stolen = (262144 - stolen) * 1024 / 4096;
475 0 : break;
476 : case AGP_INTEL_GMCH_GMS_STOLEN_96M:
477 0 : isc->stolen = (98304 - stolen) * 1024 / 4096;
478 0 : break;
479 : case AGP_INTEL_GMCH_GMS_STOLEN_160M:
480 0 : isc->stolen = (163840 - stolen) * 1024 / 4096;
481 0 : break;
482 : case AGP_INTEL_GMCH_GMS_STOLEN_224M:
483 0 : isc->stolen = (229376 - stolen) * 1024 / 4096;
484 0 : break;
485 : case AGP_INTEL_GMCH_GMS_STOLEN_352M:
486 0 : isc->stolen = (360448 - stolen) * 1024 / 4096;
487 0 : break;
488 : default:
489 0 : isc->stolen = 0;
490 0 : printf("unknown memory configuration, disabling\n");
491 0 : 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 0 : isc->stolen = 0;
503 :
504 : /* GATT address is already in there, make sure it's enabled */
505 0 : gatt->ag_physical = READ4(AGP_I810_PGTBL_CTL) & ~1;
506 0 : break;
507 :
508 : default:
509 0 : printf(": unknown initialisation\n");
510 0 : return;
511 : }
512 : /* Intel recommends that you have a fake page bound to the gtt always */
513 0 : if (agp_alloc_dmamem(pa->pa_dmat, AGP_PAGE_SIZE, &isc->scrib_dmamap,
514 0 : &tmp, &isc->scrib_seg) != 0) {
515 0 : printf(": can't get scribble page\n");
516 0 : return;
517 : }
518 0 : agp_i810_configure(isc);
519 :
520 0 : isc->agpdev = (struct agp_softc *)agp_attach_bus(pa, &agp_i810_methods,
521 0 : isc->isc_apaddr, isc->isc_apsize, &isc->dev);
522 0 : isc->agpdev->sc_stolen_entries = isc->stolen;
523 0 : return;
524 : out:
525 :
526 0 : if (isc->gatt) {
527 0 : if (isc->gatt->ag_size != 0)
528 0 : agp_free_dmamem(pa->pa_dmat, isc->gatt->ag_size,
529 0 : isc->gatt->ag_dmamap, &isc->gatt->ag_dmaseg);
530 0 : free(isc->gatt, M_AGP, sizeof (*isc->gatt));
531 0 : }
532 0 : if (isc->gtt_size != 0)
533 0 : bus_space_unmap(isc->gtt_bst, isc->gtt_bsh, isc->gtt_size);
534 0 : }
535 :
536 : int
537 0 : agp_i810_activate(struct device *arg, int act)
538 : {
539 0 : 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 0 : switch (act) {
546 : case DVACT_RESUME:
547 0 : agp_i810_configure(isc);
548 0 : break;
549 : }
550 :
551 0 : return (0);
552 : }
553 :
554 : void
555 0 : agp_i810_configure(struct agp_i810_softc *isc)
556 : {
557 : bus_addr_t tmp;
558 :
559 0 : tmp = isc->isc_apaddr;
560 0 : if (isc->chiptype == CHIP_I810) {
561 0 : tmp += isc->dcache_size;
562 0 : } else {
563 0 : tmp += isc->stolen << AGP_PAGE_SHIFT;
564 : }
565 :
566 0 : agp_flush_cache();
567 : /* Install the GATT. */
568 0 : WRITE4(AGP_I810_PGTBL_CTL, isc->gatt->ag_physical | 1);
569 :
570 : /* initialise all gtt entries to point to scribble page */
571 0 : for (; tmp < (isc->isc_apaddr + isc->isc_apsize);
572 0 : tmp += AGP_PAGE_SIZE)
573 0 : 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 0 : agp_flush_cache();
580 0 : }
581 :
582 : void
583 0 : agp_i810_bind_page(void *sc, bus_addr_t offset, paddr_t physical, int flags)
584 : {
585 0 : 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 0 : if (flags & BUS_DMA_COHERENT)
592 0 : physical |= INTEL_COHERENT;
593 :
594 0 : intagp_write_gtt(isc, offset - isc->isc_apaddr, physical);
595 0 : }
596 :
597 : void
598 0 : agp_i810_unbind_page(void *sc, bus_size_t offset)
599 : {
600 0 : struct agp_i810_softc *isc = sc;
601 :
602 0 : intagp_write_gtt(isc, offset - isc->isc_apaddr,
603 0 : isc->scrib_dmamap->dm_segs[0].ds_addr);
604 0 : }
605 :
606 : /*
607 : * Writing via memory mapped registers already flushes all TLBs.
608 : */
609 : void
610 0 : agp_i810_flush_tlb(void *sc)
611 : {
612 0 : }
613 :
614 : int
615 0 : agp_i810_enable(void *sc, u_int32_t mode)
616 : {
617 0 : return (0);
618 : }
619 :
620 : void
621 0 : 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 0 : if (isc->chiptype != CHIP_I810 &&
627 0 : (off >> AGP_PAGE_SHIFT) < isc->stolen) {
628 0 : printf("intagp: binding into stolen memory! (0x%lx)\n",
629 : (off >> AGP_PAGE_SHIFT));
630 0 : }
631 :
632 0 : if (v != 0) {
633 0 : pte = v | INTEL_ENABLED;
634 : /* 965+ can do 36-bit addressing, add in the extra bits */
635 0 : switch (isc->chiptype) {
636 : case CHIP_I965:
637 : case CHIP_G4X:
638 : case CHIP_PINEVIEW:
639 : case CHIP_G33:
640 : case CHIP_IRONLAKE:
641 0 : pte |= (v & 0x0000000f00000000ULL) >> 28;
642 0 : break;
643 : }
644 : }
645 :
646 0 : wroff = (off >> AGP_PAGE_SHIFT) * 4;
647 0 : bus_space_write_4(isc->gtt_bst, isc->gtt_bsh, wroff, pte);
648 0 : }
|