hammer2 - Redo refactor code, fix races, add assertions
[dragonfly.git] / sys / dev / agp / agp_i810.c
CommitLineData
ab5a0ec8 1/*
984263bc
MD
2 * Copyright (c) 2000 Doug Rabson
3 * Copyright (c) 2000 Ruslan Ermilov
a904aa53 4 * Copyright (c) 2011 The FreeBSD Foundation
984263bc
MD
5 * All rights reserved.
6 *
a904aa53
FT
7 * Portions of this software were developed by Konstantin Belousov
8 * under sponsorship from the FreeBSD Foundation.
9 *
984263bc
MD
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 *
7f9ec87c 31 * $FreeBSD: src/sys/dev/agp/agp_i810.c,v 1.56 2010/03/12 21:34:23 rnoland Exp $
984263bc
MD
32 */
33
34/*
35 * Fixes for 830/845G support: David Dawes <dawes@xfree86.org>
fdc3c5be 36 * 852GM/855GM/865G support added by David Dawes <dawes@xfree86.org>
a904aa53
FT
37 *
38 * This is generic Intel GTT handling code, morphed from the AGP
39 * bridge code.
984263bc
MD
40 */
41
a904aa53
FT
42#if 0
43#define KTR_AGP_I810 KTR_DEV
44#else
45#define KTR_AGP_I810 0
46#endif
47
984263bc
MD
48#include <sys/param.h>
49#include <sys/systm.h>
50#include <sys/malloc.h>
51#include <sys/kernel.h>
52#include <sys/bus.h>
53#include <sys/lock.h>
1f7ab7c9 54#include <sys/rman.h>
984263bc 55
1f2de5d4
MD
56#include <bus/pci/pcivar.h>
57#include <bus/pci/pcireg.h>
58#include "agppriv.h"
59#include "agpreg.h"
a904aa53 60#include <dev/agp/agp_i810.h>
984263bc
MD
61
62#include <vm/vm.h>
63#include <vm/vm_object.h>
64#include <vm/vm_page.h>
65#include <vm/vm_pageout.h>
66#include <vm/pmap.h>
67
fdc3c5be
HT
68#include <machine/md_var.h>
69
70#define bus_read_1(r, o) \
71 bus_space_read_1((r)->r_bustag, (r)->r_bushandle, (o))
72#define bus_read_4(r, o) \
73 bus_space_read_4((r)->r_bustag, (r)->r_bushandle, (o))
74#define bus_write_4(r, o, v) \
75 bus_space_write_4((r)->r_bustag, (r)->r_bushandle, (o), (v))
76
984263bc
MD
77MALLOC_DECLARE(M_AGP);
78
a904aa53
FT
79struct agp_i810_match;
80
81static int agp_i810_check_active(device_t bridge_dev);
82static int agp_i830_check_active(device_t bridge_dev);
83static int agp_i915_check_active(device_t bridge_dev);
84static int agp_sb_check_active(device_t bridge_dev);
85
86static void agp_82852_set_desc(device_t dev,
87 const struct agp_i810_match *match);
88static void agp_i810_set_desc(device_t dev, const struct agp_i810_match *match);
89
90static void agp_i810_dump_regs(device_t dev);
91static void agp_i830_dump_regs(device_t dev);
92static void agp_i855_dump_regs(device_t dev);
93static void agp_i915_dump_regs(device_t dev);
94static void agp_i965_dump_regs(device_t dev);
95static void agp_sb_dump_regs(device_t dev);
96
97static int agp_i810_get_stolen_size(device_t dev);
98static int agp_i830_get_stolen_size(device_t dev);
99static int agp_i915_get_stolen_size(device_t dev);
100static int agp_sb_get_stolen_size(device_t dev);
101
102static int agp_i810_get_gtt_mappable_entries(device_t dev);
103static int agp_i830_get_gtt_mappable_entries(device_t dev);
104static int agp_i915_get_gtt_mappable_entries(device_t dev);
105
106static int agp_i810_get_gtt_total_entries(device_t dev);
107static int agp_i965_get_gtt_total_entries(device_t dev);
108static int agp_gen5_get_gtt_total_entries(device_t dev);
109static int agp_sb_get_gtt_total_entries(device_t dev);
110
111static int agp_i810_install_gatt(device_t dev);
112static int agp_i830_install_gatt(device_t dev);
113
114static void agp_i810_deinstall_gatt(device_t dev);
115static void agp_i830_deinstall_gatt(device_t dev);
116
117static void agp_i810_install_gtt_pte(device_t dev, u_int index,
118 vm_offset_t physical, int flags);
119static void agp_i830_install_gtt_pte(device_t dev, u_int index,
120 vm_offset_t physical, int flags);
121static void agp_i915_install_gtt_pte(device_t dev, u_int index,
122 vm_offset_t physical, int flags);
123static void agp_i965_install_gtt_pte(device_t dev, u_int index,
124 vm_offset_t physical, int flags);
125static void agp_g4x_install_gtt_pte(device_t dev, u_int index,
126 vm_offset_t physical, int flags);
127static void agp_sb_install_gtt_pte(device_t dev, u_int index,
128 vm_offset_t physical, int flags);
129
130static void agp_i810_write_gtt(device_t dev, u_int index, uint32_t pte);
131static void agp_i915_write_gtt(device_t dev, u_int index, uint32_t pte);
132static void agp_i965_write_gtt(device_t dev, u_int index, uint32_t pte);
133static void agp_g4x_write_gtt(device_t dev, u_int index, uint32_t pte);
134static void agp_sb_write_gtt(device_t dev, u_int index, uint32_t pte);
135
136static u_int32_t agp_i810_read_gtt_pte(device_t dev, u_int index);
137static u_int32_t agp_i915_read_gtt_pte(device_t dev, u_int index);
138static u_int32_t agp_i965_read_gtt_pte(device_t dev, u_int index);
139static u_int32_t agp_g4x_read_gtt_pte(device_t dev, u_int index);
140
141static vm_paddr_t agp_i810_read_gtt_pte_paddr(device_t dev, u_int index);
142static vm_paddr_t agp_i915_read_gtt_pte_paddr(device_t dev, u_int index);
143static vm_paddr_t agp_sb_read_gtt_pte_paddr(device_t dev, u_int index);
144
145static int agp_i810_set_aperture(device_t dev, u_int32_t aperture);
146static int agp_i830_set_aperture(device_t dev, u_int32_t aperture);
147static int agp_i915_set_aperture(device_t dev, u_int32_t aperture);
148
149static int agp_i810_chipset_flush_setup(device_t dev);
150static int agp_i915_chipset_flush_setup(device_t dev);
151static int agp_i965_chipset_flush_setup(device_t dev);
152
153static void agp_i810_chipset_flush_teardown(device_t dev);
154static void agp_i915_chipset_flush_teardown(device_t dev);
155static void agp_i965_chipset_flush_teardown(device_t dev);
156
157static void agp_i810_chipset_flush(device_t dev);
158static void agp_i830_chipset_flush(device_t dev);
159static void agp_i915_chipset_flush(device_t dev);
160
fdc3c5be
HT
161enum {
162 CHIP_I810, /* i810/i815 */
163 CHIP_I830, /* 830M/845G */
164 CHIP_I855, /* 852GM/855GM/865G */
165 CHIP_I915, /* 915G/915GM */
166 CHIP_I965, /* G965 */
167 CHIP_G33, /* G33/Q33/Q35 */
7f9ec87c 168 CHIP_IGD, /* Pineview */
f16c0bab 169 CHIP_G4X, /* G45/Q45 */
a904aa53 170 CHIP_SB, /* SandyBridge */
fdc3c5be 171};
984263bc 172
fdc3c5be
HT
173/* The i810 through i855 have the registers at BAR 1, and the GATT gets
174 * allocated by us. The i915 has registers in BAR 0 and the GATT is at the
175 * start of the stolen memory, and should only be accessed by the OS through
176 * BAR 3. The G965 has registers and GATT in the same BAR (0) -- first 512KB
177 * is registers, second 512KB is GATT.
178 */
179static struct resource_spec agp_i810_res_spec[] = {
180 { SYS_RES_MEMORY, AGP_I810_MMADR, RF_ACTIVE | RF_SHAREABLE },
181 { -1, 0 }
182};
183
184static struct resource_spec agp_i915_res_spec[] = {
185 { SYS_RES_MEMORY, AGP_I915_MMADR, RF_ACTIVE | RF_SHAREABLE },
186 { SYS_RES_MEMORY, AGP_I915_GTTADR, RF_ACTIVE | RF_SHAREABLE },
187 { -1, 0 }
188};
189
190static struct resource_spec agp_i965_res_spec[] = {
191 { SYS_RES_MEMORY, AGP_I965_GTTMMADR, RF_ACTIVE | RF_SHAREABLE },
192 { -1, 0 }
193};
984263bc 194
a904aa53
FT
195static struct resource_spec agp_g4x_res_spec[] = {
196 { SYS_RES_MEMORY, AGP_G4X_MMADR, RF_ACTIVE | RF_SHAREABLE },
197 { SYS_RES_MEMORY, AGP_G4X_GTTADR, RF_ACTIVE | RF_SHAREABLE },
198 { -1, 0 }
199};
200
984263bc
MD
201struct agp_i810_softc {
202 struct agp_softc agp;
203 u_int32_t initial_aperture; /* aperture size at startup */
204 struct agp_gatt *gatt;
984263bc 205 u_int32_t dcache_size; /* i810 only */
a904aa53
FT
206 u_int32_t stolen; /* number of i830/845 gtt
207 entries for stolen memory */
208 u_int stolen_size; /* BIOS-reserved graphics memory */
209 u_int gtt_total_entries; /* Total number of gtt ptes */
210 u_int gtt_mappable_entries; /* Number of gtt ptes mappable by CPU */
984263bc 211 device_t bdev; /* bridge device */
fdc3c5be 212 void *argb_cursor; /* contigmalloc area for ARGB cursor */
fdc3c5be 213 struct resource *sc_res[2];
a904aa53
FT
214 const struct agp_i810_match *match;
215 int sc_flush_page_rid;
216 struct resource *sc_flush_page_res;
217 void *sc_flush_page_vaddr;
218 int sc_bios_allocated_flush_page;
219};
220
221static device_t intel_agp;
222
223struct agp_i810_driver {
224 int chiptype;
225 int gen;
226 int busdma_addr_mask_sz;
227 struct resource_spec *res_spec;
228 int (*check_active)(device_t);
229 void (*set_desc)(device_t, const struct agp_i810_match *);
230 void (*dump_regs)(device_t);
231 int (*get_stolen_size)(device_t);
232 int (*get_gtt_total_entries)(device_t);
233 int (*get_gtt_mappable_entries)(device_t);
234 int (*install_gatt)(device_t);
235 void (*deinstall_gatt)(device_t);
236 void (*write_gtt)(device_t, u_int, uint32_t);
237 void (*install_gtt_pte)(device_t, u_int, vm_offset_t, int);
238 u_int32_t (*read_gtt_pte)(device_t, u_int);
239 vm_paddr_t (*read_gtt_pte_paddr)(device_t , u_int);
240 int (*set_aperture)(device_t, u_int32_t);
241 int (*chipset_flush_setup)(device_t);
242 void (*chipset_flush_teardown)(device_t);
243 void (*chipset_flush)(device_t);
244};
245
246static const struct agp_i810_driver agp_i810_i810_driver = {
247 .chiptype = CHIP_I810,
248 .gen = 1,
249 .busdma_addr_mask_sz = 32,
250 .res_spec = agp_i810_res_spec,
251 .check_active = agp_i810_check_active,
252 .set_desc = agp_i810_set_desc,
253 .dump_regs = agp_i810_dump_regs,
254 .get_stolen_size = agp_i810_get_stolen_size,
255 .get_gtt_mappable_entries = agp_i810_get_gtt_mappable_entries,
256 .get_gtt_total_entries = agp_i810_get_gtt_total_entries,
257 .install_gatt = agp_i810_install_gatt,
258 .deinstall_gatt = agp_i810_deinstall_gatt,
259 .write_gtt = agp_i810_write_gtt,
260 .install_gtt_pte = agp_i810_install_gtt_pte,
261 .read_gtt_pte = agp_i810_read_gtt_pte,
262 .read_gtt_pte_paddr = agp_i810_read_gtt_pte_paddr,
263 .set_aperture = agp_i810_set_aperture,
264 .chipset_flush_setup = agp_i810_chipset_flush_setup,
265 .chipset_flush_teardown = agp_i810_chipset_flush_teardown,
266 .chipset_flush = agp_i810_chipset_flush,
267};
268
269static const struct agp_i810_driver agp_i810_i815_driver = {
270 .chiptype = CHIP_I810,
271 .gen = 2,
272 .busdma_addr_mask_sz = 32,
273 .res_spec = agp_i810_res_spec,
274 .check_active = agp_i810_check_active,
275 .set_desc = agp_i810_set_desc,
276 .dump_regs = agp_i810_dump_regs,
277 .get_stolen_size = agp_i810_get_stolen_size,
278 .get_gtt_mappable_entries = agp_i830_get_gtt_mappable_entries,
279 .get_gtt_total_entries = agp_i810_get_gtt_total_entries,
280 .install_gatt = agp_i810_install_gatt,
281 .deinstall_gatt = agp_i810_deinstall_gatt,
282 .write_gtt = agp_i810_write_gtt,
283 .install_gtt_pte = agp_i810_install_gtt_pte,
284 .read_gtt_pte = agp_i810_read_gtt_pte,
285 .read_gtt_pte_paddr = agp_i810_read_gtt_pte_paddr,
286 .set_aperture = agp_i810_set_aperture,
287 .chipset_flush_setup = agp_i810_chipset_flush_setup,
288 .chipset_flush_teardown = agp_i810_chipset_flush_teardown,
289 .chipset_flush = agp_i830_chipset_flush,
290};
291
292static const struct agp_i810_driver agp_i810_i830_driver = {
293 .chiptype = CHIP_I830,
294 .gen = 2,
295 .busdma_addr_mask_sz = 32,
296 .res_spec = agp_i810_res_spec,
297 .check_active = agp_i830_check_active,
298 .set_desc = agp_i810_set_desc,
299 .dump_regs = agp_i830_dump_regs,
300 .get_stolen_size = agp_i830_get_stolen_size,
301 .get_gtt_mappable_entries = agp_i830_get_gtt_mappable_entries,
302 .get_gtt_total_entries = agp_i810_get_gtt_total_entries,
303 .install_gatt = agp_i830_install_gatt,
304 .deinstall_gatt = agp_i830_deinstall_gatt,
305 .write_gtt = agp_i810_write_gtt,
306 .install_gtt_pte = agp_i830_install_gtt_pte,
307 .read_gtt_pte = agp_i810_read_gtt_pte,
308 .read_gtt_pte_paddr = agp_i810_read_gtt_pte_paddr,
309 .set_aperture = agp_i830_set_aperture,
310 .chipset_flush_setup = agp_i810_chipset_flush_setup,
311 .chipset_flush_teardown = agp_i810_chipset_flush_teardown,
312 .chipset_flush = agp_i830_chipset_flush,
313};
314
315static const struct agp_i810_driver agp_i810_i855_driver = {
316 .chiptype = CHIP_I855,
317 .gen = 2,
318 .busdma_addr_mask_sz = 32,
319 .res_spec = agp_i810_res_spec,
320 .check_active = agp_i830_check_active,
321 .set_desc = agp_82852_set_desc,
322 .dump_regs = agp_i855_dump_regs,
323 .get_stolen_size = agp_i915_get_stolen_size,
324 .get_gtt_mappable_entries = agp_i915_get_gtt_mappable_entries,
325 .get_gtt_total_entries = agp_i810_get_gtt_total_entries,
326 .install_gatt = agp_i830_install_gatt,
327 .deinstall_gatt = agp_i830_deinstall_gatt,
328 .write_gtt = agp_i810_write_gtt,
329 .install_gtt_pte = agp_i830_install_gtt_pte,
330 .read_gtt_pte = agp_i810_read_gtt_pte,
331 .read_gtt_pte_paddr = agp_i810_read_gtt_pte_paddr,
332 .set_aperture = agp_i830_set_aperture,
333 .chipset_flush_setup = agp_i810_chipset_flush_setup,
334 .chipset_flush_teardown = agp_i810_chipset_flush_teardown,
335 .chipset_flush = agp_i830_chipset_flush,
336};
337
338static const struct agp_i810_driver agp_i810_i865_driver = {
339 .chiptype = CHIP_I855,
340 .gen = 2,
341 .busdma_addr_mask_sz = 32,
342 .res_spec = agp_i810_res_spec,
343 .check_active = agp_i830_check_active,
344 .set_desc = agp_i810_set_desc,
345 .dump_regs = agp_i855_dump_regs,
346 .get_stolen_size = agp_i915_get_stolen_size,
347 .get_gtt_mappable_entries = agp_i915_get_gtt_mappable_entries,
348 .get_gtt_total_entries = agp_i810_get_gtt_total_entries,
349 .install_gatt = agp_i830_install_gatt,
350 .deinstall_gatt = agp_i830_deinstall_gatt,
351 .write_gtt = agp_i810_write_gtt,
352 .install_gtt_pte = agp_i830_install_gtt_pte,
353 .read_gtt_pte = agp_i810_read_gtt_pte,
354 .read_gtt_pte_paddr = agp_i810_read_gtt_pte_paddr,
355 .set_aperture = agp_i915_set_aperture,
356 .chipset_flush_setup = agp_i810_chipset_flush_setup,
357 .chipset_flush_teardown = agp_i810_chipset_flush_teardown,
358 .chipset_flush = agp_i830_chipset_flush,
359};
360
361static const struct agp_i810_driver agp_i810_i915_driver = {
362 .chiptype = CHIP_I915,
363 .gen = 3,
364 .busdma_addr_mask_sz = 32,
365 .res_spec = agp_i915_res_spec,
366 .check_active = agp_i915_check_active,
367 .set_desc = agp_i810_set_desc,
368 .dump_regs = agp_i915_dump_regs,
369 .get_stolen_size = agp_i915_get_stolen_size,
370 .get_gtt_mappable_entries = agp_i915_get_gtt_mappable_entries,
371 .get_gtt_total_entries = agp_i810_get_gtt_total_entries,
372 .install_gatt = agp_i830_install_gatt,
373 .deinstall_gatt = agp_i830_deinstall_gatt,
374 .write_gtt = agp_i915_write_gtt,
375 .install_gtt_pte = agp_i915_install_gtt_pte,
376 .read_gtt_pte = agp_i915_read_gtt_pte,
377 .read_gtt_pte_paddr = agp_i915_read_gtt_pte_paddr,
378 .set_aperture = agp_i915_set_aperture,
379 .chipset_flush_setup = agp_i915_chipset_flush_setup,
380 .chipset_flush_teardown = agp_i915_chipset_flush_teardown,
381 .chipset_flush = agp_i915_chipset_flush,
382};
383
384static const struct agp_i810_driver agp_i810_g965_driver = {
385 .chiptype = CHIP_I965,
386 .gen = 4,
387 .busdma_addr_mask_sz = 36,
388 .res_spec = agp_i965_res_spec,
389 .check_active = agp_i915_check_active,
390 .set_desc = agp_i810_set_desc,
391 .dump_regs = agp_i965_dump_regs,
392 .get_stolen_size = agp_i915_get_stolen_size,
393 .get_gtt_mappable_entries = agp_i915_get_gtt_mappable_entries,
394 .get_gtt_total_entries = agp_i965_get_gtt_total_entries,
395 .install_gatt = agp_i830_install_gatt,
396 .deinstall_gatt = agp_i830_deinstall_gatt,
397 .write_gtt = agp_i965_write_gtt,
398 .install_gtt_pte = agp_i965_install_gtt_pte,
399 .read_gtt_pte = agp_i965_read_gtt_pte,
400 .read_gtt_pte_paddr = agp_i915_read_gtt_pte_paddr,
401 .set_aperture = agp_i915_set_aperture,
402 .chipset_flush_setup = agp_i965_chipset_flush_setup,
403 .chipset_flush_teardown = agp_i965_chipset_flush_teardown,
404 .chipset_flush = agp_i915_chipset_flush,
405};
406
407static const struct agp_i810_driver agp_i810_g33_driver = {
408 .chiptype = CHIP_G33,
409 .gen = 3,
410 .busdma_addr_mask_sz = 36,
411 .res_spec = agp_i915_res_spec,
412 .check_active = agp_i915_check_active,
413 .set_desc = agp_i810_set_desc,
414 .dump_regs = agp_i965_dump_regs,
415 .get_stolen_size = agp_i915_get_stolen_size,
416 .get_gtt_mappable_entries = agp_i915_get_gtt_mappable_entries,
417 .get_gtt_total_entries = agp_i965_get_gtt_total_entries,
418 .install_gatt = agp_i830_install_gatt,
419 .deinstall_gatt = agp_i830_deinstall_gatt,
420 .write_gtt = agp_i915_write_gtt,
421 .install_gtt_pte = agp_i915_install_gtt_pte,
422 .read_gtt_pte = agp_i915_read_gtt_pte,
423 .read_gtt_pte_paddr = agp_i915_read_gtt_pte_paddr,
424 .set_aperture = agp_i915_set_aperture,
425 .chipset_flush_setup = agp_i965_chipset_flush_setup,
426 .chipset_flush_teardown = agp_i965_chipset_flush_teardown,
427 .chipset_flush = agp_i915_chipset_flush,
428};
429
430static const struct agp_i810_driver agp_i810_igd_driver = {
431 .chiptype = CHIP_IGD,
432 .gen = 3,
433 .busdma_addr_mask_sz = 36,
434 .res_spec = agp_i915_res_spec,
435 .check_active = agp_i915_check_active,
436 .set_desc = agp_i810_set_desc,
437 .dump_regs = agp_i915_dump_regs,
438 .get_stolen_size = agp_i915_get_stolen_size,
439 .get_gtt_mappable_entries = agp_i915_get_gtt_mappable_entries,
440 .get_gtt_total_entries = agp_i965_get_gtt_total_entries,
441 .install_gatt = agp_i830_install_gatt,
442 .deinstall_gatt = agp_i830_deinstall_gatt,
443 .write_gtt = agp_i915_write_gtt,
444 .install_gtt_pte = agp_i915_install_gtt_pte,
445 .read_gtt_pte = agp_i915_read_gtt_pte,
446 .read_gtt_pte_paddr = agp_i915_read_gtt_pte_paddr,
447 .set_aperture = agp_i915_set_aperture,
448 .chipset_flush_setup = agp_i965_chipset_flush_setup,
449 .chipset_flush_teardown = agp_i965_chipset_flush_teardown,
450 .chipset_flush = agp_i915_chipset_flush,
451};
452
453static const struct agp_i810_driver agp_i810_g4x_driver = {
454 .chiptype = CHIP_G4X,
455 .gen = 5,
456 .busdma_addr_mask_sz = 36,
457 .res_spec = agp_i965_res_spec,
458 .check_active = agp_i915_check_active,
459 .set_desc = agp_i810_set_desc,
460 .dump_regs = agp_i965_dump_regs,
461 .get_stolen_size = agp_i915_get_stolen_size,
462 .get_gtt_mappable_entries = agp_i915_get_gtt_mappable_entries,
463 .get_gtt_total_entries = agp_gen5_get_gtt_total_entries,
464 .install_gatt = agp_i830_install_gatt,
465 .deinstall_gatt = agp_i830_deinstall_gatt,
466 .write_gtt = agp_g4x_write_gtt,
467 .install_gtt_pte = agp_g4x_install_gtt_pte,
468 .read_gtt_pte = agp_g4x_read_gtt_pte,
469 .read_gtt_pte_paddr = agp_i915_read_gtt_pte_paddr,
470 .set_aperture = agp_i915_set_aperture,
471 .chipset_flush_setup = agp_i965_chipset_flush_setup,
472 .chipset_flush_teardown = agp_i965_chipset_flush_teardown,
473 .chipset_flush = agp_i915_chipset_flush,
474};
475
476static const struct agp_i810_driver agp_i810_sb_driver = {
477 .chiptype = CHIP_SB,
478 .gen = 6,
479 .busdma_addr_mask_sz = 40,
480 .res_spec = agp_g4x_res_spec,
481 .check_active = agp_sb_check_active,
482 .set_desc = agp_i810_set_desc,
483 .dump_regs = agp_sb_dump_regs,
484 .get_stolen_size = agp_sb_get_stolen_size,
485 .get_gtt_mappable_entries = agp_i915_get_gtt_mappable_entries,
486 .get_gtt_total_entries = agp_sb_get_gtt_total_entries,
487 .install_gatt = agp_i830_install_gatt,
488 .deinstall_gatt = agp_i830_deinstall_gatt,
489 .write_gtt = agp_sb_write_gtt,
490 .install_gtt_pte = agp_sb_install_gtt_pte,
491 .read_gtt_pte = agp_g4x_read_gtt_pte,
492 .read_gtt_pte_paddr = agp_sb_read_gtt_pte_paddr,
493 .set_aperture = agp_i915_set_aperture,
494 .chipset_flush_setup = agp_i810_chipset_flush_setup,
495 .chipset_flush_teardown = agp_i810_chipset_flush_teardown,
496 .chipset_flush = agp_i810_chipset_flush,
fdc3c5be
HT
497};
498
499/* For adding new devices, devid is the id of the graphics controller
500 * (pci:0:2:0, for example). The placeholder (usually at pci:0:2:1) for the
501 * second head should never be added. The bridge_offset is the offset to
502 * subtract from devid to get the id of the hostb that the device is on.
503 */
504static const struct agp_i810_match {
505 int devid;
fdc3c5be 506 char *name;
a904aa53 507 const struct agp_i810_driver *driver;
fdc3c5be 508} agp_i810_matches[] = {
a904aa53
FT
509 {
510 .devid = 0x71218086,
511 .name = "Intel 82810 (i810 GMCH) SVGA controller",
512 .driver = &agp_i810_i810_driver
513 },
514 {
515 .devid = 0x71238086,
516 .name = "Intel 82810-DC100 (i810-DC100 GMCH) SVGA controller",
517 .driver = &agp_i810_i810_driver
518 },
519 {
520 .devid = 0x71258086,
521 .name = "Intel 82810E (i810E GMCH) SVGA controller",
522 .driver = &agp_i810_i810_driver
523 },
524 {
525 .devid = 0x11328086,
526 .name = "Intel 82815 (i815 GMCH) SVGA controller",
527 .driver = &agp_i810_i815_driver
528 },
529 {
530 .devid = 0x35778086,
531 .name = "Intel 82830M (830M GMCH) SVGA controller",
532 .driver = &agp_i810_i830_driver
533 },
534 {
535 .devid = 0x25628086,
536 .name = "Intel 82845M (845M GMCH) SVGA controller",
537 .driver = &agp_i810_i830_driver
538 },
539 {
540 .devid = 0x35828086,
541 .name = "Intel 82852/855GM SVGA controller",
542 .driver = &agp_i810_i855_driver
543 },
544 {
545 .devid = 0x25728086,
546 .name = "Intel 82865G (865G GMCH) SVGA controller",
547 .driver = &agp_i810_i865_driver
548 },
549 {
550 .devid = 0x25828086,
551 .name = "Intel 82915G (915G GMCH) SVGA controller",
552 .driver = &agp_i810_i915_driver
553 },
554 {
555 .devid = 0x258A8086,
556 .name = "Intel E7221 SVGA controller",
557 .driver = &agp_i810_i915_driver
558 },
559 {
560 .devid = 0x25928086,
561 .name = "Intel 82915GM (915GM GMCH) SVGA controller",
562 .driver = &agp_i810_i915_driver
563 },
564 {
565 .devid = 0x27728086,
566 .name = "Intel 82945G (945G GMCH) SVGA controller",
567 .driver = &agp_i810_i915_driver
568 },
569 {
570 .devid = 0x27A28086,
571 .name = "Intel 82945GM (945GM GMCH) SVGA controller",
572 .driver = &agp_i810_i915_driver
573 },
574 {
575 .devid = 0x27AE8086,
576 .name = "Intel 945GME SVGA controller",
577 .driver = &agp_i810_i915_driver
578 },
579 {
580 .devid = 0x29728086,
581 .name = "Intel 946GZ SVGA controller",
582 .driver = &agp_i810_g965_driver
583 },
584 {
585 .devid = 0x29828086,
586 .name = "Intel G965 SVGA controller",
587 .driver = &agp_i810_g965_driver
588 },
589 {
590 .devid = 0x29928086,
591 .name = "Intel Q965 SVGA controller",
592 .driver = &agp_i810_g965_driver
593 },
594 {
595 .devid = 0x29A28086,
596 .name = "Intel G965 SVGA controller",
597 .driver = &agp_i810_g965_driver
598 },
599 {
600 .devid = 0x29B28086,
601 .name = "Intel Q35 SVGA controller",
602 .driver = &agp_i810_g33_driver
603 },
604 {
605 .devid = 0x29C28086,
606 .name = "Intel G33 SVGA controller",
607 .driver = &agp_i810_g33_driver
608 },
609 {
610 .devid = 0x29D28086,
611 .name = "Intel Q33 SVGA controller",
612 .driver = &agp_i810_g33_driver
613 },
614 {
615 .devid = 0xA0018086,
616 .name = "Intel Pineview SVGA controller",
617 .driver = &agp_i810_igd_driver
618 },
619 {
620 .devid = 0xA0118086,
621 .name = "Intel Pineview (M) SVGA controller",
622 .driver = &agp_i810_igd_driver
623 },
624 {
625 .devid = 0x2A028086,
626 .name = "Intel GM965 SVGA controller",
627 .driver = &agp_i810_g965_driver
628 },
629 {
630 .devid = 0x2A128086,
631 .name = "Intel GME965 SVGA controller",
632 .driver = &agp_i810_g965_driver
633 },
634 {
635 .devid = 0x2A428086,
636 .name = "Intel GM45 SVGA controller",
637 .driver = &agp_i810_g4x_driver
638 },
639 {
640 .devid = 0x2E028086,
641 .name = "Intel Eaglelake SVGA controller",
642 .driver = &agp_i810_g4x_driver
643 },
644 {
645 .devid = 0x2E128086,
646 .name = "Intel Q45 SVGA controller",
647 .driver = &agp_i810_g4x_driver
648 },
649 {
650 .devid = 0x2E228086,
651 .name = "Intel G45 SVGA controller",
652 .driver = &agp_i810_g4x_driver
653 },
654 {
655 .devid = 0x2E328086,
656 .name = "Intel G41 SVGA controller",
657 .driver = &agp_i810_g4x_driver
658 },
659 {
660 .devid = 0x00428086,
661 .name = "Intel Ironlake (D) SVGA controller",
662 .driver = &agp_i810_g4x_driver
663 },
664 {
665 .devid = 0x00468086,
666 .name = "Intel Ironlake (M) SVGA controller",
667 .driver = &agp_i810_g4x_driver
668 },
669 {
670 .devid = 0x01028086,
671 .name = "SandyBridge desktop GT1 IG",
672 .driver = &agp_i810_sb_driver
673 },
674 {
675 .devid = 0x01128086,
676 .name = "SandyBridge desktop GT2 IG",
677 .driver = &agp_i810_sb_driver
678 },
679 {
680 .devid = 0x01228086,
681 .name = "SandyBridge desktop GT2+ IG",
682 .driver = &agp_i810_sb_driver
683 },
684 {
685 .devid = 0x01068086,
686 .name = "SandyBridge mobile GT1 IG",
687 .driver = &agp_i810_sb_driver
688 },
689 {
690 .devid = 0x01168086,
691 .name = "SandyBridge mobile GT2 IG",
692 .driver = &agp_i810_sb_driver
693 },
694 {
695 .devid = 0x01268086,
696 .name = "SandyBridge mobile GT2+ IG",
697 .driver = &agp_i810_sb_driver
698 },
699 {
700 .devid = 0x010a8086,
701 .name = "SandyBridge server IG",
702 .driver = &agp_i810_sb_driver
703 },
704 {
705 .devid = 0x01528086,
706 .name = "IvyBridge desktop GT1 IG",
707 .driver = &agp_i810_sb_driver
708 },
709 {
710 .devid = 0x01628086,
711 .name = "IvyBridge desktop GT2 IG",
712 .driver = &agp_i810_sb_driver
713 },
714 {
715 .devid = 0x01568086,
716 .name = "IvyBridge mobile GT1 IG",
717 .driver = &agp_i810_sb_driver
718 },
719 {
720 .devid = 0x01668086,
721 .name = "IvyBridge mobile GT2 IG",
722 .driver = &agp_i810_sb_driver
723 },
724 {
725 .devid = 0x015a8086,
726 .name = "IvyBridge server GT1 IG",
727 .driver = &agp_i810_sb_driver
728 },
246f9ec5
FT
729 {
730 .devid = 0x016a8086,
731 .name = "IvyBridge server GT2 IG",
732 .driver = &agp_i810_sb_driver
733 },
a904aa53
FT
734 {
735 .devid = 0,
736 }
984263bc
MD
737};
738
fdc3c5be 739static const struct agp_i810_match*
984263bc
MD
740agp_i810_match(device_t dev)
741{
fdc3c5be
HT
742 int i, devid;
743
1e058a43 744 if (pci_get_class(dev) != PCIC_DISPLAY)
a904aa53 745 return (NULL);
984263bc 746
fdc3c5be
HT
747 devid = pci_get_devid(dev);
748 for (i = 0; agp_i810_matches[i].devid != 0; i++) {
749 if (agp_i810_matches[i].devid == devid)
a904aa53 750 break;
fdc3c5be
HT
751 }
752 if (agp_i810_matches[i].devid == 0)
a904aa53 753 return (NULL);
fdc3c5be 754 else
a904aa53 755 return (&agp_i810_matches[i]);
984263bc
MD
756}
757
758/*
759 * Find bridge device.
760 */
761static device_t
762agp_i810_find_bridge(device_t dev)
763{
984263bc 764
a904aa53 765 return (pci_find_dbsf(0, 0, 0, 0));
984263bc
MD
766}
767
fdc3c5be
HT
768static void
769agp_i810_identify(driver_t *driver, device_t parent)
770{
771
772 if (device_find_child(parent, "agp", -1) == NULL &&
773 agp_i810_match(parent))
774 device_add_child(parent, "agp", -1);
775}
776
a904aa53
FT
777static int
778agp_i810_check_active(device_t bridge_dev)
779{
780 u_int8_t smram;
781
782 smram = pci_read_config(bridge_dev, AGP_I810_SMRAM, 1);
783 if ((smram & AGP_I810_SMRAM_GMS) == AGP_I810_SMRAM_GMS_DISABLED)
784 return (ENXIO);
785 return (0);
786}
787
788static int
789agp_i830_check_active(device_t bridge_dev)
790{
791 int gcc1;
792
793 gcc1 = pci_read_config(bridge_dev, AGP_I830_GCC1, 1);
794 if ((gcc1 & AGP_I830_GCC1_DEV2) == AGP_I830_GCC1_DEV2_DISABLED)
795 return (ENXIO);
796 return (0);
797}
798
799static int
800agp_i915_check_active(device_t bridge_dev)
801{
802 int deven;
803
804 deven = pci_read_config(bridge_dev, AGP_I915_DEVEN, 4);
805 if ((deven & AGP_I915_DEVEN_D2F0) == AGP_I915_DEVEN_D2F0_DISABLED)
806 return (ENXIO);
807 return (0);
808}
809
810static int
811agp_sb_check_active(device_t bridge_dev)
812{
813 int deven;
814
815 deven = pci_read_config(bridge_dev, AGP_I915_DEVEN, 4);
816 if ((deven & AGP_SB_DEVEN_D2EN) == AGP_SB_DEVEN_D2EN_DISABLED)
817 return (ENXIO);
818 return (0);
819}
820
821static void
822agp_82852_set_desc(device_t dev, const struct agp_i810_match *match)
823{
824
825 switch (pci_read_config(dev, AGP_I85X_CAPID, 1)) {
826 case AGP_I855_GME:
827 device_set_desc(dev,
828 "Intel 82855GME (855GME GMCH) SVGA controller");
829 break;
830 case AGP_I855_GM:
831 device_set_desc(dev,
832 "Intel 82855GM (855GM GMCH) SVGA controller");
833 break;
834 case AGP_I852_GME:
835 device_set_desc(dev,
836 "Intel 82852GME (852GME GMCH) SVGA controller");
837 break;
838 case AGP_I852_GM:
839 device_set_desc(dev,
840 "Intel 82852GM (852GM GMCH) SVGA controller");
841 break;
842 default:
843 device_set_desc(dev,
844 "Intel 8285xM (85xGM GMCH) SVGA controller");
845 break;
846 }
847}
848
849static void
850agp_i810_set_desc(device_t dev, const struct agp_i810_match *match)
851{
852
853 device_set_desc(dev, match->name);
854}
855
984263bc
MD
856static int
857agp_i810_probe(device_t dev)
858{
fdc3c5be
HT
859 device_t bdev;
860 const struct agp_i810_match *match;
a904aa53 861 int err;
fdc3c5be
HT
862
863 if (resource_disabled("agp", device_get_unit(dev)))
864 return (ENXIO);
865 match = agp_i810_match(dev);
866 if (match == NULL)
a904aa53 867 return (ENXIO);
984263bc 868
fdc3c5be 869 bdev = agp_i810_find_bridge(dev);
a904aa53 870 if (bdev == NULL) {
fdc3c5be
HT
871 if (bootverbose)
872 kprintf("I810: can't find bridge device\n");
a904aa53 873 return (ENXIO);
fdc3c5be 874 }
984263bc 875
fdc3c5be
HT
876 /*
877 * checking whether internal graphics device has been activated.
878 */
a904aa53
FT
879 err = match->driver->check_active(bdev);
880 if (err != 0) {
881 if (bootverbose)
882 kprintf("i810: disabled, not probing\n");
883 return (err);
984263bc
MD
884 }
885
a904aa53
FT
886 match->driver->set_desc(dev, match);
887 return (BUS_PROBE_DEFAULT);
fdc3c5be
HT
888}
889
890static void
891agp_i810_dump_regs(device_t dev)
892{
893 struct agp_i810_softc *sc = device_get_softc(dev);
894
895 device_printf(dev, "AGP_I810_PGTBL_CTL: %08x\n",
896 bus_read_4(sc->sc_res[0], AGP_I810_PGTBL_CTL));
a904aa53
FT
897 device_printf(dev, "AGP_I810_MISCC: 0x%04x\n",
898 pci_read_config(sc->bdev, AGP_I810_MISCC, 2));
899}
fdc3c5be 900
a904aa53
FT
901static void
902agp_i830_dump_regs(device_t dev)
903{
904 struct agp_i810_softc *sc = device_get_softc(dev);
905
906 device_printf(dev, "AGP_I810_PGTBL_CTL: %08x\n",
907 bus_read_4(sc->sc_res[0], AGP_I810_PGTBL_CTL));
908 device_printf(dev, "AGP_I830_GCC1: 0x%02x\n",
909 pci_read_config(sc->bdev, AGP_I830_GCC1, 1));
984263bc
MD
910}
911
a904aa53
FT
912static void
913agp_i855_dump_regs(device_t dev)
984263bc
MD
914{
915 struct agp_i810_softc *sc = device_get_softc(dev);
984263bc 916
a904aa53
FT
917 device_printf(dev, "AGP_I810_PGTBL_CTL: %08x\n",
918 bus_read_4(sc->sc_res[0], AGP_I810_PGTBL_CTL));
919 device_printf(dev, "AGP_I855_GCC1: 0x%02x\n",
920 pci_read_config(sc->bdev, AGP_I855_GCC1, 1));
921}
984263bc 922
a904aa53
FT
923static void
924agp_i915_dump_regs(device_t dev)
925{
926 struct agp_i810_softc *sc = device_get_softc(dev);
984263bc 927
a904aa53
FT
928 device_printf(dev, "AGP_I810_PGTBL_CTL: %08x\n",
929 bus_read_4(sc->sc_res[0], AGP_I810_PGTBL_CTL));
930 device_printf(dev, "AGP_I855_GCC1: 0x%02x\n",
931 pci_read_config(sc->bdev, AGP_I855_GCC1, 1));
932 device_printf(dev, "AGP_I915_MSAC: 0x%02x\n",
933 pci_read_config(sc->bdev, AGP_I915_MSAC, 1));
934}
fdc3c5be 935
a904aa53
FT
936static void
937agp_i965_dump_regs(device_t dev)
938{
939 struct agp_i810_softc *sc = device_get_softc(dev);
984263bc 940
a904aa53
FT
941 device_printf(dev, "AGP_I965_PGTBL_CTL2: %08x\n",
942 bus_read_4(sc->sc_res[0], AGP_I965_PGTBL_CTL2));
943 device_printf(dev, "AGP_I855_GCC1: 0x%02x\n",
944 pci_read_config(sc->bdev, AGP_I855_GCC1, 1));
945 device_printf(dev, "AGP_I965_MSAC: 0x%02x\n",
946 pci_read_config(sc->bdev, AGP_I965_MSAC, 1));
947}
fdc3c5be 948
a904aa53
FT
949static void
950agp_sb_dump_regs(device_t dev)
951{
952 struct agp_i810_softc *sc = device_get_softc(dev);
984263bc 953
a904aa53
FT
954 device_printf(dev, "AGP_SNB_GFX_MODE: %08x\n",
955 bus_read_4(sc->sc_res[0], AGP_SNB_GFX_MODE));
956 device_printf(dev, "AGP_SNB_GCC1: 0x%04x\n",
957 pci_read_config(sc->bdev, AGP_SNB_GCC1, 2));
958}
959
960static int
961agp_i810_get_stolen_size(device_t dev)
962{
963 struct agp_i810_softc *sc;
964
965 sc = device_get_softc(dev);
966 sc->stolen = 0;
967 sc->stolen_size = 0;
968 return (0);
969}
984263bc 970
a904aa53
FT
971static int
972agp_i830_get_stolen_size(device_t dev)
973{
974 struct agp_i810_softc *sc;
975 unsigned int gcc1;
984263bc 976
a904aa53 977 sc = device_get_softc(dev);
984263bc 978
a904aa53
FT
979 gcc1 = pci_read_config(sc->bdev, AGP_I830_GCC1, 1);
980 switch (gcc1 & AGP_I830_GCC1_GMS) {
981 case AGP_I830_GCC1_GMS_STOLEN_512:
982 sc->stolen = (512 - 132) * 1024 / 4096;
983 sc->stolen_size = 512 * 1024;
984 break;
985 case AGP_I830_GCC1_GMS_STOLEN_1024:
986 sc->stolen = (1024 - 132) * 1024 / 4096;
987 sc->stolen_size = 1024 * 1024;
988 break;
989 case AGP_I830_GCC1_GMS_STOLEN_8192:
990 sc->stolen = (8192 - 132) * 1024 / 4096;
991 sc->stolen_size = 8192 * 1024;
992 break;
993 default:
994 sc->stolen = 0;
995 device_printf(dev,
996 "unknown memory configuration, disabling (GCC1 %x)\n",
997 gcc1);
998 return (EINVAL);
999 }
1000 return (0);
1001}
984263bc 1002
a904aa53
FT
1003static int
1004agp_i915_get_stolen_size(device_t dev)
1005{
1006 struct agp_i810_softc *sc;
1007 unsigned int gcc1, stolen, gtt_size;
984263bc 1008
a904aa53 1009 sc = device_get_softc(dev);
fdc3c5be 1010
a904aa53
FT
1011 /*
1012 * Stolen memory is set up at the beginning of the aperture by
1013 * the BIOS, consisting of the GATT followed by 4kb for the
1014 * BIOS display.
1015 */
1016 switch (sc->match->driver->chiptype) {
1017 case CHIP_I855:
1018 gtt_size = 128;
1019 break;
1020 case CHIP_I915:
1021 gtt_size = 256;
1022 break;
1023 case CHIP_I965:
1024 switch (bus_read_4(sc->sc_res[0], AGP_I810_PGTBL_CTL) &
1025 AGP_I810_PGTBL_SIZE_MASK) {
1026 case AGP_I810_PGTBL_SIZE_128KB:
fdc3c5be
HT
1027 gtt_size = 128;
1028 break;
a904aa53 1029 case AGP_I810_PGTBL_SIZE_256KB:
fdc3c5be
HT
1030 gtt_size = 256;
1031 break;
a904aa53
FT
1032 case AGP_I810_PGTBL_SIZE_512KB:
1033 gtt_size = 512;
f16c0bab 1034 break;
a904aa53
FT
1035 case AGP_I965_PGTBL_SIZE_1MB:
1036 gtt_size = 1024;
fdc3c5be 1037 break;
a904aa53
FT
1038 case AGP_I965_PGTBL_SIZE_2MB:
1039 gtt_size = 2048;
1040 break;
1041 case AGP_I965_PGTBL_SIZE_1_5MB:
1042 gtt_size = 1024 + 512;
f16c0bab 1043 break;
fdc3c5be 1044 default:
a904aa53
FT
1045 device_printf(dev, "Bad PGTBL size\n");
1046 return (EINVAL);
fdc3c5be 1047 }
a904aa53
FT
1048 break;
1049 case CHIP_G33:
1050 gcc1 = pci_read_config(sc->bdev, AGP_I855_GCC1, 2);
1051 switch (gcc1 & AGP_G33_MGGC_GGMS_MASK) {
1052 case AGP_G33_MGGC_GGMS_SIZE_1M:
1053 gtt_size = 1024;
f16c0bab 1054 break;
a904aa53
FT
1055 case AGP_G33_MGGC_GGMS_SIZE_2M:
1056 gtt_size = 2048;
ab5a0ec8
MD
1057 break;
1058 default:
a904aa53
FT
1059 device_printf(dev, "Bad PGTBL size\n");
1060 return (EINVAL);
ab5a0ec8 1061 }
a904aa53
FT
1062 break;
1063 case CHIP_IGD:
1064 case CHIP_G4X:
1065 gtt_size = 0;
1066 break;
1067 default:
1068 device_printf(dev, "Bad chiptype\n");
1069 return (EINVAL);
1070 }
f16c0bab 1071
a904aa53
FT
1072 /* GCC1 is called MGGC on i915+ */
1073 gcc1 = pci_read_config(sc->bdev, AGP_I855_GCC1, 1);
1074 switch (gcc1 & AGP_I855_GCC1_GMS) {
1075 case AGP_I855_GCC1_GMS_STOLEN_1M:
1076 stolen = 1024;
1077 break;
1078 case AGP_I855_GCC1_GMS_STOLEN_4M:
1079 stolen = 4 * 1024;
1080 break;
1081 case AGP_I855_GCC1_GMS_STOLEN_8M:
1082 stolen = 8 * 1024;
1083 break;
1084 case AGP_I855_GCC1_GMS_STOLEN_16M:
1085 stolen = 16 * 1024;
1086 break;
1087 case AGP_I855_GCC1_GMS_STOLEN_32M:
1088 stolen = 32 * 1024;
1089 break;
1090 case AGP_I915_GCC1_GMS_STOLEN_48M:
1091 stolen = sc->match->driver->gen > 2 ? 48 * 1024 : 0;
1092 break;
1093 case AGP_I915_GCC1_GMS_STOLEN_64M:
1094 stolen = sc->match->driver->gen > 2 ? 64 * 1024 : 0;
1095 break;
1096 case AGP_G33_GCC1_GMS_STOLEN_128M:
1097 stolen = sc->match->driver->gen > 2 ? 128 * 1024 : 0;
1098 break;
1099 case AGP_G33_GCC1_GMS_STOLEN_256M:
1100 stolen = sc->match->driver->gen > 2 ? 256 * 1024 : 0;
1101 break;
1102 case AGP_G4X_GCC1_GMS_STOLEN_96M:
1103 if (sc->match->driver->chiptype == CHIP_I965 ||
1104 sc->match->driver->chiptype == CHIP_G4X)
1105 stolen = 96 * 1024;
1106 else
1107 stolen = 0;
1108 break;
1109 case AGP_G4X_GCC1_GMS_STOLEN_160M:
1110 if (sc->match->driver->chiptype == CHIP_I965 ||
1111 sc->match->driver->chiptype == CHIP_G4X)
1112 stolen = 160 * 1024;
1113 else
1114 stolen = 0;
1115 break;
1116 case AGP_G4X_GCC1_GMS_STOLEN_224M:
1117 if (sc->match->driver->chiptype == CHIP_I965 ||
1118 sc->match->driver->chiptype == CHIP_G4X)
1119 stolen = 224 * 1024;
1120 else
1121 stolen = 0;
1122 break;
1123 case AGP_G4X_GCC1_GMS_STOLEN_352M:
1124 if (sc->match->driver->chiptype == CHIP_I965 ||
1125 sc->match->driver->chiptype == CHIP_G4X)
1126 stolen = 352 * 1024;
1127 else
1128 stolen = 0;
1129 break;
1130 default:
1131 device_printf(dev,
1132 "unknown memory configuration, disabling (GCC1 %x)\n",
1133 gcc1);
1134 return (EINVAL);
1135 }
f16c0bab 1136
a904aa53
FT
1137 gtt_size += 4;
1138 sc->stolen_size = stolen * 1024;
1139 sc->stolen = (stolen - gtt_size) * 1024 / 4096;
984263bc 1140
a904aa53
FT
1141 return (0);
1142}
ab5a0ec8 1143
a904aa53
FT
1144static int
1145agp_sb_get_stolen_size(device_t dev)
1146{
1147 struct agp_i810_softc *sc;
1148 uint16_t gmch_ctl;
1149
1150 sc = device_get_softc(dev);
1151 gmch_ctl = pci_read_config(sc->bdev, AGP_SNB_GCC1, 2);
1152 switch (gmch_ctl & AGP_SNB_GMCH_GMS_STOLEN_MASK) {
1153 case AGP_SNB_GMCH_GMS_STOLEN_32M:
1154 sc->stolen_size = 32 * 1024 * 1024;
1155 break;
1156 case AGP_SNB_GMCH_GMS_STOLEN_64M:
1157 sc->stolen_size = 64 * 1024 * 1024;
1158 break;
1159 case AGP_SNB_GMCH_GMS_STOLEN_96M:
1160 sc->stolen_size = 96 * 1024 * 1024;
1161 break;
1162 case AGP_SNB_GMCH_GMS_STOLEN_128M:
1163 sc->stolen_size = 128 * 1024 * 1024;
1164 break;
1165 case AGP_SNB_GMCH_GMS_STOLEN_160M:
1166 sc->stolen_size = 160 * 1024 * 1024;
1167 break;
1168 case AGP_SNB_GMCH_GMS_STOLEN_192M:
1169 sc->stolen_size = 192 * 1024 * 1024;
1170 break;
1171 case AGP_SNB_GMCH_GMS_STOLEN_224M:
1172 sc->stolen_size = 224 * 1024 * 1024;
1173 break;
1174 case AGP_SNB_GMCH_GMS_STOLEN_256M:
1175 sc->stolen_size = 256 * 1024 * 1024;
1176 break;
1177 case AGP_SNB_GMCH_GMS_STOLEN_288M:
1178 sc->stolen_size = 288 * 1024 * 1024;
1179 break;
1180 case AGP_SNB_GMCH_GMS_STOLEN_320M:
1181 sc->stolen_size = 320 * 1024 * 1024;
1182 break;
1183 case AGP_SNB_GMCH_GMS_STOLEN_352M:
1184 sc->stolen_size = 352 * 1024 * 1024;
1185 break;
1186 case AGP_SNB_GMCH_GMS_STOLEN_384M:
1187 sc->stolen_size = 384 * 1024 * 1024;
1188 break;
1189 case AGP_SNB_GMCH_GMS_STOLEN_416M:
1190 sc->stolen_size = 416 * 1024 * 1024;
1191 break;
1192 case AGP_SNB_GMCH_GMS_STOLEN_448M:
1193 sc->stolen_size = 448 * 1024 * 1024;
1194 break;
1195 case AGP_SNB_GMCH_GMS_STOLEN_480M:
1196 sc->stolen_size = 480 * 1024 * 1024;
1197 break;
1198 case AGP_SNB_GMCH_GMS_STOLEN_512M:
1199 sc->stolen_size = 512 * 1024 * 1024;
1200 break;
fdc3c5be 1201 }
a904aa53
FT
1202 sc->stolen = (sc->stolen_size - 4) / 4096;
1203 return (0);
1204}
1205
1206static int
1207agp_i810_get_gtt_mappable_entries(device_t dev)
1208{
1209 struct agp_i810_softc *sc;
1210 uint32_t ap;
1211 uint16_t miscc;
1212
1213 sc = device_get_softc(dev);
1214 miscc = pci_read_config(sc->bdev, AGP_I810_MISCC, 2);
1215 if ((miscc & AGP_I810_MISCC_WINSIZE) == AGP_I810_MISCC_WINSIZE_32)
1216 ap = 32;
1217 else
1218 ap = 64;
1219 sc->gtt_mappable_entries = (ap * 1024 * 1024) >> AGP_PAGE_SHIFT;
1220 return (0);
1221}
1222
1223static int
1224agp_i830_get_gtt_mappable_entries(device_t dev)
1225{
1226 struct agp_i810_softc *sc;
1227 uint32_t ap;
1228 uint16_t gmch_ctl;
1229
1230 sc = device_get_softc(dev);
1231 gmch_ctl = pci_read_config(sc->bdev, AGP_I830_GCC1, 2);
1232 if ((gmch_ctl & AGP_I830_GCC1_GMASIZE) == AGP_I830_GCC1_GMASIZE_64)
1233 ap = 64;
1234 else
1235 ap = 128;
1236 sc->gtt_mappable_entries = (ap * 1024 * 1024) >> AGP_PAGE_SHIFT;
1237 return (0);
1238}
1239
1240static int
1241agp_i915_get_gtt_mappable_entries(device_t dev)
1242{
1243 struct agp_i810_softc *sc;
1244 uint32_t ap;
1245
1246 sc = device_get_softc(dev);
1247 ap = AGP_GET_APERTURE(dev);
1248 sc->gtt_mappable_entries = ap >> AGP_PAGE_SHIFT;
1249 return (0);
1250}
1251
1252static int
1253agp_i810_get_gtt_total_entries(device_t dev)
1254{
1255 struct agp_i810_softc *sc;
1256
1257 sc = device_get_softc(dev);
1258 sc->gtt_total_entries = sc->gtt_mappable_entries;
1259 return (0);
1260}
fdc3c5be 1261
a904aa53
FT
1262static int
1263agp_i965_get_gtt_total_entries(device_t dev)
1264{
1265 struct agp_i810_softc *sc;
1266 uint32_t pgetbl_ctl;
1267 int error;
1268
1269 sc = device_get_softc(dev);
1270 error = 0;
1271 pgetbl_ctl = bus_read_4(sc->sc_res[0], AGP_I810_PGTBL_CTL);
1272 switch (pgetbl_ctl & AGP_I810_PGTBL_SIZE_MASK) {
1273 case AGP_I810_PGTBL_SIZE_128KB:
1274 sc->gtt_total_entries = 128 * 1024 / 4;
1275 break;
1276 case AGP_I810_PGTBL_SIZE_256KB:
1277 sc->gtt_total_entries = 256 * 1024 / 4;
1278 break;
1279 case AGP_I810_PGTBL_SIZE_512KB:
1280 sc->gtt_total_entries = 512 * 1024 / 4;
1281 break;
1282 /* GTT pagetable sizes bigger than 512KB are not possible on G33! */
1283 case AGP_I810_PGTBL_SIZE_1MB:
1284 sc->gtt_total_entries = 1024 * 1024 / 4;
1285 break;
1286 case AGP_I810_PGTBL_SIZE_2MB:
1287 sc->gtt_total_entries = 2 * 1024 * 1024 / 4;
1288 break;
1289 case AGP_I810_PGTBL_SIZE_1_5MB:
1290 sc->gtt_total_entries = (1024 + 512) * 1024 / 4;
1291 break;
1292 default:
1293 device_printf(dev, "Unknown page table size\n");
1294 error = ENXIO;
1295 }
1296 return (error);
1297}
1298
1299static void
1300agp_gen5_adjust_pgtbl_size(device_t dev, uint32_t sz)
1301{
1302 struct agp_i810_softc *sc;
1303 uint32_t pgetbl_ctl, pgetbl_ctl2;
1304
1305 sc = device_get_softc(dev);
1306
1307 /* Disable per-process page table. */
1308 pgetbl_ctl2 = bus_read_4(sc->sc_res[0], AGP_I965_PGTBL_CTL2);
1309 pgetbl_ctl2 &= ~AGP_I810_PGTBL_ENABLED;
1310 bus_write_4(sc->sc_res[0], AGP_I965_PGTBL_CTL2, pgetbl_ctl2);
1311
1312 /* Write the new ggtt size. */
1313 pgetbl_ctl = bus_read_4(sc->sc_res[0], AGP_I810_PGTBL_CTL);
1314 pgetbl_ctl &= ~AGP_I810_PGTBL_SIZE_MASK;
1315 pgetbl_ctl |= sz;
1316 bus_write_4(sc->sc_res[0], AGP_I810_PGTBL_CTL, pgetbl_ctl);
1317}
1318
1319static int
1320agp_gen5_get_gtt_total_entries(device_t dev)
1321{
1322 struct agp_i810_softc *sc;
1323 uint16_t gcc1;
1324
1325 sc = device_get_softc(dev);
1326
1327 gcc1 = pci_read_config(sc->bdev, AGP_I830_GCC1, 2);
1328 switch (gcc1 & AGP_G4x_GCC1_SIZE_MASK) {
1329 case AGP_G4x_GCC1_SIZE_1M:
1330 case AGP_G4x_GCC1_SIZE_VT_1M:
1331 agp_gen5_adjust_pgtbl_size(dev, AGP_I810_PGTBL_SIZE_1MB);
1332 break;
1333 case AGP_G4x_GCC1_SIZE_VT_1_5M:
1334 agp_gen5_adjust_pgtbl_size(dev, AGP_I810_PGTBL_SIZE_1_5MB);
1335 break;
1336 case AGP_G4x_GCC1_SIZE_2M:
1337 case AGP_G4x_GCC1_SIZE_VT_2M:
1338 agp_gen5_adjust_pgtbl_size(dev, AGP_I810_PGTBL_SIZE_2MB);
1339 break;
1340 default:
1341 device_printf(dev, "Unknown page table size\n");
1342 return (ENXIO);
1343 }
1344
1345 return (agp_i965_get_gtt_total_entries(dev));
1346}
1347
1348static int
1349agp_sb_get_gtt_total_entries(device_t dev)
1350{
1351 struct agp_i810_softc *sc;
1352 uint16_t gcc1;
1353
1354 sc = device_get_softc(dev);
1355
1356 gcc1 = pci_read_config(sc->bdev, AGP_SNB_GCC1, 2);
1357 switch (gcc1 & AGP_SNB_GTT_SIZE_MASK) {
1358 default:
1359 case AGP_SNB_GTT_SIZE_0M:
1360 kprintf("Bad GTT size mask: 0x%04x\n", gcc1);
1361 return (ENXIO);
1362 case AGP_SNB_GTT_SIZE_1M:
1363 sc->gtt_total_entries = 1024 * 1024 / 4;
1364 break;
1365 case AGP_SNB_GTT_SIZE_2M:
1366 sc->gtt_total_entries = 2 * 1024 * 1024 / 4;
1367 break;
1368 }
1369 return (0);
1370}
1371
1372static int
1373agp_i810_install_gatt(device_t dev)
1374{
1375 struct agp_i810_softc *sc;
1376
1377 sc = device_get_softc(dev);
1378
1379 /* Some i810s have on-chip memory called dcache. */
1380 if ((bus_read_1(sc->sc_res[0], AGP_I810_DRT) & AGP_I810_DRT_POPULATED)
1381 != 0)
1382 sc->dcache_size = 4 * 1024 * 1024;
1383 else
1384 sc->dcache_size = 0;
1385
1386 /* According to the specs the gatt on the i810 must be 64k. */
1387 sc->gatt->ag_virtual = contigmalloc(64 * 1024, M_AGP, 0, 0, ~0,
1388 PAGE_SIZE, 0);
1389 if (sc->gatt->ag_virtual == NULL) {
1390 if (bootverbose)
1391 device_printf(dev, "contiguous allocation failed\n");
1392 return (ENOMEM);
1393 }
1394
1395 bzero(sc->gatt->ag_virtual, sc->gatt->ag_entries * sizeof(u_int32_t));
1396 sc->gatt->ag_physical = vtophys((vm_offset_t)sc->gatt->ag_virtual);
1397 agp_flush_cache();
1398 /* Install the GATT. */
1399 bus_write_4(sc->sc_res[0], AGP_I810_PGTBL_CTL,
1400 sc->gatt->ag_physical | 1);
1401 return (0);
1402}
1403
1404static int
1405agp_i830_install_gatt(device_t dev)
1406{
1407 struct agp_i810_softc *sc;
1408 uint32_t pgtblctl;
1409
1410 sc = device_get_softc(dev);
1411
1412 /*
1413 * The i830 automatically initializes the 128k gatt on boot.
1414 * GATT address is already in there, make sure it's enabled.
1415 */
1416 pgtblctl = bus_read_4(sc->sc_res[0], AGP_I810_PGTBL_CTL);
1417 pgtblctl |= 1;
1418 bus_write_4(sc->sc_res[0], AGP_I810_PGTBL_CTL, pgtblctl);
1419
1420 sc->gatt->ag_physical = pgtblctl & ~1;
1421 return (0);
1422}
1423
1424static int
1425agp_i810_attach(device_t dev)
1426{
1427 struct agp_i810_softc *sc;
1428 int error;
1429
1430 sc = device_get_softc(dev);
1431 sc->bdev = agp_i810_find_bridge(dev);
1432 if (sc->bdev == NULL)
1433 return (ENOENT);
1434
1435 sc->match = agp_i810_match(dev);
1436
1437 agp_set_aperture_resource(dev, sc->match->driver->gen <= 2 ?
1438 AGP_APBASE : AGP_I915_GMADR);
1439 error = agp_generic_attach(dev);
1440 if (error)
1441 return (error);
1442
1443 if (ptoa((vm_paddr_t)Maxmem) >
1444 (1ULL << sc->match->driver->busdma_addr_mask_sz) - 1) {
1445 device_printf(dev, "agp_i810 does not support physical "
1446 "memory above %ju.\n", (uintmax_t)(1ULL <<
1447 sc->match->driver->busdma_addr_mask_sz) - 1);
1448 return (ENOENT);
1449 }
1450
1451 if (bus_alloc_resources(dev, sc->match->driver->res_spec, sc->sc_res)) {
1452 agp_generic_detach(dev);
1453 return (ENODEV);
1454 }
1455
1456 sc->initial_aperture = AGP_GET_APERTURE(dev);
1457 sc->gatt = kmalloc(sizeof(struct agp_gatt), M_AGP, M_WAITOK);
1458 sc->gatt->ag_entries = AGP_GET_APERTURE(dev) >> AGP_PAGE_SHIFT;
1459
1460 if ((error = sc->match->driver->get_stolen_size(dev)) != 0 ||
1461 (error = sc->match->driver->install_gatt(dev)) != 0 ||
1462 (error = sc->match->driver->get_gtt_mappable_entries(dev)) != 0 ||
1463 (error = sc->match->driver->get_gtt_total_entries(dev)) != 0 ||
1464 (error = sc->match->driver->chipset_flush_setup(dev)) != 0) {
1465 bus_release_resources(dev, sc->match->driver->res_spec,
1466 sc->sc_res);
1467 kfree(sc->gatt, M_AGP);
1468 agp_generic_detach(dev);
1469 return (error);
1470 }
1471
1472 intel_agp = dev;
7f9ec87c
FT
1473 device_printf(dev, "aperture size is %dM",
1474 sc->initial_aperture / 1024 / 1024);
1475 if (sc->stolen > 0)
1476 kprintf(", detected %dk stolen memory\n", sc->stolen * 4);
1477 else
1478 kprintf("\n");
a904aa53
FT
1479 if (bootverbose) {
1480 sc->match->driver->dump_regs(dev);
1481 device_printf(dev, "Mappable GTT entries: %d\n",
1482 sc->gtt_mappable_entries);
1483 device_printf(dev, "Total GTT entries: %d\n",
1484 sc->gtt_total_entries);
1485 }
1486 return (0);
1487}
7f9ec87c 1488
a904aa53
FT
1489static void
1490agp_i810_deinstall_gatt(device_t dev)
1491{
1492 struct agp_i810_softc *sc;
1493
1494 sc = device_get_softc(dev);
1495 bus_write_4(sc->sc_res[0], AGP_I810_PGTBL_CTL, 0);
1496 contigfree(sc->gatt->ag_virtual, 64 * 1024, M_AGP);
1497}
fdc3c5be 1498
a904aa53
FT
1499static void
1500agp_i830_deinstall_gatt(device_t dev)
1501{
1502 struct agp_i810_softc *sc;
1503 unsigned int pgtblctl;
1504
1505 sc = device_get_softc(dev);
1506 pgtblctl = bus_read_4(sc->sc_res[0], AGP_I810_PGTBL_CTL);
1507 pgtblctl &= ~1;
1508 bus_write_4(sc->sc_res[0], AGP_I810_PGTBL_CTL, pgtblctl);
984263bc
MD
1509}
1510
1511static int
1512agp_i810_detach(device_t dev)
1513{
a904aa53 1514 struct agp_i810_softc *sc;
984263bc 1515
a904aa53 1516 sc = device_get_softc(dev);
67e2dc5d 1517 agp_free_cdev(dev);
984263bc
MD
1518
1519 /* Clear the GATT base. */
a904aa53
FT
1520 sc->match->driver->deinstall_gatt(dev);
1521
1522 sc->match->driver->chipset_flush_teardown(dev);
984263bc
MD
1523
1524 /* Put the aperture back the way it started. */
1525 AGP_SET_APERTURE(dev, sc->initial_aperture);
1526
efda3bd0 1527 kfree(sc->gatt, M_AGP);
a904aa53 1528 bus_release_resources(dev, sc->match->driver->res_spec, sc->sc_res);
67e2dc5d 1529 agp_free_res(dev);
984263bc 1530
a904aa53 1531 return (0);
984263bc
MD
1532}
1533
2f1d30c1
HT
1534static int
1535agp_i810_resume(device_t dev)
1536{
1537 struct agp_i810_softc *sc;
1538 sc = device_get_softc(dev);
1539
1540 AGP_SET_APERTURE(dev, sc->initial_aperture);
1541
1542 /* Install the GATT. */
1543 bus_write_4(sc->sc_res[0], AGP_I810_PGTBL_CTL,
1544 sc->gatt->ag_physical | 1);
1545
1546 return (bus_generic_resume(dev));
1547}
1548
fdc3c5be
HT
1549/**
1550 * Sets the PCI resource size of the aperture on i830-class and below chipsets,
1551 * while returning failure on later chipsets when an actual change is
1552 * requested.
1553 *
1554 * This whole function is likely bogus, as the kernel would probably need to
1555 * reconfigure the placement of the AGP aperture if a larger size is requested,
1556 * which doesn't happen currently.
1557 */
984263bc
MD
1558static int
1559agp_i810_set_aperture(device_t dev, u_int32_t aperture)
1560{
a904aa53
FT
1561 struct agp_i810_softc *sc;
1562 u_int16_t miscc;
984263bc 1563
a904aa53
FT
1564 sc = device_get_softc(dev);
1565 /*
1566 * Double check for sanity.
1567 */
1568 if (aperture != 32 * 1024 * 1024 && aperture != 64 * 1024 * 1024) {
1569 device_printf(dev, "bad aperture size %d\n", aperture);
1570 return (EINVAL);
1571 }
fdc3c5be 1572
a904aa53
FT
1573 miscc = pci_read_config(sc->bdev, AGP_I810_MISCC, 2);
1574 miscc &= ~AGP_I810_MISCC_WINSIZE;
1575 if (aperture == 32 * 1024 * 1024)
1576 miscc |= AGP_I810_MISCC_WINSIZE_32;
1577 else
1578 miscc |= AGP_I810_MISCC_WINSIZE_64;
984263bc 1579
a904aa53
FT
1580 pci_write_config(sc->bdev, AGP_I810_MISCC, miscc, 2);
1581 return (0);
1582}
984263bc 1583
a904aa53
FT
1584static int
1585agp_i830_set_aperture(device_t dev, u_int32_t aperture)
1586{
1587 struct agp_i810_softc *sc;
1588 u_int16_t gcc1;
1589
1590 sc = device_get_softc(dev);
1591
1592 if (aperture != 64 * 1024 * 1024 &&
1593 aperture != 128 * 1024 * 1024) {
1594 device_printf(dev, "bad aperture size %d\n", aperture);
1595 return (EINVAL);
984263bc 1596 }
a904aa53
FT
1597 gcc1 = pci_read_config(sc->bdev, AGP_I830_GCC1, 2);
1598 gcc1 &= ~AGP_I830_GCC1_GMASIZE;
1599 if (aperture == 64 * 1024 * 1024)
1600 gcc1 |= AGP_I830_GCC1_GMASIZE_64;
1601 else
1602 gcc1 |= AGP_I830_GCC1_GMASIZE_128;
1603
1604 pci_write_config(sc->bdev, AGP_I830_GCC1, gcc1, 2);
1605 return (0);
1606}
1607
1608static int
1609agp_i915_set_aperture(device_t dev, u_int32_t aperture)
1610{
984263bc 1611
a904aa53
FT
1612 return (agp_generic_set_aperture(dev, aperture));
1613}
1614
1615static int
1616agp_i810_method_set_aperture(device_t dev, u_int32_t aperture)
1617{
1618 struct agp_i810_softc *sc;
1619
1620 sc = device_get_softc(dev);
1621 return (sc->match->driver->set_aperture(dev, aperture));
984263bc
MD
1622}
1623
fdc3c5be 1624/**
a904aa53
FT
1625 * Writes a GTT entry mapping the page at the given offset from the
1626 * beginning of the aperture to the given physical address. Setup the
1627 * caching mode according to flags.
1628 *
1629 * For gen 1, 2 and 3, GTT start is located at AGP_I810_GTT offset
1630 * from corresponding BAR start. For gen 4, offset is 512KB +
1631 * AGP_I810_GTT, for gen 5 and 6 it is 2MB + AGP_I810_GTT.
1632 *
1633 * Also, the bits of the physical page address above 4GB needs to be
1634 * placed into bits 40-32 of PTE.
fdc3c5be
HT
1635 */
1636static void
a904aa53
FT
1637agp_i810_install_gtt_pte(device_t dev, u_int index, vm_offset_t physical,
1638 int flags)
1639{
1640 uint32_t pte;
1641
1642 pte = (u_int32_t)physical | I810_PTE_VALID;
1643 if (flags == AGP_DCACHE_MEMORY)
1644 pte |= I810_PTE_LOCAL;
1645 else if (flags == AGP_USER_CACHED_MEMORY)
1646 pte |= I830_PTE_SYSTEM_CACHED;
1647 agp_i810_write_gtt(dev, index, pte);
1648}
1649
1650static void
1651agp_i810_write_gtt(device_t dev, u_int index, uint32_t pte)
1652{
1653 struct agp_i810_softc *sc;
1654
1655 sc = device_get_softc(dev);
1656 bus_write_4(sc->sc_res[0], AGP_I810_GTT + index * 4, pte);
1657}
1658
1659static void
1660agp_i830_install_gtt_pte(device_t dev, u_int index, vm_offset_t physical,
1661 int flags)
1662{
1663 uint32_t pte;
1664
1665 pte = (u_int32_t)physical | I810_PTE_VALID;
1666 if (flags == AGP_USER_CACHED_MEMORY)
1667 pte |= I830_PTE_SYSTEM_CACHED;
1668 agp_i810_write_gtt(dev, index, pte);
1669}
1670
1671static void
1672agp_i915_install_gtt_pte(device_t dev, u_int index, vm_offset_t physical,
1673 int flags)
1674{
1675 uint32_t pte;
1676
1677 pte = (u_int32_t)physical | I810_PTE_VALID;
1678 if (flags == AGP_USER_CACHED_MEMORY)
1679 pte |= I830_PTE_SYSTEM_CACHED;
1680 pte |= (physical & 0x0000000f00000000ull) >> 28;
1681 agp_i915_write_gtt(dev, index, pte);
1682}
1683
1684static void
1685agp_i915_write_gtt(device_t dev, u_int index, uint32_t pte)
1686{
1687 struct agp_i810_softc *sc;
1688
1689 sc = device_get_softc(dev);
1690 bus_write_4(sc->sc_res[1], index * 4, pte);
1691}
1692
1693static void
1694agp_i965_install_gtt_pte(device_t dev, u_int index, vm_offset_t physical,
1695 int flags)
1696{
1697 uint32_t pte;
1698
1699 pte = (u_int32_t)physical | I810_PTE_VALID;
1700 if (flags == AGP_USER_CACHED_MEMORY)
1701 pte |= I830_PTE_SYSTEM_CACHED;
1702 pte |= (physical & 0x0000000f00000000ull) >> 28;
1703 agp_i965_write_gtt(dev, index, pte);
1704}
1705
1706static void
1707agp_i965_write_gtt(device_t dev, u_int index, uint32_t pte)
1708{
1709 struct agp_i810_softc *sc;
1710
1711 sc = device_get_softc(dev);
1712 bus_write_4(sc->sc_res[0], index * 4 + (512 * 1024), pte);
1713}
1714
1715static void
1716agp_g4x_install_gtt_pte(device_t dev, u_int index, vm_offset_t physical,
1717 int flags)
1718{
1719 uint32_t pte;
1720
1721 pte = (u_int32_t)physical | I810_PTE_VALID;
1722 if (flags == AGP_USER_CACHED_MEMORY)
1723 pte |= I830_PTE_SYSTEM_CACHED;
1724 pte |= (physical & 0x0000000f00000000ull) >> 28;
1725 agp_g4x_write_gtt(dev, index, pte);
1726}
1727
1728static void
1729agp_g4x_write_gtt(device_t dev, u_int index, uint32_t pte)
1730{
1731 struct agp_i810_softc *sc;
1732
1733 sc = device_get_softc(dev);
1734 bus_write_4(sc->sc_res[0], index * 4 + (2 * 1024 * 1024), pte);
1735}
1736
1737static void
1738agp_sb_install_gtt_pte(device_t dev, u_int index, vm_offset_t physical,
1739 int flags)
1740{
1741 int type_mask, gfdt;
1742 uint32_t pte;
1743
1744 pte = (u_int32_t)physical | I810_PTE_VALID;
1745 type_mask = flags & ~AGP_USER_CACHED_MEMORY_GFDT;
1746 gfdt = (flags & AGP_USER_CACHED_MEMORY_GFDT) != 0 ? GEN6_PTE_GFDT : 0;
1747
1748 if (type_mask == AGP_USER_MEMORY)
1749 pte |= GEN6_PTE_UNCACHED;
1750 else if (type_mask == AGP_USER_CACHED_MEMORY_LLC_MLC)
1751 pte |= GEN6_PTE_LLC_MLC | gfdt;
1752 else
1753 pte |= GEN6_PTE_LLC | gfdt;
1754
1755 pte |= (physical & 0x000000ff00000000ull) >> 28;
1756 agp_sb_write_gtt(dev, index, pte);
1757}
1758
1759static void
1760agp_sb_write_gtt(device_t dev, u_int index, uint32_t pte)
1761{
1762 struct agp_i810_softc *sc;
1763
1764 sc = device_get_softc(dev);
1765 bus_write_4(sc->sc_res[0], index * 4 + (2 * 1024 * 1024), pte);
1766}
1767
1768static int
1769agp_i810_bind_page(device_t dev, vm_offset_t offset, vm_offset_t physical)
fdc3c5be
HT
1770{
1771 struct agp_i810_softc *sc = device_get_softc(dev);
a904aa53 1772 u_int index;
fdc3c5be 1773
a904aa53
FT
1774 if (offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT)) {
1775 device_printf(dev, "failed: offset is 0x%08jx, "
1776 "shift is %d, entries is %d\n", (intmax_t)offset,
1777 AGP_PAGE_SHIFT, sc->gatt->ag_entries);
1778 return (EINVAL);
1779 }
1780 index = offset >> AGP_PAGE_SHIFT;
1781 if (sc->stolen != 0 && index < sc->stolen) {
1782 device_printf(dev, "trying to bind into stolen memory\n");
1783 return (EINVAL);
fdc3c5be 1784 }
a904aa53
FT
1785 sc->match->driver->install_gtt_pte(dev, index, physical, 0);
1786 return (0);
1787}
fdc3c5be 1788
a904aa53
FT
1789static int
1790agp_i810_unbind_page(device_t dev, vm_offset_t offset)
1791{
1792 struct agp_i810_softc *sc;
1793 u_int index;
1794
1795 sc = device_get_softc(dev);
1796 if (offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT))
1797 return (EINVAL);
1798 index = offset >> AGP_PAGE_SHIFT;
1799 if (sc->stolen != 0 && index < sc->stolen) {
1800 device_printf(dev, "trying to unbind from stolen memory\n");
1801 return (EINVAL);
fdc3c5be 1802 }
a904aa53
FT
1803 sc->match->driver->install_gtt_pte(dev, index, 0, 0);
1804 return (0);
1805}
1806
1807static u_int32_t
1808agp_i810_read_gtt_pte(device_t dev, u_int index)
1809{
1810 struct agp_i810_softc *sc;
1811 u_int32_t pte;
1812
1813 sc = device_get_softc(dev);
1814 pte = bus_read_4(sc->sc_res[0], AGP_I810_GTT + index * 4);
1815 return (pte);
fdc3c5be
HT
1816}
1817
a904aa53
FT
1818static u_int32_t
1819agp_i915_read_gtt_pte(device_t dev, u_int index)
984263bc 1820{
a904aa53
FT
1821 struct agp_i810_softc *sc;
1822 u_int32_t pte;
984263bc 1823
a904aa53
FT
1824 sc = device_get_softc(dev);
1825 pte = bus_read_4(sc->sc_res[1], index * 4);
1826 return (pte);
1827}
984263bc 1828
a904aa53
FT
1829static u_int32_t
1830agp_i965_read_gtt_pte(device_t dev, u_int index)
1831{
1832 struct agp_i810_softc *sc;
1833 u_int32_t pte;
1834
1835 sc = device_get_softc(dev);
1836 pte = bus_read_4(sc->sc_res[0], index * 4 + (512 * 1024));
1837 return (pte);
1838}
984263bc 1839
a904aa53
FT
1840static u_int32_t
1841agp_g4x_read_gtt_pte(device_t dev, u_int index)
1842{
1843 struct agp_i810_softc *sc;
1844 u_int32_t pte;
fdc3c5be 1845
a904aa53
FT
1846 sc = device_get_softc(dev);
1847 pte = bus_read_4(sc->sc_res[0], index * 4 + (2 * 1024 * 1024));
1848 return (pte);
984263bc
MD
1849}
1850
a904aa53
FT
1851static vm_paddr_t
1852agp_i810_read_gtt_pte_paddr(device_t dev, u_int index)
984263bc 1853{
a904aa53
FT
1854 struct agp_i810_softc *sc;
1855 u_int32_t pte;
1856 vm_paddr_t res;
984263bc 1857
a904aa53
FT
1858 sc = device_get_softc(dev);
1859 pte = sc->match->driver->read_gtt_pte(dev, index);
1860 res = pte & ~PAGE_MASK;
1861 return (res);
1862}
984263bc 1863
a904aa53
FT
1864static vm_paddr_t
1865agp_i915_read_gtt_pte_paddr(device_t dev, u_int index)
1866{
1867 struct agp_i810_softc *sc;
1868 u_int32_t pte;
1869 vm_paddr_t res;
984263bc 1870
a904aa53
FT
1871 sc = device_get_softc(dev);
1872 pte = sc->match->driver->read_gtt_pte(dev, index);
1873 res = (pte & ~PAGE_MASK) | ((pte & 0xf0) << 28);
1874 return (res);
1875}
1876
1877static vm_paddr_t
1878agp_sb_read_gtt_pte_paddr(device_t dev, u_int index)
1879{
1880 struct agp_i810_softc *sc;
1881 u_int32_t pte;
1882 vm_paddr_t res;
fdc3c5be 1883
a904aa53
FT
1884 sc = device_get_softc(dev);
1885 pte = sc->match->driver->read_gtt_pte(dev, index);
1886 res = (pte & ~PAGE_MASK) | ((pte & 0xff0) << 28);
1887 return (res);
984263bc
MD
1888}
1889
1890/*
1891 * Writing via memory mapped registers already flushes all TLBs.
1892 */
1893static void
1894agp_i810_flush_tlb(device_t dev)
1895{
1896}
1897
1898static int
1899agp_i810_enable(device_t dev, u_int32_t mode)
1900{
1901
a904aa53 1902 return (0);
984263bc
MD
1903}
1904
1905static struct agp_memory *
1906agp_i810_alloc_memory(device_t dev, int type, vm_size_t size)
1907{
a904aa53 1908 struct agp_i810_softc *sc;
984263bc 1909 struct agp_memory *mem;
a904aa53 1910 vm_page_t m;
984263bc 1911
a904aa53 1912 sc = device_get_softc(dev);
984263bc 1913
a904aa53
FT
1914 if ((size & (AGP_PAGE_SIZE - 1)) != 0 ||
1915 sc->agp.as_allocated + size > sc->agp.as_maxmem)
1916 return (0);
984263bc
MD
1917
1918 if (type == 1) {
1919 /*
1920 * Mapping local DRAM into GATT.
1921 */
a904aa53
FT
1922 if (sc->match->driver->chiptype != CHIP_I810)
1923 return (0);
984263bc 1924 if (size != sc->dcache_size)
a904aa53 1925 return (0);
984263bc
MD
1926 } else if (type == 2) {
1927 /*
fdc3c5be
HT
1928 * Type 2 is the contiguous physical memory type, that hands
1929 * back a physical address. This is used for cursors on i810.
1930 * Hand back as many single pages with physical as the user
1931 * wants, but only allow one larger allocation (ARGB cursor)
1932 * for simplicity.
984263bc 1933 */
fdc3c5be
HT
1934 if (size != AGP_PAGE_SIZE) {
1935 if (sc->argb_cursor != NULL)
a904aa53 1936 return (0);
fdc3c5be
HT
1937
1938 /* Allocate memory for ARGB cursor, if we can. */
1939 sc->argb_cursor = contigmalloc(size, M_AGP,
1940 0, 0, ~0, PAGE_SIZE, 0);
1941 if (sc->argb_cursor == NULL)
a904aa53 1942 return (0);
fdc3c5be 1943 }
984263bc
MD
1944 }
1945
efda3bd0 1946 mem = kmalloc(sizeof *mem, M_AGP, M_INTWAIT);
984263bc
MD
1947 mem->am_id = sc->agp.as_nextid++;
1948 mem->am_size = size;
1949 mem->am_type = type;
fdc3c5be 1950 if (type != 1 && (type != 2 || size == AGP_PAGE_SIZE))
984263bc 1951 mem->am_obj = vm_object_allocate(OBJT_DEFAULT,
a904aa53 1952 atop(round_page(size)));
984263bc
MD
1953 else
1954 mem->am_obj = 0;
1955
1956 if (type == 2) {
fdc3c5be
HT
1957 if (size == AGP_PAGE_SIZE) {
1958 /*
1959 * Allocate and wire down the page now so that we can
1960 * get its physical address.
1961 */
a904aa53 1962 VM_OBJECT_LOCK(mem->am_obj);
d2d8515b
MD
1963 m = vm_page_grab(mem->am_obj, 0, VM_ALLOC_NORMAL |
1964 VM_ALLOC_ZERO |
1965 VM_ALLOC_RETRY);
fdc3c5be 1966 vm_page_wire(m);
a904aa53 1967 VM_OBJECT_UNLOCK(mem->am_obj);
fdc3c5be
HT
1968 mem->am_physical = VM_PAGE_TO_PHYS(m);
1969 vm_page_wakeup(m);
1970 } else {
1971 /* Our allocation is already nicely wired down for us.
1972 * Just grab the physical address.
1973 */
1974 mem->am_physical = vtophys(sc->argb_cursor);
1975 }
a904aa53 1976 } else
984263bc 1977 mem->am_physical = 0;
984263bc
MD
1978
1979 mem->am_offset = 0;
1980 mem->am_is_bound = 0;
1981 TAILQ_INSERT_TAIL(&sc->agp.as_memory, mem, am_link);
1982 sc->agp.as_allocated += size;
1983
a904aa53 1984 return (mem);
984263bc
MD
1985}
1986
1987static int
1988agp_i810_free_memory(device_t dev, struct agp_memory *mem)
1989{
a904aa53 1990 struct agp_i810_softc *sc;
984263bc
MD
1991
1992 if (mem->am_is_bound)
a904aa53
FT
1993 return (EBUSY);
1994
1995 sc = device_get_softc(dev);
984263bc
MD
1996
1997 if (mem->am_type == 2) {
fdc3c5be
HT
1998 if (mem->am_size == AGP_PAGE_SIZE) {
1999 /*
2000 * Unwire the page which we wired in alloc_memory.
2001 */
77912481 2002 vm_page_t m;
b12defdc
MD
2003
2004 vm_object_hold(mem->am_obj);
2005 m = vm_page_lookup_busy_wait(mem->am_obj, 0,
2006 FALSE, "agppg");
2007 vm_object_drop(mem->am_obj);
fdc3c5be 2008 vm_page_unwire(m, 0);
b12defdc 2009 vm_page_wakeup(m);
fdc3c5be
HT
2010 } else {
2011 contigfree(sc->argb_cursor, mem->am_size, M_AGP);
2012 sc->argb_cursor = NULL;
2013 }
984263bc
MD
2014 }
2015
2016 sc->agp.as_allocated -= mem->am_size;
2017 TAILQ_REMOVE(&sc->agp.as_memory, mem, am_link);
2018 if (mem->am_obj)
2019 vm_object_deallocate(mem->am_obj);
efda3bd0 2020 kfree(mem, M_AGP);
a904aa53 2021 return (0);
984263bc
MD
2022}
2023
2024static int
a904aa53 2025agp_i810_bind_memory(device_t dev, struct agp_memory *mem, vm_offset_t offset)
984263bc 2026{
a904aa53 2027 struct agp_i810_softc *sc;
984263bc
MD
2028 vm_offset_t i;
2029
fdc3c5be 2030 /* Do some sanity checks first. */
7f9ec87c 2031 if ((offset & (AGP_PAGE_SIZE - 1)) != 0 ||
fdc3c5be
HT
2032 offset + mem->am_size > AGP_GET_APERTURE(dev)) {
2033 device_printf(dev, "binding memory at bad offset %#x\n",
2034 (int)offset);
a904aa53 2035 return (EINVAL);
fdc3c5be
HT
2036 }
2037
a904aa53 2038 sc = device_get_softc(dev);
fdc3c5be
HT
2039 if (mem->am_type == 2 && mem->am_size != AGP_PAGE_SIZE) {
2040 lockmgr(&sc->agp.as_lock, LK_EXCLUSIVE);
2041 if (mem->am_is_bound) {
2042 lockmgr(&sc->agp.as_lock, LK_RELEASE);
2043 return EINVAL;
2044 }
2045 /* The memory's already wired down, just stick it in the GTT. */
2046 for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) {
a904aa53
FT
2047 sc->match->driver->install_gtt_pte(dev, (offset + i) >>
2048 AGP_PAGE_SHIFT, mem->am_physical + i, 0);
fdc3c5be
HT
2049 }
2050 agp_flush_cache();
2051 mem->am_offset = offset;
2052 mem->am_is_bound = 1;
2053 lockmgr(&sc->agp.as_lock, LK_RELEASE);
a904aa53 2054 return (0);
fdc3c5be
HT
2055 }
2056
984263bc 2057 if (mem->am_type != 1)
a904aa53 2058 return (agp_generic_bind_memory(dev, mem, offset));
984263bc 2059
a904aa53
FT
2060 /*
2061 * Mapping local DRAM into GATT.
2062 */
2063 if (sc->match->driver->chiptype != CHIP_I810)
2064 return (EINVAL);
2065 for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE)
fdc3c5be
HT
2066 bus_write_4(sc->sc_res[0],
2067 AGP_I810_GTT + (i >> AGP_PAGE_SHIFT) * 4, i | 3);
984263bc 2068
a904aa53 2069 return (0);
984263bc
MD
2070}
2071
2072static int
2073agp_i810_unbind_memory(device_t dev, struct agp_memory *mem)
2074{
a904aa53 2075 struct agp_i810_softc *sc;
984263bc
MD
2076 vm_offset_t i;
2077
a904aa53
FT
2078 sc = device_get_softc(dev);
2079
fdc3c5be
HT
2080 if (mem->am_type == 2 && mem->am_size != AGP_PAGE_SIZE) {
2081 lockmgr(&sc->agp.as_lock, LK_EXCLUSIVE);
2082 if (!mem->am_is_bound) {
2083 lockmgr(&sc->agp.as_lock, LK_RELEASE);
a904aa53 2084 return (EINVAL);
fdc3c5be
HT
2085 }
2086
2087 for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) {
a904aa53
FT
2088 sc->match->driver->install_gtt_pte(dev,
2089 (mem->am_offset + i) >> AGP_PAGE_SHIFT, 0, 0);
fdc3c5be
HT
2090 }
2091 agp_flush_cache();
2092 mem->am_is_bound = 0;
2093 lockmgr(&sc->agp.as_lock, LK_RELEASE);
a904aa53 2094 return (0);
fdc3c5be
HT
2095 }
2096
984263bc 2097 if (mem->am_type != 1)
a904aa53 2098 return (agp_generic_unbind_memory(dev, mem));
984263bc 2099
a904aa53
FT
2100 if (sc->match->driver->chiptype != CHIP_I810)
2101 return (EINVAL);
fdc3c5be 2102 for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) {
a904aa53
FT
2103 sc->match->driver->install_gtt_pte(dev, i >> AGP_PAGE_SHIFT,
2104 0, 0);
fdc3c5be 2105 }
a904aa53 2106 return (0);
984263bc
MD
2107}
2108
2109static device_method_t agp_i810_methods[] = {
2110 /* Device interface */
fdc3c5be 2111 DEVMETHOD(device_identify, agp_i810_identify),
984263bc
MD
2112 DEVMETHOD(device_probe, agp_i810_probe),
2113 DEVMETHOD(device_attach, agp_i810_attach),
2114 DEVMETHOD(device_detach, agp_i810_detach),
2f1d30c1
HT
2115 DEVMETHOD(device_suspend, bus_generic_suspend),
2116 DEVMETHOD(device_resume, agp_i810_resume),
984263bc
MD
2117
2118 /* AGP interface */
fdc3c5be 2119 DEVMETHOD(agp_get_aperture, agp_generic_get_aperture),
a904aa53 2120 DEVMETHOD(agp_set_aperture, agp_i810_method_set_aperture),
984263bc
MD
2121 DEVMETHOD(agp_bind_page, agp_i810_bind_page),
2122 DEVMETHOD(agp_unbind_page, agp_i810_unbind_page),
2123 DEVMETHOD(agp_flush_tlb, agp_i810_flush_tlb),
2124 DEVMETHOD(agp_enable, agp_i810_enable),
2125 DEVMETHOD(agp_alloc_memory, agp_i810_alloc_memory),
2126 DEVMETHOD(agp_free_memory, agp_i810_free_memory),
2127 DEVMETHOD(agp_bind_memory, agp_i810_bind_memory),
2128 DEVMETHOD(agp_unbind_memory, agp_i810_unbind_memory),
a904aa53 2129 DEVMETHOD(agp_chipset_flush, agp_intel_gtt_chipset_flush),
984263bc 2130
d3c9c58e 2131 DEVMETHOD_END
984263bc
MD
2132};
2133
2134static driver_t agp_i810_driver = {
2135 "agp",
2136 agp_i810_methods,
2137 sizeof(struct agp_i810_softc),
2138};
2139
2140static devclass_t agp_devclass;
2141
aa2b9d05 2142DRIVER_MODULE(agp_i810, vgapci, agp_i810_driver, agp_devclass, NULL, NULL);
f7841f3c
MD
2143MODULE_DEPEND(agp_i810, agp, 1, 1, 1);
2144MODULE_DEPEND(agp_i810, pci, 1, 1, 1);
a904aa53
FT
2145
2146extern vm_page_t bogus_page;
2147
2148void
2149agp_intel_gtt_clear_range(device_t dev, u_int first_entry, u_int num_entries)
2150{
2151 struct agp_i810_softc *sc;
2152 u_int i;
2153
2154 sc = device_get_softc(dev);
2155 for (i = 0; i < num_entries; i++)
2156 sc->match->driver->install_gtt_pte(dev, first_entry + i,
2157 VM_PAGE_TO_PHYS(bogus_page), 0);
2158 sc->match->driver->read_gtt_pte(dev, first_entry + num_entries - 1);
2159}
2160
2161void
2162agp_intel_gtt_insert_pages(device_t dev, u_int first_entry, u_int num_entries,
2163 vm_page_t *pages, u_int flags)
2164{
2165 struct agp_i810_softc *sc;
2166 u_int i;
2167
2168 sc = device_get_softc(dev);
2169 for (i = 0; i < num_entries; i++) {
2170 KKASSERT(pages[i]->valid == VM_PAGE_BITS_ALL);
2171 KKASSERT(pages[i]->wire_count > 0);
2172 sc->match->driver->install_gtt_pte(dev, first_entry + i,
2173 VM_PAGE_TO_PHYS(pages[i]), flags);
2174 }
2175 sc->match->driver->read_gtt_pte(dev, first_entry + num_entries - 1);
2176}
2177
2178struct intel_gtt
2179agp_intel_gtt_get(device_t dev)
2180{
2181 struct agp_i810_softc *sc;
2182 struct intel_gtt res;
2183
2184 sc = device_get_softc(dev);
2185 res.stolen_size = sc->stolen_size;
2186 res.gtt_total_entries = sc->gtt_total_entries;
2187 res.gtt_mappable_entries = sc->gtt_mappable_entries;
2188 res.do_idle_maps = 0;
2189 res.scratch_page_dma = VM_PAGE_TO_PHYS(bogus_page);
2190 return (res);
2191}
2192
2193static int
2194agp_i810_chipset_flush_setup(device_t dev)
2195{
2196
2197 return (0);
2198}
2199
2200static void
2201agp_i810_chipset_flush_teardown(device_t dev)
2202{
2203
2204 /* Nothing to do. */
2205}
2206
2207static void
2208agp_i810_chipset_flush(device_t dev)
2209{
2210
2211 /* Nothing to do. */
2212}
2213
2214static void
2215agp_i830_chipset_flush(device_t dev)
2216{
2217 struct agp_i810_softc *sc;
2218 uint32_t hic;
2219 int i;
2220
2221 sc = device_get_softc(dev);
2222 cpu_wbinvd_on_all_cpus();
2223 hic = bus_read_4(sc->sc_res[0], AGP_I830_HIC);
2224 bus_write_4(sc->sc_res[0], AGP_I830_HIC, hic | (1 << 31));
2225 for (i = 0; i < 20000 /* 1 sec */; i++) {
2226 hic = bus_read_4(sc->sc_res[0], AGP_I830_HIC);
2227 if ((hic & (1 << 31)) != 0)
2228 break;
2229 DELAY(50);
2230 }
2231}
2232
2233static int
2234agp_i915_chipset_flush_alloc_page(device_t dev, uint64_t start, uint64_t end)
2235{
2236 struct agp_i810_softc *sc;
2237 device_t vga;
2238
2239 sc = device_get_softc(dev);
2240 vga = device_get_parent(dev);
2241 sc->sc_flush_page_rid = 100;
2242 sc->sc_flush_page_res = BUS_ALLOC_RESOURCE(device_get_parent(vga), dev,
2243 SYS_RES_MEMORY, &sc->sc_flush_page_rid, start, end, PAGE_SIZE,
2244 RF_ACTIVE, -1);
2245 if (sc->sc_flush_page_res == NULL) {
2246 device_printf(dev, "Failed to allocate flush page at 0x%jx\n",
2247 (uintmax_t)start);
2248 return (EINVAL);
2249 }
2250 sc->sc_flush_page_vaddr = rman_get_virtual(sc->sc_flush_page_res);
2251 if (bootverbose) {
2252 device_printf(dev, "Allocated flush page phys 0x%jx virt %p\n",
2253 (uintmax_t)rman_get_start(sc->sc_flush_page_res),
2254 sc->sc_flush_page_vaddr);
2255 }
2256 return (0);
2257}
2258
2259static void
2260agp_i915_chipset_flush_free_page(device_t dev)
2261{
2262 struct agp_i810_softc *sc;
2263 device_t vga;
2264
2265 sc = device_get_softc(dev);
2266 vga = device_get_parent(dev);
2267 if (sc->sc_flush_page_res == NULL)
2268 return;
2269 BUS_DEACTIVATE_RESOURCE(device_get_parent(vga), dev, SYS_RES_MEMORY,
2270 sc->sc_flush_page_rid, sc->sc_flush_page_res);
2271 BUS_RELEASE_RESOURCE(device_get_parent(vga), dev, SYS_RES_MEMORY,
2272 sc->sc_flush_page_rid, sc->sc_flush_page_res);
2273}
2274
2275static int
2276agp_i915_chipset_flush_setup(device_t dev)
2277{
2278 struct agp_i810_softc *sc;
2279 uint32_t temp;
2280 int error;
2281
2282 sc = device_get_softc(dev);
2283 temp = pci_read_config(sc->bdev, AGP_I915_IFPADDR, 4);
2284 if ((temp & 1) != 0) {
2285 temp &= ~1;
2286 if (bootverbose)
2287 device_printf(dev,
2288 "Found already configured flush page at 0x%jx\n",
2289 (uintmax_t)temp);
2290 sc->sc_bios_allocated_flush_page = 1;
2291 /*
2292 * In the case BIOS initialized the flush pointer (?)
2293 * register, expect that BIOS also set up the resource
2294 * for the page.
2295 */
2296 error = agp_i915_chipset_flush_alloc_page(dev, temp,
2297 temp + PAGE_SIZE - 1);
2298 if (error != 0)
2299 return (error);
2300 } else {
2301 sc->sc_bios_allocated_flush_page = 0;
2302 error = agp_i915_chipset_flush_alloc_page(dev, 0, 0xffffffff);
2303 if (error != 0)
2304 return (error);
2305 temp = rman_get_start(sc->sc_flush_page_res);
2306 pci_write_config(sc->bdev, AGP_I915_IFPADDR, temp | 1, 4);
2307 }
2308 return (0);
2309}
2310
2311static void
2312agp_i915_chipset_flush_teardown(device_t dev)
2313{
2314 struct agp_i810_softc *sc;
2315 uint32_t temp;
2316
2317 sc = device_get_softc(dev);
2318 if (sc->sc_flush_page_res == NULL)
2319 return;
2320 if (!sc->sc_bios_allocated_flush_page) {
2321 temp = pci_read_config(sc->bdev, AGP_I915_IFPADDR, 4);
2322 temp &= ~1;
2323 pci_write_config(sc->bdev, AGP_I915_IFPADDR, temp, 4);
2324 }
2325 agp_i915_chipset_flush_free_page(dev);
2326}
2327
2328static int
2329agp_i965_chipset_flush_setup(device_t dev)
2330{
2331 struct agp_i810_softc *sc;
2332 uint64_t temp;
2333 uint32_t temp_hi, temp_lo;
2334 int error;
2335
2336 sc = device_get_softc(dev);
2337
2338 temp_hi = pci_read_config(sc->bdev, AGP_I965_IFPADDR + 4, 4);
2339 temp_lo = pci_read_config(sc->bdev, AGP_I965_IFPADDR, 4);
2340
2341 if ((temp_lo & 1) != 0) {
2342 temp = ((uint64_t)temp_hi << 32) | (temp_lo & ~1);
2343 if (bootverbose)
2344 device_printf(dev,
2345 "Found already configured flush page at 0x%jx\n",
2346 (uintmax_t)temp);
2347 sc->sc_bios_allocated_flush_page = 1;
2348 /*
2349 * In the case BIOS initialized the flush pointer (?)
2350 * register, expect that BIOS also set up the resource
2351 * for the page.
2352 */
2353 error = agp_i915_chipset_flush_alloc_page(dev, temp,
2354 temp + PAGE_SIZE - 1);
2355 if (error != 0)
2356 return (error);
2357 } else {
2358 sc->sc_bios_allocated_flush_page = 0;
2359 error = agp_i915_chipset_flush_alloc_page(dev, 0, ~0);
2360 if (error != 0)
2361 return (error);
2362 temp = rman_get_start(sc->sc_flush_page_res);
2363 pci_write_config(sc->bdev, AGP_I965_IFPADDR + 4,
2364 (temp >> 32) & UINT32_MAX, 4);
2365 pci_write_config(sc->bdev, AGP_I965_IFPADDR,
2366 (temp & UINT32_MAX) | 1, 4);
2367 }
2368 return (0);
2369}
2370
2371static void
2372agp_i965_chipset_flush_teardown(device_t dev)
2373{
2374 struct agp_i810_softc *sc;
2375 uint32_t temp_lo;
2376
2377 sc = device_get_softc(dev);
2378 if (sc->sc_flush_page_res == NULL)
2379 return;
2380 if (!sc->sc_bios_allocated_flush_page) {
2381 temp_lo = pci_read_config(sc->bdev, AGP_I965_IFPADDR, 4);
2382 temp_lo &= ~1;
2383 pci_write_config(sc->bdev, AGP_I965_IFPADDR, temp_lo, 4);
2384 }
2385 agp_i915_chipset_flush_free_page(dev);
2386}
2387
2388static void
2389agp_i915_chipset_flush(device_t dev)
2390{
2391 struct agp_i810_softc *sc;
2392
2393 sc = device_get_softc(dev);
2394 *(uint32_t *)sc->sc_flush_page_vaddr = 1;
2395}
2396
2397int
2398agp_intel_gtt_chipset_flush(device_t dev)
2399{
2400 struct agp_i810_softc *sc;
2401
2402 sc = device_get_softc(dev);
2403 sc->match->driver->chipset_flush(dev);
2404 return (0);
2405}
2406
2407void
2408agp_intel_gtt_unmap_memory(device_t dev, struct sglist *sg_list)
2409{
2410}
2411
2412int
2413agp_intel_gtt_map_memory(device_t dev, vm_page_t *pages, u_int num_entries,
2414 struct sglist **sg_list)
2415{
839fbabb 2416#if 0
a904aa53 2417 struct agp_i810_softc *sc;
839fbabb 2418#endif
a904aa53
FT
2419 struct sglist *sg;
2420 int i;
2421#if 0
2422 int error;
2423 bus_dma_tag_t dmat;
2424#endif
2425
2426 if (*sg_list != NULL)
2427 return (0);
839fbabb 2428#if 0
a904aa53 2429 sc = device_get_softc(dev);
839fbabb 2430#endif
a904aa53
FT
2431 sg = sglist_alloc(num_entries, M_WAITOK /* XXXKIB */);
2432 for (i = 0; i < num_entries; i++) {
2433 sg->sg_segs[i].ss_paddr = VM_PAGE_TO_PHYS(pages[i]);
2434 sg->sg_segs[i].ss_len = PAGE_SIZE;
2435 }
2436
2437#if 0
2438 error = bus_dma_tag_create(bus_get_dma_tag(dev),
2439 1 /* alignment */, 0 /* boundary */,
2440 1ULL << sc->match->busdma_addr_mask_sz /* lowaddr */,
2441 BUS_SPACE_MAXADDR /* highaddr */,
2442 NULL /* filtfunc */, NULL /* filtfuncarg */,
2443 BUS_SPACE_MAXADDR /* maxsize */,
2444 BUS_SPACE_UNRESTRICTED /* nsegments */,
2445 BUS_SPACE_MAXADDR /* maxsegsz */,
2446 0 /* flags */, NULL /* lockfunc */, NULL /* lockfuncarg */,
2447 &dmat);
2448 if (error != 0) {
2449 sglist_free(sg);
2450 return (error);
2451 }
2452 /* XXXKIB */
2453#endif
2454 *sg_list = sg;
2455 return (0);
2456}
2457
2458void
2459agp_intel_gtt_insert_sg_entries(device_t dev, struct sglist *sg_list,
2460 u_int first_entry, u_int flags)
2461{
2462 struct agp_i810_softc *sc;
2463 vm_paddr_t spaddr;
2464 size_t slen;
2465 u_int i, j;
2466
2467 sc = device_get_softc(dev);
2468 for (i = j = 0; j < sg_list->sg_nseg; j++) {
2469 spaddr = sg_list->sg_segs[i].ss_paddr;
2470 slen = sg_list->sg_segs[i].ss_len;
2471 for (; slen > 0; i++) {
2472 sc->match->driver->install_gtt_pte(dev, first_entry + i,
2473 spaddr, flags);
2474 spaddr += AGP_PAGE_SIZE;
2475 slen -= AGP_PAGE_SIZE;
2476 }
2477 }
2478 sc->match->driver->read_gtt_pte(dev, first_entry + i - 1);
2479}
2480
2481void
2482intel_gtt_clear_range(u_int first_entry, u_int num_entries)
2483{
2484
2485 agp_intel_gtt_clear_range(intel_agp, first_entry, num_entries);
2486}
2487
2488void
2489intel_gtt_insert_pages(u_int first_entry, u_int num_entries, vm_page_t *pages,
2490 u_int flags)
2491{
2492
2493 agp_intel_gtt_insert_pages(intel_agp, first_entry, num_entries,
2494 pages, flags);
2495}
2496
2497struct intel_gtt
2498intel_gtt_get(void)
2499{
2500
2501 return (agp_intel_gtt_get(intel_agp));
2502}
2503
2504int
2505intel_gtt_chipset_flush(void)
2506{
2507
2508 return (agp_intel_gtt_chipset_flush(intel_agp));
2509}
2510
2511void
2512intel_gtt_unmap_memory(struct sglist *sg_list)
2513{
2514
2515 agp_intel_gtt_unmap_memory(intel_agp, sg_list);
2516}
2517
2518int
2519intel_gtt_map_memory(vm_page_t *pages, u_int num_entries,
2520 struct sglist **sg_list)
2521{
2522
2523 return (agp_intel_gtt_map_memory(intel_agp, pages, num_entries,
2524 sg_list));
2525}
2526
2527void
2528intel_gtt_insert_sg_entries(struct sglist *sg_list, u_int first_entry,
2529 u_int flags)
2530{
2531
2532 agp_intel_gtt_insert_sg_entries(intel_agp, sg_list, first_entry, flags);
2533}
2534
2535device_t
2536intel_gtt_get_bridge_device(void)
2537{
2538 struct agp_i810_softc *sc;
2539
2540 sc = device_get_softc(intel_agp);
2541 return (sc->bdev);
2542}
2543
2544vm_paddr_t
2545intel_gtt_read_pte_paddr(u_int entry)
2546{
2547 struct agp_i810_softc *sc;
2548
2549 sc = device_get_softc(intel_agp);
2550 return (sc->match->driver->read_gtt_pte_paddr(intel_agp, entry));
2551}
2552
2553u_int32_t
2554intel_gtt_read_pte(u_int entry)
2555{
2556 struct agp_i810_softc *sc;
2557
2558 sc = device_get_softc(intel_agp);
2559 return (sc->match->driver->read_gtt_pte(intel_agp, entry));
2560}
2561
2562void
2563intel_gtt_write(u_int entry, uint32_t val)
2564{
2565 struct agp_i810_softc *sc;
2566
2567 sc = device_get_softc(intel_agp);
d63cf994 2568 sc->match->driver->write_gtt(intel_agp, entry, val);
a904aa53 2569}