1/*	$NetBSD: agp_i810.c,v 1.73 2011/04/04 20:37:56 dyoung 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 *	$FreeBSD: src/sys/pci/agp_i810.c,v 1.4 2001/07/05 21:28:47 jhb Exp $
30 */
31
32#include <sys/cdefs.h>
33__KERNEL_RCSID(0, "$NetBSD: agp_i810.c,v 1.73 2011/04/04 20:37:56 dyoung Exp $");
34
35#include <sys/param.h>
36#include <sys/systm.h>
37#include <sys/malloc.h>
38#include <sys/kernel.h>
39#include <sys/proc.h>
40#include <sys/device.h>
41#include <sys/conf.h>
42
43#include <dev/pci/pcivar.h>
44#include <dev/pci/pcireg.h>
45#include <dev/pci/pcidevs.h>
46#include <dev/pci/agpvar.h>
47#include <dev/pci/agpreg.h>
48
49#include <sys/agpio.h>
50
51#include <sys/bus.h>
52
53#include "agp_intel.h"
54
55#define READ1(off)	bus_space_read_1(isc->bst, isc->bsh, off)
56#define READ4(off)	bus_space_read_4(isc->bst, isc->bsh, off)
57#define WRITE4(off,v)	bus_space_write_4(isc->bst, isc->bsh, off, v)
58
59#define CHIP_I810 0	/* i810/i815 */
60#define CHIP_I830 1	/* 830M/845G */
61#define CHIP_I855 2	/* 852GM/855GM/865G */
62#define CHIP_I915 3	/* 915G/915GM/945G/945GM/945GME */
63#define CHIP_I965 4	/* 965Q/965PM */
64#define CHIP_G33  5	/* G33/Q33/Q35 */
65#define CHIP_G4X  6	/* G45/Q45 */
66
67struct agp_i810_softc {
68	u_int32_t initial_aperture;	/* aperture size at startup */
69	struct agp_gatt *gatt;
70	int chiptype;			/* i810-like or i830 */
71	u_int32_t dcache_size;		/* i810 only */
72	u_int32_t stolen;		/* number of i830/845 gtt entries
73					   for stolen memory */
74	bus_space_tag_t bst;		/* register bus_space tag */
75	bus_space_handle_t bsh;		/* register bus_space handle */
76	bus_space_tag_t gtt_bst;	/* GTT bus_space tag */
77	bus_space_handle_t gtt_bsh;	/* GTT bus_space handle */
78	struct pci_attach_args vga_pa;
79
80	u_int32_t pgtblctl;
81};
82
83/* XXX hack, see below */
84static bus_addr_t agp_i810_vga_regbase;
85static bus_space_handle_t agp_i810_vga_bsh;
86
87static u_int32_t agp_i810_get_aperture(struct agp_softc *);
88static int agp_i810_set_aperture(struct agp_softc *, u_int32_t);
89static int agp_i810_bind_page(struct agp_softc *, off_t, bus_addr_t);
90static int agp_i810_unbind_page(struct agp_softc *, off_t);
91static void agp_i810_flush_tlb(struct agp_softc *);
92static int agp_i810_enable(struct agp_softc *, u_int32_t mode);
93static struct agp_memory *agp_i810_alloc_memory(struct agp_softc *, int,
94						vsize_t);
95static int agp_i810_free_memory(struct agp_softc *, struct agp_memory *);
96static int agp_i810_bind_memory(struct agp_softc *, struct agp_memory *, off_t);
97static int agp_i810_unbind_memory(struct agp_softc *, struct agp_memory *);
98
99static bool agp_i810_resume(device_t, const pmf_qual_t *);
100static int agp_i810_init(struct agp_softc *);
101
102static int agp_i810_init(struct agp_softc *);
103static int agp_i810_write_gtt_entry(struct agp_i810_softc *, off_t,
104				    bus_addr_t);
105
106static struct agp_methods agp_i810_methods = {
107	agp_i810_get_aperture,
108	agp_i810_set_aperture,
109	agp_i810_bind_page,
110	agp_i810_unbind_page,
111	agp_i810_flush_tlb,
112	agp_i810_enable,
113	agp_i810_alloc_memory,
114	agp_i810_free_memory,
115	agp_i810_bind_memory,
116	agp_i810_unbind_memory,
117};
118
119static int
120agp_i810_write_gtt_entry(struct agp_i810_softc *isc, off_t off, bus_addr_t v)
121{
122	u_int32_t pte;
123	bus_size_t base_off, wroff;
124
125	/* Bits 11:4 (physical start address extension) should be zero. */
126	if ((v & 0xff0) != 0)
127		return EINVAL;
128
129	pte = (u_int32_t)v;
130	/*
131	 * We need to massage the pte if bus_addr_t is wider than 32 bits.
132	 * The compiler isn't smart enough, hence the casts to uintmax_t.
133	 */
134	if (sizeof(bus_addr_t) > sizeof(u_int32_t)) {
135		/* 965+ can do 36-bit addressing, add in the extra bits. */
136		if (isc->chiptype == CHIP_I965 ||
137		    isc->chiptype == CHIP_G33 ||
138		    isc->chiptype == CHIP_G4X) {
139			if (((uintmax_t)v >> 36) != 0)
140				return EINVAL;
141			pte |= (v >> 28) & 0xf0;
142		} else {
143			if (((uintmax_t)v >> 32) != 0)
144				return EINVAL;
145		}
146	}
147
148	base_off = 0;
149	wroff = (off >> AGP_PAGE_SHIFT) * 4;
150
151	switch (isc->chiptype) {
152	case CHIP_I810:
153	case CHIP_I830:
154	case CHIP_I855:
155		base_off = AGP_I810_GTT;
156		break;
157	case CHIP_I965:
158		base_off = AGP_I965_GTT;
159		break;
160	case CHIP_G4X:
161		base_off = AGP_G4X_GTT;
162		break;
163	case CHIP_I915:
164	case CHIP_G33:
165		bus_space_write_4(isc->gtt_bst, isc->gtt_bsh, wroff, pte);
166		return 0;
167	}
168
169	WRITE4(base_off + wroff, pte);
170	return 0;
171}
172
173/* XXXthorpej -- duplicated code (see arch/x86/pci/pchb.c) */
174static int
175agp_i810_vgamatch(const struct pci_attach_args *pa)
176{
177
178	if (PCI_CLASS(pa->pa_class) != PCI_CLASS_DISPLAY ||
179	    PCI_SUBCLASS(pa->pa_class) != PCI_SUBCLASS_DISPLAY_VGA)
180		return (0);
181
182	switch (PCI_PRODUCT(pa->pa_id)) {
183	case PCI_PRODUCT_INTEL_82810_GC:
184	case PCI_PRODUCT_INTEL_82810_DC100_GC:
185	case PCI_PRODUCT_INTEL_82810E_GC:
186	case PCI_PRODUCT_INTEL_82815_FULL_GRAPH:
187	case PCI_PRODUCT_INTEL_82830MP_IV:
188	case PCI_PRODUCT_INTEL_82845G_IGD:
189	case PCI_PRODUCT_INTEL_82855GM_IGD:
190	case PCI_PRODUCT_INTEL_82865_IGD:
191	case PCI_PRODUCT_INTEL_82915G_IGD:
192	case PCI_PRODUCT_INTEL_82915GM_IGD:
193	case PCI_PRODUCT_INTEL_82945P_IGD:
194	case PCI_PRODUCT_INTEL_82945GM_IGD:
195	case PCI_PRODUCT_INTEL_82945GM_IGD_1:
196	case PCI_PRODUCT_INTEL_82945GME_IGD:
197	case PCI_PRODUCT_INTEL_E7221_IGD:
198	case PCI_PRODUCT_INTEL_82965Q_IGD:
199	case PCI_PRODUCT_INTEL_82965Q_IGD_1:
200	case PCI_PRODUCT_INTEL_82965PM_IGD:
201	case PCI_PRODUCT_INTEL_82965PM_IGD_1:
202	case PCI_PRODUCT_INTEL_82G33_IGD:
203	case PCI_PRODUCT_INTEL_82G33_IGD_1:
204	case PCI_PRODUCT_INTEL_82965G_IGD:
205	case PCI_PRODUCT_INTEL_82965G_IGD_1:
206	case PCI_PRODUCT_INTEL_82965GME_IGD:
207	case PCI_PRODUCT_INTEL_82Q35_IGD:
208	case PCI_PRODUCT_INTEL_82Q35_IGD_1:
209	case PCI_PRODUCT_INTEL_82Q33_IGD:
210	case PCI_PRODUCT_INTEL_82Q33_IGD_1:
211	case PCI_PRODUCT_INTEL_82G35_IGD:
212	case PCI_PRODUCT_INTEL_82G35_IGD_1:
213	case PCI_PRODUCT_INTEL_82946GZ_IGD:
214	case PCI_PRODUCT_INTEL_82GM45_IGD:
215	case PCI_PRODUCT_INTEL_82GM45_IGD_1:
216	case PCI_PRODUCT_INTEL_82IGD_E_IGD:
217	case PCI_PRODUCT_INTEL_82Q45_IGD:
218	case PCI_PRODUCT_INTEL_82G45_IGD:
219	case PCI_PRODUCT_INTEL_82G41_IGD:
220	case PCI_PRODUCT_INTEL_82B43_IGD:
221	case PCI_PRODUCT_INTEL_IRONLAKE_D_IGD:
222	case PCI_PRODUCT_INTEL_IRONLAKE_M_IGD:
223	case PCI_PRODUCT_INTEL_PINEVIEW_IGD:
224	case PCI_PRODUCT_INTEL_PINEVIEW_M_IGD:
225		return (1);
226	}
227
228	return (0);
229}
230
231static int
232agp_i965_map_aperture(struct pci_attach_args *pa, struct agp_softc *sc, int reg)
233{
234        /*
235         * Find the aperture. Don't map it (yet), this would
236         * eat KVA.
237         */
238        if (pci_mapreg_info(pa->pa_pc, pa->pa_tag, reg,
239            PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_64BIT, &sc->as_apaddr, &sc->as_apsize,
240            &sc->as_apflags) != 0)
241                return ENXIO;
242
243        sc->as_apt = pa->pa_memt;
244
245        return 0;
246}
247
248int
249agp_i810_attach(device_t parent, device_t self, void *aux)
250{
251	struct agp_softc *sc = device_private(self);
252	struct agp_i810_softc *isc;
253	struct agp_gatt *gatt;
254	int error, apbase;
255	bus_addr_t mmadr;
256	bus_size_t mmadrsize;
257
258	isc = malloc(sizeof *isc, M_AGP, M_NOWAIT|M_ZERO);
259	if (isc == NULL) {
260		aprint_error(": can't allocate chipset-specific softc\n");
261		return ENOMEM;
262	}
263	sc->as_chipc = isc;
264	sc->as_methods = &agp_i810_methods;
265
266	if (pci_find_device(&isc->vga_pa, agp_i810_vgamatch) == 0) {
267#if NAGP_INTEL > 0
268		const struct pci_attach_args *pa = aux;
269
270		switch (PCI_PRODUCT(pa->pa_id)) {
271		case PCI_PRODUCT_INTEL_82840_HB:
272		case PCI_PRODUCT_INTEL_82865_HB:
273		case PCI_PRODUCT_INTEL_82845G_DRAM:
274		case PCI_PRODUCT_INTEL_82815_FULL_HUB:
275		case PCI_PRODUCT_INTEL_82855GM_MCH:
276			return agp_intel_attach(parent, self, aux);
277		}
278#endif
279		aprint_error(": can't find internal VGA device config space\n");
280		free(isc, M_AGP);
281		return ENOENT;
282	}
283
284	/* XXXfvdl */
285	sc->as_dmat = isc->vga_pa.pa_dmat;
286
287	switch (PCI_PRODUCT(isc->vga_pa.pa_id)) {
288	case PCI_PRODUCT_INTEL_82810_GC:
289	case PCI_PRODUCT_INTEL_82810_DC100_GC:
290	case PCI_PRODUCT_INTEL_82810E_GC:
291	case PCI_PRODUCT_INTEL_82815_FULL_GRAPH:
292		isc->chiptype = CHIP_I810;
293		break;
294	case PCI_PRODUCT_INTEL_82830MP_IV:
295	case PCI_PRODUCT_INTEL_82845G_IGD:
296		isc->chiptype = CHIP_I830;
297		break;
298	case PCI_PRODUCT_INTEL_82855GM_IGD:
299	case PCI_PRODUCT_INTEL_82865_IGD:
300		isc->chiptype = CHIP_I855;
301		break;
302	case PCI_PRODUCT_INTEL_82915G_IGD:
303	case PCI_PRODUCT_INTEL_82915GM_IGD:
304	case PCI_PRODUCT_INTEL_82945P_IGD:
305	case PCI_PRODUCT_INTEL_82945GM_IGD:
306	case PCI_PRODUCT_INTEL_82945GM_IGD_1:
307	case PCI_PRODUCT_INTEL_82945GME_IGD:
308	case PCI_PRODUCT_INTEL_E7221_IGD:
309	case PCI_PRODUCT_INTEL_PINEVIEW_IGD:
310	case PCI_PRODUCT_INTEL_PINEVIEW_M_IGD:
311		isc->chiptype = CHIP_I915;
312		break;
313	case PCI_PRODUCT_INTEL_82965Q_IGD:
314	case PCI_PRODUCT_INTEL_82965Q_IGD_1:
315	case PCI_PRODUCT_INTEL_82965PM_IGD:
316	case PCI_PRODUCT_INTEL_82965PM_IGD_1:
317	case PCI_PRODUCT_INTEL_82965G_IGD:
318	case PCI_PRODUCT_INTEL_82965G_IGD_1:
319	case PCI_PRODUCT_INTEL_82965GME_IGD:
320	case PCI_PRODUCT_INTEL_82946GZ_IGD:
321	case PCI_PRODUCT_INTEL_82G35_IGD:
322	case PCI_PRODUCT_INTEL_82G35_IGD_1:
323		isc->chiptype = CHIP_I965;
324		break;
325	case PCI_PRODUCT_INTEL_82Q35_IGD:
326	case PCI_PRODUCT_INTEL_82Q35_IGD_1:
327	case PCI_PRODUCT_INTEL_82G33_IGD:
328	case PCI_PRODUCT_INTEL_82G33_IGD_1:
329	case PCI_PRODUCT_INTEL_82Q33_IGD:
330	case PCI_PRODUCT_INTEL_82Q33_IGD_1:
331		isc->chiptype = CHIP_G33;
332		break;
333	case PCI_PRODUCT_INTEL_82GM45_IGD:
334	case PCI_PRODUCT_INTEL_82GM45_IGD_1:
335	case PCI_PRODUCT_INTEL_82IGD_E_IGD:
336	case PCI_PRODUCT_INTEL_82Q45_IGD:
337	case PCI_PRODUCT_INTEL_82G45_IGD:
338	case PCI_PRODUCT_INTEL_82G41_IGD:
339	case PCI_PRODUCT_INTEL_82B43_IGD:
340	case PCI_PRODUCT_INTEL_IRONLAKE_D_IGD:
341	case PCI_PRODUCT_INTEL_IRONLAKE_M_IGD:
342		isc->chiptype = CHIP_G4X;
343		break;
344	}
345
346	switch (isc->chiptype) {
347	case CHIP_I915:
348	case CHIP_G33:
349		apbase = AGP_I915_GMADR;
350		break;
351	case CHIP_I965:
352	case CHIP_G4X:
353		apbase = AGP_I965_GMADR;
354		break;
355	default:
356		apbase = AGP_I810_GMADR;
357		break;
358	}
359
360	if (isc->chiptype == CHIP_I965 || isc->chiptype == CHIP_G4X) {
361		error = agp_i965_map_aperture(&isc->vga_pa, sc, apbase);
362	} else {
363		error = agp_map_aperture(&isc->vga_pa, sc, apbase);
364	}
365	if (error != 0) {
366		aprint_error(": can't map aperture\n");
367		free(isc, M_AGP);
368		return error;
369	}
370
371	if (isc->chiptype == CHIP_I915 || isc->chiptype == CHIP_G33) {
372		error = pci_mapreg_map(&isc->vga_pa, AGP_I915_MMADR,
373		    PCI_MAPREG_TYPE_MEM, 0, &isc->bst, &isc->bsh,
374		    &mmadr, &mmadrsize);
375		if (error != 0) {
376			aprint_error(": can't map mmadr registers\n");
377			agp_generic_detach(sc);
378			return error;
379		}
380		error = pci_mapreg_map(&isc->vga_pa, AGP_I915_GTTADR,
381		    PCI_MAPREG_TYPE_MEM, 0, &isc->gtt_bst, &isc->gtt_bsh,
382		    NULL, NULL);
383		if (error != 0) {
384			aprint_error(": can't map gttadr registers\n");
385			/* XXX we should release mmadr here */
386			agp_generic_detach(sc);
387			return error;
388		}
389	} else if (isc->chiptype == CHIP_I965 || isc->chiptype == CHIP_G4X) {
390		error = pci_mapreg_map(&isc->vga_pa, AGP_I965_MMADR,
391		    PCI_MAPREG_TYPE_MEM, 0, &isc->bst, &isc->bsh,
392		    &mmadr, &mmadrsize);
393		if (error != 0) {
394			aprint_error(": can't map mmadr registers\n");
395			agp_generic_detach(sc);
396			return error;
397		}
398	} else {
399		error = pci_mapreg_map(&isc->vga_pa, AGP_I810_MMADR,
400		    PCI_MAPREG_TYPE_MEM, 0, &isc->bst, &isc->bsh,
401		    &mmadr, &mmadrsize);
402		if (error != 0) {
403			aprint_error(": can't map mmadr registers\n");
404			agp_generic_detach(sc);
405			return error;
406		}
407	}
408
409	isc->initial_aperture = AGP_GET_APERTURE(sc);
410
411	gatt = malloc(sizeof(struct agp_gatt), M_AGP, M_NOWAIT);
412	if (!gatt) {
413 		agp_generic_detach(sc);
414 		return ENOMEM;
415	}
416	isc->gatt = gatt;
417
418	gatt->ag_entries = AGP_GET_APERTURE(sc) >> AGP_PAGE_SHIFT;
419
420	if (!pmf_device_register(self, NULL, agp_i810_resume))
421		aprint_error_dev(self, "couldn't establish power handler\n");
422
423	/*
424	 * XXX horrible hack to allow drm code to use our mapping
425	 * of VGA chip registers
426	 */
427	agp_i810_vga_regbase = mmadr;
428	agp_i810_vga_bsh = isc->bsh;
429
430	return agp_i810_init(sc);
431}
432
433/*
434 * XXX horrible hack to allow drm code to use our mapping
435 * of VGA chip registers
436 */
437int
438agp_i810_borrow(bus_addr_t base, bus_space_handle_t *hdlp)
439{
440
441	if (!agp_i810_vga_regbase || base != agp_i810_vga_regbase)
442		return 0;
443	*hdlp = agp_i810_vga_bsh;
444	return 1;
445}
446
447static int agp_i810_init(struct agp_softc *sc)
448{
449	struct agp_i810_softc *isc;
450	struct agp_gatt *gatt;
451
452	isc = sc->as_chipc;
453	gatt = isc->gatt;
454
455	if (isc->chiptype == CHIP_I810) {
456		void *virtual;
457		int dummyseg;
458
459		/* Some i810s have on-chip memory called dcache */
460		if (READ1(AGP_I810_DRT) & AGP_I810_DRT_POPULATED)
461			isc->dcache_size = 4 * 1024 * 1024;
462		else
463			isc->dcache_size = 0;
464
465		/* According to the specs the gatt on the i810 must be 64k */
466		if (agp_alloc_dmamem(sc->as_dmat, 64 * 1024,
467		    0, &gatt->ag_dmamap, &virtual, &gatt->ag_physical,
468		    &gatt->ag_dmaseg, 1, &dummyseg) != 0) {
469			free(gatt, M_AGP);
470			agp_generic_detach(sc);
471			return ENOMEM;
472		}
473		gatt->ag_virtual = (uint32_t *)virtual;
474		gatt->ag_size = gatt->ag_entries * sizeof(u_int32_t);
475		memset(gatt->ag_virtual, 0, gatt->ag_size);
476
477		agp_flush_cache();
478		/* Install the GATT. */
479		WRITE4(AGP_I810_PGTBL_CTL, gatt->ag_physical | 1);
480	} else if (isc->chiptype == CHIP_I830) {
481		/* The i830 automatically initializes the 128k gatt on boot. */
482		pcireg_t reg;
483		u_int32_t pgtblctl;
484		u_int16_t gcc1;
485
486		reg = pci_conf_read(sc->as_pc, sc->as_tag, AGP_I830_GCC0);
487		gcc1 = (u_int16_t)(reg >> 16);
488		switch (gcc1 & AGP_I830_GCC1_GMS) {
489		case AGP_I830_GCC1_GMS_STOLEN_512:
490			isc->stolen = (512 - 132) * 1024 / 4096;
491			break;
492		case AGP_I830_GCC1_GMS_STOLEN_1024:
493			isc->stolen = (1024 - 132) * 1024 / 4096;
494			break;
495		case AGP_I830_GCC1_GMS_STOLEN_8192:
496			isc->stolen = (8192 - 132) * 1024 / 4096;
497			break;
498		default:
499			isc->stolen = 0;
500			aprint_error(
501			    ": unknown memory configuration, disabling\n");
502			agp_generic_detach(sc);
503			return EINVAL;
504		}
505
506		if (isc->stolen > 0) {
507			aprint_normal(": detected %dk stolen memory\n%s",
508			    isc->stolen * 4, device_xname(sc->as_dev));
509		}
510
511		/* GATT address is already in there, make sure it's enabled */
512		pgtblctl = READ4(AGP_I810_PGTBL_CTL);
513		pgtblctl |= 1;
514		WRITE4(AGP_I810_PGTBL_CTL, pgtblctl);
515
516		gatt->ag_physical = pgtblctl & ~1;
517	} else if (isc->chiptype == CHIP_I855 || isc->chiptype == CHIP_I915 ||
518		   isc->chiptype == CHIP_I965 || isc->chiptype == CHIP_G33 ||
519		   isc->chiptype == CHIP_G4X) {
520		pcireg_t reg;
521		u_int32_t pgtblctl, gtt_size, stolen;
522		u_int16_t gcc1;
523
524		reg = pci_conf_read(sc->as_pc, sc->as_tag, AGP_I855_GCC1);
525		gcc1 = (u_int16_t)(reg >> 16);
526
527		pgtblctl = READ4(AGP_I810_PGTBL_CTL);
528
529		/* Stolen memory is set up at the beginning of the aperture by
530                 * the BIOS, consisting of the GATT followed by 4kb for the
531		 * BIOS display.
532                 */
533                switch (isc->chiptype) {
534		case CHIP_I855:
535			gtt_size = 128;
536			break;
537                case CHIP_I915:
538			gtt_size = 256;
539			break;
540		case CHIP_I965:
541			switch (pgtblctl & AGP_I810_PGTBL_SIZE_MASK) {
542			case AGP_I810_PGTBL_SIZE_128KB:
543			case AGP_I810_PGTBL_SIZE_512KB:
544				gtt_size = 512;
545				break;
546			case AGP_I965_PGTBL_SIZE_1MB:
547				gtt_size = 1024;
548				break;
549			case AGP_I965_PGTBL_SIZE_2MB:
550				gtt_size = 2048;
551				break;
552			case AGP_I965_PGTBL_SIZE_1_5MB:
553				gtt_size = 1024 + 512;
554				break;
555			default:
556				aprint_error("Bad PGTBL size\n");
557				agp_generic_detach(sc);
558				return EINVAL;
559			}
560			break;
561		case CHIP_G33:
562			switch (gcc1 & AGP_G33_PGTBL_SIZE_MASK) {
563			case AGP_G33_PGTBL_SIZE_1M:
564				gtt_size = 1024;
565				break;
566			case AGP_G33_PGTBL_SIZE_2M:
567				gtt_size = 2048;
568				break;
569			default:
570				aprint_error(": Bad PGTBL size\n");
571				agp_generic_detach(sc);
572				return EINVAL;
573			}
574			break;
575		case CHIP_G4X:
576			gtt_size = 0;
577			break;
578		default:
579			aprint_error(": bad chiptype\n");
580			agp_generic_detach(sc);
581			return EINVAL;
582		}
583
584		switch (gcc1 & AGP_I855_GCC1_GMS) {
585		case AGP_I855_GCC1_GMS_STOLEN_1M:
586			stolen = 1024;
587			break;
588		case AGP_I855_GCC1_GMS_STOLEN_4M:
589			stolen = 4 * 1024;
590			break;
591		case AGP_I855_GCC1_GMS_STOLEN_8M:
592			stolen = 8 * 1024;
593			break;
594		case AGP_I855_GCC1_GMS_STOLEN_16M:
595			stolen = 16 * 1024;
596			break;
597		case AGP_I855_GCC1_GMS_STOLEN_32M:
598			stolen = 32 * 1024;
599			break;
600		case AGP_I915_GCC1_GMS_STOLEN_48M:
601			stolen = 48 * 1024;
602			break;
603		case AGP_I915_GCC1_GMS_STOLEN_64M:
604			stolen = 64 * 1024;
605			break;
606		case AGP_G33_GCC1_GMS_STOLEN_128M:
607			stolen = 128 * 1024;
608			break;
609		case AGP_G33_GCC1_GMS_STOLEN_256M:
610			stolen = 256 * 1024;
611			break;
612		case AGP_G4X_GCC1_GMS_STOLEN_96M:
613			stolen = 96 * 1024;
614			break;
615		case AGP_G4X_GCC1_GMS_STOLEN_160M:
616			stolen = 160 * 1024;
617			break;
618		case AGP_G4X_GCC1_GMS_STOLEN_224M:
619			stolen = 224 * 1024;
620			break;
621		case AGP_G4X_GCC1_GMS_STOLEN_352M:
622			stolen = 352 * 1024;
623			break;
624		default:
625			aprint_error(
626			    ": unknown memory configuration, disabling\n");
627			agp_generic_detach(sc);
628			return EINVAL;
629		}
630
631		switch (gcc1 & AGP_I855_GCC1_GMS) {
632		case AGP_I915_GCC1_GMS_STOLEN_48M:
633		case AGP_I915_GCC1_GMS_STOLEN_64M:
634			if (isc->chiptype != CHIP_I915 &&
635			    isc->chiptype != CHIP_I965 &&
636			    isc->chiptype != CHIP_G33 &&
637			    isc->chiptype != CHIP_G4X)
638				stolen = 0;
639			break;
640		case AGP_G33_GCC1_GMS_STOLEN_128M:
641		case AGP_G33_GCC1_GMS_STOLEN_256M:
642			if (isc->chiptype != CHIP_I965 &&
643			    isc->chiptype != CHIP_G33 &&
644			    isc->chiptype != CHIP_G4X)
645				stolen = 0;
646			break;
647		case AGP_G4X_GCC1_GMS_STOLEN_96M:
648		case AGP_G4X_GCC1_GMS_STOLEN_160M:
649		case AGP_G4X_GCC1_GMS_STOLEN_224M:
650		case AGP_G4X_GCC1_GMS_STOLEN_352M:
651			if (isc->chiptype != CHIP_I965 &&
652			    isc->chiptype != CHIP_G4X)
653				stolen = 0;
654			break;
655		}
656
657		/* BIOS space */
658		gtt_size += 4;
659
660		isc->stolen = (stolen - gtt_size) * 1024 / 4096;
661
662		if (isc->stolen > 0) {
663			aprint_normal(": detected %dk stolen memory\n%s",
664			    isc->stolen * 4, device_xname(sc->as_dev));
665		}
666
667		/* GATT address is already in there, make sure it's enabled */
668		pgtblctl |= 1;
669		WRITE4(AGP_I810_PGTBL_CTL, pgtblctl);
670
671		gatt->ag_physical = pgtblctl & ~1;
672	}
673
674	/*
675	 * Make sure the chipset can see everything.
676	 */
677	agp_flush_cache();
678
679	return 0;
680}
681
682#if 0
683static int
684agp_i810_detach(struct agp_softc *sc)
685{
686	int error;
687	struct agp_i810_softc *isc = sc->as_chipc;
688
689	error = agp_generic_detach(sc);
690	if (error)
691		return error;
692
693	/* Clear the GATT base. */
694	if (sc->chiptype == CHIP_I810) {
695		WRITE4(AGP_I810_PGTBL_CTL, 0);
696	} else {
697		unsigned int pgtblctl;
698		pgtblctl = READ4(AGP_I810_PGTBL_CTL);
699		pgtblctl &= ~1;
700		WRITE4(AGP_I810_PGTBL_CTL, pgtblctl);
701	}
702
703	/* Put the aperture back the way it started. */
704	AGP_SET_APERTURE(sc, isc->initial_aperture);
705
706	if (sc->chiptype == CHIP_I810) {
707		agp_free_dmamem(sc->as_dmat, gatt->ag_size, gatt->ag_dmamap,
708		    (void *)gatt->ag_virtual, &gatt->ag_dmaseg, 1);
709	}
710	free(sc->gatt, M_AGP);
711
712	return 0;
713}
714#endif
715
716static u_int32_t
717agp_i810_get_aperture(struct agp_softc *sc)
718{
719	struct agp_i810_softc *isc = sc->as_chipc;
720	pcireg_t reg;
721	u_int32_t size;
722	u_int16_t miscc, gcc1, msac;
723
724	size = 0;
725
726	switch (isc->chiptype) {
727	case CHIP_I810:
728		reg = pci_conf_read(sc->as_pc, sc->as_tag, AGP_I810_SMRAM);
729		miscc = (u_int16_t)(reg >> 16);
730		if ((miscc & AGP_I810_MISCC_WINSIZE) ==
731		    AGP_I810_MISCC_WINSIZE_32)
732			size = 32 * 1024 * 1024;
733		else
734			size = 64 * 1024 * 1024;
735		break;
736	case CHIP_I830:
737		reg = pci_conf_read(sc->as_pc, sc->as_tag, AGP_I830_GCC0);
738		gcc1 = (u_int16_t)(reg >> 16);
739		if ((gcc1 & AGP_I830_GCC1_GMASIZE) == AGP_I830_GCC1_GMASIZE_64)
740			size = 64 * 1024 * 1024;
741		else
742			size = 128 * 1024 * 1024;
743		break;
744	case CHIP_I855:
745		size = 128 * 1024 * 1024;
746		break;
747	case CHIP_I915:
748	case CHIP_G33:
749	case CHIP_G4X:
750		reg = pci_conf_read(sc->as_pc, sc->as_tag, AGP_I915_MSAC);
751		msac = (u_int16_t)(reg >> 16);
752		if (msac & AGP_I915_MSAC_APER_128M)
753			size = 128 * 1024 * 1024;
754		else
755			size = 256 * 1024 * 1024;
756		break;
757	case CHIP_I965:
758		size = 512 * 1024 * 1024;
759		break;
760	default:
761		aprint_error(": Unknown chipset\n");
762	}
763
764	return size;
765}
766
767static int
768agp_i810_set_aperture(struct agp_softc *sc, u_int32_t aperture)
769{
770	struct agp_i810_softc *isc = sc->as_chipc;
771	pcireg_t reg;
772	u_int16_t miscc, gcc1;
773
774	switch (isc->chiptype) {
775	case CHIP_I810:
776		/*
777		 * Double check for sanity.
778		 */
779		if (aperture != (32 * 1024 * 1024) &&
780		    aperture != (64 * 1024 * 1024)) {
781			aprint_error_dev(sc->as_dev, "bad aperture size %d\n",
782			    aperture);
783			return EINVAL;
784		}
785
786		reg = pci_conf_read(sc->as_pc, sc->as_tag, AGP_I810_SMRAM);
787		miscc = (u_int16_t)(reg >> 16);
788		miscc &= ~AGP_I810_MISCC_WINSIZE;
789		if (aperture == 32 * 1024 * 1024)
790			miscc |= AGP_I810_MISCC_WINSIZE_32;
791		else
792			miscc |= AGP_I810_MISCC_WINSIZE_64;
793
794		reg &= 0x0000ffff;
795		reg |= ((pcireg_t)miscc) << 16;
796		pci_conf_write(sc->as_pc, sc->as_tag, AGP_I810_SMRAM, reg);
797		break;
798	case CHIP_I830:
799		if (aperture != (64 * 1024 * 1024) &&
800		    aperture != (128 * 1024 * 1024)) {
801			aprint_error_dev(sc->as_dev, "bad aperture size %d\n",
802			    aperture);
803			return EINVAL;
804		}
805		reg = pci_conf_read(sc->as_pc, sc->as_tag, AGP_I830_GCC0);
806		gcc1 = (u_int16_t)(reg >> 16);
807		gcc1 &= ~AGP_I830_GCC1_GMASIZE;
808		if (aperture == 64 * 1024 * 1024)
809			gcc1 |= AGP_I830_GCC1_GMASIZE_64;
810		else
811			gcc1 |= AGP_I830_GCC1_GMASIZE_128;
812
813		reg &= 0x0000ffff;
814		reg |= ((pcireg_t)gcc1) << 16;
815		pci_conf_write(sc->as_pc, sc->as_tag, AGP_I830_GCC0, reg);
816		break;
817	case CHIP_I855:
818	case CHIP_I915:
819		if (aperture != agp_i810_get_aperture(sc)) {
820			aprint_error_dev(sc->as_dev, "bad aperture size %d\n",
821			    aperture);
822			return EINVAL;
823		}
824		break;
825	case CHIP_I965:
826		if (aperture != 512 * 1024 * 1024) {
827			aprint_error_dev(sc->as_dev, "bad aperture size %d\n",
828			    aperture);
829			return EINVAL;
830		}
831		break;
832	}
833
834	return 0;
835}
836
837static int
838agp_i810_bind_page(struct agp_softc *sc, off_t offset, bus_addr_t physical)
839{
840	struct agp_i810_softc *isc = sc->as_chipc;
841
842	if (offset < 0 || offset >= (isc->gatt->ag_entries << AGP_PAGE_SHIFT)) {
843#ifdef AGP_DEBUG
844		printf("%s: failed: offset 0x%08x, shift %d, entries %d\n",
845		    device_xname(sc->as_dev), (int)offset, AGP_PAGE_SHIFT,
846		    isc->gatt->ag_entries);
847#endif
848		return EINVAL;
849	}
850
851	if (isc->chiptype != CHIP_I810) {
852		if ((offset >> AGP_PAGE_SHIFT) < isc->stolen) {
853#ifdef AGP_DEBUG
854			printf("%s: trying to bind into stolen memory\n",
855			    device_xname(sc->as_dev));
856#endif
857			return EINVAL;
858		}
859	}
860
861	return agp_i810_write_gtt_entry(isc, offset, physical | 1);
862}
863
864static int
865agp_i810_unbind_page(struct agp_softc *sc, off_t offset)
866{
867	struct agp_i810_softc *isc = sc->as_chipc;
868
869	if (offset < 0 || offset >= (isc->gatt->ag_entries << AGP_PAGE_SHIFT))
870		return EINVAL;
871
872	if (isc->chiptype != CHIP_I810 ) {
873		if ((offset >> AGP_PAGE_SHIFT) < isc->stolen) {
874#ifdef AGP_DEBUG
875			printf("%s: trying to unbind from stolen memory\n",
876			    device_xname(sc->as_dev));
877#endif
878			return EINVAL;
879		}
880	}
881
882	return agp_i810_write_gtt_entry(isc, offset, 0);
883}
884
885/*
886 * Writing via memory mapped registers already flushes all TLBs.
887 */
888static void
889agp_i810_flush_tlb(struct agp_softc *sc)
890{
891}
892
893static int
894agp_i810_enable(struct agp_softc *sc, u_int32_t mode)
895{
896
897	return 0;
898}
899
900static struct agp_memory *
901agp_i810_alloc_memory(struct agp_softc *sc, int type, vsize_t size)
902{
903	struct agp_i810_softc *isc = sc->as_chipc;
904	struct agp_memory *mem;
905
906#ifdef AGP_DEBUG
907	printf("AGP: alloc(%d, 0x%x)\n", type, (int) size);
908#endif
909
910	if ((size & (AGP_PAGE_SIZE - 1)) != 0)
911		return 0;
912
913	if (sc->as_allocated + size > sc->as_maxmem)
914		return 0;
915
916	if (type == 1) {
917		/*
918		 * Mapping local DRAM into GATT.
919		 */
920		if (isc->chiptype != CHIP_I810 )
921			return 0;
922		if (size != isc->dcache_size)
923			return 0;
924	} else if (type == 2) {
925		/*
926		 * Bogus mapping for the hardware cursor.
927		 */
928		if (size != AGP_PAGE_SIZE && size != 4 * AGP_PAGE_SIZE)
929			return 0;
930	}
931
932	mem = malloc(sizeof *mem, M_AGP, M_WAITOK|M_ZERO);
933	if (mem == NULL)
934		return NULL;
935	mem->am_id = sc->as_nextid++;
936	mem->am_size = size;
937	mem->am_type = type;
938
939	if (type == 2) {
940		/*
941		 * Allocate and wire down the memory now so that we can
942		 * get its physical address.
943		 */
944		mem->am_dmaseg = malloc(sizeof *mem->am_dmaseg, M_AGP,
945		    M_WAITOK);
946		if (mem->am_dmaseg == NULL) {
947			free(mem, M_AGP);
948			return NULL;
949		}
950		if (agp_alloc_dmamem(sc->as_dmat, size, 0,
951		    &mem->am_dmamap, &mem->am_virtual, &mem->am_physical,
952		    mem->am_dmaseg, 1, &mem->am_nseg) != 0) {
953			free(mem->am_dmaseg, M_AGP);
954			free(mem, M_AGP);
955			return NULL;
956		}
957		memset(mem->am_virtual, 0, size);
958	} else if (type != 1) {
959		if (bus_dmamap_create(sc->as_dmat, size, size / PAGE_SIZE + 1,
960				      size, 0, BUS_DMA_NOWAIT,
961				      &mem->am_dmamap) != 0) {
962			free(mem, M_AGP);
963			return NULL;
964		}
965	}
966
967	TAILQ_INSERT_TAIL(&sc->as_memory, mem, am_link);
968	sc->as_allocated += size;
969
970	return mem;
971}
972
973static int
974agp_i810_free_memory(struct agp_softc *sc, struct agp_memory *mem)
975{
976	if (mem->am_is_bound)
977		return EBUSY;
978
979	if (mem->am_type == 2) {
980		agp_free_dmamem(sc->as_dmat, mem->am_size, mem->am_dmamap,
981		    mem->am_virtual, mem->am_dmaseg, mem->am_nseg);
982		free(mem->am_dmaseg, M_AGP);
983	}
984
985	sc->as_allocated -= mem->am_size;
986	TAILQ_REMOVE(&sc->as_memory, mem, am_link);
987	free(mem, M_AGP);
988	return 0;
989}
990
991static int
992agp_i810_bind_memory(struct agp_softc *sc, struct agp_memory *mem,
993		     off_t offset)
994{
995	struct agp_i810_softc *isc = sc->as_chipc;
996	u_int32_t regval, i;
997
998	if (mem->am_is_bound != 0)
999		return EINVAL;
1000
1001	/*
1002	 * XXX evil hack: the PGTBL_CTL appearently gets overwritten by the
1003	 * X server for mysterious reasons which leads to crashes if we write
1004	 * to the GTT through the MMIO window.
1005	 * Until the issue is solved, simply restore it.
1006	 */
1007	regval = bus_space_read_4(isc->bst, isc->bsh, AGP_I810_PGTBL_CTL);
1008	if (regval != (isc->gatt->ag_physical | 1)) {
1009		printf("agp_i810_bind_memory: PGTBL_CTL is 0x%x - fixing\n",
1010		       regval);
1011		bus_space_write_4(isc->bst, isc->bsh, AGP_I810_PGTBL_CTL,
1012				  isc->gatt->ag_physical | 1);
1013	}
1014
1015	if (mem->am_type == 2) {
1016		for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE)
1017			agp_i810_bind_page(sc, offset + i,
1018			    mem->am_physical + i);
1019		mem->am_offset = offset;
1020		mem->am_is_bound = 1;
1021		return 0;
1022	}
1023
1024	if (mem->am_type != 1)
1025		return agp_generic_bind_memory(sc, mem, offset);
1026
1027	if (isc->chiptype != CHIP_I810)
1028		return EINVAL;
1029
1030	for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE)
1031		agp_i810_write_gtt_entry(isc, offset + i, i | 3);
1032	mem->am_offset = offset;
1033	mem->am_is_bound = 1;
1034	return 0;
1035}
1036
1037static int
1038agp_i810_unbind_memory(struct agp_softc *sc, struct agp_memory *mem)
1039{
1040	struct agp_i810_softc *isc = sc->as_chipc;
1041	u_int32_t i;
1042
1043	if (mem->am_is_bound == 0)
1044		return EINVAL;
1045
1046	if (mem->am_type == 2) {
1047		for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE)
1048			agp_i810_unbind_page(sc, mem->am_offset + i);
1049		mem->am_offset = 0;
1050		mem->am_is_bound = 0;
1051		return 0;
1052	}
1053
1054	if (mem->am_type != 1)
1055		return agp_generic_unbind_memory(sc, mem);
1056
1057	if (isc->chiptype != CHIP_I810)
1058		return EINVAL;
1059
1060	for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE)
1061		agp_i810_write_gtt_entry(isc, mem->am_offset + i, 0);
1062	mem->am_offset = 0;
1063	mem->am_is_bound = 0;
1064	return 0;
1065}
1066
1067static bool
1068agp_i810_resume(device_t dv, const pmf_qual_t *qual)
1069{
1070	struct agp_softc *sc = device_private(dv);
1071	struct agp_i810_softc *isc = sc->as_chipc;
1072
1073	isc->pgtblctl = READ4(AGP_I810_PGTBL_CTL);
1074	agp_flush_cache();
1075
1076	return true;
1077}
1078