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