agp: Remove support for Valleyview hardware
[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.
984263bc
MD
30 */
31
32/*
33 * Fixes for 830/845G support: David Dawes <dawes@xfree86.org>
fdc3c5be 34 * 852GM/855GM/865G support added by David Dawes <dawes@xfree86.org>
a904aa53
FT
35 *
36 * This is generic Intel GTT handling code, morphed from the AGP
37 * bridge code.
984263bc
MD
38 */
39
a904aa53
FT
40#if 0
41#define KTR_AGP_I810 KTR_DEV
42#else
43#define KTR_AGP_I810 0
44#endif
45
984263bc
MD
46#include <sys/param.h>
47#include <sys/systm.h>
48#include <sys/malloc.h>
49#include <sys/kernel.h>
50#include <sys/bus.h>
51#include <sys/lock.h>
1f7ab7c9 52#include <sys/rman.h>
984263bc 53
dcb4b80d 54#include "pcidevs.h"
1f2de5d4
MD
55#include <bus/pci/pcivar.h>
56#include <bus/pci/pcireg.h>
57#include "agppriv.h"
58#include "agpreg.h"
b2776052 59#include <drm/intel-gtt.h>
984263bc
MD
60
61#include <vm/vm.h>
62#include <vm/vm_object.h>
63#include <vm/vm_page.h>
7414ebeb 64#include <vm/vm_param.h>
984263bc
MD
65#include <vm/vm_pageout.h>
66#include <vm/pmap.h>
67
7414ebeb
MD
68#include <vm/vm_page2.h>
69
fdc3c5be
HT
70#include <machine/md_var.h>
71
72#define bus_read_1(r, o) \
73 bus_space_read_1((r)->r_bustag, (r)->r_bushandle, (o))
74#define bus_read_4(r, o) \
75 bus_space_read_4((r)->r_bustag, (r)->r_bushandle, (o))
76#define bus_write_4(r, o, v) \
77 bus_space_write_4((r)->r_bustag, (r)->r_bushandle, (o), (v))
78
984263bc
MD
79MALLOC_DECLARE(M_AGP);
80
a904aa53
FT
81struct agp_i810_match;
82
a904aa53
FT
83static int agp_i915_check_active(device_t bridge_dev);
84static int agp_sb_check_active(device_t bridge_dev);
85
a904aa53
FT
86static void agp_i810_set_desc(device_t dev, const struct agp_i810_match *match);
87
a904aa53
FT
88static void agp_i915_dump_regs(device_t dev);
89static void agp_i965_dump_regs(device_t dev);
90static void agp_sb_dump_regs(device_t dev);
91
a904aa53
FT
92static int agp_i915_get_stolen_size(device_t dev);
93static int agp_sb_get_stolen_size(device_t dev);
09d2c144 94static int agp_gen8_get_stolen_size(device_t dev);
a904aa53 95
a904aa53
FT
96static int agp_i915_get_gtt_mappable_entries(device_t dev);
97
98static int agp_i810_get_gtt_total_entries(device_t dev);
99static int agp_i965_get_gtt_total_entries(device_t dev);
100static int agp_gen5_get_gtt_total_entries(device_t dev);
101static int agp_sb_get_gtt_total_entries(device_t dev);
09d2c144 102static int agp_gen8_get_gtt_total_entries(device_t dev);
a904aa53 103
a904aa53 104static int agp_i830_install_gatt(device_t dev);
7414ebeb 105static int agp_sb_install_gatt(device_t dev);
a904aa53 106
a904aa53 107static void agp_i830_deinstall_gatt(device_t dev);
7414ebeb 108static void agp_sb_deinstall_gatt(device_t dev);
a904aa53 109
a904aa53
FT
110static void agp_i915_install_gtt_pte(device_t dev, u_int index,
111 vm_offset_t physical, int flags);
112static void agp_i965_install_gtt_pte(device_t dev, u_int index,
113 vm_offset_t physical, int flags);
114static void agp_g4x_install_gtt_pte(device_t dev, u_int index,
115 vm_offset_t physical, int flags);
116static void agp_sb_install_gtt_pte(device_t dev, u_int index,
117 vm_offset_t physical, int flags);
09d2c144
MD
118static void agp_gen8_install_gtt_pte(device_t dev, u_int index,
119 vm_offset_t physical, int flags);
a904aa53 120
a904aa53
FT
121static void agp_i915_write_gtt(device_t dev, u_int index, uint32_t pte);
122static void agp_i965_write_gtt(device_t dev, u_int index, uint32_t pte);
123static void agp_g4x_write_gtt(device_t dev, u_int index, uint32_t pte);
124static void agp_sb_write_gtt(device_t dev, u_int index, uint32_t pte);
125
09d2c144
MD
126static void agp_i915_sync_gtt_pte(device_t dev, u_int index);
127static void agp_i965_sync_gtt_pte(device_t dev, u_int index);
128static void agp_g4x_sync_gtt_pte(device_t dev, u_int index);
a904aa53 129
a904aa53
FT
130static int agp_i915_set_aperture(device_t dev, u_int32_t aperture);
131
132static int agp_i810_chipset_flush_setup(device_t dev);
133static int agp_i915_chipset_flush_setup(device_t dev);
134static int agp_i965_chipset_flush_setup(device_t dev);
135
136static void agp_i810_chipset_flush_teardown(device_t dev);
137static void agp_i915_chipset_flush_teardown(device_t dev);
138static void agp_i965_chipset_flush_teardown(device_t dev);
139
140static void agp_i810_chipset_flush(device_t dev);
a904aa53
FT
141static void agp_i915_chipset_flush(device_t dev);
142
fdc3c5be
HT
143enum {
144 CHIP_I810, /* i810/i815 */
145 CHIP_I830, /* 830M/845G */
146 CHIP_I855, /* 852GM/855GM/865G */
147 CHIP_I915, /* 915G/915GM */
148 CHIP_I965, /* G965 */
149 CHIP_G33, /* G33/Q33/Q35 */
7f9ec87c 150 CHIP_IGD, /* Pineview */
f16c0bab 151 CHIP_G4X, /* G45/Q45 */
a904aa53 152 CHIP_SB, /* SandyBridge */
fdc3c5be 153};
984263bc 154
fdc3c5be
HT
155/* The i810 through i855 have the registers at BAR 1, and the GATT gets
156 * allocated by us. The i915 has registers in BAR 0 and the GATT is at the
157 * start of the stolen memory, and should only be accessed by the OS through
158 * BAR 3. The G965 has registers and GATT in the same BAR (0) -- first 512KB
159 * is registers, second 512KB is GATT.
160 */
fdc3c5be
HT
161static struct resource_spec agp_i915_res_spec[] = {
162 { SYS_RES_MEMORY, AGP_I915_MMADR, RF_ACTIVE | RF_SHAREABLE },
163 { SYS_RES_MEMORY, AGP_I915_GTTADR, RF_ACTIVE | RF_SHAREABLE },
164 { -1, 0 }
165};
166
167static struct resource_spec agp_i965_res_spec[] = {
168 { SYS_RES_MEMORY, AGP_I965_GTTMMADR, RF_ACTIVE | RF_SHAREABLE },
169 { -1, 0 }
170};
984263bc 171
a904aa53
FT
172static struct resource_spec agp_g4x_res_spec[] = {
173 { SYS_RES_MEMORY, AGP_G4X_MMADR, RF_ACTIVE | RF_SHAREABLE },
174 { SYS_RES_MEMORY, AGP_G4X_GTTADR, RF_ACTIVE | RF_SHAREABLE },
175 { -1, 0 }
176};
177
984263bc
MD
178struct agp_i810_softc {
179 struct agp_softc agp;
180 u_int32_t initial_aperture; /* aperture size at startup */
181 struct agp_gatt *gatt;
984263bc 182 u_int32_t dcache_size; /* i810 only */
a904aa53
FT
183 u_int32_t stolen; /* number of i830/845 gtt
184 entries for stolen memory */
185 u_int stolen_size; /* BIOS-reserved graphics memory */
186 u_int gtt_total_entries; /* Total number of gtt ptes */
187 u_int gtt_mappable_entries; /* Number of gtt ptes mappable by CPU */
984263bc 188 device_t bdev; /* bridge device */
fdc3c5be 189 void *argb_cursor; /* contigmalloc area for ARGB cursor */
7414ebeb 190 struct resource *sc_res[3];
a904aa53
FT
191 const struct agp_i810_match *match;
192 int sc_flush_page_rid;
193 struct resource *sc_flush_page_res;
194 void *sc_flush_page_vaddr;
195 int sc_bios_allocated_flush_page;
196};
197
198static device_t intel_agp;
199
200struct agp_i810_driver {
201 int chiptype;
202 int gen;
203 int busdma_addr_mask_sz;
204 struct resource_spec *res_spec;
205 int (*check_active)(device_t);
206 void (*set_desc)(device_t, const struct agp_i810_match *);
207 void (*dump_regs)(device_t);
208 int (*get_stolen_size)(device_t);
209 int (*get_gtt_total_entries)(device_t);
210 int (*get_gtt_mappable_entries)(device_t);
211 int (*install_gatt)(device_t);
212 void (*deinstall_gatt)(device_t);
213 void (*write_gtt)(device_t, u_int, uint32_t);
214 void (*install_gtt_pte)(device_t, u_int, vm_offset_t, int);
09d2c144 215 void (*sync_gtt_pte)(device_t, u_int);
a904aa53
FT
216 int (*set_aperture)(device_t, u_int32_t);
217 int (*chipset_flush_setup)(device_t);
218 void (*chipset_flush_teardown)(device_t);
219 void (*chipset_flush)(device_t);
220};
221
bc2fd6c1
FT
222static struct {
223 struct intel_gtt base;
224} intel_private;
225
a904aa53
FT
226static const struct agp_i810_driver agp_i810_i915_driver = {
227 .chiptype = CHIP_I915,
228 .gen = 3,
229 .busdma_addr_mask_sz = 32,
230 .res_spec = agp_i915_res_spec,
231 .check_active = agp_i915_check_active,
232 .set_desc = agp_i810_set_desc,
233 .dump_regs = agp_i915_dump_regs,
234 .get_stolen_size = agp_i915_get_stolen_size,
235 .get_gtt_mappable_entries = agp_i915_get_gtt_mappable_entries,
236 .get_gtt_total_entries = agp_i810_get_gtt_total_entries,
237 .install_gatt = agp_i830_install_gatt,
238 .deinstall_gatt = agp_i830_deinstall_gatt,
239 .write_gtt = agp_i915_write_gtt,
240 .install_gtt_pte = agp_i915_install_gtt_pte,
09d2c144 241 .sync_gtt_pte = agp_i915_sync_gtt_pte,
a904aa53
FT
242 .set_aperture = agp_i915_set_aperture,
243 .chipset_flush_setup = agp_i915_chipset_flush_setup,
244 .chipset_flush_teardown = agp_i915_chipset_flush_teardown,
245 .chipset_flush = agp_i915_chipset_flush,
246};
247
248static const struct agp_i810_driver agp_i810_g965_driver = {
249 .chiptype = CHIP_I965,
250 .gen = 4,
251 .busdma_addr_mask_sz = 36,
252 .res_spec = agp_i965_res_spec,
253 .check_active = agp_i915_check_active,
254 .set_desc = agp_i810_set_desc,
255 .dump_regs = agp_i965_dump_regs,
256 .get_stolen_size = agp_i915_get_stolen_size,
257 .get_gtt_mappable_entries = agp_i915_get_gtt_mappable_entries,
258 .get_gtt_total_entries = agp_i965_get_gtt_total_entries,
259 .install_gatt = agp_i830_install_gatt,
260 .deinstall_gatt = agp_i830_deinstall_gatt,
261 .write_gtt = agp_i965_write_gtt,
262 .install_gtt_pte = agp_i965_install_gtt_pte,
09d2c144 263 .sync_gtt_pte = agp_i965_sync_gtt_pte,
a904aa53
FT
264 .set_aperture = agp_i915_set_aperture,
265 .chipset_flush_setup = agp_i965_chipset_flush_setup,
266 .chipset_flush_teardown = agp_i965_chipset_flush_teardown,
267 .chipset_flush = agp_i915_chipset_flush,
268};
269
270static const struct agp_i810_driver agp_i810_g33_driver = {
271 .chiptype = CHIP_G33,
272 .gen = 3,
273 .busdma_addr_mask_sz = 36,
274 .res_spec = agp_i915_res_spec,
275 .check_active = agp_i915_check_active,
276 .set_desc = agp_i810_set_desc,
277 .dump_regs = agp_i965_dump_regs,
278 .get_stolen_size = agp_i915_get_stolen_size,
279 .get_gtt_mappable_entries = agp_i915_get_gtt_mappable_entries,
280 .get_gtt_total_entries = agp_i965_get_gtt_total_entries,
281 .install_gatt = agp_i830_install_gatt,
282 .deinstall_gatt = agp_i830_deinstall_gatt,
283 .write_gtt = agp_i915_write_gtt,
99e9e211 284 .install_gtt_pte = agp_i965_install_gtt_pte,
09d2c144 285 .sync_gtt_pte = agp_i915_sync_gtt_pte,
a904aa53
FT
286 .set_aperture = agp_i915_set_aperture,
287 .chipset_flush_setup = agp_i965_chipset_flush_setup,
288 .chipset_flush_teardown = agp_i965_chipset_flush_teardown,
289 .chipset_flush = agp_i915_chipset_flush,
290};
291
99e9e211 292static const struct agp_i810_driver pineview_gtt_driver = {
a904aa53
FT
293 .chiptype = CHIP_IGD,
294 .gen = 3,
295 .busdma_addr_mask_sz = 36,
296 .res_spec = agp_i915_res_spec,
297 .check_active = agp_i915_check_active,
298 .set_desc = agp_i810_set_desc,
299 .dump_regs = agp_i915_dump_regs,
300 .get_stolen_size = agp_i915_get_stolen_size,
301 .get_gtt_mappable_entries = agp_i915_get_gtt_mappable_entries,
302 .get_gtt_total_entries = agp_i965_get_gtt_total_entries,
303 .install_gatt = agp_i830_install_gatt,
304 .deinstall_gatt = agp_i830_deinstall_gatt,
305 .write_gtt = agp_i915_write_gtt,
99e9e211 306 .install_gtt_pte = agp_i965_install_gtt_pte,
09d2c144 307 .sync_gtt_pte = agp_i915_sync_gtt_pte,
a904aa53
FT
308 .set_aperture = agp_i915_set_aperture,
309 .chipset_flush_setup = agp_i965_chipset_flush_setup,
310 .chipset_flush_teardown = agp_i965_chipset_flush_teardown,
311 .chipset_flush = agp_i915_chipset_flush,
312};
313
314static const struct agp_i810_driver agp_i810_g4x_driver = {
315 .chiptype = CHIP_G4X,
316 .gen = 5,
317 .busdma_addr_mask_sz = 36,
318 .res_spec = agp_i965_res_spec,
319 .check_active = agp_i915_check_active,
320 .set_desc = agp_i810_set_desc,
321 .dump_regs = agp_i965_dump_regs,
322 .get_stolen_size = agp_i915_get_stolen_size,
323 .get_gtt_mappable_entries = agp_i915_get_gtt_mappable_entries,
324 .get_gtt_total_entries = agp_gen5_get_gtt_total_entries,
325 .install_gatt = agp_i830_install_gatt,
326 .deinstall_gatt = agp_i830_deinstall_gatt,
327 .write_gtt = agp_g4x_write_gtt,
328 .install_gtt_pte = agp_g4x_install_gtt_pte,
09d2c144 329 .sync_gtt_pte = agp_g4x_sync_gtt_pte,
a904aa53
FT
330 .set_aperture = agp_i915_set_aperture,
331 .chipset_flush_setup = agp_i965_chipset_flush_setup,
332 .chipset_flush_teardown = agp_i965_chipset_flush_teardown,
333 .chipset_flush = agp_i915_chipset_flush,
334};
335
336static const struct agp_i810_driver agp_i810_sb_driver = {
337 .chiptype = CHIP_SB,
338 .gen = 6,
339 .busdma_addr_mask_sz = 40,
340 .res_spec = agp_g4x_res_spec,
341 .check_active = agp_sb_check_active,
342 .set_desc = agp_i810_set_desc,
343 .dump_regs = agp_sb_dump_regs,
344 .get_stolen_size = agp_sb_get_stolen_size,
345 .get_gtt_mappable_entries = agp_i915_get_gtt_mappable_entries,
346 .get_gtt_total_entries = agp_sb_get_gtt_total_entries,
7414ebeb
MD
347 .install_gatt = agp_sb_install_gatt,
348 .deinstall_gatt = agp_sb_deinstall_gatt,
a904aa53
FT
349 .write_gtt = agp_sb_write_gtt,
350 .install_gtt_pte = agp_sb_install_gtt_pte,
09d2c144 351 .sync_gtt_pte = agp_g4x_sync_gtt_pte,
a904aa53
FT
352 .set_aperture = agp_i915_set_aperture,
353 .chipset_flush_setup = agp_i810_chipset_flush_setup,
354 .chipset_flush_teardown = agp_i810_chipset_flush_teardown,
355 .chipset_flush = agp_i810_chipset_flush,
fdc3c5be
HT
356};
357
09d2c144
MD
358static const struct agp_i810_driver broadwell_gtt_driver = {
359 .chiptype = CHIP_SB,
360 .gen = 8,
361 .busdma_addr_mask_sz = 40,
362 .res_spec = agp_g4x_res_spec,
363 .check_active = agp_sb_check_active,
364 .set_desc = agp_i810_set_desc,
365 .dump_regs = agp_sb_dump_regs,
366 .get_stolen_size = agp_gen8_get_stolen_size,
367 .get_gtt_mappable_entries = agp_i915_get_gtt_mappable_entries,
368 .get_gtt_total_entries = agp_gen8_get_gtt_total_entries,
369 .install_gatt = agp_i830_install_gatt,
370 .deinstall_gatt = agp_i830_deinstall_gatt,
371 .write_gtt = NULL,
372 .install_gtt_pte = agp_gen8_install_gtt_pte,
373 .sync_gtt_pte = agp_g4x_sync_gtt_pte,
8d36a65a
FT
374 .set_aperture = agp_i915_set_aperture,
375 .chipset_flush_setup = agp_i810_chipset_flush_setup,
376 .chipset_flush_teardown = agp_i810_chipset_flush_teardown,
377 .chipset_flush = agp_i810_chipset_flush,
378};
379
fdc3c5be
HT
380/* For adding new devices, devid is the id of the graphics controller
381 * (pci:0:2:0, for example). The placeholder (usually at pci:0:2:1) for the
382 * second head should never be added. The bridge_offset is the offset to
383 * subtract from devid to get the id of the hostb that the device is on.
384 */
385static const struct agp_i810_match {
8d36a65a 386 uint16_t devid;
fdc3c5be 387 char *name;
a904aa53 388 const struct agp_i810_driver *driver;
fdc3c5be 389} agp_i810_matches[] = {
a904aa53 390 {
31d142df 391 .devid = 0x2582,
a904aa53
FT
392 .name = "Intel 82915G (915G GMCH) SVGA controller",
393 .driver = &agp_i810_i915_driver
394 },
395 {
31d142df 396 .devid = 0x258A,
a904aa53
FT
397 .name = "Intel E7221 SVGA controller",
398 .driver = &agp_i810_i915_driver
399 },
400 {
31d142df 401 .devid = 0x2592,
a904aa53
FT
402 .name = "Intel 82915GM (915GM GMCH) SVGA controller",
403 .driver = &agp_i810_i915_driver
404 },
405 {
31d142df 406 .devid = 0x2772,
a904aa53
FT
407 .name = "Intel 82945G (945G GMCH) SVGA controller",
408 .driver = &agp_i810_i915_driver
409 },
410 {
31d142df 411 .devid = 0x27A2,
a904aa53
FT
412 .name = "Intel 82945GM (945GM GMCH) SVGA controller",
413 .driver = &agp_i810_i915_driver
414 },
415 {
31d142df 416 .devid = 0x27AE,
a904aa53
FT
417 .name = "Intel 945GME SVGA controller",
418 .driver = &agp_i810_i915_driver
419 },
420 {
31d142df 421 .devid = 0x2972,
a904aa53
FT
422 .name = "Intel 946GZ SVGA controller",
423 .driver = &agp_i810_g965_driver
424 },
425 {
31d142df 426 .devid = 0x2982,
a904aa53
FT
427 .name = "Intel G965 SVGA controller",
428 .driver = &agp_i810_g965_driver
429 },
430 {
31d142df 431 .devid = 0x2992,
a904aa53
FT
432 .name = "Intel Q965 SVGA controller",
433 .driver = &agp_i810_g965_driver
434 },
435 {
31d142df 436 .devid = 0x29A2,
a904aa53
FT
437 .name = "Intel G965 SVGA controller",
438 .driver = &agp_i810_g965_driver
439 },
440 {
31d142df 441 .devid = 0x29B2,
a904aa53
FT
442 .name = "Intel Q35 SVGA controller",
443 .driver = &agp_i810_g33_driver
444 },
445 {
31d142df 446 .devid = 0x29C2,
a904aa53
FT
447 .name = "Intel G33 SVGA controller",
448 .driver = &agp_i810_g33_driver
449 },
450 {
31d142df 451 .devid = 0x29D2,
a904aa53
FT
452 .name = "Intel Q33 SVGA controller",
453 .driver = &agp_i810_g33_driver
454 },
455 {
31d142df 456 .devid = 0xA001,
a904aa53 457 .name = "Intel Pineview SVGA controller",
99e9e211 458 .driver = &pineview_gtt_driver
a904aa53
FT
459 },
460 {
31d142df 461 .devid = 0xA011,
a904aa53 462 .name = "Intel Pineview (M) SVGA controller",
99e9e211 463 .driver = &pineview_gtt_driver
a904aa53
FT
464 },
465 {
31d142df 466 .devid = 0x2A02,
a904aa53
FT
467 .name = "Intel GM965 SVGA controller",
468 .driver = &agp_i810_g965_driver
469 },
470 {
31d142df 471 .devid = 0x2A12,
a904aa53
FT
472 .name = "Intel GME965 SVGA controller",
473 .driver = &agp_i810_g965_driver
474 },
475 {
31d142df 476 .devid = 0x2A42,
a904aa53
FT
477 .name = "Intel GM45 SVGA controller",
478 .driver = &agp_i810_g4x_driver
479 },
480 {
31d142df 481 .devid = 0x2E02,
a904aa53
FT
482 .name = "Intel Eaglelake SVGA controller",
483 .driver = &agp_i810_g4x_driver
484 },
485 {
31d142df 486 .devid = 0x2E12,
a904aa53
FT
487 .name = "Intel Q45 SVGA controller",
488 .driver = &agp_i810_g4x_driver
489 },
490 {
31d142df 491 .devid = 0x2E22,
a904aa53
FT
492 .name = "Intel G45 SVGA controller",
493 .driver = &agp_i810_g4x_driver
494 },
495 {
31d142df 496 .devid = 0x2E32,
a904aa53
FT
497 .name = "Intel G41 SVGA controller",
498 .driver = &agp_i810_g4x_driver
499 },
500 {
31d142df 501 .devid = 0x0042,
a904aa53
FT
502 .name = "Intel Ironlake (D) SVGA controller",
503 .driver = &agp_i810_g4x_driver
504 },
505 {
31d142df 506 .devid = 0x0046,
a904aa53
FT
507 .name = "Intel Ironlake (M) SVGA controller",
508 .driver = &agp_i810_g4x_driver
509 },
510 {
31d142df 511 .devid = 0x0102,
a904aa53
FT
512 .name = "SandyBridge desktop GT1 IG",
513 .driver = &agp_i810_sb_driver
514 },
515 {
31d142df 516 .devid = 0x0112,
a904aa53
FT
517 .name = "SandyBridge desktop GT2 IG",
518 .driver = &agp_i810_sb_driver
519 },
520 {
31d142df 521 .devid = 0x0122,
a904aa53
FT
522 .name = "SandyBridge desktop GT2+ IG",
523 .driver = &agp_i810_sb_driver
524 },
525 {
31d142df 526 .devid = 0x0106,
a904aa53
FT
527 .name = "SandyBridge mobile GT1 IG",
528 .driver = &agp_i810_sb_driver
529 },
530 {
31d142df 531 .devid = 0x0116,
a904aa53
FT
532 .name = "SandyBridge mobile GT2 IG",
533 .driver = &agp_i810_sb_driver
534 },
535 {
31d142df 536 .devid = 0x0126,
a904aa53
FT
537 .name = "SandyBridge mobile GT2+ IG",
538 .driver = &agp_i810_sb_driver
539 },
540 {
31d142df 541 .devid = 0x010a,
a904aa53
FT
542 .name = "SandyBridge server IG",
543 .driver = &agp_i810_sb_driver
544 },
545 {
31d142df 546 .devid = 0x0152,
a904aa53
FT
547 .name = "IvyBridge desktop GT1 IG",
548 .driver = &agp_i810_sb_driver
549 },
550 {
31d142df 551 .devid = 0x0162,
a904aa53
FT
552 .name = "IvyBridge desktop GT2 IG",
553 .driver = &agp_i810_sb_driver
554 },
555 {
31d142df 556 .devid = 0x0156,
a904aa53
FT
557 .name = "IvyBridge mobile GT1 IG",
558 .driver = &agp_i810_sb_driver
559 },
560 {
31d142df 561 .devid = 0x0166,
a904aa53
FT
562 .name = "IvyBridge mobile GT2 IG",
563 .driver = &agp_i810_sb_driver
564 },
565 {
31d142df 566 .devid = 0x015a,
a904aa53
FT
567 .name = "IvyBridge server GT1 IG",
568 .driver = &agp_i810_sb_driver
569 },
246f9ec5 570 {
31d142df 571 .devid = 0x016a,
246f9ec5
FT
572 .name = "IvyBridge server GT2 IG",
573 .driver = &agp_i810_sb_driver
574 },
8d36a65a
FT
575 {
576 .devid = 0x0402,
577 .name = "Haswell desktop GT1 IG",
578 .driver = &agp_i810_sb_driver
579 },
580 {
581 .devid = 0x0412,
582 .name = "Haswell desktop GT2 IG",
583 .driver = &agp_i810_sb_driver
584 },
bb66151c 585 { 0x041e, "Haswell", &agp_i810_sb_driver },
cf614546 586 { 0x0422, "Haswell", &agp_i810_sb_driver },
8d36a65a
FT
587 {
588 .devid = 0x0406,
589 .name = "Haswell mobile GT1 IG",
590 .driver = &agp_i810_sb_driver
591 },
592 {
593 .devid = 0x0416,
594 .name = "Haswell mobile GT2 IG",
595 .driver = &agp_i810_sb_driver
596 },
cf614546 597 { 0x0426, "Haswell", &agp_i810_sb_driver },
8d36a65a
FT
598 {
599 .devid = 0x040a,
600 .name = "Haswell server GT1 IG",
601 .driver = &agp_i810_sb_driver
602 },
603 {
604 .devid = 0x041a,
605 .name = "Haswell server GT2 IG",
606 .driver = &agp_i810_sb_driver
607 },
cf614546
FT
608 { 0x042a, "Haswell", &agp_i810_sb_driver },
609 { 0x0c02, "Haswell", &agp_i810_sb_driver },
610 { 0x0c12, "Haswell", &agp_i810_sb_driver },
611 { 0x0c22, "Haswell", &agp_i810_sb_driver },
612 { 0x0c06, "Haswell", &agp_i810_sb_driver },
8d36a65a
FT
613 {
614 .devid = 0x0c16,
615 .name = "Haswell SDV",
616 .driver = &agp_i810_sb_driver
617 },
cf614546
FT
618 { 0x0c26, "Haswell", &agp_i810_sb_driver },
619 { 0x0c0a, "Haswell", &agp_i810_sb_driver },
620 { 0x0c1a, "Haswell", &agp_i810_sb_driver },
621 { 0x0c2a, "Haswell", &agp_i810_sb_driver },
622 { 0x0a02, "Haswell", &agp_i810_sb_driver },
623 { 0x0a12, "Haswell", &agp_i810_sb_driver },
624 { 0x0a22, "Haswell", &agp_i810_sb_driver },
625 { 0x0a06, "Haswell", &agp_i810_sb_driver },
626 { 0x0a16, "Haswell", &agp_i810_sb_driver },
627 { 0x0a26, "Haswell", &agp_i810_sb_driver },
628 { 0x0a0a, "Haswell", &agp_i810_sb_driver },
629 { 0x0a1a, "Haswell", &agp_i810_sb_driver },
630 { 0x0a2a, "Haswell", &agp_i810_sb_driver },
631 { 0x0d12, "Haswell", &agp_i810_sb_driver },
632 { 0x0d22, "Haswell", &agp_i810_sb_driver },
633 { 0x0d32, "Haswell", &agp_i810_sb_driver },
634 { 0x0d16, "Haswell", &agp_i810_sb_driver },
635 { 0x0d26, "Haswell", &agp_i810_sb_driver },
636 { 0x0d36, "Haswell", &agp_i810_sb_driver },
637 { 0x0d1a, "Haswell", &agp_i810_sb_driver },
638 { 0x0d2a, "Haswell", &agp_i810_sb_driver },
639 { 0x0d3a, "Haswell", &agp_i810_sb_driver },
09d2c144
MD
640
641 { 0x1602, "Broadwell", &broadwell_gtt_driver }, /* m */
642 { 0x1606, "Broadwell", &broadwell_gtt_driver },
643 { 0x160B, "Broadwell", &broadwell_gtt_driver },
644 { 0x160E, "Broadwell", &broadwell_gtt_driver },
645 { 0x1616, "Broadwell", &broadwell_gtt_driver },
b12129b5 646 { 0x161E, "Broadwell", &broadwell_gtt_driver },
09d2c144
MD
647
648 { 0x160A, "Broadwell", &broadwell_gtt_driver }, /* d */
649 { 0x160D, "Broadwell", &broadwell_gtt_driver },
a904aa53
FT
650 {
651 .devid = 0,
652 }
984263bc
MD
653};
654
fdc3c5be 655static const struct agp_i810_match*
984263bc
MD
656agp_i810_match(device_t dev)
657{
fdc3c5be
HT
658 int i, devid;
659
31d142df 660 if (pci_get_vendor(dev) != PCI_VENDOR_INTEL)
a904aa53 661 return (NULL);
984263bc 662
26b66f28 663 devid = pci_get_device(dev);
fdc3c5be
HT
664 for (i = 0; agp_i810_matches[i].devid != 0; i++) {
665 if (agp_i810_matches[i].devid == devid)
a904aa53 666 break;
fdc3c5be
HT
667 }
668 if (agp_i810_matches[i].devid == 0)
a904aa53 669 return (NULL);
fdc3c5be 670 else
a904aa53 671 return (&agp_i810_matches[i]);
984263bc
MD
672}
673
674/*
675 * Find bridge device.
676 */
677static device_t
678agp_i810_find_bridge(device_t dev)
679{
984263bc 680
a904aa53 681 return (pci_find_dbsf(0, 0, 0, 0));
984263bc
MD
682}
683
fdc3c5be
HT
684static void
685agp_i810_identify(driver_t *driver, device_t parent)
686{
687
688 if (device_find_child(parent, "agp", -1) == NULL &&
689 agp_i810_match(parent))
690 device_add_child(parent, "agp", -1);
691}
692
a904aa53
FT
693static int
694agp_i915_check_active(device_t bridge_dev)
695{
696 int deven;
697
698 deven = pci_read_config(bridge_dev, AGP_I915_DEVEN, 4);
699 if ((deven & AGP_I915_DEVEN_D2F0) == AGP_I915_DEVEN_D2F0_DISABLED)
700 return (ENXIO);
701 return (0);
702}
703
704static int
705agp_sb_check_active(device_t bridge_dev)
706{
707 int deven;
708
709 deven = pci_read_config(bridge_dev, AGP_I915_DEVEN, 4);
710 if ((deven & AGP_SB_DEVEN_D2EN) == AGP_SB_DEVEN_D2EN_DISABLED)
711 return (ENXIO);
712 return (0);
713}
714
a904aa53
FT
715static void
716agp_i810_set_desc(device_t dev, const struct agp_i810_match *match)
717{
718
719 device_set_desc(dev, match->name);
720}
721
984263bc
MD
722static int
723agp_i810_probe(device_t dev)
724{
fdc3c5be
HT
725 device_t bdev;
726 const struct agp_i810_match *match;
7414ebeb 727 int err = 0;
fdc3c5be
HT
728
729 if (resource_disabled("agp", device_get_unit(dev)))
730 return (ENXIO);
731 match = agp_i810_match(dev);
732 if (match == NULL)
a904aa53 733 return (ENXIO);
984263bc 734
fdc3c5be 735 bdev = agp_i810_find_bridge(dev);
a904aa53 736 if (bdev == NULL) {
fdc3c5be
HT
737 if (bootverbose)
738 kprintf("I810: can't find bridge device\n");
a904aa53 739 return (ENXIO);
fdc3c5be 740 }
984263bc 741
fdc3c5be
HT
742 /*
743 * checking whether internal graphics device has been activated.
744 */
7414ebeb
MD
745 if (match->driver->check_active != NULL) {
746 err = match->driver->check_active(bdev);
747 if (err != 0) {
748 if (bootverbose)
749 kprintf("i810: disabled, not probing\n");
750 return (err);
751 }
984263bc
MD
752 }
753
a904aa53
FT
754 match->driver->set_desc(dev, match);
755 return (BUS_PROBE_DEFAULT);
fdc3c5be
HT
756}
757
a904aa53
FT
758static void
759agp_i915_dump_regs(device_t dev)
760{
761 struct agp_i810_softc *sc = device_get_softc(dev);
984263bc 762
a904aa53
FT
763 device_printf(dev, "AGP_I810_PGTBL_CTL: %08x\n",
764 bus_read_4(sc->sc_res[0], AGP_I810_PGTBL_CTL));
765 device_printf(dev, "AGP_I855_GCC1: 0x%02x\n",
766 pci_read_config(sc->bdev, AGP_I855_GCC1, 1));
767 device_printf(dev, "AGP_I915_MSAC: 0x%02x\n",
768 pci_read_config(sc->bdev, AGP_I915_MSAC, 1));
769}
fdc3c5be 770
a904aa53
FT
771static void
772agp_i965_dump_regs(device_t dev)
773{
774 struct agp_i810_softc *sc = device_get_softc(dev);
984263bc 775
a904aa53
FT
776 device_printf(dev, "AGP_I965_PGTBL_CTL2: %08x\n",
777 bus_read_4(sc->sc_res[0], AGP_I965_PGTBL_CTL2));
778 device_printf(dev, "AGP_I855_GCC1: 0x%02x\n",
7414ebeb 779 pci_read_config(dev, AGP_I855_GCC1, 1));
a904aa53 780 device_printf(dev, "AGP_I965_MSAC: 0x%02x\n",
7414ebeb 781 pci_read_config(dev, AGP_I965_MSAC, 1));
a904aa53 782}
fdc3c5be 783
a904aa53
FT
784static void
785agp_sb_dump_regs(device_t dev)
786{
787 struct agp_i810_softc *sc = device_get_softc(dev);
984263bc 788
a904aa53
FT
789 device_printf(dev, "AGP_SNB_GFX_MODE: %08x\n",
790 bus_read_4(sc->sc_res[0], AGP_SNB_GFX_MODE));
791 device_printf(dev, "AGP_SNB_GCC1: 0x%04x\n",
7414ebeb 792 pci_read_config(dev, AGP_SNB_GCC1, 2));
a904aa53
FT
793}
794
a904aa53
FT
795static int
796agp_i915_get_stolen_size(device_t dev)
797{
798 struct agp_i810_softc *sc;
799 unsigned int gcc1, stolen, gtt_size;
984263bc 800
a904aa53 801 sc = device_get_softc(dev);
fdc3c5be 802
a904aa53
FT
803 /*
804 * Stolen memory is set up at the beginning of the aperture by
805 * the BIOS, consisting of the GATT followed by 4kb for the
806 * BIOS display.
807 */
808 switch (sc->match->driver->chiptype) {
809 case CHIP_I855:
810 gtt_size = 128;
811 break;
812 case CHIP_I915:
813 gtt_size = 256;
814 break;
815 case CHIP_I965:
816 switch (bus_read_4(sc->sc_res[0], AGP_I810_PGTBL_CTL) &
817 AGP_I810_PGTBL_SIZE_MASK) {
818 case AGP_I810_PGTBL_SIZE_128KB:
fdc3c5be
HT
819 gtt_size = 128;
820 break;
a904aa53 821 case AGP_I810_PGTBL_SIZE_256KB:
fdc3c5be
HT
822 gtt_size = 256;
823 break;
a904aa53
FT
824 case AGP_I810_PGTBL_SIZE_512KB:
825 gtt_size = 512;
f16c0bab 826 break;
a904aa53
FT
827 case AGP_I965_PGTBL_SIZE_1MB:
828 gtt_size = 1024;
fdc3c5be 829 break;
a904aa53
FT
830 case AGP_I965_PGTBL_SIZE_2MB:
831 gtt_size = 2048;
832 break;
833 case AGP_I965_PGTBL_SIZE_1_5MB:
834 gtt_size = 1024 + 512;
f16c0bab 835 break;
fdc3c5be 836 default:
a904aa53
FT
837 device_printf(dev, "Bad PGTBL size\n");
838 return (EINVAL);
fdc3c5be 839 }
a904aa53
FT
840 break;
841 case CHIP_G33:
842 gcc1 = pci_read_config(sc->bdev, AGP_I855_GCC1, 2);
843 switch (gcc1 & AGP_G33_MGGC_GGMS_MASK) {
844 case AGP_G33_MGGC_GGMS_SIZE_1M:
845 gtt_size = 1024;
f16c0bab 846 break;
a904aa53
FT
847 case AGP_G33_MGGC_GGMS_SIZE_2M:
848 gtt_size = 2048;
ab5a0ec8
MD
849 break;
850 default:
a904aa53
FT
851 device_printf(dev, "Bad PGTBL size\n");
852 return (EINVAL);
ab5a0ec8 853 }
a904aa53
FT
854 break;
855 case CHIP_IGD:
856 case CHIP_G4X:
857 gtt_size = 0;
858 break;
859 default:
860 device_printf(dev, "Bad chiptype\n");
861 return (EINVAL);
862 }
f16c0bab 863
a904aa53
FT
864 /* GCC1 is called MGGC on i915+ */
865 gcc1 = pci_read_config(sc->bdev, AGP_I855_GCC1, 1);
866 switch (gcc1 & AGP_I855_GCC1_GMS) {
867 case AGP_I855_GCC1_GMS_STOLEN_1M:
868 stolen = 1024;
869 break;
870 case AGP_I855_GCC1_GMS_STOLEN_4M:
871 stolen = 4 * 1024;
872 break;
873 case AGP_I855_GCC1_GMS_STOLEN_8M:
874 stolen = 8 * 1024;
875 break;
876 case AGP_I855_GCC1_GMS_STOLEN_16M:
877 stolen = 16 * 1024;
878 break;
879 case AGP_I855_GCC1_GMS_STOLEN_32M:
880 stolen = 32 * 1024;
881 break;
882 case AGP_I915_GCC1_GMS_STOLEN_48M:
883 stolen = sc->match->driver->gen > 2 ? 48 * 1024 : 0;
884 break;
885 case AGP_I915_GCC1_GMS_STOLEN_64M:
886 stolen = sc->match->driver->gen > 2 ? 64 * 1024 : 0;
887 break;
888 case AGP_G33_GCC1_GMS_STOLEN_128M:
889 stolen = sc->match->driver->gen > 2 ? 128 * 1024 : 0;
890 break;
891 case AGP_G33_GCC1_GMS_STOLEN_256M:
892 stolen = sc->match->driver->gen > 2 ? 256 * 1024 : 0;
893 break;
894 case AGP_G4X_GCC1_GMS_STOLEN_96M:
895 if (sc->match->driver->chiptype == CHIP_I965 ||
896 sc->match->driver->chiptype == CHIP_G4X)
897 stolen = 96 * 1024;
898 else
899 stolen = 0;
900 break;
901 case AGP_G4X_GCC1_GMS_STOLEN_160M:
902 if (sc->match->driver->chiptype == CHIP_I965 ||
903 sc->match->driver->chiptype == CHIP_G4X)
904 stolen = 160 * 1024;
905 else
906 stolen = 0;
907 break;
908 case AGP_G4X_GCC1_GMS_STOLEN_224M:
909 if (sc->match->driver->chiptype == CHIP_I965 ||
910 sc->match->driver->chiptype == CHIP_G4X)
911 stolen = 224 * 1024;
912 else
913 stolen = 0;
914 break;
915 case AGP_G4X_GCC1_GMS_STOLEN_352M:
916 if (sc->match->driver->chiptype == CHIP_I965 ||
917 sc->match->driver->chiptype == CHIP_G4X)
918 stolen = 352 * 1024;
919 else
920 stolen = 0;
921 break;
922 default:
923 device_printf(dev,
924 "unknown memory configuration, disabling (GCC1 %x)\n",
925 gcc1);
926 return (EINVAL);
927 }
f16c0bab 928
a904aa53
FT
929 gtt_size += 4;
930 sc->stolen_size = stolen * 1024;
931 sc->stolen = (stolen - gtt_size) * 1024 / 4096;
984263bc 932
a904aa53
FT
933 return (0);
934}
ab5a0ec8 935
a904aa53
FT
936static int
937agp_sb_get_stolen_size(device_t dev)
938{
939 struct agp_i810_softc *sc;
940 uint16_t gmch_ctl;
941
942 sc = device_get_softc(dev);
7414ebeb
MD
943 gmch_ctl = pci_read_config(dev, AGP_SNB_GCC1, 2);
944
a904aa53
FT
945 switch (gmch_ctl & AGP_SNB_GMCH_GMS_STOLEN_MASK) {
946 case AGP_SNB_GMCH_GMS_STOLEN_32M:
947 sc->stolen_size = 32 * 1024 * 1024;
948 break;
949 case AGP_SNB_GMCH_GMS_STOLEN_64M:
950 sc->stolen_size = 64 * 1024 * 1024;
951 break;
952 case AGP_SNB_GMCH_GMS_STOLEN_96M:
953 sc->stolen_size = 96 * 1024 * 1024;
954 break;
955 case AGP_SNB_GMCH_GMS_STOLEN_128M:
956 sc->stolen_size = 128 * 1024 * 1024;
957 break;
958 case AGP_SNB_GMCH_GMS_STOLEN_160M:
959 sc->stolen_size = 160 * 1024 * 1024;
960 break;
961 case AGP_SNB_GMCH_GMS_STOLEN_192M:
962 sc->stolen_size = 192 * 1024 * 1024;
963 break;
964 case AGP_SNB_GMCH_GMS_STOLEN_224M:
965 sc->stolen_size = 224 * 1024 * 1024;
966 break;
967 case AGP_SNB_GMCH_GMS_STOLEN_256M:
968 sc->stolen_size = 256 * 1024 * 1024;
969 break;
970 case AGP_SNB_GMCH_GMS_STOLEN_288M:
971 sc->stolen_size = 288 * 1024 * 1024;
972 break;
973 case AGP_SNB_GMCH_GMS_STOLEN_320M:
974 sc->stolen_size = 320 * 1024 * 1024;
975 break;
976 case AGP_SNB_GMCH_GMS_STOLEN_352M:
977 sc->stolen_size = 352 * 1024 * 1024;
978 break;
979 case AGP_SNB_GMCH_GMS_STOLEN_384M:
980 sc->stolen_size = 384 * 1024 * 1024;
981 break;
982 case AGP_SNB_GMCH_GMS_STOLEN_416M:
983 sc->stolen_size = 416 * 1024 * 1024;
984 break;
985 case AGP_SNB_GMCH_GMS_STOLEN_448M:
986 sc->stolen_size = 448 * 1024 * 1024;
987 break;
988 case AGP_SNB_GMCH_GMS_STOLEN_480M:
989 sc->stolen_size = 480 * 1024 * 1024;
990 break;
991 case AGP_SNB_GMCH_GMS_STOLEN_512M:
992 sc->stolen_size = 512 * 1024 * 1024;
993 break;
fdc3c5be 994 }
a904aa53
FT
995 sc->stolen = (sc->stolen_size - 4) / 4096;
996 return (0);
997}
998
09d2c144
MD
999static int
1000agp_gen8_get_stolen_size(device_t dev)
1001{
1002 struct agp_i810_softc *sc;
1003 uint16_t gcc1;
1004 int v;
1005
1006 sc = device_get_softc(dev);
7414ebeb 1007 gcc1 = pci_read_config(dev, AGP_SNB_GCC1, 2);
09d2c144
MD
1008 v = (gcc1 >> 8) & 0xFF;
1009 sc->stolen_size = v * (32L * 1024 * 1024); /* 32MB increments */
09d2c144
MD
1010
1011 return 0;
1012}
1013
a904aa53
FT
1014static int
1015agp_i915_get_gtt_mappable_entries(device_t dev)
1016{
1017 struct agp_i810_softc *sc;
1018 uint32_t ap;
1019
1020 sc = device_get_softc(dev);
1021 ap = AGP_GET_APERTURE(dev);
1022 sc->gtt_mappable_entries = ap >> AGP_PAGE_SHIFT;
1023 return (0);
1024}
1025
1026static int
1027agp_i810_get_gtt_total_entries(device_t dev)
1028{
1029 struct agp_i810_softc *sc;
1030
1031 sc = device_get_softc(dev);
1032 sc->gtt_total_entries = sc->gtt_mappable_entries;
1033 return (0);
1034}
fdc3c5be 1035
a904aa53
FT
1036static int
1037agp_i965_get_gtt_total_entries(device_t dev)
1038{
1039 struct agp_i810_softc *sc;
1040 uint32_t pgetbl_ctl;
1041 int error;
1042
1043 sc = device_get_softc(dev);
1044 error = 0;
1045 pgetbl_ctl = bus_read_4(sc->sc_res[0], AGP_I810_PGTBL_CTL);
1046 switch (pgetbl_ctl & AGP_I810_PGTBL_SIZE_MASK) {
1047 case AGP_I810_PGTBL_SIZE_128KB:
1048 sc->gtt_total_entries = 128 * 1024 / 4;
1049 break;
1050 case AGP_I810_PGTBL_SIZE_256KB:
1051 sc->gtt_total_entries = 256 * 1024 / 4;
1052 break;
1053 case AGP_I810_PGTBL_SIZE_512KB:
1054 sc->gtt_total_entries = 512 * 1024 / 4;
1055 break;
1056 /* GTT pagetable sizes bigger than 512KB are not possible on G33! */
1057 case AGP_I810_PGTBL_SIZE_1MB:
1058 sc->gtt_total_entries = 1024 * 1024 / 4;
1059 break;
1060 case AGP_I810_PGTBL_SIZE_2MB:
1061 sc->gtt_total_entries = 2 * 1024 * 1024 / 4;
1062 break;
1063 case AGP_I810_PGTBL_SIZE_1_5MB:
1064 sc->gtt_total_entries = (1024 + 512) * 1024 / 4;
1065 break;
1066 default:
1067 device_printf(dev, "Unknown page table size\n");
1068 error = ENXIO;
1069 }
1070 return (error);
1071}
1072
1073static void
1074agp_gen5_adjust_pgtbl_size(device_t dev, uint32_t sz)
1075{
1076 struct agp_i810_softc *sc;
1077 uint32_t pgetbl_ctl, pgetbl_ctl2;
1078
1079 sc = device_get_softc(dev);
1080
1081 /* Disable per-process page table. */
1082 pgetbl_ctl2 = bus_read_4(sc->sc_res[0], AGP_I965_PGTBL_CTL2);
1083 pgetbl_ctl2 &= ~AGP_I810_PGTBL_ENABLED;
1084 bus_write_4(sc->sc_res[0], AGP_I965_PGTBL_CTL2, pgetbl_ctl2);
1085
1086 /* Write the new ggtt size. */
1087 pgetbl_ctl = bus_read_4(sc->sc_res[0], AGP_I810_PGTBL_CTL);
1088 pgetbl_ctl &= ~AGP_I810_PGTBL_SIZE_MASK;
1089 pgetbl_ctl |= sz;
1090 bus_write_4(sc->sc_res[0], AGP_I810_PGTBL_CTL, pgetbl_ctl);
1091}
1092
1093static int
1094agp_gen5_get_gtt_total_entries(device_t dev)
1095{
1096 struct agp_i810_softc *sc;
1097 uint16_t gcc1;
1098
1099 sc = device_get_softc(dev);
1100
1101 gcc1 = pci_read_config(sc->bdev, AGP_I830_GCC1, 2);
1102 switch (gcc1 & AGP_G4x_GCC1_SIZE_MASK) {
1103 case AGP_G4x_GCC1_SIZE_1M:
1104 case AGP_G4x_GCC1_SIZE_VT_1M:
1105 agp_gen5_adjust_pgtbl_size(dev, AGP_I810_PGTBL_SIZE_1MB);
1106 break;
1107 case AGP_G4x_GCC1_SIZE_VT_1_5M:
1108 agp_gen5_adjust_pgtbl_size(dev, AGP_I810_PGTBL_SIZE_1_5MB);
1109 break;
1110 case AGP_G4x_GCC1_SIZE_2M:
1111 case AGP_G4x_GCC1_SIZE_VT_2M:
1112 agp_gen5_adjust_pgtbl_size(dev, AGP_I810_PGTBL_SIZE_2MB);
1113 break;
1114 default:
1115 device_printf(dev, "Unknown page table size\n");
1116 return (ENXIO);
1117 }
1118
1119 return (agp_i965_get_gtt_total_entries(dev));
1120}
1121
1122static int
1123agp_sb_get_gtt_total_entries(device_t dev)
1124{
1125 struct agp_i810_softc *sc;
1126 uint16_t gcc1;
1127
1128 sc = device_get_softc(dev);
1129
7414ebeb 1130 gcc1 = pci_read_config(dev, AGP_SNB_GCC1, 2);
a904aa53
FT
1131 switch (gcc1 & AGP_SNB_GTT_SIZE_MASK) {
1132 default:
1133 case AGP_SNB_GTT_SIZE_0M:
1134 kprintf("Bad GTT size mask: 0x%04x\n", gcc1);
1135 return (ENXIO);
1136 case AGP_SNB_GTT_SIZE_1M:
1137 sc->gtt_total_entries = 1024 * 1024 / 4;
1138 break;
1139 case AGP_SNB_GTT_SIZE_2M:
1140 sc->gtt_total_entries = 2 * 1024 * 1024 / 4;
1141 break;
1142 }
1143 return (0);
1144}
1145
09d2c144
MD
1146static int
1147agp_gen8_get_gtt_total_entries(device_t dev)
1148{
1149 struct agp_i810_softc *sc;
1150 uint16_t gcc1;
1151 int v;
1152
1153 sc = device_get_softc(dev);
1154
7414ebeb 1155 gcc1 = pci_read_config(dev, AGP_SNB_GCC1, 2);
09d2c144
MD
1156 v = (gcc1 >> 6) & 3;
1157 if (v)
1158 v = 1 << v;
1159 sc->gtt_total_entries = (v << 20) / 8;
1160
1161 /*
1162 * XXX limit to 2GB due to misc integer overflows calculated on
1163 * this field.
1164 */
1165 while ((long)sc->gtt_total_entries * PAGE_SIZE >= 4LL*1024*1024*1024)
1166 sc->gtt_total_entries >>= 1;
1167
1168 kprintf("GTT SIZE %ld representing %ldM vmap\n",
1169 (long)sc->gtt_total_entries * 8,
1170 (long)sc->gtt_total_entries * PAGE_SIZE);
1171
1172 return 0;
1173}
1174
a904aa53
FT
1175static int
1176agp_i830_install_gatt(device_t dev)
1177{
1178 struct agp_i810_softc *sc;
1179 uint32_t pgtblctl;
1180
1181 sc = device_get_softc(dev);
1182
1183 /*
1184 * The i830 automatically initializes the 128k gatt on boot.
1185 * GATT address is already in there, make sure it's enabled.
1186 */
1187 pgtblctl = bus_read_4(sc->sc_res[0], AGP_I810_PGTBL_CTL);
1188 pgtblctl |= 1;
1189 bus_write_4(sc->sc_res[0], AGP_I810_PGTBL_CTL, pgtblctl);
1190
1191 sc->gatt->ag_physical = pgtblctl & ~1;
1192 return (0);
1193}
1194
7414ebeb
MD
1195static int
1196agp_sb_install_gatt(device_t dev)
1197{
1198 struct agp_i810_softc *sc;
1199 uint32_t pgtblctl;
1200
1201 sc = device_get_softc(dev);
1202
1203 /*
1204 * The i830 automatically initializes the 128k gatt on boot.
1205 * GATT address is already in there, make sure it's enabled.
1206 */
1207 pgtblctl = bus_read_4(sc->sc_res[0], AGP_I810_PGTBL_CTL);
1208 pgtblctl |= 1;
1209 bus_write_4(sc->sc_res[0], AGP_I810_PGTBL_CTL, pgtblctl);
1210
1211 sc->gatt->ag_physical = pgtblctl & ~1;
1212 return (0);
1213}
1214
a904aa53
FT
1215static int
1216agp_i810_attach(device_t dev)
1217{
1218 struct agp_i810_softc *sc;
1219 int error;
1220
1221 sc = device_get_softc(dev);
1222 sc->bdev = agp_i810_find_bridge(dev);
1223 if (sc->bdev == NULL)
1224 return (ENOENT);
1225
1226 sc->match = agp_i810_match(dev);
1227
1228 agp_set_aperture_resource(dev, sc->match->driver->gen <= 2 ?
1229 AGP_APBASE : AGP_I915_GMADR);
1230 error = agp_generic_attach(dev);
1231 if (error)
1232 return (error);
1233
1234 if (ptoa((vm_paddr_t)Maxmem) >
1235 (1ULL << sc->match->driver->busdma_addr_mask_sz) - 1) {
1236 device_printf(dev, "agp_i810 does not support physical "
1237 "memory above %ju.\n", (uintmax_t)(1ULL <<
1238 sc->match->driver->busdma_addr_mask_sz) - 1);
1239 return (ENOENT);
1240 }
1241
1242 if (bus_alloc_resources(dev, sc->match->driver->res_spec, sc->sc_res)) {
1243 agp_generic_detach(dev);
1244 return (ENODEV);
1245 }
1246
1247 sc->initial_aperture = AGP_GET_APERTURE(dev);
1248 sc->gatt = kmalloc(sizeof(struct agp_gatt), M_AGP, M_WAITOK);
1249 sc->gatt->ag_entries = AGP_GET_APERTURE(dev) >> AGP_PAGE_SHIFT;
1250
1251 if ((error = sc->match->driver->get_stolen_size(dev)) != 0 ||
1252 (error = sc->match->driver->install_gatt(dev)) != 0 ||
1253 (error = sc->match->driver->get_gtt_mappable_entries(dev)) != 0 ||
1254 (error = sc->match->driver->get_gtt_total_entries(dev)) != 0 ||
1255 (error = sc->match->driver->chipset_flush_setup(dev)) != 0) {
1256 bus_release_resources(dev, sc->match->driver->res_spec,
1257 sc->sc_res);
1258 kfree(sc->gatt, M_AGP);
1259 agp_generic_detach(dev);
1260 return (error);
1261 }
1262
1263 intel_agp = dev;
7f9ec87c
FT
1264 device_printf(dev, "aperture size is %dM",
1265 sc->initial_aperture / 1024 / 1024);
1266 if (sc->stolen > 0)
1267 kprintf(", detected %dk stolen memory\n", sc->stolen * 4);
1268 else
1269 kprintf("\n");
a904aa53
FT
1270 if (bootverbose) {
1271 sc->match->driver->dump_regs(dev);
1272 device_printf(dev, "Mappable GTT entries: %d\n",
1273 sc->gtt_mappable_entries);
1274 device_printf(dev, "Total GTT entries: %d\n",
1275 sc->gtt_total_entries);
1276 }
1277 return (0);
1278}
7f9ec87c 1279
a904aa53
FT
1280static void
1281agp_i830_deinstall_gatt(device_t dev)
1282{
1283 struct agp_i810_softc *sc;
1284 unsigned int pgtblctl;
1285
1286 sc = device_get_softc(dev);
1287 pgtblctl = bus_read_4(sc->sc_res[0], AGP_I810_PGTBL_CTL);
1288 pgtblctl &= ~1;
1289 bus_write_4(sc->sc_res[0], AGP_I810_PGTBL_CTL, pgtblctl);
984263bc
MD
1290}
1291
7414ebeb
MD
1292static void
1293agp_sb_deinstall_gatt(device_t dev)
1294{
1295 struct agp_i810_softc *sc;
1296 unsigned int pgtblctl;
1297
1298 sc = device_get_softc(dev);
1299 if (sc->sc_res[0]) {
1300 pgtblctl = bus_read_4(sc->sc_res[0], AGP_I810_PGTBL_CTL);
1301 pgtblctl &= ~1;
1302 bus_write_4(sc->sc_res[0], AGP_I810_PGTBL_CTL, pgtblctl);
1303 }
1304}
1305
984263bc
MD
1306static int
1307agp_i810_detach(device_t dev)
1308{
a904aa53 1309 struct agp_i810_softc *sc;
984263bc 1310
a904aa53 1311 sc = device_get_softc(dev);
67e2dc5d 1312 agp_free_cdev(dev);
984263bc
MD
1313
1314 /* Clear the GATT base. */
a904aa53
FT
1315 sc->match->driver->deinstall_gatt(dev);
1316
1317 sc->match->driver->chipset_flush_teardown(dev);
984263bc
MD
1318
1319 /* Put the aperture back the way it started. */
1320 AGP_SET_APERTURE(dev, sc->initial_aperture);
1321
efda3bd0 1322 kfree(sc->gatt, M_AGP);
a904aa53 1323 bus_release_resources(dev, sc->match->driver->res_spec, sc->sc_res);
67e2dc5d 1324 agp_free_res(dev);
984263bc 1325
a904aa53 1326 return (0);
984263bc
MD
1327}
1328
2f1d30c1
HT
1329static int
1330agp_i810_resume(device_t dev)
1331{
1332 struct agp_i810_softc *sc;
1333 sc = device_get_softc(dev);
1334
1335 AGP_SET_APERTURE(dev, sc->initial_aperture);
1336
1337 /* Install the GATT. */
1338 bus_write_4(sc->sc_res[0], AGP_I810_PGTBL_CTL,
1339 sc->gatt->ag_physical | 1);
1340
1341 return (bus_generic_resume(dev));
1342}
1343
fdc3c5be
HT
1344/**
1345 * Sets the PCI resource size of the aperture on i830-class and below chipsets,
1346 * while returning failure on later chipsets when an actual change is
1347 * requested.
1348 *
1349 * This whole function is likely bogus, as the kernel would probably need to
1350 * reconfigure the placement of the AGP aperture if a larger size is requested,
1351 * which doesn't happen currently.
1352 */
a904aa53
FT
1353
1354static int
1355agp_i915_set_aperture(device_t dev, u_int32_t aperture)
1356{
984263bc 1357
a904aa53
FT
1358 return (agp_generic_set_aperture(dev, aperture));
1359}
1360
1361static int
1362agp_i810_method_set_aperture(device_t dev, u_int32_t aperture)
1363{
1364 struct agp_i810_softc *sc;
1365
1366 sc = device_get_softc(dev);
1367 return (sc->match->driver->set_aperture(dev, aperture));
984263bc
MD
1368}
1369
fdc3c5be 1370/**
a904aa53
FT
1371 * Writes a GTT entry mapping the page at the given offset from the
1372 * beginning of the aperture to the given physical address. Setup the
1373 * caching mode according to flags.
1374 *
1375 * For gen 1, 2 and 3, GTT start is located at AGP_I810_GTT offset
1376 * from corresponding BAR start. For gen 4, offset is 512KB +
1377 * AGP_I810_GTT, for gen 5 and 6 it is 2MB + AGP_I810_GTT.
1378 *
1379 * Also, the bits of the physical page address above 4GB needs to be
1380 * placed into bits 40-32 of PTE.
fdc3c5be 1381 */
a904aa53
FT
1382static void
1383agp_i915_install_gtt_pte(device_t dev, u_int index, vm_offset_t physical,
1384 int flags)
1385{
1386 uint32_t pte;
1387
1388 pte = (u_int32_t)physical | I810_PTE_VALID;
1389 if (flags == AGP_USER_CACHED_MEMORY)
1390 pte |= I830_PTE_SYSTEM_CACHED;
99e9e211 1391
a904aa53
FT
1392 agp_i915_write_gtt(dev, index, pte);
1393}
1394
1395static void
1396agp_i915_write_gtt(device_t dev, u_int index, uint32_t pte)
1397{
1398 struct agp_i810_softc *sc;
1399
1400 sc = device_get_softc(dev);
7414ebeb 1401 bus_write_4(sc->sc_res[0], index * 4, pte);
a904aa53
FT
1402}
1403
1404static void
1405agp_i965_install_gtt_pte(device_t dev, u_int index, vm_offset_t physical,
1406 int flags)
1407{
1408 uint32_t pte;
1409
1410 pte = (u_int32_t)physical | I810_PTE_VALID;
1411 if (flags == AGP_USER_CACHED_MEMORY)
1412 pte |= I830_PTE_SYSTEM_CACHED;
99e9e211
FT
1413
1414 pte |= (physical >> 28) & 0xf0;
a904aa53
FT
1415 agp_i965_write_gtt(dev, index, pte);
1416}
1417
1418static void
1419agp_i965_write_gtt(device_t dev, u_int index, uint32_t pte)
1420{
1421 struct agp_i810_softc *sc;
1422
1423 sc = device_get_softc(dev);
1424 bus_write_4(sc->sc_res[0], index * 4 + (512 * 1024), pte);
1425}
1426
1427static void
1428agp_g4x_install_gtt_pte(device_t dev, u_int index, vm_offset_t physical,
1429 int flags)
1430{
1431 uint32_t pte;
1432
1433 pte = (u_int32_t)physical | I810_PTE_VALID;
1434 if (flags == AGP_USER_CACHED_MEMORY)
1435 pte |= I830_PTE_SYSTEM_CACHED;
99e9e211
FT
1436
1437 pte |= (physical >> 28) & 0xf0;
a904aa53
FT
1438 agp_g4x_write_gtt(dev, index, pte);
1439}
1440
1441static void
1442agp_g4x_write_gtt(device_t dev, u_int index, uint32_t pte)
1443{
1444 struct agp_i810_softc *sc;
1445
1446 sc = device_get_softc(dev);
1447 bus_write_4(sc->sc_res[0], index * 4 + (2 * 1024 * 1024), pte);
1448}
1449
1450static void
09d2c144
MD
1451agp_sb_install_gtt_pte(device_t dev, u_int index,
1452 vm_offset_t physical, int flags)
a904aa53
FT
1453{
1454 int type_mask, gfdt;
1455 uint32_t pte;
1456
1457 pte = (u_int32_t)physical | I810_PTE_VALID;
1458 type_mask = flags & ~AGP_USER_CACHED_MEMORY_GFDT;
1459 gfdt = (flags & AGP_USER_CACHED_MEMORY_GFDT) != 0 ? GEN6_PTE_GFDT : 0;
1460
1461 if (type_mask == AGP_USER_MEMORY)
1462 pte |= GEN6_PTE_UNCACHED;
1463 else if (type_mask == AGP_USER_CACHED_MEMORY_LLC_MLC)
1464 pte |= GEN6_PTE_LLC_MLC | gfdt;
1465 else
1466 pte |= GEN6_PTE_LLC | gfdt;
1467
1468 pte |= (physical & 0x000000ff00000000ull) >> 28;
1469 agp_sb_write_gtt(dev, index, pte);
7414ebeb
MD
1470}
1471
09d2c144
MD
1472static void
1473agp_gen8_install_gtt_pte(device_t dev, u_int index,
1474 vm_offset_t physical, int flags)
1475{
1476 struct agp_i810_softc *sc;
1477 int type_mask;
1478 uint64_t pte;
1479
1480 pte = (u_int64_t)physical | GEN8_PTE_PRESENT | GEN8_PTE_RW;
1481 type_mask = flags & ~AGP_USER_CACHED_MEMORY_GFDT;
1482
1483 if (type_mask == AGP_USER_MEMORY)
1484 pte |= GEN8_PTE_PWT; /* XXX */
1485 else if (type_mask == AGP_USER_CACHED_MEMORY_LLC_MLC)
1486 pte |= GEN8_PTE_PWT; /* XXX */
1487 else
1488 pte |= GEN8_PTE_PWT; /* XXX */
1489
1490 sc = device_get_softc(dev);
1491 bus_write_4(sc->sc_res[0], index * 8 + (2 * 1024 * 1024),
1492 (uint32_t)pte);
1493 bus_write_4(sc->sc_res[0], index * 8 + (2 * 1024 * 1024) + 4,
1494 (uint32_t)(pte >> 32));
1495}
1496
a904aa53
FT
1497static void
1498agp_sb_write_gtt(device_t dev, u_int index, uint32_t pte)
1499{
1500 struct agp_i810_softc *sc;
1501
1502 sc = device_get_softc(dev);
1503 bus_write_4(sc->sc_res[0], index * 4 + (2 * 1024 * 1024), pte);
1504}
1505
1506static int
1507agp_i810_bind_page(device_t dev, vm_offset_t offset, vm_offset_t physical)
fdc3c5be
HT
1508{
1509 struct agp_i810_softc *sc = device_get_softc(dev);
a904aa53 1510 u_int index;
fdc3c5be 1511
a904aa53
FT
1512 if (offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT)) {
1513 device_printf(dev, "failed: offset is 0x%08jx, "
1514 "shift is %d, entries is %d\n", (intmax_t)offset,
1515 AGP_PAGE_SHIFT, sc->gatt->ag_entries);
1516 return (EINVAL);
1517 }
1518 index = offset >> AGP_PAGE_SHIFT;
1519 if (sc->stolen != 0 && index < sc->stolen) {
1520 device_printf(dev, "trying to bind into stolen memory\n");
1521 return (EINVAL);
fdc3c5be 1522 }
a904aa53
FT
1523 sc->match->driver->install_gtt_pte(dev, index, physical, 0);
1524 return (0);
1525}
fdc3c5be 1526
a904aa53
FT
1527static int
1528agp_i810_unbind_page(device_t dev, vm_offset_t offset)
1529{
1530 struct agp_i810_softc *sc;
1531 u_int index;
1532
1533 sc = device_get_softc(dev);
1534 if (offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT))
1535 return (EINVAL);
1536 index = offset >> AGP_PAGE_SHIFT;
1537 if (sc->stolen != 0 && index < sc->stolen) {
1538 device_printf(dev, "trying to unbind from stolen memory\n");
1539 return (EINVAL);
fdc3c5be 1540 }
a904aa53
FT
1541 sc->match->driver->install_gtt_pte(dev, index, 0, 0);
1542 return (0);
1543}
1544
09d2c144
MD
1545static void
1546agp_i915_sync_gtt_pte(device_t dev, u_int index)
a904aa53
FT
1547{
1548 struct agp_i810_softc *sc;
fdc3c5be 1549
a904aa53 1550 sc = device_get_softc(dev);
09d2c144 1551 bus_read_4(sc->sc_res[1], index * 4);
984263bc
MD
1552}
1553
09d2c144
MD
1554static void
1555agp_i965_sync_gtt_pte(device_t dev, u_int index)
a904aa53
FT
1556{
1557 struct agp_i810_softc *sc;
984263bc 1558
a904aa53 1559 sc = device_get_softc(dev);
09d2c144 1560 bus_read_4(sc->sc_res[0], index * 4 + (512 * 1024));
a904aa53
FT
1561}
1562
09d2c144
MD
1563static void
1564agp_g4x_sync_gtt_pte(device_t dev, u_int index)
a904aa53
FT
1565{
1566 struct agp_i810_softc *sc;
fdc3c5be 1567
a904aa53 1568 sc = device_get_softc(dev);
09d2c144 1569 bus_read_4(sc->sc_res[0], index * 4 + (2 * 1024 * 1024));
984263bc
MD
1570}
1571
1572/*
1573 * Writing via memory mapped registers already flushes all TLBs.
1574 */
1575static void
1576agp_i810_flush_tlb(device_t dev)
1577{
1578}
1579
1580static int
1581agp_i810_enable(device_t dev, u_int32_t mode)
1582{
1583
a904aa53 1584 return (0);
984263bc
MD
1585}
1586
1587static struct agp_memory *
1588agp_i810_alloc_memory(device_t dev, int type, vm_size_t size)
1589{
a904aa53 1590 struct agp_i810_softc *sc;
984263bc 1591 struct agp_memory *mem;
a904aa53 1592 vm_page_t m;
984263bc 1593
a904aa53 1594 sc = device_get_softc(dev);
984263bc 1595
a904aa53
FT
1596 if ((size & (AGP_PAGE_SIZE - 1)) != 0 ||
1597 sc->agp.as_allocated + size > sc->agp.as_maxmem)
1598 return (0);
984263bc
MD
1599
1600 if (type == 1) {
1601 /*
1602 * Mapping local DRAM into GATT.
1603 */
a904aa53
FT
1604 if (sc->match->driver->chiptype != CHIP_I810)
1605 return (0);
984263bc 1606 if (size != sc->dcache_size)
a904aa53 1607 return (0);
984263bc
MD
1608 } else if (type == 2) {
1609 /*
fdc3c5be
HT
1610 * Type 2 is the contiguous physical memory type, that hands
1611 * back a physical address. This is used for cursors on i810.
1612 * Hand back as many single pages with physical as the user
1613 * wants, but only allow one larger allocation (ARGB cursor)
1614 * for simplicity.
984263bc 1615 */
fdc3c5be
HT
1616 if (size != AGP_PAGE_SIZE) {
1617 if (sc->argb_cursor != NULL)
a904aa53 1618 return (0);
fdc3c5be
HT
1619
1620 /* Allocate memory for ARGB cursor, if we can. */
1621 sc->argb_cursor = contigmalloc(size, M_AGP,
1622 0, 0, ~0, PAGE_SIZE, 0);
1623 if (sc->argb_cursor == NULL)
a904aa53 1624 return (0);
fdc3c5be 1625 }
984263bc
MD
1626 }
1627
efda3bd0 1628 mem = kmalloc(sizeof *mem, M_AGP, M_INTWAIT);
984263bc
MD
1629 mem->am_id = sc->agp.as_nextid++;
1630 mem->am_size = size;
1631 mem->am_type = type;
fdc3c5be 1632 if (type != 1 && (type != 2 || size == AGP_PAGE_SIZE))
984263bc 1633 mem->am_obj = vm_object_allocate(OBJT_DEFAULT,
a904aa53 1634 atop(round_page(size)));
984263bc
MD
1635 else
1636 mem->am_obj = 0;
1637
1638 if (type == 2) {
fdc3c5be
HT
1639 if (size == AGP_PAGE_SIZE) {
1640 /*
1641 * Allocate and wire down the page now so that we can
1642 * get its physical address.
1643 */
a904aa53 1644 VM_OBJECT_LOCK(mem->am_obj);
d2d8515b
MD
1645 m = vm_page_grab(mem->am_obj, 0, VM_ALLOC_NORMAL |
1646 VM_ALLOC_ZERO |
1647 VM_ALLOC_RETRY);
fdc3c5be 1648 vm_page_wire(m);
a904aa53 1649 VM_OBJECT_UNLOCK(mem->am_obj);
fdc3c5be
HT
1650 mem->am_physical = VM_PAGE_TO_PHYS(m);
1651 vm_page_wakeup(m);
1652 } else {
1653 /* Our allocation is already nicely wired down for us.
1654 * Just grab the physical address.
1655 */
1656 mem->am_physical = vtophys(sc->argb_cursor);
1657 }
a904aa53 1658 } else
984263bc 1659 mem->am_physical = 0;
984263bc
MD
1660
1661 mem->am_offset = 0;
1662 mem->am_is_bound = 0;
1663 TAILQ_INSERT_TAIL(&sc->agp.as_memory, mem, am_link);
1664 sc->agp.as_allocated += size;
1665
a904aa53 1666 return (mem);
984263bc
MD
1667}
1668
1669static int
1670agp_i810_free_memory(device_t dev, struct agp_memory *mem)
1671{
a904aa53 1672 struct agp_i810_softc *sc;
984263bc
MD
1673
1674 if (mem->am_is_bound)
a904aa53
FT
1675 return (EBUSY);
1676
1677 sc = device_get_softc(dev);
984263bc
MD
1678
1679 if (mem->am_type == 2) {
fdc3c5be
HT
1680 if (mem->am_size == AGP_PAGE_SIZE) {
1681 /*
1682 * Unwire the page which we wired in alloc_memory.
1683 */
77912481 1684 vm_page_t m;
b12defdc
MD
1685
1686 vm_object_hold(mem->am_obj);
1687 m = vm_page_lookup_busy_wait(mem->am_obj, 0,
1688 FALSE, "agppg");
1689 vm_object_drop(mem->am_obj);
fdc3c5be 1690 vm_page_unwire(m, 0);
b12defdc 1691 vm_page_wakeup(m);
fdc3c5be
HT
1692 } else {
1693 contigfree(sc->argb_cursor, mem->am_size, M_AGP);
1694 sc->argb_cursor = NULL;
1695 }
984263bc
MD
1696 }
1697
1698 sc->agp.as_allocated -= mem->am_size;
1699 TAILQ_REMOVE(&sc->agp.as_memory, mem, am_link);
1700 if (mem->am_obj)
1701 vm_object_deallocate(mem->am_obj);
efda3bd0 1702 kfree(mem, M_AGP);
a904aa53 1703 return (0);
984263bc
MD
1704}
1705
1706static int
a904aa53 1707agp_i810_bind_memory(device_t dev, struct agp_memory *mem, vm_offset_t offset)
984263bc 1708{
a904aa53 1709 struct agp_i810_softc *sc;
984263bc
MD
1710 vm_offset_t i;
1711
fdc3c5be 1712 /* Do some sanity checks first. */
7f9ec87c 1713 if ((offset & (AGP_PAGE_SIZE - 1)) != 0 ||
fdc3c5be
HT
1714 offset + mem->am_size > AGP_GET_APERTURE(dev)) {
1715 device_printf(dev, "binding memory at bad offset %#x\n",
1716 (int)offset);
a904aa53 1717 return (EINVAL);
fdc3c5be
HT
1718 }
1719
a904aa53 1720 sc = device_get_softc(dev);
fdc3c5be
HT
1721 if (mem->am_type == 2 && mem->am_size != AGP_PAGE_SIZE) {
1722 lockmgr(&sc->agp.as_lock, LK_EXCLUSIVE);
1723 if (mem->am_is_bound) {
1724 lockmgr(&sc->agp.as_lock, LK_RELEASE);
1725 return EINVAL;
1726 }
1727 /* The memory's already wired down, just stick it in the GTT. */
1728 for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) {
a904aa53
FT
1729 sc->match->driver->install_gtt_pte(dev, (offset + i) >>
1730 AGP_PAGE_SHIFT, mem->am_physical + i, 0);
fdc3c5be
HT
1731 }
1732 agp_flush_cache();
1733 mem->am_offset = offset;
1734 mem->am_is_bound = 1;
1735 lockmgr(&sc->agp.as_lock, LK_RELEASE);
a904aa53 1736 return (0);
fdc3c5be
HT
1737 }
1738
984263bc 1739 if (mem->am_type != 1)
a904aa53 1740 return (agp_generic_bind_memory(dev, mem, offset));
984263bc 1741
a904aa53
FT
1742 /*
1743 * Mapping local DRAM into GATT.
1744 */
1745 if (sc->match->driver->chiptype != CHIP_I810)
1746 return (EINVAL);
1747 for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE)
fdc3c5be
HT
1748 bus_write_4(sc->sc_res[0],
1749 AGP_I810_GTT + (i >> AGP_PAGE_SHIFT) * 4, i | 3);
984263bc 1750
a904aa53 1751 return (0);
984263bc
MD
1752}
1753
1754static int
1755agp_i810_unbind_memory(device_t dev, struct agp_memory *mem)
1756{
a904aa53 1757 struct agp_i810_softc *sc;
984263bc
MD
1758 vm_offset_t i;
1759
a904aa53
FT
1760 sc = device_get_softc(dev);
1761
fdc3c5be
HT
1762 if (mem->am_type == 2 && mem->am_size != AGP_PAGE_SIZE) {
1763 lockmgr(&sc->agp.as_lock, LK_EXCLUSIVE);
1764 if (!mem->am_is_bound) {
1765 lockmgr(&sc->agp.as_lock, LK_RELEASE);
a904aa53 1766 return (EINVAL);
fdc3c5be
HT
1767 }
1768
1769 for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) {
a904aa53
FT
1770 sc->match->driver->install_gtt_pte(dev,
1771 (mem->am_offset + i) >> AGP_PAGE_SHIFT, 0, 0);
fdc3c5be
HT
1772 }
1773 agp_flush_cache();
1774 mem->am_is_bound = 0;
1775 lockmgr(&sc->agp.as_lock, LK_RELEASE);
a904aa53 1776 return (0);
fdc3c5be
HT
1777 }
1778
984263bc 1779 if (mem->am_type != 1)
a904aa53 1780 return (agp_generic_unbind_memory(dev, mem));
984263bc 1781
a904aa53
FT
1782 if (sc->match->driver->chiptype != CHIP_I810)
1783 return (EINVAL);
fdc3c5be 1784 for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) {
a904aa53
FT
1785 sc->match->driver->install_gtt_pte(dev, i >> AGP_PAGE_SHIFT,
1786 0, 0);
fdc3c5be 1787 }
a904aa53 1788 return (0);
984263bc
MD
1789}
1790
1791static device_method_t agp_i810_methods[] = {
1792 /* Device interface */
fdc3c5be 1793 DEVMETHOD(device_identify, agp_i810_identify),
984263bc
MD
1794 DEVMETHOD(device_probe, agp_i810_probe),
1795 DEVMETHOD(device_attach, agp_i810_attach),
1796 DEVMETHOD(device_detach, agp_i810_detach),
2f1d30c1
HT
1797 DEVMETHOD(device_suspend, bus_generic_suspend),
1798 DEVMETHOD(device_resume, agp_i810_resume),
984263bc
MD
1799
1800 /* AGP interface */
fdc3c5be 1801 DEVMETHOD(agp_get_aperture, agp_generic_get_aperture),
a904aa53 1802 DEVMETHOD(agp_set_aperture, agp_i810_method_set_aperture),
984263bc
MD
1803 DEVMETHOD(agp_bind_page, agp_i810_bind_page),
1804 DEVMETHOD(agp_unbind_page, agp_i810_unbind_page),
1805 DEVMETHOD(agp_flush_tlb, agp_i810_flush_tlb),
1806 DEVMETHOD(agp_enable, agp_i810_enable),
1807 DEVMETHOD(agp_alloc_memory, agp_i810_alloc_memory),
1808 DEVMETHOD(agp_free_memory, agp_i810_free_memory),
1809 DEVMETHOD(agp_bind_memory, agp_i810_bind_memory),
1810 DEVMETHOD(agp_unbind_memory, agp_i810_unbind_memory),
a904aa53 1811 DEVMETHOD(agp_chipset_flush, agp_intel_gtt_chipset_flush),
984263bc 1812
d3c9c58e 1813 DEVMETHOD_END
984263bc
MD
1814};
1815
1816static driver_t agp_i810_driver = {
1817 "agp",
1818 agp_i810_methods,
1819 sizeof(struct agp_i810_softc),
1820};
1821
1822static devclass_t agp_devclass;
1823
aa2b9d05 1824DRIVER_MODULE(agp_i810, vgapci, agp_i810_driver, agp_devclass, NULL, NULL);
f7841f3c
MD
1825MODULE_DEPEND(agp_i810, agp, 1, 1, 1);
1826MODULE_DEPEND(agp_i810, pci, 1, 1, 1);
a904aa53
FT
1827
1828extern vm_page_t bogus_page;
1829
1830void
1831agp_intel_gtt_clear_range(device_t dev, u_int first_entry, u_int num_entries)
1832{
1833 struct agp_i810_softc *sc;
1834 u_int i;
1835
1836 sc = device_get_softc(dev);
1837 for (i = 0; i < num_entries; i++)
1838 sc->match->driver->install_gtt_pte(dev, first_entry + i,
1839 VM_PAGE_TO_PHYS(bogus_page), 0);
09d2c144 1840 sc->match->driver->sync_gtt_pte(dev, first_entry + num_entries - 1);
a904aa53
FT
1841}
1842
1843void
1844agp_intel_gtt_insert_pages(device_t dev, u_int first_entry, u_int num_entries,
1845 vm_page_t *pages, u_int flags)
1846{
1847 struct agp_i810_softc *sc;
1848 u_int i;
1849
1850 sc = device_get_softc(dev);
1851 for (i = 0; i < num_entries; i++) {
1852 KKASSERT(pages[i]->valid == VM_PAGE_BITS_ALL);
1853 KKASSERT(pages[i]->wire_count > 0);
1854 sc->match->driver->install_gtt_pte(dev, first_entry + i,
1855 VM_PAGE_TO_PHYS(pages[i]), flags);
1856 }
09d2c144 1857 sc->match->driver->sync_gtt_pte(dev, first_entry + num_entries - 1);
a904aa53
FT
1858}
1859
1860struct intel_gtt
1861agp_intel_gtt_get(device_t dev)
1862{
1863 struct agp_i810_softc *sc;
1864 struct intel_gtt res;
1865
1866 sc = device_get_softc(dev);
1867 res.stolen_size = sc->stolen_size;
1868 res.gtt_total_entries = sc->gtt_total_entries;
1869 res.gtt_mappable_entries = sc->gtt_mappable_entries;
1870 res.do_idle_maps = 0;
1871 res.scratch_page_dma = VM_PAGE_TO_PHYS(bogus_page);
1872 return (res);
1873}
1874
1875static int
1876agp_i810_chipset_flush_setup(device_t dev)
1877{
1878
1879 return (0);
1880}
1881
1882static void
1883agp_i810_chipset_flush_teardown(device_t dev)
1884{
1885
1886 /* Nothing to do. */
1887}
1888
1889static void
1890agp_i810_chipset_flush(device_t dev)
1891{
1892
1893 /* Nothing to do. */
1894}
1895
a904aa53
FT
1896static int
1897agp_i915_chipset_flush_alloc_page(device_t dev, uint64_t start, uint64_t end)
1898{
1899 struct agp_i810_softc *sc;
1900 device_t vga;
1901
1902 sc = device_get_softc(dev);
1903 vga = device_get_parent(dev);
1904 sc->sc_flush_page_rid = 100;
1905 sc->sc_flush_page_res = BUS_ALLOC_RESOURCE(device_get_parent(vga), dev,
1906 SYS_RES_MEMORY, &sc->sc_flush_page_rid, start, end, PAGE_SIZE,
1907 RF_ACTIVE, -1);
1908 if (sc->sc_flush_page_res == NULL) {
1909 device_printf(dev, "Failed to allocate flush page at 0x%jx\n",
1910 (uintmax_t)start);
1911 return (EINVAL);
1912 }
1913 sc->sc_flush_page_vaddr = rman_get_virtual(sc->sc_flush_page_res);
1914 if (bootverbose) {
1915 device_printf(dev, "Allocated flush page phys 0x%jx virt %p\n",
1916 (uintmax_t)rman_get_start(sc->sc_flush_page_res),
1917 sc->sc_flush_page_vaddr);
1918 }
1919 return (0);
1920}
1921
1922static void
1923agp_i915_chipset_flush_free_page(device_t dev)
1924{
1925 struct agp_i810_softc *sc;
1926 device_t vga;
1927
1928 sc = device_get_softc(dev);
1929 vga = device_get_parent(dev);
1930 if (sc->sc_flush_page_res == NULL)
1931 return;
1932 BUS_DEACTIVATE_RESOURCE(device_get_parent(vga), dev, SYS_RES_MEMORY,
1933 sc->sc_flush_page_rid, sc->sc_flush_page_res);
1934 BUS_RELEASE_RESOURCE(device_get_parent(vga), dev, SYS_RES_MEMORY,
1935 sc->sc_flush_page_rid, sc->sc_flush_page_res);
1936}
1937
1938static int
1939agp_i915_chipset_flush_setup(device_t dev)
1940{
1941 struct agp_i810_softc *sc;
1942 uint32_t temp;
1943 int error;
1944
1945 sc = device_get_softc(dev);
1946 temp = pci_read_config(sc->bdev, AGP_I915_IFPADDR, 4);
1947 if ((temp & 1) != 0) {
1948 temp &= ~1;
1949 if (bootverbose)
1950 device_printf(dev,
1951 "Found already configured flush page at 0x%jx\n",
1952 (uintmax_t)temp);
1953 sc->sc_bios_allocated_flush_page = 1;
1954 /*
1955 * In the case BIOS initialized the flush pointer (?)
1956 * register, expect that BIOS also set up the resource
1957 * for the page.
1958 */
1959 error = agp_i915_chipset_flush_alloc_page(dev, temp,
1960 temp + PAGE_SIZE - 1);
1961 if (error != 0)
1962 return (error);
1963 } else {
1964 sc->sc_bios_allocated_flush_page = 0;
1965 error = agp_i915_chipset_flush_alloc_page(dev, 0, 0xffffffff);
1966 if (error != 0)
1967 return (error);
1968 temp = rman_get_start(sc->sc_flush_page_res);
1969 pci_write_config(sc->bdev, AGP_I915_IFPADDR, temp | 1, 4);
1970 }
1971 return (0);
1972}
1973
1974static void
1975agp_i915_chipset_flush_teardown(device_t dev)
1976{
1977 struct agp_i810_softc *sc;
1978 uint32_t temp;
1979
1980 sc = device_get_softc(dev);
1981 if (sc->sc_flush_page_res == NULL)
1982 return;
1983 if (!sc->sc_bios_allocated_flush_page) {
1984 temp = pci_read_config(sc->bdev, AGP_I915_IFPADDR, 4);
1985 temp &= ~1;
1986 pci_write_config(sc->bdev, AGP_I915_IFPADDR, temp, 4);
1987 }
1988 agp_i915_chipset_flush_free_page(dev);
1989}
1990
1991static int
1992agp_i965_chipset_flush_setup(device_t dev)
1993{
1994 struct agp_i810_softc *sc;
1995 uint64_t temp;
1996 uint32_t temp_hi, temp_lo;
1997 int error;
1998
1999 sc = device_get_softc(dev);
2000
2001 temp_hi = pci_read_config(sc->bdev, AGP_I965_IFPADDR + 4, 4);
2002 temp_lo = pci_read_config(sc->bdev, AGP_I965_IFPADDR, 4);
2003
2004 if ((temp_lo & 1) != 0) {
2005 temp = ((uint64_t)temp_hi << 32) | (temp_lo & ~1);
2006 if (bootverbose)
2007 device_printf(dev,
2008 "Found already configured flush page at 0x%jx\n",
2009 (uintmax_t)temp);
2010 sc->sc_bios_allocated_flush_page = 1;
2011 /*
2012 * In the case BIOS initialized the flush pointer (?)
2013 * register, expect that BIOS also set up the resource
2014 * for the page.
2015 */
2016 error = agp_i915_chipset_flush_alloc_page(dev, temp,
2017 temp + PAGE_SIZE - 1);
2018 if (error != 0)
2019 return (error);
2020 } else {
2021 sc->sc_bios_allocated_flush_page = 0;
2022 error = agp_i915_chipset_flush_alloc_page(dev, 0, ~0);
2023 if (error != 0)
2024 return (error);
2025 temp = rman_get_start(sc->sc_flush_page_res);
2026 pci_write_config(sc->bdev, AGP_I965_IFPADDR + 4,
2027 (temp >> 32) & UINT32_MAX, 4);
2028 pci_write_config(sc->bdev, AGP_I965_IFPADDR,
2029 (temp & UINT32_MAX) | 1, 4);
2030 }
2031 return (0);
2032}
2033
2034static void
2035agp_i965_chipset_flush_teardown(device_t dev)
2036{
2037 struct agp_i810_softc *sc;
2038 uint32_t temp_lo;
2039
2040 sc = device_get_softc(dev);
2041 if (sc->sc_flush_page_res == NULL)
2042 return;
2043 if (!sc->sc_bios_allocated_flush_page) {
2044 temp_lo = pci_read_config(sc->bdev, AGP_I965_IFPADDR, 4);
2045 temp_lo &= ~1;
2046 pci_write_config(sc->bdev, AGP_I965_IFPADDR, temp_lo, 4);
2047 }
2048 agp_i915_chipset_flush_free_page(dev);
2049}
2050
2051static void
2052agp_i915_chipset_flush(device_t dev)
2053{
2054 struct agp_i810_softc *sc;
2055
2056 sc = device_get_softc(dev);
2057 *(uint32_t *)sc->sc_flush_page_vaddr = 1;
2058}
2059
2060int
2061agp_intel_gtt_chipset_flush(device_t dev)
2062{
2063 struct agp_i810_softc *sc;
2064
2065 sc = device_get_softc(dev);
2066 sc->match->driver->chipset_flush(dev);
2067 return (0);
2068}
2069
2070void
2071agp_intel_gtt_unmap_memory(device_t dev, struct sglist *sg_list)
2072{
2073}
2074
2075int
2076agp_intel_gtt_map_memory(device_t dev, vm_page_t *pages, u_int num_entries,
2077 struct sglist **sg_list)
2078{
839fbabb 2079#if 0
a904aa53 2080 struct agp_i810_softc *sc;
839fbabb 2081#endif
a904aa53
FT
2082 struct sglist *sg;
2083 int i;
2084#if 0
2085 int error;
2086 bus_dma_tag_t dmat;
2087#endif
2088
2089 if (*sg_list != NULL)
2090 return (0);
839fbabb 2091#if 0
a904aa53 2092 sc = device_get_softc(dev);
839fbabb 2093#endif
a904aa53
FT
2094 sg = sglist_alloc(num_entries, M_WAITOK /* XXXKIB */);
2095 for (i = 0; i < num_entries; i++) {
2096 sg->sg_segs[i].ss_paddr = VM_PAGE_TO_PHYS(pages[i]);
2097 sg->sg_segs[i].ss_len = PAGE_SIZE;
2098 }
2099
2100#if 0
2101 error = bus_dma_tag_create(bus_get_dma_tag(dev),
2102 1 /* alignment */, 0 /* boundary */,
2103 1ULL << sc->match->busdma_addr_mask_sz /* lowaddr */,
2104 BUS_SPACE_MAXADDR /* highaddr */,
2105 NULL /* filtfunc */, NULL /* filtfuncarg */,
2106 BUS_SPACE_MAXADDR /* maxsize */,
2107 BUS_SPACE_UNRESTRICTED /* nsegments */,
2108 BUS_SPACE_MAXADDR /* maxsegsz */,
2109 0 /* flags */, NULL /* lockfunc */, NULL /* lockfuncarg */,
2110 &dmat);
2111 if (error != 0) {
2112 sglist_free(sg);
2113 return (error);
2114 }
2115 /* XXXKIB */
2116#endif
2117 *sg_list = sg;
2118 return (0);
2119}
2120
2121void
2122agp_intel_gtt_insert_sg_entries(device_t dev, struct sglist *sg_list,
2123 u_int first_entry, u_int flags)
2124{
2125 struct agp_i810_softc *sc;
2126 vm_paddr_t spaddr;
2127 size_t slen;
2128 u_int i, j;
2129
2130 sc = device_get_softc(dev);
2131 for (i = j = 0; j < sg_list->sg_nseg; j++) {
2132 spaddr = sg_list->sg_segs[i].ss_paddr;
2133 slen = sg_list->sg_segs[i].ss_len;
2134 for (; slen > 0; i++) {
2135 sc->match->driver->install_gtt_pte(dev, first_entry + i,
2136 spaddr, flags);
2137 spaddr += AGP_PAGE_SIZE;
2138 slen -= AGP_PAGE_SIZE;
2139 }
2140 }
09d2c144 2141 sc->match->driver->sync_gtt_pte(dev, first_entry + i - 1);
a904aa53
FT
2142}
2143
2144void
2145intel_gtt_clear_range(u_int first_entry, u_int num_entries)
2146{
2147
2148 agp_intel_gtt_clear_range(intel_agp, first_entry, num_entries);
2149}
2150
2151void
2152intel_gtt_insert_pages(u_int first_entry, u_int num_entries, vm_page_t *pages,
2153 u_int flags)
2154{
2155
2156 agp_intel_gtt_insert_pages(intel_agp, first_entry, num_entries,
2157 pages, flags);
2158}
2159
9edbd4a0
FT
2160void intel_gtt_get(size_t *gtt_total, size_t *stolen_size,
2161 phys_addr_t *mappable_base, unsigned long *mappable_end)
a904aa53 2162{
26efd328
FT
2163 struct agp_info ainfo;
2164
bc2fd6c1 2165 intel_private.base = agp_intel_gtt_get(intel_agp);
9edbd4a0
FT
2166
2167 *gtt_total = intel_private.base.gtt_total_entries << PAGE_SHIFT;
2168 *stolen_size = intel_private.base.stolen_size;
26efd328
FT
2169 agp_get_info(intel_agp, &ainfo);
2170 *mappable_base = ainfo.ai_aperture_base;
9edbd4a0 2171 *mappable_end = intel_private.base.gtt_mappable_entries << PAGE_SHIFT;
a904aa53
FT
2172}
2173
2174int
2175intel_gtt_chipset_flush(void)
2176{
2177
2178 return (agp_intel_gtt_chipset_flush(intel_agp));
2179}
2180
2181void
2182intel_gtt_unmap_memory(struct sglist *sg_list)
2183{
2184
2185 agp_intel_gtt_unmap_memory(intel_agp, sg_list);
2186}
2187
2188int
2189intel_gtt_map_memory(vm_page_t *pages, u_int num_entries,
2190 struct sglist **sg_list)
2191{
2192
2193 return (agp_intel_gtt_map_memory(intel_agp, pages, num_entries,
2194 sg_list));
2195}
2196
2197void
2198intel_gtt_insert_sg_entries(struct sglist *sg_list, u_int first_entry,
2199 u_int flags)
2200{
2201
2202 agp_intel_gtt_insert_sg_entries(intel_agp, sg_list, first_entry, flags);
2203}
2204
09d2c144
MD
2205/*
2206 * Only used by gen6
2207 */
2208void
2209intel_gtt_sync_pte(u_int entry)
a904aa53
FT
2210{
2211 struct agp_i810_softc *sc;
2212
2213 sc = device_get_softc(intel_agp);
09d2c144 2214 sc->match->driver->sync_gtt_pte(intel_agp, entry);
a904aa53
FT
2215}
2216
09d2c144
MD
2217/*
2218 * Only used by gen6
2219 */
a904aa53
FT
2220void
2221intel_gtt_write(u_int entry, uint32_t val)
2222{
2223 struct agp_i810_softc *sc;
2224
2225 sc = device_get_softc(intel_agp);
d63cf994 2226 sc->match->driver->write_gtt(intel_agp, entry, val);
a904aa53 2227}