agp_i810.c revision 158655
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: head/sys/dev/agp/agp_i810.c 158655 2006-05-16 16:19:48Z anholt $");
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
63MALLOC_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
75struct 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
95static const char*
96agp_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 */
155static device_t
156agp_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
199static void
200agp_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
208static int
209agp_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
283static int
284agp_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
469static int
470agp_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
510static u_int32_t
511agp_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
545static int
546agp_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
615static int
616agp_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
641static int
642agp_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 */
668static void
669agp_i810_flush_tlb(device_t dev)
670{
671}
672
673static int
674agp_i810_enable(device_t dev, u_int32_t mode)
675{
676
677	return 0;
678}
679
680static struct agp_memory *
681agp_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
761static int
762agp_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
796static int
797agp_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
851static int
852agp_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
893static 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
915static driver_t agp_i810_driver = {
916	"agp",
917	agp_i810_methods,
918	sizeof(struct agp_i810_softc),
919};
920
921static devclass_t agp_devclass;
922
923DRIVER_MODULE(agp_i810, vgapci, agp_i810_driver, agp_devclass, 0, 0);
924MODULE_DEPEND(agp_i810, agp, 1, 1, 1);
925MODULE_DEPEND(agp_i810, pci, 1, 1, 1);
926