xref: /openbsd-src/sys/dev/pci/agp_i810.c (revision a28daedfc357b214be5c701aa8ba8adb29a7f1c2)
1 /*	$OpenBSD: agp_i810.c,v 1.48 2009/04/20 01:28:45 oga Exp $	*/
2 
3 /*-
4  * Copyright (c) 2000 Doug Rabson
5  * Copyright (c) 2000 Ruslan Ermilov
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  */
30 
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/malloc.h>
34 #include <sys/kernel.h>
35 #include <sys/lock.h>
36 #include <sys/proc.h>
37 #include <sys/device.h>
38 #include <sys/conf.h>
39 #include <sys/agpio.h>
40 
41 #include <dev/pci/pcivar.h>
42 #include <dev/pci/pcireg.h>
43 #include <dev/pci/pcidevs.h>
44 #include <dev/pci/agpvar.h>
45 #include <dev/pci/agpreg.h>
46 #include <dev/pci/vga_pcivar.h>
47 
48 #include <machine/bus.h>
49 
50 #define READ1(off)	bus_space_read_1(isc->map->bst, isc->map->bsh, off)
51 #define READ4(off)	bus_space_read_4(isc->map->bst, isc->map->bsh, off)
52 #define WRITE4(off,v)	bus_space_write_4(isc->map->bst, isc->map->bsh, off, v)
53 
54 #define WRITEGTT(off,v)	bus_space_write_4(isc->gtt_map->bst, isc->gtt_map->bsh, off, v)
55 #define WRITE_GATT(off,v)	agp_i810_write_gatt(isc, off, v)
56 
57 enum {
58 	CHIP_NONE	= 0,	/* not integrated graphics */
59 	CHIP_I810	= 1,	/* i810/i815 */
60 	CHIP_I830	= 2,	/* i830/i845 */
61 	CHIP_I855	= 3,	/* i852GM/i855GM/i865G */
62 	CHIP_I915	= 4,	/* i915G/i915GM */
63 	CHIP_I965	= 5,	/* i965/i965GM */
64 	CHIP_G33	= 6,	/* G33/Q33/Q35 */
65 	CHIP_G4X	= 7	/* G4X */
66 };
67 
68 struct agp_i810_softc {
69 	struct device		 dev;
70 	struct agp_softc	*agpdev;
71 	struct agp_gatt		*gatt;
72 	struct vga_pci_bar	*map;
73 	struct vga_pci_bar	*gtt_map;
74 	int			 chiptype;	/* i810-like or i830 */
75 	bus_size_t		 aperture;	/* current aperture size */
76 	u_int32_t		 dcache_size;	/* i810 only */
77 	u_int32_t		 stolen;	/* number of i830/845 gtt
78 						   entries for stolen memory */
79 };
80 
81 void	agp_i810_attach(struct device *, struct device *, void *);
82 int	agp_i810_probe(struct device *, void *, void *);
83 int	agp_i810_get_chiptype(struct pci_attach_args *);
84 bus_size_t agp_i810_get_aperture(void *);
85 int	agp_i810_bind_page(void *, off_t, bus_addr_t);
86 int	agp_i810_unbind_page(void *, off_t);
87 void	agp_i810_flush_tlb(void *);
88 int	agp_i810_enable(void *, u_int32_t mode);
89 struct agp_memory * agp_i810_alloc_memory(void *, int, vsize_t);
90 int	agp_i810_free_memory(void *, struct agp_memory *);
91 int	agp_i810_bind_memory(void *, struct agp_memory *, off_t);
92 int	agp_i810_unbind_memory(void *, struct agp_memory *);
93 void	agp_i810_write_gatt(struct agp_i810_softc *, bus_size_t, u_int32_t);
94 int	intagp_gmch_match(struct pci_attach_args *);
95 
96 struct cfattach intagp_ca = {
97 	sizeof(struct agp_i810_softc), agp_i810_probe, agp_i810_attach
98 };
99 
100 struct cfdriver intagp_cd = {
101 	NULL, "intagp", DV_DULL
102 };
103 
104 struct agp_methods agp_i810_methods = {
105 	agp_i810_get_aperture,
106 	agp_i810_bind_page,
107 	agp_i810_unbind_page,
108 	agp_i810_flush_tlb,
109 	agp_i810_enable,
110 	agp_i810_alloc_memory,
111 	agp_i810_free_memory,
112 	agp_i810_bind_memory,
113 	agp_i810_unbind_memory,
114 };
115 
116 int
117 agp_i810_get_chiptype(struct pci_attach_args *pa)
118 {
119 	switch (PCI_PRODUCT(pa->pa_id)) {
120 	case PCI_PRODUCT_INTEL_82810_IGD:
121 	case PCI_PRODUCT_INTEL_82810_DC100_IGD:
122 	case PCI_PRODUCT_INTEL_82810E_IGD:
123 	case PCI_PRODUCT_INTEL_82815_IGD:
124 		return (CHIP_I810);
125 		break;
126 	case PCI_PRODUCT_INTEL_82830M_IGD:
127 	case PCI_PRODUCT_INTEL_82845G_IGD:
128 		return (CHIP_I830);
129 		break;
130 	case PCI_PRODUCT_INTEL_82855GM_IGD:
131 	case PCI_PRODUCT_INTEL_82865G_IGD:
132 		return (CHIP_I855);
133 		break;
134 	case PCI_PRODUCT_INTEL_82915G_IGD_1:
135 	case PCI_PRODUCT_INTEL_82915G_IGD_2:
136 	case PCI_PRODUCT_INTEL_82915GM_IGD_1:
137 	case PCI_PRODUCT_INTEL_82915GM_IGD_2:
138 	case PCI_PRODUCT_INTEL_82945G_IGD_1:
139 	case PCI_PRODUCT_INTEL_82945G_IGD_2:
140 	case PCI_PRODUCT_INTEL_82945GM_IGD_1:
141 	case PCI_PRODUCT_INTEL_82945GM_IGD_2:
142 	case PCI_PRODUCT_INTEL_82945GME_IGD_1:
143 		return (CHIP_I915);
144 		break;
145 	case PCI_PRODUCT_INTEL_82946GZ_IGD_1:
146 	case PCI_PRODUCT_INTEL_82946GZ_IGD_2:
147 	case PCI_PRODUCT_INTEL_82Q965_IGD_1:
148 	case PCI_PRODUCT_INTEL_82Q965_IGD_2:
149 	case PCI_PRODUCT_INTEL_82G965_IGD_1:
150 	case PCI_PRODUCT_INTEL_82G965_IGD_2:
151 	case PCI_PRODUCT_INTEL_82GM965_IGD_1:
152 	case PCI_PRODUCT_INTEL_82GM965_IGD_2:
153 	case PCI_PRODUCT_INTEL_82GME965_IGD_1:
154 	case PCI_PRODUCT_INTEL_82GME965_IGD_2:
155 	case PCI_PRODUCT_INTEL_82G35_IGD_1:
156 	case PCI_PRODUCT_INTEL_82G35_IGD_2:
157 		return (CHIP_I965);
158 		break;
159 	case PCI_PRODUCT_INTEL_82G33_IGD_1:
160 	case PCI_PRODUCT_INTEL_82G33_IGD_2:
161 	case PCI_PRODUCT_INTEL_82Q35_IGD_1:
162 	case PCI_PRODUCT_INTEL_82Q35_IGD_2:
163 		return (CHIP_G33);
164 		break;
165 	case PCI_PRODUCT_INTEL_82GM45_IGD_1:
166 	case PCI_PRODUCT_INTEL_82Q45_IGD_1:
167 	case PCI_PRODUCT_INTEL_82G45_IGD_1:
168 		return (CHIP_G4X);
169 		break;
170 	}
171 	return (CHIP_NONE);
172 }
173 
174 /*
175  * We're intel IGD, bus 0 function 0 dev 0 should be the GMCH, so it should
176  * be Intel
177  */
178 int
179 intagp_gmch_match(struct pci_attach_args *pa)
180 {
181 	if (pa->pa_bus == 0 && pa->pa_device == 0 && pa->pa_function == 0 &&
182 	    PCI_VENDOR(pa->pa_id) == PCI_VENDOR_INTEL &&
183 	    PCI_CLASS(pa->pa_class) == PCI_CLASS_BRIDGE &&
184 	    PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_BRIDGE_HOST)
185 		return (1);
186 	return (0);
187 }
188 
189 int
190 agp_i810_probe(struct device *parent, void *match, void *aux)
191 {
192 	struct pci_attach_args	*pa = aux;
193 
194 	if (PCI_CLASS(pa->pa_class) != PCI_CLASS_DISPLAY ||
195 	    PCI_SUBCLASS(pa->pa_class) != PCI_SUBCLASS_DISPLAY_VGA)
196 		return (0);
197 
198 	return (agp_i810_get_chiptype(pa) != CHIP_NONE);
199 }
200 
201 void
202 agp_i810_attach(struct device *parent, struct device *self, void *aux)
203 {
204 	struct agp_i810_softc		*isc = (struct agp_i810_softc *)self;
205 	struct agp_gatt 		*gatt;
206 	struct pci_attach_args		*pa = aux, bpa;
207 	struct vga_pci_softc		*vga = (struct vga_pci_softc *)parent;
208 	bus_addr_t			 mmaddr, gmaddr;
209 	pcireg_t			 memtype;
210 
211 	isc->chiptype = agp_i810_get_chiptype(pa);
212 
213 	switch (isc->chiptype) {
214 	case CHIP_I915:
215 	case CHIP_G33:
216 		gmaddr = AGP_I915_GMADR;
217 		mmaddr = AGP_I915_MMADR;
218 		memtype = PCI_MAPREG_TYPE_MEM;
219 		break;
220 	case CHIP_I965:
221 	case CHIP_G4X:
222 		gmaddr = AGP_I965_GMADR;
223 		mmaddr = AGP_I965_MMADR;
224 		memtype = PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT;
225 		break;
226 	default:
227 		gmaddr = AGP_APBASE;
228 		mmaddr = AGP_I810_MMADR;
229 		memtype = PCI_MAPREG_TYPE_MEM;
230 		break;
231 	}
232 
233 	if (pci_mapreg_info(pa->pa_pc, pa->pa_tag, gmaddr, memtype,
234 	    NULL, &isc->aperture, NULL) != 0) {
235 		printf("can't get aperture size\n");
236 		return;
237 	}
238 
239 	isc->map = vga_pci_bar_map(vga, mmaddr, 0, BUS_SPACE_MAP_LINEAR);
240 	if (isc->map == NULL) {
241 		printf("can't map mmadr registers\n");
242 		return;
243 	}
244 
245 	if (isc->chiptype == CHIP_I915 || isc->chiptype == CHIP_G33) {
246 		isc->gtt_map = vga_pci_bar_map(vga, AGP_I915_GTTADR, 0,
247 		    BUS_SPACE_MAP_LINEAR);
248 		if (isc->gtt_map == NULL) {
249 			printf("can't map gatt registers\n");
250 			goto out;
251 		}
252 	}
253 
254 	gatt = malloc(sizeof(*gatt), M_AGP, M_NOWAIT | M_ZERO);
255 	if (gatt == NULL) {
256 		printf("can't alloc gatt\n");
257 		goto out;
258 	}
259 	isc->gatt = gatt;
260 
261 	gatt->ag_entries = isc->aperture >> AGP_PAGE_SHIFT;
262 
263 	/*
264 	 * Find the GMCH, some of the registers we need to read for
265 	 * configuration purposes are on there. it's always at
266 	 * 0/0/0 (bus/dev/func).
267 	 */
268 	if (pci_find_device(&bpa, intagp_gmch_match) == 0) {
269 		printf("can't find GMCH\n");
270 		goto out;
271 	}
272 
273 	if (isc->chiptype == CHIP_I810) {
274 		/* Some i810s have on-chip memory called dcache */
275 		if (READ1(AGP_I810_DRT) & AGP_I810_DRT_POPULATED)
276 			isc->dcache_size = 4 * 1024 * 1024;
277 		else
278 			isc->dcache_size = 0;
279 
280 		/* According to the specs the gatt on the i810 must be 64k */
281 		if (agp_alloc_dmamem(pa->pa_dmat, 64 * 1024, &gatt->ag_dmamap,
282 		    &gatt->ag_physical, &gatt->ag_dmaseg) != 0) {
283 			goto out;
284 		}
285 		gatt->ag_size = gatt->ag_entries * sizeof(u_int32_t);
286 
287 		if (bus_dmamem_map(pa->pa_dmat, &gatt->ag_dmaseg, 1, 64 * 1024,
288 		    (caddr_t *)&gatt->ag_virtual, BUS_DMA_NOWAIT) != 0)
289 			goto out;
290 
291 		agp_flush_cache();
292 		/* Install the GATT. */
293 		WRITE4(AGP_I810_PGTBL_CTL, gatt->ag_physical | 1);
294 	} else if (isc->chiptype == CHIP_I830) {
295 		/* The i830 automatically initializes the 128k gatt on boot. */
296 		pcireg_t reg;
297 		u_int32_t pgtblctl;
298 		u_int16_t gcc1;
299 
300 		reg = pci_conf_read(bpa.pa_pc, bpa.pa_tag, AGP_I830_GCC0);
301 		gcc1 = (u_int16_t)(reg >> 16);
302 		switch (gcc1 & AGP_I830_GCC1_GMS) {
303 		case AGP_I830_GCC1_GMS_STOLEN_512:
304 			isc->stolen = (512 - 132) * 1024 / 4096;
305 			break;
306 		case AGP_I830_GCC1_GMS_STOLEN_1024:
307 			isc->stolen = (1024 - 132) * 1024 / 4096;
308 			break;
309 		case AGP_I830_GCC1_GMS_STOLEN_8192:
310 			isc->stolen = (8192 - 132) * 1024 / 4096;
311 			break;
312 		default:
313 			isc->stolen = 0;
314 			printf("unknown memory configuration, disabling\n");
315 			goto out;
316 		}
317 #ifdef DEBUG
318 		if (isc->stolen > 0) {
319 			printf(": detected %dk stolen memory",
320 			    isc->stolen * 4);
321 		} else
322 			printf(": no preallocated video memory\n");
323 #endif
324 
325 		/* GATT address is already in there, make sure it's enabled */
326 		pgtblctl = READ4(AGP_I810_PGTBL_CTL);
327 		pgtblctl |= 1;
328 		WRITE4(AGP_I810_PGTBL_CTL, pgtblctl);
329 
330 		gatt->ag_physical = pgtblctl & ~1;
331 	} else if (isc->chiptype == CHIP_I855 || isc->chiptype == CHIP_I915 ||
332 		   isc->chiptype == CHIP_I965 || isc->chiptype == CHIP_G33 ||
333 		   isc->chiptype == CHIP_G4X) {
334 		pcireg_t reg;
335 		u_int32_t pgtblctl, stolen;
336 		u_int16_t gcc1;
337 
338 		/* Stolen memory is set up at the beginning of the aperture by
339 		 * the BIOS, consisting of the GATT followed by 4kb for the
340 		 * BIOS display.
341 		 */
342 
343 		reg = pci_conf_read(bpa.pa_pc, bpa.pa_tag, AGP_I855_GCC1);
344 		gcc1 = (u_int16_t)(reg >> 16);
345                 switch (isc->chiptype) {
346 		case CHIP_I855:
347 		/* The 855GM automatically initializes the 128k gatt on boot. */
348 			stolen = 128 + 4;
349 			break;
350                 case CHIP_I915:
351 		/* The 915G automatically initializes the 256k gatt on boot. */
352 			stolen = 256 + 4;
353 			break;
354 		case CHIP_I965:
355 			switch (READ4(AGP_I810_PGTBL_CTL) &
356 			    AGP_I810_PGTBL_SIZE_MASK) {
357 			case AGP_I810_PGTBL_SIZE_512KB:
358 				stolen = 512 + 4;
359 				break;
360 			case AGP_I810_PGTBL_SIZE_256KB:
361 				stolen = 256 + 4;
362 				break;
363 			case AGP_I810_PGTBL_SIZE_128KB:
364 			default:
365 				stolen = 128 + 4;
366 				break;
367 			}
368 			break;
369 		case CHIP_G33:
370 			switch (gcc1 & AGP_G33_PGTBL_SIZE_MASK) {
371 			case AGP_G33_PGTBL_SIZE_2M:
372 				stolen = 2048 + 4;
373 				break;
374 			case AGP_G33_PGTBL_SIZE_1M:
375 			default:
376 				stolen = 1024 + 4;
377 				break;
378 			}
379 			break;
380 		case CHIP_G4X:
381 			/*
382 			 * GTT stolen is separate from graphics stolen on
383 			 * 4 series hardware. so ignore it in stolen gtt entries
384 			 * counting. However, 4Kb of stolen memory isn't mapped
385 			 * to the GTT.
386 			 */
387 			stolen = 4;
388 			break;
389 		default:
390 			printf("bad chiptype\n");
391 			goto out;
392 		}
393 
394 		switch (gcc1 & AGP_I855_GCC1_GMS) {
395 		case AGP_I855_GCC1_GMS_STOLEN_1M:
396 			isc->stolen = (1024 - stolen) * 1024 / 4096;
397 			break;
398 		case AGP_I855_GCC1_GMS_STOLEN_4M:
399 			isc->stolen = (4096 - stolen) * 1024 / 4096;
400 			break;
401 		case AGP_I855_GCC1_GMS_STOLEN_8M:
402 			isc->stolen = (8192 - stolen) * 1024 / 4096;
403 			break;
404 		case AGP_I855_GCC1_GMS_STOLEN_16M:
405 			isc->stolen = (16384 - stolen) * 1024 / 4096;
406 			break;
407 		case AGP_I855_GCC1_GMS_STOLEN_32M:
408 			isc->stolen = (32768 - stolen) * 1024 / 4096;
409 			break;
410 		case AGP_I915_GCC1_GMS_STOLEN_48M:
411 			isc->stolen = (49152 - stolen) * 1024 / 4096;
412 			break;
413 		case AGP_I915_GCC1_GMS_STOLEN_64M:
414 			isc->stolen = (65536 - stolen) * 1024 / 4096;
415 			break;
416 		case AGP_G33_GCC1_GMS_STOLEN_128M:
417 			isc->stolen = (131072 - stolen) * 1024 / 4096;
418 			break;
419 		case AGP_G33_GCC1_GMS_STOLEN_256M:
420 			isc->stolen = (262144 - stolen) * 1024 / 4096;
421 			break;
422 		case AGP_INTEL_GMCH_GMS_STOLEN_96M:
423 			isc->stolen = (98304 - stolen) * 1024 / 4096;
424 			break;
425 		case AGP_INTEL_GMCH_GMS_STOLEN_160M:
426 			isc->stolen = (163840 - stolen) * 1024 / 4096;
427 			break;
428 		case AGP_INTEL_GMCH_GMS_STOLEN_224M:
429 			isc->stolen = (229376 - stolen) * 1024 / 4096;
430 			break;
431 		case AGP_INTEL_GMCH_GMS_STOLEN_352M:
432 			isc->stolen = (360448 - stolen) * 1024 / 4096;
433 			break;
434 		default:
435 			isc->stolen = 0;
436 			printf("unknown memory configuration, disabling\n");
437 			goto out;
438 		}
439 #ifdef DEBUG
440 		if (isc->stolen > 0) {
441 			printf(": detected %dk stolen memory",
442 			    isc->stolen * 4);
443 		} else
444 			printf(": no preallocated video memory\n");
445 #endif
446 
447 		/* GATT address is already in there, make sure it's enabled */
448 		pgtblctl = READ4(AGP_I810_PGTBL_CTL);
449 		pgtblctl |= 1;
450 		WRITE4(AGP_I810_PGTBL_CTL, pgtblctl);
451 
452 		gatt->ag_physical = pgtblctl & ~1;
453 	}
454 
455 	/*
456 	 * Make sure the chipset can see everything.
457 	 */
458 	agp_flush_cache();
459 
460 	isc->agpdev = (struct agp_softc *)agp_attach_bus(pa, &agp_i810_methods,
461 	    gmaddr, memtype, &isc->dev);
462 	return;
463 out:
464 
465 	if (isc->gatt)
466 		if (isc->gatt->ag_size != 0)
467 			agp_free_dmamem(pa->pa_dmat, gatt->ag_size,
468 			    gatt->ag_dmamap, &gatt->ag_dmaseg);
469 		free(isc->gatt, M_AGP);
470 	if (isc->gtt_map != NULL)
471 		vga_pci_bar_unmap(isc->gtt_map);
472 	if (isc->map != NULL)
473 		vga_pci_bar_unmap(isc->map);
474 }
475 
476 #if 0
477 int
478 agp_i810_detach(struct agp_softc *sc)
479 {
480 	int error;
481 	struct agp_i810_softc *isc = sc->sc_chipc;
482 
483 	error = agp_generic_detach(sc);
484 	if (error)
485 		return (error);
486 
487 	/* Clear the GATT base. */
488 	if (sc->chiptype == CHIP_I810) {
489 		WRITE4(AGP_I810_PGTBL_CTL, 0);
490 	} else {
491 		unsigned int pgtblctl;
492 		pgtblctl = READ4(AGP_I810_PGTBL_CTL);
493 		pgtblctl &= ~1;
494 		WRITE4(AGP_I810_PGTBL_CTL, pgtblctl);
495 	}
496 
497 	if (sc->chiptype == CHIP_I810) {
498 		bus_dmamem_unmap(pa->pa_dmat, isc->gatt->ag_virtual,
499 		    gatt->ag_size);
500 		agp_free_dmamem(sc->sc_dmat, gatt->ag_size, gatt->ag_dmamap,
501 		    &gatt->ag_dmaseg);
502 	}
503 	free(sc->gatt, M_AGP);
504 
505 	return (0);
506 }
507 #endif
508 
509 bus_size_t
510 agp_i810_get_aperture(void *sc)
511 {
512 	struct agp_i810_softc	*isc = sc;
513 
514 	return (isc->aperture);
515 }
516 
517 int
518 agp_i810_bind_page(void *sc, off_t offset, bus_addr_t physical)
519 {
520 	struct agp_i810_softc *isc = sc;
521 
522 	if (offset < 0 || offset >= (isc->gatt->ag_entries << AGP_PAGE_SHIFT)) {
523 #ifdef DEBUG
524 		printf("agp: failed: offset 0x%08x, shift %d, entries %d\n",
525 		    (int)offset, AGP_PAGE_SHIFT, isc->gatt->ag_entries);
526 #endif
527 		return (EINVAL);
528 	}
529 
530 	if (isc->chiptype != CHIP_I810) {
531 		if ((offset >> AGP_PAGE_SHIFT) < isc->stolen) {
532 #ifdef DEBUG
533 			printf("agp: trying to bind into stolen memory\n");
534 #endif
535 			return (EINVAL);
536 		}
537 	}
538 
539 	WRITE_GATT(offset, physical);
540 	return (0);
541 }
542 
543 int
544 agp_i810_unbind_page(void *sc, off_t offset)
545 {
546 	struct agp_i810_softc *isc = sc;
547 
548 	if (offset < 0 || offset >= (isc->gatt->ag_entries << AGP_PAGE_SHIFT))
549 		return (EINVAL);
550 
551 	if (isc->chiptype != CHIP_I810 ) {
552 		if ((offset >> AGP_PAGE_SHIFT) < isc->stolen) {
553 #ifdef DEBUG
554 			printf("agp: trying to unbind from stolen memory\n");
555 #endif
556 			return (EINVAL);
557 		}
558 	}
559 
560 	WRITE_GATT(offset, 0);
561 	return (0);
562 }
563 
564 /*
565  * Writing via memory mapped registers already flushes all TLBs.
566  */
567 void
568 agp_i810_flush_tlb(void *sc)
569 {
570 }
571 
572 int
573 agp_i810_enable(void *sc, u_int32_t mode)
574 {
575 	return (0);
576 }
577 
578 struct agp_memory *
579 agp_i810_alloc_memory(void *softc, int type, vsize_t size)
580 {
581 	struct agp_i810_softc	*isc = softc;
582 	struct agp_softc	*sc = isc->agpdev;
583 	struct agp_memory	*mem;
584 	int			 error;
585 
586 	if ((size & (AGP_PAGE_SIZE - 1)) != 0)
587 		return (NULL);
588 
589 	if (sc->sc_allocated + size > sc->sc_maxmem)
590 		return (NULL);
591 
592 	if (type == 1) {
593 		/*
594 		 * Mapping local DRAM into GATT.
595 		 */
596 		if (isc->chiptype != CHIP_I810 )
597 			return (NULL);
598 		if (size != isc->dcache_size)
599 			return (NULL);
600 	} else if (type == 2) {
601 		/*
602 		 * Bogus mapping of 1 or 4 pages for the hardware cursor.
603 		 */
604 		if (size != AGP_PAGE_SIZE && size != 4 * AGP_PAGE_SIZE) {
605 #ifdef DEBUG
606 			printf("agp: trying to map %lu for hw cursor\n", size);
607 #endif
608 			return (NULL);
609 		}
610 	}
611 
612 	mem = malloc(sizeof *mem, M_AGP, M_WAITOK | M_ZERO);
613 	mem->am_id = sc->sc_nextid++;
614 	mem->am_size = size;
615 	mem->am_type = type;
616 
617 	if (type == 2) {
618 		/*
619 		 * Allocate and wire down the pages now so that we can
620 		 * get their physical address.
621 		 */
622 		if ((mem->am_dmaseg = malloc(sizeof (*mem->am_dmaseg), M_AGP,
623 		    M_WAITOK | M_CANFAIL)) == NULL)
624 			return (NULL);
625 
626 		if ((error = agp_alloc_dmamem(sc->sc_dmat, size,
627 		    &mem->am_dmamap, &mem->am_physical, mem->am_dmaseg)) != 0) {
628 			free(mem, M_AGP);
629 			printf("agp: agp_alloc_dmamem(%d)\n", error);
630 			return (NULL);
631 		}
632 	} else if (type != 1) {
633 		if ((error = bus_dmamap_create(sc->sc_dmat, size,
634 		    size / PAGE_SIZE + 1, size, 0, BUS_DMA_NOWAIT,
635 		    &mem->am_dmamap)) != 0) {
636 			free(mem, M_AGP);
637 			printf("agp: bus_dmamap_create(%d)\n", error);
638 			return (NULL);
639 		}
640 	}
641 
642 	TAILQ_INSERT_TAIL(&sc->sc_memory, mem, am_link);
643 	sc->sc_allocated += size;
644 
645 	return (mem);
646 }
647 
648 int
649 agp_i810_free_memory(void *softc, struct agp_memory *mem)
650 {
651 	struct agp_i810_softc	*isc = softc;
652 	struct agp_softc	*sc = isc->agpdev;
653 
654 	if (mem->am_is_bound)
655 		return (EBUSY);
656 
657 	if (mem->am_type == 2) {
658 		agp_free_dmamem(sc->sc_dmat, mem->am_size, mem->am_dmamap,
659 		    mem->am_dmaseg);
660 		free(mem->am_dmaseg, M_AGP);
661 	} else if (mem->am_type != 1) {
662 		bus_dmamap_destroy(sc->sc_dmat, mem->am_dmamap);
663 	}
664 
665 	sc->sc_allocated -= mem->am_size;
666 	TAILQ_REMOVE(&sc->sc_memory, mem, am_link);
667 	free(mem, M_AGP);
668 	return (0);
669 }
670 
671 int
672 agp_i810_bind_memory(void *sc, struct agp_memory *mem, off_t offset)
673 {
674 	struct agp_i810_softc	*isc = sc;
675 	u_int32_t 		 regval, i;
676 
677 	if (mem->am_is_bound != 0)
678 		return (EINVAL);
679 	/*
680 	 * XXX evil hack: the PGTBL_CTL appearently gets overwritten by the
681 	 * X server for mysterious reasons which leads to crashes if we write
682 	 * to the GTT through the MMIO window.
683 	 * Until the issue is solved, simply restore it.
684 	 */
685 	regval = READ4(AGP_I810_PGTBL_CTL);
686 	if (regval != (isc->gatt->ag_physical | 1)) {
687 		printf("agp_i810_bind_memory: PGTBL_CTL is 0x%x - fixing\n",
688 		    regval);
689 		WRITE4(AGP_I810_PGTBL_CTL, isc->gatt->ag_physical | 1);
690 	}
691 
692 	if (mem->am_type == 2) {
693 		for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) {
694 			WRITE_GATT(offset + i, (mem->am_physical + i));
695 		}
696 		mem->am_offset = offset;
697 		mem->am_is_bound = 1;
698 		return (0);
699 	}
700 
701 	if (mem->am_type != 1)
702 		return (agp_generic_bind_memory(isc->agpdev, mem, offset));
703 
704 	if (isc->chiptype != CHIP_I810)
705 		return (EINVAL);
706 
707 	for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE)
708 		WRITE4(AGP_I810_GTT +
709 		    (u_int32_t)(offset >> AGP_PAGE_SHIFT) * 4, i | 3);
710 	mem->am_is_bound = 1;
711 	return (0);
712 }
713 
714 int
715 agp_i810_unbind_memory(void *sc, struct agp_memory *mem)
716 {
717 	struct agp_i810_softc	*isc = sc;
718 	u_int32_t		 i;
719 
720 	if (mem->am_is_bound == 0)
721 		return (EINVAL);
722 
723 	if (mem->am_type == 2) {
724 		for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) {
725 			WRITE_GATT(mem->am_offset + i, 0);
726 		}
727 		mem->am_offset = 0;
728 		mem->am_is_bound = 0;
729 		return (0);
730 	}
731 
732 	if (mem->am_type != 1)
733 		return (agp_generic_unbind_memory(isc->agpdev, mem));
734 
735 	if (isc->chiptype != CHIP_I810)
736 		return (EINVAL);
737 
738 	for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE)
739 		WRITE4(AGP_I810_GTT + (i >> AGP_PAGE_SHIFT) * 4, 0);
740 	mem->am_is_bound = 0;
741 	return (0);
742 }
743 
744 void
745 agp_i810_write_gatt(struct agp_i810_softc *isc, bus_size_t off, u_int32_t v)
746 {
747 	u_int32_t d;
748 
749 	d = v | 1;
750 
751 	if (isc->chiptype == CHIP_I915 || isc->chiptype == CHIP_G33)
752 		WRITEGTT((u_int32_t)((off) >> AGP_PAGE_SHIFT) * 4, v ? d : 0);
753 	else if (isc->chiptype == CHIP_I965 || isc->chiptype == CHIP_G4X) {
754 		d |= (v & 0x0000000f00000000ULL) >> 28;
755 		WRITE4((isc->chiptype == CHIP_I965 ? AGP_I965_GTT : AGP_G4X_GTT)
756 		    + (u_int32_t)((off) >> AGP_PAGE_SHIFT) * 4,
757 		    v ? d : 0);
758 	} else
759 		WRITE4(AGP_I810_GTT + (u_int32_t)((off) >> AGP_PAGE_SHIFT) * 4,
760 		    v ? d : 0);
761 }
762