xref: /freebsd/sys/dev/agp/agp_i810.c (revision b3a1f9373a31b644f8a65de1ba35929af3f6a9fe)
1 /*-
2  * Copyright (c) 2000 Doug Rabson
3  * Copyright (c) 2000 Ruslan Ermilov
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27 
28 /*
29  * Fixes for 830/845G support: David Dawes <dawes@xfree86.org>
30  * 852GM/855GM/865G support added by David Dawes <dawes@xfree86.org>
31  */
32 
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
35 
36 #include "opt_bus.h"
37 
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/malloc.h>
41 #include <sys/kernel.h>
42 #include <sys/module.h>
43 #include <sys/bus.h>
44 #include <sys/lock.h>
45 #include <sys/mutex.h>
46 #include <sys/proc.h>
47 
48 #include <dev/pci/pcivar.h>
49 #include <dev/pci/pcireg.h>
50 #include <pci/agppriv.h>
51 #include <pci/agpreg.h>
52 
53 #include <vm/vm.h>
54 #include <vm/vm_object.h>
55 #include <vm/vm_page.h>
56 #include <vm/vm_pageout.h>
57 #include <vm/pmap.h>
58 
59 #include <machine/bus.h>
60 #include <machine/resource.h>
61 #include <sys/rman.h>
62 
63 MALLOC_DECLARE(M_AGP);
64 
65 #define READ1(off)	bus_space_read_1(sc->bst, sc->bsh, off)
66 #define READ4(off)	bus_space_read_4(sc->bst, sc->bsh, off)
67 #define WRITE4(off,v)	bus_space_write_4(sc->bst, sc->bsh, off, v)
68 #define WRITEGTT(off,v)	bus_space_write_4(sc->gtt_bst, sc->gtt_bsh, off, v)
69 
70 #define CHIP_I810 0	/* i810/i815 */
71 #define CHIP_I830 1	/* 830M/845G */
72 #define CHIP_I855 2	/* 852GM/855GM/865G */
73 #define CHIP_I915 3	/* 915G/915GM */
74 
75 struct agp_i810_softc {
76 	struct agp_softc agp;
77 	u_int32_t initial_aperture;	/* aperture size at startup */
78 	struct agp_gatt *gatt;
79 	int chiptype;			/* i810-like or i830 */
80 	u_int32_t dcache_size;		/* i810 only */
81 	u_int32_t stolen;		/* number of i830/845 gtt entries for stolen memory */
82 	device_t bdev;			/* bridge device */
83 
84 	struct resource *regs;		/* memory mapped GC registers */
85 	bus_space_tag_t bst;		/* bus_space tag */
86 	bus_space_handle_t bsh;		/* bus_space handle */
87 
88 	struct resource *gtt;		/* memory mapped GATT entries */
89 	bus_space_tag_t gtt_bst;	/* bus_space tag */
90 	bus_space_handle_t gtt_bsh;	/* bus_space handle */
91 
92 	void *argb_cursor;		/* contigmalloc area for ARGB cursor */
93 };
94 
95 static const char*
96 agp_i810_match(device_t dev)
97 {
98 	if (pci_get_class(dev) != PCIC_DISPLAY
99 	    || pci_get_subclass(dev) != PCIS_DISPLAY_VGA)
100 		return NULL;
101 
102 	switch (pci_get_devid(dev)) {
103 	case 0x71218086:
104 		return ("Intel 82810 (i810 GMCH) SVGA controller");
105 
106 	case 0x71238086:
107 		return ("Intel 82810-DC100 (i810-DC100 GMCH) SVGA controller");
108 
109 	case 0x71258086:
110 		return ("Intel 82810E (i810E GMCH) SVGA controller");
111 
112 	case 0x11328086:
113 		return ("Intel 82815 (i815 GMCH) SVGA controller");
114 
115 	case 0x35778086:
116 		return ("Intel 82830M (830M GMCH) SVGA controller");
117 
118 	case 0x25628086:
119 		return ("Intel 82845G (845G GMCH) SVGA controller");
120 
121 	case 0x35828086:
122 		switch (pci_read_config(dev, AGP_I85X_CAPID, 1)) {
123 		case AGP_I855_GME:
124 			return ("Intel 82855GME (855GME GMCH) SVGA controller");
125 
126 		case AGP_I855_GM:
127 			return ("Intel 82855GM (855GM GMCH) SVGA controller");
128 
129 		case AGP_I852_GME:
130 			return ("Intel 82852GME (852GME GMCH) SVGA controller");
131 
132 		case AGP_I852_GM:
133 			return ("Intel 82852GM (852GM GMCH) SVGA controller");
134 
135 		default:
136 			return ("Intel 8285xM (85xGM GMCH) SVGA controller");
137 		}
138 
139 	case 0x25728086:
140 		return ("Intel 82865G (865G GMCH) SVGA controller");
141 
142 	case 0x25828086:
143 		return ("Intel 82915G (915G GMCH) SVGA controller");
144 
145 	case 0x25928086:
146 		return ("Intel 82915GM (915GM GMCH) SVGA controller");
147 	};
148 
149 	return NULL;
150 }
151 
152 /*
153  * Find bridge device.
154  */
155 static device_t
156 agp_i810_find_bridge(device_t dev)
157 {
158 	device_t *children, child;
159 	int nchildren, i;
160 	u_int32_t devid;
161 
162 	/*
163 	 * Calculate bridge device's ID.
164 	 */
165 	devid = pci_get_devid(dev);
166 	switch (devid) {
167 	case 0x71218086:
168 	case 0x71238086:
169 	case 0x71258086:
170 		devid -= 0x10000;
171 		break;
172 
173 	case 0x11328086:
174 	case 0x35778086:
175 	case 0x25628086:
176 	case 0x35828086:
177 	case 0x25728086:
178 	case 0x25828086:
179 	case 0x25928086:
180 		devid -= 0x20000;
181 		break;
182 	};
183 	if (device_get_children(device_get_parent(device_get_parent(dev)),
184 	    &children, &nchildren))
185 		return 0;
186 
187 	for (i = 0; i < nchildren; i++) {
188 		child = children[i];
189 
190 		if (pci_get_devid(child) == devid) {
191 			free(children, M_TEMP);
192 			return child;
193 		}
194 	}
195 	free(children, M_TEMP);
196 	return 0;
197 }
198 
199 static void
200 agp_i810_identify(driver_t *driver, device_t parent)
201 {
202 
203 	if (device_find_child(parent, "agp", -1) == NULL &&
204 	    agp_i810_match(parent))
205 		device_add_child(parent, "agp", -1);
206 }
207 
208 static int
209 agp_i810_probe(device_t dev)
210 {
211 	const char *desc;
212 
213 	if (resource_disabled("agp", device_get_unit(dev)))
214 		return (ENXIO);
215 	desc = agp_i810_match(dev);
216 	if (desc) {
217 		device_t bdev;
218 		u_int8_t smram;
219 		unsigned int gcc1;
220 		int devid = pci_get_devid(dev);
221 
222 		bdev = agp_i810_find_bridge(dev);
223 		if (!bdev) {
224 			if (bootverbose)
225 				printf("I810: can't find bridge device\n");
226 			return ENXIO;
227 		}
228 
229 		/*
230 		 * checking whether internal graphics device has been activated.
231 		 */
232 		switch (devid) {
233 			/* i810 */
234 		case 0x71218086:
235 		case 0x71238086:
236 		case 0x71258086:
237 		case 0x11328086:
238 			smram = pci_read_config(bdev, AGP_I810_SMRAM, 1);
239 			if ((smram & AGP_I810_SMRAM_GMS)
240 			    == AGP_I810_SMRAM_GMS_DISABLED) {
241 				if (bootverbose)
242 					printf("I810: disabled, not probing\n");
243 				return ENXIO;
244 			}
245 			break;
246 
247 			/* i830 */
248 		case 0x35778086:
249 		case 0x35828086:
250 		case 0x25628086:
251 		case 0x25728086:
252 			gcc1 = pci_read_config(bdev, AGP_I830_GCC1, 1);
253 			if ((gcc1 & AGP_I830_GCC1_DEV2) == AGP_I830_GCC1_DEV2_DISABLED) {
254 				if (bootverbose)
255 					printf("I830: disabled, not probing\n");
256 				return ENXIO;
257 			}
258 			break;
259 
260 			/* i915 */
261 		case 0x25828086:
262 		case 0x25928086:
263 			gcc1 = pci_read_config(bdev, AGP_I915_DEVEN, 4);
264 			if ((gcc1 & AGP_I915_DEVEN_D2F0) ==
265 			    AGP_I915_DEVEN_D2F0_DISABLED) {
266 				if (bootverbose)
267 					printf("I915: disabled, not probing\n");
268 				return ENXIO;
269 			}
270 			break;
271 
272 		default:
273 			return ENXIO;
274 		}
275 
276 		device_set_desc(dev, desc);
277 		return BUS_PROBE_DEFAULT;
278 	}
279 
280 	return ENXIO;
281 }
282 
283 static int
284 agp_i810_attach(device_t dev)
285 {
286 	struct agp_i810_softc *sc = device_get_softc(dev);
287 	struct agp_gatt *gatt;
288 	int error, rid;
289 
290 	sc->bdev = agp_i810_find_bridge(dev);
291 	if (!sc->bdev)
292 		return ENOENT;
293 
294 	error = agp_generic_attach(dev);
295 	if (error)
296 		return error;
297 
298 	switch (pci_get_devid(dev)) {
299 	case 0x71218086:
300 	case 0x71238086:
301 	case 0x71258086:
302 	case 0x11328086:
303 		sc->chiptype = CHIP_I810;
304 		break;
305 	case 0x35778086:
306 	case 0x25628086:
307 		sc->chiptype = CHIP_I830;
308 		break;
309 	case 0x35828086:
310 	case 0x25728086:
311 		sc->chiptype = CHIP_I855;
312 		break;
313 	case 0x25828086:
314 	case 0x25928086:
315 		sc->chiptype = CHIP_I915;
316 		break;
317 	};
318 
319 	/* Same for i810 and i830 */
320 	if (sc->chiptype == CHIP_I915)
321 		rid = AGP_I915_MMADR;
322 	else
323 		rid = AGP_I810_MMADR;
324 
325 	sc->regs = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
326 					  RF_ACTIVE);
327 	if (!sc->regs) {
328 		agp_generic_detach(dev);
329 		return ENODEV;
330 	}
331 	sc->bst = rman_get_bustag(sc->regs);
332 	sc->bsh = rman_get_bushandle(sc->regs);
333 
334 	if (sc->chiptype == CHIP_I915) {
335 		rid = AGP_I915_GTTADR;
336 		sc->gtt = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
337 						 RF_ACTIVE);
338 		if (!sc->gtt) {
339 			bus_release_resource(dev, SYS_RES_MEMORY,
340 					     AGP_I810_MMADR, sc->regs);
341 			agp_generic_detach(dev);
342 			return ENODEV;
343 		}
344 		sc->gtt_bst = rman_get_bustag(sc->gtt);
345 		sc->gtt_bsh = rman_get_bushandle(sc->gtt);
346 	}
347 
348 	sc->initial_aperture = AGP_GET_APERTURE(dev);
349 
350 	gatt = malloc( sizeof(struct agp_gatt), M_AGP, M_NOWAIT);
351 	if (!gatt) {
352  		agp_generic_detach(dev);
353  		return ENOMEM;
354 	}
355 	sc->gatt = gatt;
356 
357 	gatt->ag_entries = AGP_GET_APERTURE(dev) >> AGP_PAGE_SHIFT;
358 
359 	if ( sc->chiptype == CHIP_I810 ) {
360 		/* Some i810s have on-chip memory called dcache */
361 		if (READ1(AGP_I810_DRT) & AGP_I810_DRT_POPULATED)
362 			sc->dcache_size = 4 * 1024 * 1024;
363 		else
364 			sc->dcache_size = 0;
365 
366 		/* According to the specs the gatt on the i810 must be 64k */
367 		gatt->ag_virtual = contigmalloc( 64 * 1024, M_AGP, 0,
368 					0, ~0, PAGE_SIZE, 0);
369 		if (!gatt->ag_virtual) {
370 			if (bootverbose)
371 				device_printf(dev, "contiguous allocation failed\n");
372 			free(gatt, M_AGP);
373 			agp_generic_detach(dev);
374 			return ENOMEM;
375 		}
376 		bzero(gatt->ag_virtual, gatt->ag_entries * sizeof(u_int32_t));
377 
378 		gatt->ag_physical = vtophys((vm_offset_t) gatt->ag_virtual);
379 		agp_flush_cache();
380 		/* Install the GATT. */
381 		WRITE4(AGP_I810_PGTBL_CTL, gatt->ag_physical | 1);
382 	} else if ( sc->chiptype == CHIP_I830 ) {
383 		/* The i830 automatically initializes the 128k gatt on boot. */
384 		unsigned int gcc1, pgtblctl;
385 
386 		gcc1 = pci_read_config(sc->bdev, AGP_I830_GCC1, 1);
387 		switch (gcc1 & AGP_I830_GCC1_GMS) {
388 			case AGP_I830_GCC1_GMS_STOLEN_512:
389 				sc->stolen = (512 - 132) * 1024 / 4096;
390 				break;
391 			case AGP_I830_GCC1_GMS_STOLEN_1024:
392 				sc->stolen = (1024 - 132) * 1024 / 4096;
393 				break;
394 			case AGP_I830_GCC1_GMS_STOLEN_8192:
395 				sc->stolen = (8192 - 132) * 1024 / 4096;
396 				break;
397 			default:
398 				sc->stolen = 0;
399 				device_printf(dev, "unknown memory configuration, disabling\n");
400 				agp_generic_detach(dev);
401 				return EINVAL;
402 		}
403 		if (sc->stolen > 0)
404 			device_printf(dev, "detected %dk stolen memory\n", sc->stolen * 4);
405 		device_printf(dev, "aperture size is %dM\n", sc->initial_aperture / 1024 / 1024);
406 
407 		/* GATT address is already in there, make sure it's enabled */
408 		pgtblctl = READ4(AGP_I810_PGTBL_CTL);
409 		pgtblctl |= 1;
410 		WRITE4(AGP_I810_PGTBL_CTL, pgtblctl);
411 
412 		gatt->ag_physical = pgtblctl & ~1;
413 	} else if (sc->chiptype == CHIP_I855 || sc->chiptype == CHIP_I915) {	/* CHIP_I855 */
414 		unsigned int gcc1, pgtblctl, stolen;
415 
416 		/* Stolen memory is set up at the beginning of the aperture by
417 		 * the BIOS, consisting of the GATT followed by 4kb for the BIOS
418 		 * display.
419 		 */
420 		if (sc->chiptype == CHIP_I855)
421 			stolen = 132;
422 		else
423 			stolen = 260;
424 
425 		gcc1 = pci_read_config(sc->bdev, AGP_I855_GCC1, 1);
426 		switch (gcc1 & AGP_I855_GCC1_GMS) {
427 			case AGP_I855_GCC1_GMS_STOLEN_1M:
428 				sc->stolen = (1024 - stolen) * 1024 / 4096;
429 				break;
430 			case AGP_I855_GCC1_GMS_STOLEN_4M:
431 				sc->stolen = (4096 - stolen) * 1024 / 4096;
432 				break;
433 			case AGP_I855_GCC1_GMS_STOLEN_8M:
434 				sc->stolen = (8192 - stolen) * 1024 / 4096;
435 				break;
436 			case AGP_I855_GCC1_GMS_STOLEN_16M:
437 				sc->stolen = (16384 - stolen) * 1024 / 4096;
438 				break;
439 			case AGP_I855_GCC1_GMS_STOLEN_32M:
440 				sc->stolen = (32768 - stolen) * 1024 / 4096;
441 				break;
442 			case AGP_I915_GCC1_GMS_STOLEN_48M:
443 				sc->stolen = (49152 - stolen) * 1024 / 4096;
444 				break;
445 			case AGP_I915_GCC1_GMS_STOLEN_64M:
446 				sc->stolen = (65536 - stolen) * 1024 / 4096;
447 				break;
448 			default:
449 				sc->stolen = 0;
450 				device_printf(dev, "unknown memory configuration, disabling\n");
451 				agp_generic_detach(dev);
452 				return EINVAL;
453 		}
454 		if (sc->stolen > 0)
455 			device_printf(dev, "detected %dk stolen memory\n", sc->stolen * 4);
456 		device_printf(dev, "aperture size is %dM\n", sc->initial_aperture / 1024 / 1024);
457 
458 		/* GATT address is already in there, make sure it's enabled */
459 		pgtblctl = READ4(AGP_I810_PGTBL_CTL);
460 		pgtblctl |= 1;
461 		WRITE4(AGP_I810_PGTBL_CTL, pgtblctl);
462 
463 		gatt->ag_physical = pgtblctl & ~1;
464 	}
465 
466 	return 0;
467 }
468 
469 static int
470 agp_i810_detach(device_t dev)
471 {
472 	struct agp_i810_softc *sc = device_get_softc(dev);
473 	int error;
474 
475 	error = agp_generic_detach(dev);
476 	if (error)
477 		return error;
478 
479 	/* Clear the GATT base. */
480 	if ( sc->chiptype == CHIP_I810 ) {
481 		WRITE4(AGP_I810_PGTBL_CTL, 0);
482 	} else {
483 		unsigned int pgtblctl;
484 		pgtblctl = READ4(AGP_I810_PGTBL_CTL);
485 		pgtblctl &= ~1;
486 		WRITE4(AGP_I810_PGTBL_CTL, pgtblctl);
487 	}
488 
489 	/* Put the aperture back the way it started. */
490 	AGP_SET_APERTURE(dev, sc->initial_aperture);
491 
492 	if ( sc->chiptype == CHIP_I810 ) {
493 		contigfree(sc->gatt->ag_virtual, 64 * 1024, M_AGP);
494 	}
495 	free(sc->gatt, M_AGP);
496 
497 	if (sc->chiptype == CHIP_I915) {
498 		bus_release_resource(dev, SYS_RES_MEMORY, AGP_I915_GTTADR,
499 				     sc->gtt);
500 		bus_release_resource(dev, SYS_RES_MEMORY, AGP_I915_MMADR,
501 				     sc->regs);
502 	} else {
503 		bus_release_resource(dev, SYS_RES_MEMORY, AGP_I810_MMADR,
504 				     sc->regs);
505 	}
506 
507 	return 0;
508 }
509 
510 static u_int32_t
511 agp_i810_get_aperture(device_t dev)
512 {
513 	struct agp_i810_softc *sc = device_get_softc(dev);
514 	uint32_t temp;
515 	u_int16_t miscc;
516 
517 	switch (sc->chiptype) {
518 	case CHIP_I810:
519 		miscc = pci_read_config(sc->bdev, AGP_I810_MISCC, 2);
520 		if ((miscc & AGP_I810_MISCC_WINSIZE) == AGP_I810_MISCC_WINSIZE_32)
521 			return 32 * 1024 * 1024;
522 		else
523 			return 64 * 1024 * 1024;
524 	case CHIP_I830:
525 		temp = pci_read_config(sc->bdev, AGP_I830_GCC1, 2);
526 		if ((temp & AGP_I830_GCC1_GMASIZE) == AGP_I830_GCC1_GMASIZE_64)
527 			return 64 * 1024 * 1024;
528 		else
529 			return 128 * 1024 * 1024;
530 	case CHIP_I855:
531 		return 128 * 1024 * 1024;
532 	case CHIP_I915:
533 		temp = pci_read_config(dev, AGP_I915_MSAC, 1);
534 		if ((temp & AGP_I915_MSAC_GMASIZE) ==
535 		    AGP_I915_MSAC_GMASIZE_128) {
536 			return 128 * 1024 * 1024;
537 		} else {
538 			return 256 * 1024 * 1024;
539 		}
540 	}
541 
542 	return 0;
543 }
544 
545 static int
546 agp_i810_set_aperture(device_t dev, u_int32_t aperture)
547 {
548 	struct agp_i810_softc *sc = device_get_softc(dev);
549 	u_int16_t miscc, gcc1;
550 	u_int32_t temp;
551 
552 	switch (sc->chiptype) {
553 	case CHIP_I810:
554 		/*
555 		 * Double check for sanity.
556 		 */
557 		if (aperture != 32 * 1024 * 1024 && aperture != 64 * 1024 * 1024) {
558 			device_printf(dev, "bad aperture size %d\n", aperture);
559 			return EINVAL;
560 		}
561 
562 		miscc = pci_read_config(sc->bdev, AGP_I810_MISCC, 2);
563 		miscc &= ~AGP_I810_MISCC_WINSIZE;
564 		if (aperture == 32 * 1024 * 1024)
565 			miscc |= AGP_I810_MISCC_WINSIZE_32;
566 		else
567 			miscc |= AGP_I810_MISCC_WINSIZE_64;
568 
569 		pci_write_config(sc->bdev, AGP_I810_MISCC, miscc, 2);
570 		break;
571 	case CHIP_I830:
572 		if (aperture != 64 * 1024 * 1024 &&
573 		    aperture != 128 * 1024 * 1024) {
574 			device_printf(dev, "bad aperture size %d\n", aperture);
575 			return EINVAL;
576 		}
577 		gcc1 = pci_read_config(sc->bdev, AGP_I830_GCC1, 2);
578 		gcc1 &= ~AGP_I830_GCC1_GMASIZE;
579 		if (aperture == 64 * 1024 * 1024)
580 			gcc1 |= AGP_I830_GCC1_GMASIZE_64;
581 		else
582 			gcc1 |= AGP_I830_GCC1_GMASIZE_128;
583 
584 		pci_write_config(sc->bdev, AGP_I830_GCC1, gcc1, 2);
585 		break;
586 	case CHIP_I855:
587 		if (aperture != 128 * 1024 * 1024) {
588 			device_printf(dev, "bad aperture size %d\n", aperture);
589 			return EINVAL;
590 		}
591 		break;
592 	case CHIP_I915:
593 		temp = pci_read_config(dev, AGP_I915_MSAC, 1);
594 		temp &= ~AGP_I915_MSAC_GMASIZE;
595 
596 		switch (aperture) {
597 		case 128 * 1024 * 1024:
598 			temp |= AGP_I915_MSAC_GMASIZE_128;
599 			break;
600 		case 256 * 1024 * 1024:
601 			temp |= AGP_I915_MSAC_GMASIZE_256;
602 			break;
603 		default:
604 			device_printf(dev, "bad aperture size %d\n", aperture);
605 			return EINVAL;
606 		}
607 
608 		pci_write_config(dev, AGP_I915_MSAC, temp, 1);
609 		break;
610 	}
611 
612 	return 0;
613 }
614 
615 static int
616 agp_i810_bind_page(device_t dev, int offset, vm_offset_t physical)
617 {
618 	struct agp_i810_softc *sc = device_get_softc(dev);
619 
620 	if (offset < 0 || offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT)) {
621 		device_printf(dev, "failed: offset is 0x%08x, shift is %d, entries is %d\n", offset, AGP_PAGE_SHIFT, sc->gatt->ag_entries);
622 		return EINVAL;
623 	}
624 
625 	if ( sc->chiptype != CHIP_I810 ) {
626 		if ( (offset >> AGP_PAGE_SHIFT) < sc->stolen ) {
627 			device_printf(dev, "trying to bind into stolen memory");
628 			return EINVAL;
629 		}
630 	}
631 
632 	if (sc->chiptype == CHIP_I915) {
633 		WRITEGTT((offset >> AGP_PAGE_SHIFT) * 4, physical | 1);
634 	} else {
635 		WRITE4(AGP_I810_GTT + (offset >> AGP_PAGE_SHIFT) * 4, physical | 1);
636 	}
637 
638 	return 0;
639 }
640 
641 static int
642 agp_i810_unbind_page(device_t dev, int offset)
643 {
644 	struct agp_i810_softc *sc = device_get_softc(dev);
645 
646 	if (offset < 0 || offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT))
647 		return EINVAL;
648 
649 	if ( sc->chiptype != CHIP_I810 ) {
650 		if ( (offset >> AGP_PAGE_SHIFT) < sc->stolen ) {
651 			device_printf(dev, "trying to unbind from stolen memory");
652 			return EINVAL;
653 		}
654 	}
655 
656 	if (sc->chiptype == CHIP_I915) {
657 		WRITEGTT((offset >> AGP_PAGE_SHIFT) * 4, 0);
658 	} else {
659 		WRITE4(AGP_I810_GTT + (offset >> AGP_PAGE_SHIFT) * 4, 0);
660 	}
661 
662 	return 0;
663 }
664 
665 /*
666  * Writing via memory mapped registers already flushes all TLBs.
667  */
668 static void
669 agp_i810_flush_tlb(device_t dev)
670 {
671 }
672 
673 static int
674 agp_i810_enable(device_t dev, u_int32_t mode)
675 {
676 
677 	return 0;
678 }
679 
680 static struct agp_memory *
681 agp_i810_alloc_memory(device_t dev, int type, vm_size_t size)
682 {
683 	struct agp_i810_softc *sc = device_get_softc(dev);
684 	struct agp_memory *mem;
685 
686 	if ((size & (AGP_PAGE_SIZE - 1)) != 0)
687 		return 0;
688 
689 	if (sc->agp.as_allocated + size > sc->agp.as_maxmem)
690 		return 0;
691 
692 	if (type == 1) {
693 		/*
694 		 * Mapping local DRAM into GATT.
695 		 */
696 		if ( sc->chiptype != CHIP_I810 )
697 			return 0;
698 		if (size != sc->dcache_size)
699 			return 0;
700 	} else if (type == 2) {
701 		/*
702 		 * Type 2 is the contiguous physical memory type, that hands
703 		 * back a physical address.  This is used for cursors on i810.
704 		 * Hand back as many single pages with physical as the user
705 		 * wants, but only allow one larger allocation (ARGB cursor)
706 		 * for simplicity.
707 		 */
708 		if (size != AGP_PAGE_SIZE) {
709 			if (sc->argb_cursor != NULL)
710 				return 0;
711 
712 			/* Allocate memory for ARGB cursor, if we can. */
713 			sc->argb_cursor = contigmalloc(size, M_AGP,
714 			   0, 0, ~0, PAGE_SIZE, 0);
715 			if (sc->argb_cursor == NULL)
716 				return 0;
717 		}
718 	}
719 
720 	mem = malloc(sizeof *mem, M_AGP, M_WAITOK);
721 	mem->am_id = sc->agp.as_nextid++;
722 	mem->am_size = size;
723 	mem->am_type = type;
724 	if (type != 1 && (type != 2 || size == AGP_PAGE_SIZE))
725 		mem->am_obj = vm_object_allocate(OBJT_DEFAULT,
726 						 atop(round_page(size)));
727 	else
728 		mem->am_obj = 0;
729 
730 	if (type == 2) {
731 		if (size == AGP_PAGE_SIZE) {
732 			/*
733 			 * Allocate and wire down the page now so that we can
734 			 * get its physical address.
735 			 */
736 			vm_page_t m;
737 
738 			VM_OBJECT_LOCK(mem->am_obj);
739 			m = vm_page_grab(mem->am_obj, 0, VM_ALLOC_NOBUSY |
740 			    VM_ALLOC_WIRED | VM_ALLOC_ZERO | VM_ALLOC_RETRY);
741 			VM_OBJECT_UNLOCK(mem->am_obj);
742 			mem->am_physical = VM_PAGE_TO_PHYS(m);
743 		} else {
744 			/* Our allocation is already nicely wired down for us.
745 			 * Just grab the physical address.
746 			 */
747 			mem->am_physical = vtophys(sc->argb_cursor);
748 		}
749 	} else {
750 		mem->am_physical = 0;
751 	}
752 
753 	mem->am_offset = 0;
754 	mem->am_is_bound = 0;
755 	TAILQ_INSERT_TAIL(&sc->agp.as_memory, mem, am_link);
756 	sc->agp.as_allocated += size;
757 
758 	return mem;
759 }
760 
761 static int
762 agp_i810_free_memory(device_t dev, struct agp_memory *mem)
763 {
764 	struct agp_i810_softc *sc = device_get_softc(dev);
765 
766 	if (mem->am_is_bound)
767 		return EBUSY;
768 
769 	if (mem->am_type == 2) {
770 		if (mem->am_size == AGP_PAGE_SIZE) {
771 			/*
772 			 * Unwire the page which we wired in alloc_memory.
773 			 */
774 			vm_page_t m;
775 
776 			VM_OBJECT_LOCK(mem->am_obj);
777 			m = vm_page_lookup(mem->am_obj, 0);
778 			VM_OBJECT_UNLOCK(mem->am_obj);
779 			vm_page_lock_queues();
780 			vm_page_unwire(m, 0);
781 			vm_page_unlock_queues();
782 		} else {
783 			contigfree(sc->argb_cursor, mem->am_size, M_AGP);
784 			sc->argb_cursor = NULL;
785 		}
786 	}
787 
788 	sc->agp.as_allocated -= mem->am_size;
789 	TAILQ_REMOVE(&sc->agp.as_memory, mem, am_link);
790 	if (mem->am_obj)
791 		vm_object_deallocate(mem->am_obj);
792 	free(mem, M_AGP);
793 	return 0;
794 }
795 
796 static int
797 agp_i810_bind_memory(device_t dev, struct agp_memory *mem,
798 		     vm_offset_t offset)
799 {
800 	struct agp_i810_softc *sc = device_get_softc(dev);
801 	vm_offset_t i;
802 
803 	/* Do some sanity checks first. */
804 	if (offset < 0 || (offset & (AGP_PAGE_SIZE - 1)) != 0 ||
805 	    offset + mem->am_size > AGP_GET_APERTURE(dev)) {
806 		device_printf(dev, "binding memory at bad offset %#x\n",
807 		    (int)offset);
808 		return EINVAL;
809 	}
810 
811 	if (mem->am_type == 2 && mem->am_size != AGP_PAGE_SIZE) {
812 		mtx_lock(&sc->agp.as_lock);
813 		if (mem->am_is_bound) {
814 			mtx_unlock(&sc->agp.as_lock);
815 			return EINVAL;
816 		}
817 		/* The memory's already wired down, just stick it in the GTT. */
818 		for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) {
819 			u_int32_t physical = mem->am_physical + i;
820 
821 			if (sc->chiptype == CHIP_I915) {
822 				WRITEGTT(((offset + i) >> AGP_PAGE_SHIFT) * 4,
823 				    physical | 1);
824 			} else {
825 				WRITE4(AGP_I810_GTT +
826 				    ((offset + i) >> AGP_PAGE_SHIFT) * 4,
827 				    physical | 1);
828 			}
829 		}
830 		agp_flush_cache();
831 		mem->am_offset = offset;
832 		mem->am_is_bound = 1;
833 		mtx_unlock(&sc->agp.as_lock);
834 		return 0;
835 	}
836 
837 	if (mem->am_type != 1)
838 		return agp_generic_bind_memory(dev, mem, offset);
839 
840 	if ( sc->chiptype != CHIP_I810 )
841 		return EINVAL;
842 
843 	for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) {
844 		WRITE4(AGP_I810_GTT + (offset >> AGP_PAGE_SHIFT) * 4,
845 		       i | 3);
846 	}
847 
848 	return 0;
849 }
850 
851 static int
852 agp_i810_unbind_memory(device_t dev, struct agp_memory *mem)
853 {
854 	struct agp_i810_softc *sc = device_get_softc(dev);
855 	vm_offset_t i;
856 
857 	if (mem->am_type == 2 && mem->am_size != AGP_PAGE_SIZE) {
858 		mtx_lock(&sc->agp.as_lock);
859 		if (!mem->am_is_bound) {
860 			mtx_unlock(&sc->agp.as_lock);
861 			return EINVAL;
862 		}
863 
864 		for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) {
865 			vm_offset_t offset = mem->am_offset;
866 
867 			if (sc->chiptype == CHIP_I915) {
868 				WRITEGTT(((offset + i) >> AGP_PAGE_SHIFT) * 4,
869 				    0);
870 			} else {
871 				WRITE4(AGP_I810_GTT +
872 				    ((offset + i) >> AGP_PAGE_SHIFT) * 4, 0);
873 			}
874 		}
875 		agp_flush_cache();
876 		mem->am_is_bound = 0;
877 		mtx_unlock(&sc->agp.as_lock);
878 		return 0;
879 	}
880 
881 	if (mem->am_type != 1)
882 		return agp_generic_unbind_memory(dev, mem);
883 
884 	if ( sc->chiptype != CHIP_I810 )
885 		return EINVAL;
886 
887 	for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE)
888 		WRITE4(AGP_I810_GTT + (i >> AGP_PAGE_SHIFT) * 4, 0);
889 
890 	return 0;
891 }
892 
893 static device_method_t agp_i810_methods[] = {
894 	/* Device interface */
895 	DEVMETHOD(device_identify,	agp_i810_identify),
896 	DEVMETHOD(device_probe,		agp_i810_probe),
897 	DEVMETHOD(device_attach,	agp_i810_attach),
898 	DEVMETHOD(device_detach,	agp_i810_detach),
899 
900 	/* AGP interface */
901 	DEVMETHOD(agp_get_aperture,	agp_i810_get_aperture),
902 	DEVMETHOD(agp_set_aperture,	agp_i810_set_aperture),
903 	DEVMETHOD(agp_bind_page,	agp_i810_bind_page),
904 	DEVMETHOD(agp_unbind_page,	agp_i810_unbind_page),
905 	DEVMETHOD(agp_flush_tlb,	agp_i810_flush_tlb),
906 	DEVMETHOD(agp_enable,		agp_i810_enable),
907 	DEVMETHOD(agp_alloc_memory,	agp_i810_alloc_memory),
908 	DEVMETHOD(agp_free_memory,	agp_i810_free_memory),
909 	DEVMETHOD(agp_bind_memory,	agp_i810_bind_memory),
910 	DEVMETHOD(agp_unbind_memory,	agp_i810_unbind_memory),
911 
912 	{ 0, 0 }
913 };
914 
915 static driver_t agp_i810_driver = {
916 	"agp",
917 	agp_i810_methods,
918 	sizeof(struct agp_i810_softc),
919 };
920 
921 static devclass_t agp_devclass;
922 
923 DRIVER_MODULE(agp_i810, vgapci, agp_i810_driver, agp_devclass, 0, 0);
924 MODULE_DEPEND(agp_i810, agp, 1, 1, 1);
925 MODULE_DEPEND(agp_i810, pci, 1, 1, 1);
926