agp_amd64.c revision 173203
118334Speter/*-
252284Sobrien * Copyright (c) 2004, 2005 Jung-uk Kim <jkim@FreeBSD.org>
318334Speter * All rights reserved.
418334Speter *
518334Speter * Redistribution and use in source and binary forms, with or without
618334Speter * modification, are permitted provided that the following conditions
718334Speter * are met:
818334Speter * 1. Redistributions of source code must retain the above copyright
918334Speter *    notice, this list of conditions and the following disclaimer.
1018334Speter * 2. Redistributions in binary form must reproduce the above copyright
1118334Speter *    notice, this list of conditions and the following disclaimer in the
1218334Speter *    documentation and/or other materials provided with the distribution.
1318334Speter *
1418334Speter * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1518334Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1618334Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1718334Speter * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1818334Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1918334Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2018334Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2118334Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2218334Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2318334Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2418334Speter * SUCH DAMAGE.
2518334Speter */
2618334Speter
2718334Speter#include <sys/cdefs.h>
2818334Speter__FBSDID("$FreeBSD: head/sys/dev/agp/agp_amd64.c 173203 2007-10-30 22:09:16Z jhb $");
2918334Speter
3018334Speter#include "opt_bus.h"
3118334Speter
3218334Speter#include <sys/param.h>
3318334Speter#include <sys/systm.h>
3418334Speter#include <sys/malloc.h>
3518334Speter#include <sys/kernel.h>
3618334Speter#include <sys/module.h>
3718334Speter#include <sys/bus.h>
3818334Speter#include <sys/lock.h>
3918334Speter#include <sys/mutex.h>
4018334Speter#include <sys/proc.h>
4118334Speter
4218334Speter#include <dev/pci/pcivar.h>
4318334Speter#include <dev/pci/pcireg.h>
4418334Speter#include <pci/agppriv.h>
4518334Speter#include <pci/agpreg.h>
4618334Speter
4718334Speter#include <vm/vm.h>
4818334Speter#include <vm/vm_object.h>
4918334Speter#include <vm/pmap.h>
5050397Sobrien#include <machine/bus.h>
5118334Speter#include <machine/resource.h>
5218334Speter#include <sys/rman.h>
5318334Speter
5452284Sobrien/* XXX */
5552284Sobrienextern void pci_cfgregwrite(int, int, int, int, uint32_t, int);
5652284Sobrienextern uint32_t pci_cfgregread(int, int, int, int, int);
5718334Speter
5818334Speterstatic void agp_amd64_apbase_fixup(device_t);
5918334Speter
6018334Speterstatic void agp_amd64_uli_init(device_t);
6118334Speterstatic int agp_amd64_uli_set_aperture(device_t, uint32_t);
6218334Speter
6352284Sobrienstatic int agp_amd64_nvidia_match(uint16_t);
6450397Sobrienstatic void agp_amd64_nvidia_init(device_t);
6552284Sobrienstatic int agp_amd64_nvidia_set_aperture(device_t, uint32_t);
6618334Speter
6718334Speterstatic int agp_amd64_via_match(void);
6818334Speterstatic void agp_amd64_via_init(device_t);
6918334Speterstatic int agp_amd64_via_set_aperture(device_t, uint32_t);
7018334Speter
7118334SpeterMALLOC_DECLARE(M_AGP);
7218334Speter
7318334Speter#define	AMD64_MAX_MCTRL		8
7418334Speter
7518334Speterstruct agp_amd64_softc {
7618334Speter	struct agp_softc	agp;
7718334Speter	uint32_t		initial_aperture;
7818334Speter	struct agp_gatt		*gatt;
7918334Speter	uint32_t		apbase;
8018334Speter	int			mctrl[AMD64_MAX_MCTRL];
8118334Speter	int			n_mctrl;
8218334Speter	int			via_agp;
8318334Speter};
8418334Speter
8518334Speterstatic const char*
8618334Speteragp_amd64_match(device_t dev)
8718334Speter{
8818334Speter	if (pci_get_class(dev) != PCIC_BRIDGE ||
8918334Speter	    pci_get_subclass(dev) != PCIS_BRIDGE_HOST ||
9018334Speter	    agp_find_caps(dev) == 0)
9118334Speter		return (NULL);
9218334Speter
9352284Sobrien	switch (pci_get_devid(dev)) {
9418334Speter	case 0x74541022:
9518334Speter		return ("AMD 8151 AGP graphics tunnel");
9618334Speter	case 0x07551039:
9718334Speter		return ("SiS 755 host to AGP bridge");
9818334Speter	case 0x07601039:
9918334Speter		return ("SiS 760 host to AGP bridge");
10018334Speter	case 0x168910b9:
10118334Speter		return ("ULi M1689 AGP Controller");
10218334Speter	case 0x00d110de:
10318334Speter		if (agp_amd64_nvidia_match(0x00d2))
10418334Speter			return (NULL);
10518334Speter		return ("NVIDIA nForce3 AGP Controller");
10618334Speter	case 0x00e110de:
10718334Speter		if (agp_amd64_nvidia_match(0x00e2))
10818334Speter			return (NULL);
10918334Speter		return ("NVIDIA nForce3-250 AGP Controller");
11018334Speter	case 0x02041106:
11118334Speter		return ("VIA 8380 host to PCI bridge");
11218334Speter	case 0x02381106:
11318334Speter		return ("VIA 3238 host to PCI bridge");
11418334Speter	case 0x02821106:
11518334Speter		return ("VIA K8T800Pro host to PCI bridge");
11618334Speter	case 0x31881106:
11718334Speter		return ("VIA 8385 host to PCI bridge");
11818334Speter	};
11918334Speter
12018334Speter	return (NULL);
12118334Speter}
12218334Speter
12318334Speterstatic int
12418334Speteragp_amd64_nvidia_match(uint16_t devid)
12518334Speter{
12618334Speter	/* XXX nForce3 requires secondary AGP bridge at 0:11:0. */
12750397Sobrien	if (pci_cfgregread(0, 11, 0, PCIR_CLASS, 1) != PCIC_BRIDGE ||
12818334Speter	    pci_cfgregread(0, 11, 0, PCIR_SUBCLASS, 1) != PCIS_BRIDGE_PCI ||
12918334Speter	    pci_cfgregread(0, 11, 0, PCIR_VENDOR, 2) != 0x10de ||
13018334Speter	    pci_cfgregread(0, 11, 0, PCIR_DEVICE, 2) != devid)
13118334Speter		return (ENXIO);
13218334Speter
13318334Speter	return (0);
13418334Speter}
13518334Speter
13618334Speterstatic int
13718334Speteragp_amd64_via_match(void)
13818334Speter{
13918334Speter	/* XXX Some VIA bridge requires secondary AGP bridge at 0:1:0. */
14018334Speter	if (pci_cfgregread(0, 1, 0, PCIR_CLASS, 1) != PCIC_BRIDGE ||
14118334Speter	    pci_cfgregread(0, 1, 0, PCIR_SUBCLASS, 1) != PCIS_BRIDGE_PCI ||
14218334Speter	    pci_cfgregread(0, 1, 0, PCIR_VENDOR, 2) != 0x1106 ||
14318334Speter	    pci_cfgregread(0, 1, 0, PCIR_DEVICE, 2) != 0xb188 ||
14452284Sobrien	    (pci_cfgregread(0, 1, 0, AGP_VIA_AGPSEL, 1) & 2))
14518334Speter		return (0);
14618334Speter
14718334Speter	return (1);
14818334Speter}
14918334Speter
15018334Speterstatic int
15118334Speteragp_amd64_probe(device_t dev)
15218334Speter{
15318334Speter	const char *desc;
15418334Speter
15518334Speter	if (resource_disabled("agp", device_get_unit(dev)))
15618334Speter		return (ENXIO);
15718334Speter	if ((desc = agp_amd64_match(dev))) {
15818334Speter		device_set_desc(dev, desc);
15918334Speter		return (BUS_PROBE_DEFAULT);
16018334Speter	}
16118334Speter
16218334Speter	return (ENXIO);
16318334Speter}
16452284Sobrien
16518334Speterstatic int
16618334Speteragp_amd64_attach(device_t dev)
16718334Speter{
16818334Speter	struct agp_amd64_softc *sc = device_get_softc(dev);
16918334Speter	struct agp_gatt *gatt;
17018334Speter	int i, n, error;
17118334Speter
17218334Speter	for (i = 0, n = 0; i < PCI_SLOTMAX && n < AMD64_MAX_MCTRL; i++)
17318334Speter		if (pci_cfgregread(0, i, 3, 0, 4) == 0x11031022) {
17418334Speter			sc->mctrl[n] = i;
17552284Sobrien			n++;
17618334Speter		}
17718334Speter
17818334Speter	if (n == 0)
17918334Speter		return (ENXIO);
18018334Speter
18118334Speter	sc->n_mctrl = n;
18218334Speter
18318334Speter	if (bootverbose)
18418334Speter		device_printf(dev, "%d Miscellaneous Control unit(s) found.\n",
18552284Sobrien		    sc->n_mctrl);
18618334Speter
18718334Speter	if ((error = agp_generic_attach(dev)))
18818334Speter		return (error);
18918334Speter
19018334Speter	sc->initial_aperture = AGP_GET_APERTURE(dev);
19118334Speter
19252284Sobrien	for (;;) {
19318334Speter		gatt = agp_alloc_gatt(dev);
19418334Speter		if (gatt)
19552284Sobrien			break;
19652284Sobrien
19752284Sobrien		/*
19852284Sobrien		 * Probably contigmalloc failure. Try reducing the
19918334Speter		 * aperture so that the gatt size reduces.
20018334Speter		 */
20118334Speter		if (AGP_SET_APERTURE(dev, AGP_GET_APERTURE(dev) / 2)) {
20218334Speter			agp_generic_detach(dev);
20318334Speter			return (ENOMEM);
20418334Speter		}
20518334Speter	}
20618334Speter	sc->gatt = gatt;
20718334Speter
20818334Speter	switch (pci_get_vendor(dev)) {
20918334Speter	case 0x10b9:	/* ULi */
21018334Speter		agp_amd64_uli_init(dev);
21118334Speter		if (agp_amd64_uli_set_aperture(dev, sc->initial_aperture))
21218334Speter			return (ENXIO);
21318334Speter		break;
21418334Speter
21552284Sobrien	case 0x10de:	/* nVidia */
21652284Sobrien		agp_amd64_nvidia_init(dev);
21752284Sobrien		if (agp_amd64_nvidia_set_aperture(dev, sc->initial_aperture))
21852284Sobrien			return (ENXIO);
21952284Sobrien		break;
22052284Sobrien
22152284Sobrien	case 0x1106:	/* VIA */
22252284Sobrien		sc->via_agp = agp_amd64_via_match();
22352284Sobrien		if (sc->via_agp) {
22452284Sobrien			agp_amd64_via_init(dev);
22552284Sobrien			if (agp_amd64_via_set_aperture(dev,
22652284Sobrien			    sc->initial_aperture))
22752284Sobrien				return (ENXIO);
22852284Sobrien		}
22952284Sobrien		break;
23052284Sobrien	}
23152284Sobrien
23252284Sobrien	/* Install the gatt and enable aperture. */
23352284Sobrien	for (i = 0; i < sc->n_mctrl; i++) {
23452284Sobrien		pci_cfgregwrite(0, sc->mctrl[i], 3, AGP_AMD64_ATTBASE,
23552284Sobrien		    (uint32_t)(gatt->ag_physical >> 8) & AGP_AMD64_ATTBASE_MASK,
23652284Sobrien		    4);
23752284Sobrien		pci_cfgregwrite(0, sc->mctrl[i], 3, AGP_AMD64_APCTRL,
23852284Sobrien		    (pci_cfgregread(0, sc->mctrl[i], 3, AGP_AMD64_APCTRL, 4) |
23952284Sobrien		    AGP_AMD64_APCTRL_GARTEN) &
24052284Sobrien		    ~(AGP_AMD64_APCTRL_DISGARTCPU | AGP_AMD64_APCTRL_DISGARTIO),
24152284Sobrien		    4);
24252284Sobrien	}
24352284Sobrien
24452284Sobrien	agp_flush_cache();
24552284Sobrien
24652284Sobrien	return (0);
24718334Speter}
24818334Speter
24918334Speterstatic int
25018334Speteragp_amd64_detach(device_t dev)
25118334Speter{
25218334Speter	struct agp_amd64_softc *sc = device_get_softc(dev);
25318334Speter	int i;
25418334Speter
25518334Speter	agp_free_cdev(dev);
25618334Speter
25718334Speter	for (i = 0; i < sc->n_mctrl; i++)
25818334Speter		pci_cfgregwrite(0, sc->mctrl[i], 3, AGP_AMD64_APCTRL,
25918334Speter		    pci_cfgregread(0, sc->mctrl[i], 3, AGP_AMD64_APCTRL, 4) &
26018334Speter		    ~AGP_AMD64_APCTRL_GARTEN, 4);
26118334Speter
26218334Speter	AGP_SET_APERTURE(dev, sc->initial_aperture);
26318334Speter	agp_free_gatt(sc->gatt);
26418334Speter	agp_free_res(dev);
26518334Speter
26618334Speter	return (0);
26718334Speter}
26818334Speter
26918334Speterstatic uint32_t agp_amd64_table[] = {
27018334Speter	0x02000000,	/*   32 MB */
27118334Speter	0x04000000,	/*   64 MB */
27218334Speter	0x08000000,	/*  128 MB */
27318334Speter	0x10000000,	/*  256 MB */
27418334Speter	0x20000000,	/*  512 MB */
27518334Speter	0x40000000,	/* 1024 MB */
27618334Speter	0x80000000,	/* 2048 MB */
27718334Speter};
27818334Speter
27918334Speter#define AGP_AMD64_TABLE_SIZE \
28018334Speter	(sizeof(agp_amd64_table) / sizeof(agp_amd64_table[0]))
28118334Speter
28218334Speterstatic uint32_t
28318334Speteragp_amd64_get_aperture(device_t dev)
28418334Speter{
28518334Speter	struct agp_amd64_softc *sc = device_get_softc(dev);
28618334Speter	uint32_t i;
28718334Speter
28818334Speter	i = (pci_cfgregread(0, sc->mctrl[0], 3, AGP_AMD64_APCTRL, 4) &
28918334Speter		AGP_AMD64_APCTRL_SIZE_MASK) >> 1;
29018334Speter
29118334Speter	if (i >= AGP_AMD64_TABLE_SIZE)
29218334Speter		return (0);
29318334Speter
29418334Speter	return (agp_amd64_table[i]);
29518334Speter}
29618334Speter
29718334Speterstatic int
29818334Speteragp_amd64_set_aperture(device_t dev, uint32_t aperture)
29918334Speter{
30018334Speter	struct agp_amd64_softc *sc = device_get_softc(dev);
30118334Speter	uint32_t i;
30218334Speter	int j;
30318334Speter
30418334Speter	for (i = 0; i < AGP_AMD64_TABLE_SIZE; i++)
30518334Speter		if (agp_amd64_table[i] == aperture)
30618334Speter			break;
30718334Speter	if (i >= AGP_AMD64_TABLE_SIZE)
30818334Speter		return (EINVAL);
30918334Speter
31018334Speter	for (j = 0; j < sc->n_mctrl; j++)
31118334Speter		pci_cfgregwrite(0, sc->mctrl[j], 3, AGP_AMD64_APCTRL,
31218334Speter		    (pci_cfgregread(0, sc->mctrl[j], 3, AGP_AMD64_APCTRL, 4) &
31318334Speter		    ~(AGP_AMD64_APCTRL_SIZE_MASK)) | (i << 1), 4);
31418334Speter
31518334Speter	switch (pci_get_vendor(dev)) {
31618334Speter	case 0x10b9:	/* ULi */
31718334Speter		return (agp_amd64_uli_set_aperture(dev, aperture));
31818334Speter		break;
31918334Speter
32018334Speter	case 0x10de:	/* nVidia */
32118334Speter		return (agp_amd64_nvidia_set_aperture(dev, aperture));
32218334Speter		break;
32318334Speter
32418334Speter	case 0x1106:	/* VIA */
32518334Speter		if (sc->via_agp)
32618334Speter			return (agp_amd64_via_set_aperture(dev, aperture));
32718334Speter		break;
32852284Sobrien	}
32918334Speter
33018334Speter	return (0);
33118334Speter}
33218334Speter
33318334Speterstatic int
33418334Speteragp_amd64_bind_page(device_t dev, int offset, vm_offset_t physical)
33518334Speter{
33650397Sobrien	struct agp_amd64_softc *sc = device_get_softc(dev);
33718334Speter
33818334Speter	if (offset < 0 || offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT))
33918334Speter		return (EINVAL);
34018334Speter
34118334Speter	sc->gatt->ag_virtual[offset >> AGP_PAGE_SHIFT] =
34218334Speter	    (physical & 0xfffff000) | ((physical >> 28) & 0x00000ff0) | 3;
34318334Speter
34452284Sobrien	return (0);
34518334Speter}
34618334Speter
34718334Speterstatic int
34818334Speteragp_amd64_unbind_page(device_t dev, int offset)
34918334Speter{
35018334Speter	struct agp_amd64_softc *sc = device_get_softc(dev);
35118334Speter
35218334Speter	if (offset < 0 || offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT))
35318334Speter		return (EINVAL);
35418334Speter
35518334Speter	sc->gatt->ag_virtual[offset >> AGP_PAGE_SHIFT] = 0;
35618334Speter
35718334Speter	return (0);
35818334Speter}
35918334Speter
36018334Speterstatic void
36118334Speteragp_amd64_flush_tlb(device_t dev)
36218334Speter{
36318334Speter	struct agp_amd64_softc *sc = device_get_softc(dev);
36418334Speter	int i;
36518334Speter
36618334Speter	for (i = 0; i < sc->n_mctrl; i++)
36718334Speter		pci_cfgregwrite(0, sc->mctrl[i], 3, AGP_AMD64_CACHECTRL,
36818334Speter		    pci_cfgregread(0, sc->mctrl[i], 3, AGP_AMD64_CACHECTRL, 4) |
36918334Speter		    AGP_AMD64_CACHECTRL_INVGART, 4);
37018334Speter}
37118334Speter
37218334Speterstatic void
37318334Speteragp_amd64_apbase_fixup(device_t dev)
37418334Speter{
37518334Speter	struct agp_amd64_softc *sc = device_get_softc(dev);
37618334Speter	uint32_t apbase;
37718334Speter	int i;
37818334Speter
37918334Speter	sc->apbase = rman_get_start(sc->agp.as_aperture);
38018334Speter	apbase = (sc->apbase >> 25) & AGP_AMD64_APBASE_MASK;
38118334Speter	for (i = 0; i < sc->n_mctrl; i++)
38218334Speter		pci_cfgregwrite(0, sc->mctrl[i], 3,
38318334Speter		    AGP_AMD64_APBASE, apbase, 4);
38418334Speter}
38518334Speter
38618334Speterstatic void
38718334Speteragp_amd64_uli_init(device_t dev)
38818334Speter{
38950397Sobrien	struct agp_amd64_softc *sc = device_get_softc(dev);
39018334Speter
39118334Speter	agp_amd64_apbase_fixup(dev);
39218334Speter	pci_write_config(dev, AGP_AMD64_ULI_APBASE,
39318334Speter	    (pci_read_config(dev, AGP_AMD64_ULI_APBASE, 4) & 0x0000000f) |
39418334Speter	    sc->apbase, 4);
39518334Speter	pci_write_config(dev, AGP_AMD64_ULI_HTT_FEATURE, sc->apbase, 4);
39618334Speter}
39718334Speter
39818334Speterstatic int
39918334Speteragp_amd64_uli_set_aperture(device_t dev, uint32_t aperture)
40018334Speter{
40118334Speter	struct agp_amd64_softc *sc = device_get_softc(dev);
40218334Speter
40318334Speter	switch (aperture) {
40418334Speter	case 0x02000000:	/*  32 MB */
40518334Speter	case 0x04000000:	/*  64 MB */
40618334Speter	case 0x08000000:	/* 128 MB */
40718334Speter	case 0x10000000:	/* 256 MB */
40818334Speter		break;
40918334Speter	default:
41018334Speter		return (EINVAL);
41118334Speter	}
41218334Speter
41318334Speter	pci_write_config(dev, AGP_AMD64_ULI_ENU_SCR,
41418334Speter	    sc->apbase + aperture - 1, 4);
41518334Speter
41618334Speter	return (0);
41718334Speter}
41818334Speter
41918334Speterstatic void
42018334Speteragp_amd64_nvidia_init(device_t dev)
42118334Speter{
42218334Speter	struct agp_amd64_softc *sc = device_get_softc(dev);
42318334Speter
42418334Speter	agp_amd64_apbase_fixup(dev);
42518334Speter	pci_write_config(dev, AGP_AMD64_NVIDIA_0_APBASE,
42618334Speter	    (pci_read_config(dev, AGP_AMD64_NVIDIA_0_APBASE, 4) & 0x0000000f) |
42718334Speter	    sc->apbase, 4);
42818334Speter	pci_cfgregwrite(0, 11, 0, AGP_AMD64_NVIDIA_1_APBASE1, sc->apbase, 4);
42918334Speter	pci_cfgregwrite(0, 11, 0, AGP_AMD64_NVIDIA_1_APBASE2, sc->apbase, 4);
43018334Speter}
43118334Speter
43218334Speterstatic int
43318334Speteragp_amd64_nvidia_set_aperture(device_t dev, uint32_t aperture)
43418334Speter{
43518334Speter	struct agp_amd64_softc *sc = device_get_softc(dev);
43618334Speter	uint32_t apsize;
43718334Speter
43818334Speter	switch (aperture) {
43918334Speter	case 0x02000000:	apsize = 0x0f;	break;	/*  32 MB */
44018334Speter	case 0x04000000:	apsize = 0x0e;	break;	/*  64 MB */
44118334Speter	case 0x08000000:	apsize = 0x0c;	break;	/* 128 MB */
44218334Speter	case 0x10000000:	apsize = 0x08;	break;	/* 256 MB */
44318334Speter	case 0x20000000:	apsize = 0x00;	break;	/* 512 MB */
44418334Speter	default:
44518334Speter		return (EINVAL);
44618334Speter	}
44718334Speter
44818334Speter	pci_cfgregwrite(0, 11, 0, AGP_AMD64_NVIDIA_1_APSIZE,
44918334Speter	    (pci_cfgregread(0, 11, 0, AGP_AMD64_NVIDIA_1_APSIZE, 4) &
45018334Speter	    0xfffffff0) | apsize, 4);
45118334Speter	pci_cfgregwrite(0, 11, 0, AGP_AMD64_NVIDIA_1_APLIMIT1,
45252284Sobrien	    sc->apbase + aperture - 1, 4);
45318334Speter	pci_cfgregwrite(0, 11, 0, AGP_AMD64_NVIDIA_1_APLIMIT2,
45418334Speter	    sc->apbase + aperture - 1, 4);
45518334Speter
45618334Speter	return (0);
45718334Speter}
45818334Speter
45918334Speterstatic void
46018334Speteragp_amd64_via_init(device_t dev)
46118334Speter{
46218334Speter	struct agp_amd64_softc *sc = device_get_softc(dev);
46318334Speter
46418334Speter	agp_amd64_apbase_fixup(dev);
46518334Speter	pci_cfgregwrite(0, 1, 0, AGP3_VIA_ATTBASE, sc->gatt->ag_physical, 4);
46618334Speter	pci_cfgregwrite(0, 1, 0, AGP3_VIA_GARTCTRL,
46752284Sobrien	    pci_cfgregread(0, 1, 0, AGP3_VIA_ATTBASE, 4) | 0x180, 4);
46818334Speter}
46918334Speter
47018334Speterstatic int
47118334Speteragp_amd64_via_set_aperture(device_t dev, uint32_t aperture)
47218334Speter{
47318334Speter	uint32_t apsize;
47418334Speter
47518334Speter	apsize = ((aperture - 1) >> 20) ^ 0xff;
47618334Speter	if ((((apsize ^ 0xff) << 20) | ((1 << 20) - 1)) + 1 != aperture)
47718334Speter		return (EINVAL);
47818334Speter	pci_cfgregwrite(0, 1, 0, AGP3_VIA_APSIZE, apsize, 1);
47918334Speter
48018334Speter	return (0);
48118334Speter}
48218334Speter
48318334Speterstatic device_method_t agp_amd64_methods[] = {
48418334Speter	/* Device interface */
48518334Speter	DEVMETHOD(device_probe,		agp_amd64_probe),
48618334Speter	DEVMETHOD(device_attach,	agp_amd64_attach),
48752284Sobrien	DEVMETHOD(device_detach,	agp_amd64_detach),
48852284Sobrien	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
48952284Sobrien	DEVMETHOD(device_suspend,	bus_generic_suspend),
49052284Sobrien	DEVMETHOD(device_resume,	bus_generic_resume),
49152284Sobrien
49252284Sobrien	/* AGP interface */
49352284Sobrien	DEVMETHOD(agp_get_aperture,	agp_amd64_get_aperture),
49452284Sobrien	DEVMETHOD(agp_set_aperture,	agp_amd64_set_aperture),
49552284Sobrien	DEVMETHOD(agp_bind_page,	agp_amd64_bind_page),
49652284Sobrien	DEVMETHOD(agp_unbind_page,	agp_amd64_unbind_page),
49752284Sobrien	DEVMETHOD(agp_flush_tlb,	agp_amd64_flush_tlb),
49852284Sobrien	DEVMETHOD(agp_enable,		agp_generic_enable),
49952284Sobrien	DEVMETHOD(agp_alloc_memory,	agp_generic_alloc_memory),
50018334Speter	DEVMETHOD(agp_free_memory,	agp_generic_free_memory),
50118334Speter	DEVMETHOD(agp_bind_memory,	agp_generic_bind_memory),
50218334Speter	DEVMETHOD(agp_unbind_memory,	agp_generic_unbind_memory),
50318334Speter
50418334Speter	{ 0, 0 }
50518334Speter};
50618334Speter
50718334Speterstatic driver_t agp_amd64_driver = {
50818334Speter	"agp",
50918334Speter	agp_amd64_methods,
51018334Speter	sizeof(struct agp_amd64_softc),
51118334Speter};
51218334Speter
51318334Speterstatic devclass_t agp_devclass;
51418334Speter
51518334SpeterDRIVER_MODULE(agp_amd64, hostb, agp_amd64_driver, agp_devclass, 0, 0);
51618334SpeterMODULE_DEPEND(agp_amd64, agp, 1, 1, 1);
51718334SpeterMODULE_DEPEND(agp_amd64, pci, 1, 1, 1);
51818334Speter