xref: /openbsd-src/sys/dev/pci/mmuagp.c (revision 0f9891f1fafd8f53a63c41edb56ce51e2589b910)
1b8963103Soga /*-
2b8963103Soga  * Copyright (c) 2004, 2005 Jung-uk Kim <jkim@FreeBSD.org>
3b8963103Soga  * All rights reserved.
4b8963103Soga  *
5b8963103Soga  * Redistribution and use in source and binary forms, with or without
6b8963103Soga  * modification, are permitted provided that the following conditions
7b8963103Soga  * are met:
8b8963103Soga  * 1. Redistributions of source code must retain the above copyright
9b8963103Soga  *    notice, this list of conditions and the following disclaimer.
10b8963103Soga  * 2. Redistributions in binary form must reproduce the above copyright
11b8963103Soga  *    notice, this list of conditions and the following disclaimer in the
12b8963103Soga  *    documentation and/or other materials provided with the distribution.
13b8963103Soga  *
14b8963103Soga  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15b8963103Soga  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16b8963103Soga  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17b8963103Soga  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18b8963103Soga  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19b8963103Soga  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20b8963103Soga  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21b8963103Soga  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22b8963103Soga  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23b8963103Soga  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24b8963103Soga  * SUCH DAMAGE.
25b8963103Soga  */
26b8963103Soga 
27b8963103Soga #include <sys/param.h>
28b8963103Soga #include <sys/systm.h>
29b8963103Soga #include <sys/device.h>
30b8963103Soga 
31b8963103Soga #include <dev/pci/pcivar.h>
32b8963103Soga #include <dev/pci/pcireg.h>
33b8963103Soga #include <dev/pci/agpvar.h>
34b8963103Soga #include <dev/pci/agpreg.h>
35b8963103Soga 
36b8963103Soga #include <dev/pci/pcidevs.h>
37b8963103Soga 
38b8963103Soga #include <machine/bus.h>
39b8963103Soga 
40b8963103Soga /*
41b8963103Soga  * AMD64 GART registers
42b8963103Soga  */
43b8963103Soga #define	AGP_AMD64_APCTRL		0x90
44b8963103Soga #define	AGP_AMD64_APBASE		0x94
45b8963103Soga #define	AGP_AMD64_ATTBASE		0x98
46b8963103Soga #define	AGP_AMD64_CACHECTRL		0x9c
47b8963103Soga #define	AGP_AMD64_APCTRL_GARTEN		0x00000001
48b8963103Soga #define	AGP_AMD64_APCTRL_SIZE_MASK	0x0000000e
49b8963103Soga #define	AGP_AMD64_APCTRL_DISGARTCPU	0x00000010
50b8963103Soga #define	AGP_AMD64_APCTRL_DISGARTIO	0x00000020
51b8963103Soga #define	AGP_AMD64_APCTRL_DISWLKPRB	0x00000040
52b8963103Soga #define	AGP_AMD64_APBASE_MASK		0x00007fff
53b8963103Soga #define	AGP_AMD64_ATTBASE_MASK		0xfffffff0
54b8963103Soga #define	AGP_AMD64_CACHECTRL_INVGART	0x00000001
55b8963103Soga #define	AGP_AMD64_CACHECTRL_PTEERR	0x00000002
56b8963103Soga 
57b8963103Soga /*
58b8963103Soga  * NVIDIA nForce3 registers
59b8963103Soga  */
60b8963103Soga #define AGP_AMD64_NVIDIA_0_APBASE	0x10
61b8963103Soga #define AGP_AMD64_NVIDIA_1_APBASE1	0x50
62b8963103Soga #define AGP_AMD64_NVIDIA_1_APLIMIT1	0x54
63b8963103Soga #define AGP_AMD64_NVIDIA_1_APSIZE	0xa8
64b8963103Soga #define AGP_AMD64_NVIDIA_1_APBASE2	0xd8
65b8963103Soga #define AGP_AMD64_NVIDIA_1_APLIMIT2	0xdc
66b8963103Soga 
67b8963103Soga /*
68b8963103Soga  * ULi M1689 registers
69b8963103Soga  */
70b8963103Soga #define AGP_AMD64_ULI_APBASE		0x10
71b8963103Soga #define AGP_AMD64_ULI_HTT_FEATURE	0x50
72b8963103Soga #define AGP_AMD64_ULI_ENU_SCR		0x54
73b8963103Soga 
74b8963103Soga 
75b8963103Soga #define	AMD64_MAX_MCTRL		8
76b8963103Soga 
77b8963103Soga /* XXX nForce3 requires secondary AGP bridge at 0:11:0. */
78b8963103Soga #define AGP_AMD64_NVIDIA_PCITAG(pc)	pci_make_tag(pc, 0, 11, 0)
79b8963103Soga /* XXX Some VIA bridge requires secondary AGP bridge at 0:1:0. */
80b8963103Soga #define AGP_AMD64_VIA_PCITAG(pc)	pci_make_tag(pc, 0, 1, 0)
81b8963103Soga 
82b8963103Soga 
83b8963103Soga int	mmuagp_probe(struct device *, void *, void *);
84b8963103Soga void	mmuagp_attach(struct device *, struct device *, void *);
85b8963103Soga bus_size_t mmuagp_get_aperture(void *);
86b8963103Soga int	mmuagp_set_aperture(void *, bus_size_t);
87b8963103Soga void	mmuagp_bind_page(void *, bus_addr_t, paddr_t, int);
88b8963103Soga void	mmuagp_unbind_page(void *, bus_addr_t);
89b8963103Soga void	mmuagp_flush_tlb(void *);
90b8963103Soga 
91b8963103Soga void	mmuagp_apbase_fixup(void *);
92b8963103Soga 
93b8963103Soga void	mmuagp_uli_init(void *);
94b8963103Soga int	mmuagp_uli_set_aperture(void *, bus_size_t);
95b8963103Soga 
96b8963103Soga int	mmuagp_nvidia_match(const struct pci_attach_args *, uint16_t);
97b8963103Soga void	mmuagp_nvidia_init(void *);
98b8963103Soga int	mmuagp_nvidia_set_aperture(void *, bus_size_t);
99b8963103Soga 
100b8963103Soga int	mmuagp_via_match(const struct pci_attach_args *);
101b8963103Soga void	mmuagp_via_init(void *);
102b8963103Soga int	mmuagp_via_set_aperture(void *, bus_size_t);
103b8963103Soga 
104b8963103Soga struct mmuagp_softc {
105b8963103Soga 	struct device		 dev;
106b8963103Soga 	struct agp_softc	*agpdev;
107b8963103Soga 	struct agp_gatt		*gatt;
108b8963103Soga 	bus_addr_t		 msc_apaddr;
109b8963103Soga 	bus_size_t		 msc_apsize;
110b8963103Soga 	uint32_t		 apbase;
111b8963103Soga 	pcitag_t		 ctrl_tag;	/* use NVIDIA and VIA */
112b8963103Soga 	pcitag_t		 mctrl_tag[AMD64_MAX_MCTRL];
113b8963103Soga 	pci_chipset_tag_t	 msc_pc;
114b8963103Soga 	pcitag_t		 msc_tag;
115b8963103Soga 	int			 n_mctrl;
116b8963103Soga };
117b8963103Soga 
118*8d2c75e4Smpi const struct cfattach mmuagp_ca = {
119b8963103Soga         sizeof(struct mmuagp_softc), mmuagp_probe, mmuagp_attach
120b8963103Soga };
121b8963103Soga 
122b8963103Soga struct cfdriver mmuagp_cd = {
123b8963103Soga 	NULL, "mmuagp", DV_DULL
124b8963103Soga };
125b8963103Soga 
126b8963103Soga const struct agp_methods mmuagp_methods = {
127b8963103Soga 	mmuagp_bind_page,
128b8963103Soga 	mmuagp_unbind_page,
129b8963103Soga 	mmuagp_flush_tlb,
130b8963103Soga };
131b8963103Soga 
132b8963103Soga int
mmuagp_probe(struct device * parent,void * match,void * aux)133b8963103Soga mmuagp_probe(struct device *parent, void *match, void *aux)
134b8963103Soga {
135b8963103Soga 	struct agp_attach_args	*aa = aux;
136b8963103Soga 	struct pci_attach_args	*pa = aa->aa_pa;
137b8963103Soga 
138b8963103Soga 	/* Must be a pchb, don't attach to iommu-style agp devs */
139b8963103Soga 	if (agpbus_probe(aa) == 0)
140b8963103Soga 		return (0);
141b8963103Soga 
142b8963103Soga 	switch (PCI_VENDOR(pa->pa_id)) {
143b8963103Soga 	case PCI_VENDOR_ALI:
144b8963103Soga 		switch (PCI_PRODUCT(pa->pa_id)) {
145b8963103Soga 		case PCI_PRODUCT_ALI_M1689:
146b8963103Soga 			return (1);
147b8963103Soga 		}
148b8963103Soga 		break;
149b8963103Soga 	case PCI_VENDOR_AMD:
150b8963103Soga 		switch (PCI_PRODUCT(pa->pa_id)) {
151b8963103Soga 		case PCI_PRODUCT_AMD_8151_SC:
152b8963103Soga 			return (1);
153b8963103Soga 		}
154b8963103Soga 		break;
155b8963103Soga 	case PCI_VENDOR_NVIDIA:
156b8963103Soga 		switch (PCI_PRODUCT(pa->pa_id)) {
157b8963103Soga 		case PCI_PRODUCT_NVIDIA_NFORCE3_PCHB:
158b8963103Soga 			return (mmuagp_nvidia_match(pa,
159b8963103Soga 			    PCI_PRODUCT_NVIDIA_NFORCE3_PPB2));
160b8963103Soga 			/* NOTREACHED */
161b8963103Soga 		case PCI_PRODUCT_NVIDIA_NFORCE3_250_PCHB:
162b8963103Soga 			return (mmuagp_nvidia_match(pa,
163b8963103Soga 			    PCI_PRODUCT_NVIDIA_NFORCE3_250_AGP));
164b8963103Soga 			/* NOTREACHED */
165b8963103Soga 		}
166b8963103Soga 		break;
167b8963103Soga 	case PCI_VENDOR_SIS:
168b8963103Soga 		switch (PCI_PRODUCT(pa->pa_id)) {
169b8963103Soga 		case PCI_PRODUCT_SIS_755:
170b8963103Soga 		case PCI_PRODUCT_SIS_760:
171b8963103Soga 			return (1);
172b8963103Soga 		}
173b8963103Soga 		break;
174b8963103Soga 	case PCI_VENDOR_VIATECH:
175b8963103Soga 		switch (PCI_PRODUCT(pa->pa_id)) {
176b8963103Soga 		case PCI_PRODUCT_VIATECH_K8M800_0:
177b8963103Soga 		case PCI_PRODUCT_VIATECH_K8T890_0:
178b8963103Soga 		case PCI_PRODUCT_VIATECH_K8HTB_0:
179b8963103Soga 		case PCI_PRODUCT_VIATECH_K8HTB:
180b8963103Soga 			return (1);
181b8963103Soga 		}
182b8963103Soga 		break;
183b8963103Soga 	}
184b8963103Soga 
185b8963103Soga 	return (0);
186b8963103Soga }
187b8963103Soga 
188b8963103Soga int
mmuagp_nvidia_match(const struct pci_attach_args * pa,uint16_t devid)189b8963103Soga mmuagp_nvidia_match(const struct pci_attach_args *pa, uint16_t devid)
190b8963103Soga {
191b8963103Soga 	pcitag_t	tag;
192b8963103Soga 	pcireg_t	reg;
193b8963103Soga 
194b8963103Soga 	tag = AGP_AMD64_NVIDIA_PCITAG(pa->pa_pc);
195b8963103Soga 
196b8963103Soga 	reg = pci_conf_read(pa->pa_pc, tag, PCI_CLASS_REG);
197b8963103Soga 	if (PCI_CLASS(reg) != PCI_CLASS_BRIDGE ||
198b8963103Soga 	    PCI_SUBCLASS(reg) != PCI_SUBCLASS_BRIDGE_PCI)
199b8963103Soga 		return 0;
200b8963103Soga 
201b8963103Soga 	reg = pci_conf_read(pa->pa_pc, tag, PCI_ID_REG);
202b8963103Soga 	if (PCI_VENDOR(reg) != PCI_VENDOR_NVIDIA || PCI_PRODUCT(reg) != devid)
203b8963103Soga 		return 0;
204b8963103Soga 
205b8963103Soga 	return 1;
206b8963103Soga }
207b8963103Soga 
208b8963103Soga int
mmuagp_via_match(const struct pci_attach_args * pa)209b8963103Soga mmuagp_via_match(const struct pci_attach_args *pa)
210b8963103Soga {
211b8963103Soga 	pcitag_t tag;
212b8963103Soga 	pcireg_t reg;
213b8963103Soga 
214b8963103Soga 	tag = AGP_AMD64_VIA_PCITAG(pa->pa_pc);
215b8963103Soga 
216b8963103Soga 	reg = pci_conf_read(pa->pa_pc, tag, PCI_CLASS_REG);
217b8963103Soga 	if (PCI_CLASS(reg) != PCI_CLASS_BRIDGE ||
218b8963103Soga 	    PCI_SUBCLASS(reg) != PCI_SUBCLASS_BRIDGE_PCI)
219b8963103Soga 		return 0;
220b8963103Soga 
221b8963103Soga 	reg = pci_conf_read(pa->pa_pc, tag, PCI_ID_REG);
222b8963103Soga 	if (PCI_VENDOR(reg) != PCI_VENDOR_VIATECH ||
223b8963103Soga 	    PCI_PRODUCT(reg) != PCI_PRODUCT_VIATECH_K8HTB_AGP)
224b8963103Soga 		return 0;
225b8963103Soga 
226b8963103Soga 	return 1;
227b8963103Soga }
228b8963103Soga 
229b8963103Soga void
mmuagp_attach(struct device * parent,struct device * self,void * aux)230b8963103Soga mmuagp_attach(struct device *parent, struct device *self, void *aux)
231b8963103Soga {
232b8963103Soga 	struct mmuagp_softc	*msc = (struct mmuagp_softc *)self ;
233b8963103Soga 	struct agp_attach_args	*aa = aux;
234b8963103Soga 	struct pci_attach_args	*pa = aa->aa_pa;
235b8963103Soga 	struct agp_gatt		*gatt;
236b8963103Soga 	int			 (*set_aperture)(void *, bus_size_t) = NULL;
237b8963103Soga 	pcireg_t		 id, attbase, apctrl;
238b8963103Soga 	pcitag_t		 tag;
239b8963103Soga 	int			 maxdevs, i, n;
240b8963103Soga 
241b8963103Soga 	if (pci_mapreg_info(pa->pa_pc, pa->pa_tag, AGP_APBASE,
242b8963103Soga 	    PCI_MAPREG_TYPE_MEM, &msc->msc_apaddr, NULL, NULL) != 0) {
243b8963103Soga 		printf(": can't get aperture info\n");
244b8963103Soga 		return;
245b8963103Soga 	}
246b8963103Soga 
247b8963103Soga 	msc->msc_pc = pa->pa_pc;
248b8963103Soga 	msc->msc_tag = pa->pa_tag;
249b8963103Soga 
250b8963103Soga 	maxdevs = pci_bus_maxdevs(pa->pa_pc, 0);
251b8963103Soga 	for (i = 0, n = 0; i < maxdevs && n < AMD64_MAX_MCTRL; i++) {
252b8963103Soga 		tag = pci_make_tag(pa->pa_pc, 0, i, 3);
253b8963103Soga 		id = pci_conf_read(pa->pa_pc, tag, PCI_ID_REG);
254b8963103Soga 		if (PCI_VENDOR(id) == PCI_VENDOR_AMD &&
2553ddeb659Sjsg 		    PCI_PRODUCT(id) ==  PCI_PRODUCT_AMD_0F_MISC) {
256b8963103Soga 			msc->mctrl_tag[n] = tag;
257b8963103Soga 			n++;
258b8963103Soga 		}
259b8963103Soga 	}
260b8963103Soga 	if (n == 0) {
261b8963103Soga 		printf(": no Miscellaneous Control units found\n");
262b8963103Soga 		return;
263b8963103Soga 	}
264b8963103Soga 	msc->n_mctrl = n;
265b8963103Soga 
266b8963103Soga 	printf(": %d Miscellaneous Control unit(s) found", msc->n_mctrl);
267b8963103Soga 
268b8963103Soga 	msc->msc_apsize = mmuagp_get_aperture(msc);
269b8963103Soga 
270b8963103Soga 	for (;;) {
271b8963103Soga 		gatt = agp_alloc_gatt(pa->pa_dmat, msc->msc_apsize);
272b8963103Soga 		if (gatt != NULL)
273b8963103Soga 			break;
274b8963103Soga 
275b8963103Soga 		/*
2764b1a56afSjsg 		 * Probably failed to alloc contiguous memory. Try reducing the
277b8963103Soga 		 * aperture so that the gatt size reduces.
278b8963103Soga 		 */
279b8963103Soga 		msc->msc_apsize /= 2;
280b8963103Soga 		if (mmuagp_set_aperture(msc, msc->msc_apsize)) {
281b8963103Soga 			printf(" can't set aperture size\n");
282b8963103Soga 			return;
283b8963103Soga 		}
284b8963103Soga 	}
285b8963103Soga 	msc->gatt = gatt;
286b8963103Soga 
287b8963103Soga 	switch (PCI_VENDOR(pa->pa_id)) {
288b8963103Soga 	case PCI_VENDOR_ALI:
289b8963103Soga 		mmuagp_uli_init(msc);
290b8963103Soga 		set_aperture = mmuagp_uli_set_aperture;
291b8963103Soga 		break;
292b8963103Soga 
293b8963103Soga 	case PCI_VENDOR_NVIDIA:
294b8963103Soga 		msc->ctrl_tag = AGP_AMD64_NVIDIA_PCITAG(pa->pa_pc);
295b8963103Soga 		mmuagp_nvidia_init(msc);
296b8963103Soga 		set_aperture = mmuagp_nvidia_set_aperture;
297b8963103Soga 		break;
298b8963103Soga 
299b8963103Soga 	case PCI_VENDOR_VIATECH:
300b8963103Soga 		/* do we have to set the extra bridge too? */
301b8963103Soga 		if (mmuagp_via_match(pa)) {
302b8963103Soga 			msc->ctrl_tag = AGP_AMD64_VIA_PCITAG(pa->pa_pc);
303b8963103Soga 			mmuagp_via_init(msc);
304b8963103Soga 			set_aperture = mmuagp_via_set_aperture;
305b8963103Soga 		}
306b8963103Soga 		break;
307b8963103Soga 	}
308b8963103Soga 
309b8963103Soga 	if (set_aperture != NULL) {
310b8963103Soga 		if ((*set_aperture)(msc, msc->msc_apsize)) {
311b8963103Soga 			printf(", failed aperture set\n");
312b8963103Soga 			return;
313b8963103Soga 		}
314b8963103Soga 	}
315b8963103Soga 
316b8963103Soga 	/* Install the gatt and enable aperture. */
317b8963103Soga 	attbase = (uint32_t)(gatt->ag_physical >> 8) & AGP_AMD64_ATTBASE_MASK;
318b8963103Soga 	for (i = 0; i < msc->n_mctrl; i++) {
319b8963103Soga 		pci_conf_write(pa->pa_pc, msc->mctrl_tag[i], AGP_AMD64_ATTBASE,
320b8963103Soga 		    attbase);
321b8963103Soga 		apctrl = pci_conf_read(pa->pa_pc, msc->mctrl_tag[i],
322b8963103Soga 		    AGP_AMD64_APCTRL);
323b8963103Soga 		apctrl |= AGP_AMD64_APCTRL_GARTEN;
324b8963103Soga 		apctrl &=
325b8963103Soga 		    ~(AGP_AMD64_APCTRL_DISGARTCPU | AGP_AMD64_APCTRL_DISGARTIO);
326b8963103Soga 		pci_conf_write(pa->pa_pc, msc->mctrl_tag[i], AGP_AMD64_APCTRL,
327b8963103Soga 		    apctrl);
328b8963103Soga 	}
329b8963103Soga 
330b8963103Soga 	agp_flush_cache();
331b8963103Soga 
332b8963103Soga 	msc->agpdev = (struct agp_softc *)agp_attach_bus(pa, &mmuagp_methods,
333b8963103Soga 	    msc->msc_apaddr, msc->msc_apsize, &msc->dev);
334b8963103Soga 	return;
335b8963103Soga }
336b8963103Soga 
337b8963103Soga 
338b8963103Soga static bus_size_t mmuagp_table[] = {
339b8963103Soga 	0x02000000,	/*   32 MB */
340b8963103Soga 	0x04000000,	/*   64 MB */
341b8963103Soga 	0x08000000,	/*  128 MB */
342b8963103Soga 	0x10000000,	/*  256 MB */
343b8963103Soga 	0x20000000,	/*  512 MB */
344b8963103Soga 	0x40000000,	/* 1024 MB */
345b8963103Soga 	0x80000000,	/* 2048 MB */
346b8963103Soga };
347b8963103Soga 
348b8963103Soga #define AGP_AMD64_TABLE_SIZE \
349b8963103Soga 	(sizeof(mmuagp_table) / sizeof(mmuagp_table[0]))
350b8963103Soga 
351b8963103Soga bus_size_t
mmuagp_get_aperture(void * sc)352b8963103Soga mmuagp_get_aperture(void *sc)
353b8963103Soga {
354b8963103Soga 	struct mmuagp_softc *msc = sc;
355b8963103Soga 	uint32_t i;
356b8963103Soga 
357b8963103Soga 	i = (pci_conf_read(msc->msc_pc, msc->mctrl_tag[0], AGP_AMD64_APCTRL) &
358b8963103Soga 		AGP_AMD64_APCTRL_SIZE_MASK) >> 1;
359b8963103Soga 
360b8963103Soga 	if (i >= AGP_AMD64_TABLE_SIZE)
361b8963103Soga 		return 0;
362b8963103Soga 
363b8963103Soga 	return mmuagp_table[i];
364b8963103Soga }
365b8963103Soga 
366b8963103Soga int
mmuagp_set_aperture(void * sc,bus_size_t aperture)367b8963103Soga mmuagp_set_aperture(void *sc, bus_size_t aperture)
368b8963103Soga {
369b8963103Soga 	struct mmuagp_softc	*msc = sc;
370b8963103Soga 	uint32_t		 i;
371b8963103Soga 	pcireg_t		 apctrl;
372b8963103Soga 	int			 j;
373b8963103Soga 
374b8963103Soga 	for (i = 0; i < AGP_AMD64_TABLE_SIZE; i++)
375b8963103Soga 		if (mmuagp_table[i] == aperture)
376b8963103Soga 			break;
377b8963103Soga 	if (i >= AGP_AMD64_TABLE_SIZE)
378b8963103Soga 		return (EINVAL);
379b8963103Soga 
380b8963103Soga 	for (j = 0; j < msc->n_mctrl; j++) {
381b8963103Soga 		apctrl = pci_conf_read(msc->msc_pc, msc->mctrl_tag[0],
382b8963103Soga 		    AGP_AMD64_APCTRL);
383b8963103Soga 		pci_conf_write(msc->msc_pc, msc->mctrl_tag[0], AGP_AMD64_APCTRL,
384b8963103Soga 		    (apctrl & ~(AGP_AMD64_APCTRL_SIZE_MASK)) | (i << 1));
385b8963103Soga 	}
386b8963103Soga 
387b8963103Soga 	return (0);
388b8963103Soga }
389b8963103Soga 
390b8963103Soga void
mmuagp_bind_page(void * sc,bus_addr_t offset,paddr_t physical,int flags)391b8963103Soga mmuagp_bind_page(void *sc, bus_addr_t offset, paddr_t physical, int flags)
392b8963103Soga {
393b8963103Soga 	struct mmuagp_softc	*msc = sc;
394b8963103Soga 
395b8963103Soga 	msc->gatt->ag_virtual[(offset - msc->msc_apaddr) >> AGP_PAGE_SHIFT] =
396b8963103Soga 	    (physical & 0xfffff000) | ((physical >> 28) & 0x00000ff0) | 3;
397b8963103Soga }
398b8963103Soga 
399b8963103Soga void
mmuagp_unbind_page(void * sc,bus_addr_t offset)400b8963103Soga mmuagp_unbind_page(void *sc, bus_addr_t offset)
401b8963103Soga {
402b8963103Soga 	struct mmuagp_softc *msc = sc;
403b8963103Soga 
404b8963103Soga 	msc->gatt->ag_virtual[(offset - msc->msc_apaddr) >> AGP_PAGE_SHIFT] = 0;
405b8963103Soga }
406b8963103Soga 
407b8963103Soga void
mmuagp_flush_tlb(void * sc)408b8963103Soga mmuagp_flush_tlb(void *sc)
409b8963103Soga {
410b8963103Soga 	struct mmuagp_softc	*msc = sc;
411b8963103Soga 	pcireg_t		 cachectrl;
412b8963103Soga 	int			 i;
413b8963103Soga 
414b8963103Soga 	for (i = 0; i < msc->n_mctrl; i++) {
415b8963103Soga 		cachectrl = pci_conf_read(msc->msc_pc, msc->mctrl_tag[i],
416b8963103Soga 		    AGP_AMD64_CACHECTRL);
417b8963103Soga 		pci_conf_write(msc->msc_pc, msc->mctrl_tag[i],
418b8963103Soga 		    AGP_AMD64_CACHECTRL,
419b8963103Soga 		    cachectrl | AGP_AMD64_CACHECTRL_INVGART);
420b8963103Soga 	}
421b8963103Soga }
422b8963103Soga 
423b8963103Soga void
mmuagp_apbase_fixup(void * sc)424b8963103Soga mmuagp_apbase_fixup(void *sc)
425b8963103Soga {
426b8963103Soga 	struct mmuagp_softc	*msc = sc;
427b8963103Soga 	uint32_t		 apbase;
428b8963103Soga 	int			 i;
429b8963103Soga 
430b8963103Soga 	apbase = pci_conf_read(msc->msc_pc, msc->msc_tag, AGP_APBASE);
431b8963103Soga 	msc->apbase = PCI_MAPREG_MEM_ADDR(apbase);
432b8963103Soga 	apbase = (msc->apbase >> 25) & AGP_AMD64_APBASE_MASK;
433b8963103Soga 	for (i = 0; i < msc->n_mctrl; i++)
434b8963103Soga 		pci_conf_write(msc->msc_pc, msc->mctrl_tag[i], AGP_AMD64_APBASE,
435b8963103Soga 		    apbase);
436b8963103Soga }
437b8963103Soga 
438b8963103Soga void
mmuagp_uli_init(void * sc)439b8963103Soga mmuagp_uli_init(void *sc)
440b8963103Soga {
441b8963103Soga 	struct mmuagp_softc *msc = sc;
442b8963103Soga 	pcireg_t apbase;
443b8963103Soga 
444b8963103Soga 	mmuagp_apbase_fixup(msc);
445b8963103Soga 	apbase = pci_conf_read(msc->msc_pc, msc->msc_tag,
446b8963103Soga 	    AGP_AMD64_ULI_APBASE);
447b8963103Soga 	pci_conf_write(msc->msc_pc, msc->msc_tag, AGP_AMD64_ULI_APBASE,
448b8963103Soga 	    (apbase & 0x0000000f) | msc->apbase);
449b8963103Soga 	pci_conf_write(msc->msc_pc, msc->msc_tag, AGP_AMD64_ULI_HTT_FEATURE,
450b8963103Soga 	    msc->apbase);
451b8963103Soga }
452b8963103Soga 
453b8963103Soga int
mmuagp_uli_set_aperture(void * sc,bus_size_t aperture)454b8963103Soga mmuagp_uli_set_aperture(void *sc, bus_size_t aperture)
455b8963103Soga {
456b8963103Soga 	struct mmuagp_softc	*msc = sc;
457b8963103Soga 
458b8963103Soga 	switch (aperture) {
459b8963103Soga 	case 0x02000000:	/*  32 MB */
460b8963103Soga 	case 0x04000000:	/*  64 MB */
461b8963103Soga 	case 0x08000000:	/* 128 MB */
462b8963103Soga 	case 0x10000000:	/* 256 MB */
463b8963103Soga 		break;
464b8963103Soga 	default:
465b8963103Soga 		return EINVAL;
466b8963103Soga 	}
467b8963103Soga 
468b8963103Soga 	pci_conf_write(msc->msc_pc, msc->msc_tag, AGP_AMD64_ULI_ENU_SCR,
469b8963103Soga 	    msc->apbase + aperture - 1);
470b8963103Soga 
471b8963103Soga 	return 0;
472b8963103Soga }
473b8963103Soga 
474b8963103Soga void
mmuagp_nvidia_init(void * sc)475b8963103Soga mmuagp_nvidia_init(void *sc)
476b8963103Soga {
477b8963103Soga 	struct mmuagp_softc	*msc = sc;
478b8963103Soga 	pcireg_t		 apbase;
479b8963103Soga 
480b8963103Soga 	mmuagp_apbase_fixup(msc);
481b8963103Soga 	apbase = pci_conf_read(msc->msc_pc, msc->msc_tag,
482b8963103Soga 	    AGP_AMD64_NVIDIA_0_APBASE);
483b8963103Soga 	pci_conf_write(msc->msc_pc, msc->msc_tag, AGP_AMD64_NVIDIA_0_APBASE,
484b8963103Soga 	    (apbase & 0x0000000f) | msc->apbase);
485b8963103Soga 	pci_conf_write(msc->msc_pc, msc->ctrl_tag, AGP_AMD64_NVIDIA_1_APBASE1,
486b8963103Soga 	    msc->apbase);
487b8963103Soga 	pci_conf_write(msc->msc_pc, msc->ctrl_tag, AGP_AMD64_NVIDIA_1_APBASE2,
488b8963103Soga 	    msc->apbase);
489b8963103Soga }
490b8963103Soga 
491b8963103Soga int
mmuagp_nvidia_set_aperture(void * sc,bus_size_t aperture)492b8963103Soga mmuagp_nvidia_set_aperture(void *sc, bus_size_t aperture)
493b8963103Soga {
494b8963103Soga 	struct mmuagp_softc	*msc = sc;
495b8963103Soga 	bus_size_t		 apsize;
496b8963103Soga 
497b8963103Soga 	switch (aperture) {
498b8963103Soga 	case 0x02000000:	/*  32 MB */
499b8963103Soga 		apsize = 0x0f;
500b8963103Soga 		break;
501b8963103Soga 	case 0x04000000:	/*  64 MB */
502b8963103Soga 		apsize = 0x0e;
503b8963103Soga 		break;
504b8963103Soga 	case 0x08000000:	/* 128 MB */
505b8963103Soga 		apsize = 0x0c;
506b8963103Soga 		break;
507b8963103Soga 	case 0x10000000:	/* 256 MB */
508b8963103Soga 		apsize = 0x08;
509b8963103Soga 		break;
510b8963103Soga 	case 0x20000000:	/* 512 MB */
511b8963103Soga 		apsize = 0x00;
512b8963103Soga 		break;
513b8963103Soga 	default:
514b8963103Soga 		return (EINVAL);
515b8963103Soga 	}
516b8963103Soga 
517b8963103Soga 	pci_conf_write(msc->msc_pc, msc->ctrl_tag, AGP_AMD64_NVIDIA_1_APSIZE,
518b8963103Soga 	    (pci_conf_read(msc->msc_pc, msc->ctrl_tag,
519b8963103Soga 	    AGP_AMD64_NVIDIA_1_APSIZE) & 0xfffffff0) | apsize);
520b8963103Soga 	pci_conf_write(msc->msc_pc, msc->ctrl_tag, AGP_AMD64_NVIDIA_1_APLIMIT1,
521b8963103Soga 	    msc->apbase + aperture - 1);
522b8963103Soga 	pci_conf_write(msc->msc_pc, msc->ctrl_tag, AGP_AMD64_NVIDIA_1_APLIMIT2,
523b8963103Soga 	    msc->apbase + aperture - 1);
524b8963103Soga 
525b8963103Soga 	return (0);
526b8963103Soga }
527b8963103Soga 
528b8963103Soga void
mmuagp_via_init(void * sc)529b8963103Soga mmuagp_via_init(void *sc)
530b8963103Soga {
531b8963103Soga 	struct mmuagp_softc	*msc = sc;
532b8963103Soga 
533b8963103Soga 	mmuagp_apbase_fixup(sc);
534b8963103Soga 	pci_conf_write(msc->msc_pc, msc->ctrl_tag, AGP3_VIA_ATTBASE,
535b8963103Soga 	    msc->gatt->ag_physical);
536b8963103Soga 	pci_conf_write(msc->msc_pc, msc->ctrl_tag, AGP3_VIA_GARTCTRL,
537b8963103Soga 	    pci_conf_read(msc->msc_pc, msc->ctrl_tag, AGP3_VIA_ATTBASE) |
538b8963103Soga 	        0x180);
539b8963103Soga }
540b8963103Soga 
541b8963103Soga int
mmuagp_via_set_aperture(void * sc,bus_size_t aperture)542b8963103Soga mmuagp_via_set_aperture(void *sc, bus_size_t aperture)
543b8963103Soga {
544b8963103Soga 	struct mmuagp_softc	*msc = sc;
545b8963103Soga 	bus_size_t		 apsize;
546b8963103Soga 
547b8963103Soga 	apsize = ((aperture - 1) >> 20) ^ 0xff;
548b8963103Soga 	if ((((apsize ^ 0xff) << 20) | ((1 << 20) - 1)) + 1 != aperture)
549b8963103Soga 		return (EINVAL);
550b8963103Soga 	pci_conf_write(msc->msc_pc, msc->ctrl_tag, AGP3_VIA_APSIZE,
551b8963103Soga 	    (pci_conf_read(msc->msc_pc, msc->ctrl_tag, AGP3_VIA_APSIZE) &
552b8963103Soga 	        ~0xff) | apsize);
553b8963103Soga 
554b8963103Soga 	return 0;
555b8963103Soga }
556