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 | } |