2 * Copyright (c) 2004, 2005 Jung-uk Kim <jkim@FreeBSD.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 #include <sys/cdefs.h>
28 __KERNEL_RCSID(0, "$NetBSD: agp_amd64.c,v 1.4 2008/03/27 10:47:49 kiyohara Exp $");
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/malloc.h>
33 #include <sys/kernel.h>
36 #include <sys/device.h>
37 #include <sys/agpio.h>
39 #include <uvm/uvm_extern.h>
41 #include <dev/pci/pcivar.h>
42 #include <dev/pci/pcireg.h>
43 #include <dev/pci/agpvar.h>
44 #include <dev/pci/agpreg.h>
46 #include <dev/pci/pcidevs.h>
51 #define AMD64_MAX_MCTRL 8
53 /* XXX nForce3 requires secondary AGP bridge at 0:11:0. */
54 #define AGP_AMD64_NVIDIA_PCITAG(pc) pci_make_tag(pc, 0, 11, 0)
55 /* XXX Some VIA bridge requires secondary AGP bridge at 0:1:0. */
56 #define AGP_AMD64_VIA_PCITAG(pc) pci_make_tag(pc, 0, 1, 0)
59 static uint32_t agp_amd64_get_aperture(struct agp_softc
*);
60 static int agp_amd64_set_aperture(struct agp_softc
*, uint32_t);
61 static int agp_amd64_bind_page(struct agp_softc
*, off_t
, bus_addr_t
);
62 static int agp_amd64_unbind_page(struct agp_softc
*, off_t
);
63 static void agp_amd64_flush_tlb(struct agp_softc
*);
65 static void agp_amd64_apbase_fixup(struct agp_softc
*);
67 static void agp_amd64_uli_init(struct agp_softc
*);
68 static int agp_amd64_uli_set_aperture(struct agp_softc
*, uint32_t);
70 static int agp_amd64_nvidia_match(const struct pci_attach_args
*, uint16_t);
71 static void agp_amd64_nvidia_init(struct agp_softc
*);
72 static int agp_amd64_nvidia_set_aperture(struct agp_softc
*, uint32_t);
74 static int agp_amd64_via_match(const struct pci_attach_args
*);
75 static void agp_amd64_via_init(struct agp_softc
*);
76 static int agp_amd64_via_set_aperture(struct agp_softc
*, uint32_t);
79 struct agp_amd64_softc
{
80 uint32_t initial_aperture
;
81 struct agp_gatt
*gatt
;
83 pcitag_t ctrl_tag
; /* use NVIDIA and VIA */
84 pcitag_t mctrl_tag
[AMD64_MAX_MCTRL
];
89 static struct agp_methods agp_amd64_methods
= {
90 agp_amd64_get_aperture
,
91 agp_amd64_set_aperture
,
93 agp_amd64_unbind_page
,
96 agp_generic_alloc_memory
,
97 agp_generic_free_memory
,
98 agp_generic_bind_memory
,
99 agp_generic_unbind_memory
,
104 agp_amd64_match(const struct pci_attach_args
*pa
)
107 switch (PCI_VENDOR(pa
->pa_id
)) {
109 switch (PCI_PRODUCT(pa
->pa_id
)) {
110 case PCI_PRODUCT_AMD_AGP8151_DEV
:
116 switch (PCI_PRODUCT(pa
->pa_id
)) {
117 case PCI_PRODUCT_SIS_755
:
118 case PCI_PRODUCT_SIS_760
:
124 switch (PCI_PRODUCT(pa
->pa_id
)) {
125 case PCI_PRODUCT_ALI_M1689
:
130 case PCI_VENDOR_NVIDIA
:
131 switch (PCI_PRODUCT(pa
->pa_id
)) {
132 case PCI_PRODUCT_NVIDIA_NFORCE3_PCHB
:
133 return agp_amd64_nvidia_match(pa
,
134 PCI_PRODUCT_NVIDIA_NFORCE3_PPB2
);
138 case PCI_PRODUCT_NVIDIA_NFORCE3_250_PCHB
:
139 return agp_amd64_nvidia_match(pa
,
140 PCI_PRODUCT_NVIDIA_NFORCE3_250_AGP
);
146 case PCI_VENDOR_VIATECH
:
147 switch (PCI_PRODUCT(pa
->pa_id
)) {
148 case PCI_PRODUCT_VIATECH_K8M800_0
:
149 case PCI_PRODUCT_VIATECH_K8T890_0
:
150 case PCI_PRODUCT_VIATECH_K8HTB_0
:
151 case PCI_PRODUCT_VIATECH_K8HTB
:
161 agp_amd64_nvidia_match(const struct pci_attach_args
*pa
, uint16_t devid
)
166 tag
= AGP_AMD64_NVIDIA_PCITAG(pa
->pa_pc
);
168 reg
= pci_conf_read(pa
->pa_pc
, tag
, PCI_CLASS_REG
);
169 if (PCI_CLASS(reg
) != PCI_CLASS_BRIDGE
||
170 PCI_SUBCLASS(reg
) != PCI_SUBCLASS_BRIDGE_PCI
)
173 reg
= pci_conf_read(pa
->pa_pc
, tag
, PCI_ID_REG
);
174 if (PCI_VENDOR(reg
) != PCI_VENDOR_NVIDIA
|| PCI_PRODUCT(reg
) != devid
)
181 agp_amd64_via_match(const struct pci_attach_args
*pa
)
186 tag
= AGP_AMD64_VIA_PCITAG(pa
->pa_pc
);
188 reg
= pci_conf_read(pa
->pa_pc
, tag
, PCI_CLASS_REG
);
189 if (PCI_CLASS(reg
) != PCI_CLASS_BRIDGE
||
190 PCI_SUBCLASS(reg
) != PCI_SUBCLASS_BRIDGE_PCI
)
193 reg
= pci_conf_read(pa
->pa_pc
, tag
, PCI_ID_REG
);
194 if (PCI_VENDOR(reg
) != PCI_VENDOR_VIATECH
||
195 PCI_PRODUCT(reg
) != PCI_PRODUCT_VIATECH_K8HTB_AGP
)
202 agp_amd64_attach(device_t parent
, device_t self
, void *aux
)
204 struct agp_softc
*sc
= device_private(self
);
205 struct agp_amd64_softc
*asc
;
206 struct pci_attach_args
*pa
= aux
;
207 struct agp_gatt
*gatt
;
209 pcireg_t id
, attbase
, apctrl
;
212 asc
= malloc(sizeof(struct agp_amd64_softc
), M_AGP
, M_NOWAIT
| M_ZERO
);
214 aprint_error(": can't allocate softc\n");
218 if (agp_map_aperture(pa
, sc
, AGP_APBASE
) != 0) {
219 aprint_error(": can't map aperture\n");
224 maxdevs
= pci_bus_maxdevs(pa
->pa_pc
, 0);
225 for (i
= 0, n
= 0; i
< maxdevs
&& n
< AMD64_MAX_MCTRL
; i
++) {
226 tag
= pci_make_tag(pa
->pa_pc
, 0, i
, 3);
227 id
= pci_conf_read(pa
->pa_pc
, tag
, PCI_ID_REG
);
228 if (PCI_VENDOR(id
) == PCI_VENDOR_AMD
&&
229 PCI_PRODUCT(id
) == PCI_PRODUCT_AMD_AMD64_MISC
) {
230 asc
->mctrl_tag
[n
] = tag
;
238 aprint_normal(": %d Miscellaneous Control unit(s) found.\n",
240 aprint_normal("%s", device_xname(self
));
243 sc
->as_methods
= &agp_amd64_methods
;
244 pci_get_capability(pa
->pa_pc
, pa
->pa_tag
, PCI_CAP_AGP
, &sc
->as_capoff
,
246 asc
->initial_aperture
= AGP_GET_APERTURE(sc
);
249 gatt
= agp_alloc_gatt(sc
);
254 * Probably contigmalloc failure. Try reducing the
255 * aperture so that the gatt size reduces.
257 if (AGP_SET_APERTURE(sc
, AGP_GET_APERTURE(sc
) / 2)) {
258 agp_generic_detach(sc
);
264 switch (PCI_VENDOR(sc
->as_id
)) {
266 agp_amd64_uli_init(sc
);
267 if (agp_amd64_uli_set_aperture(sc
, asc
->initial_aperture
))
271 case PCI_VENDOR_NVIDIA
:
272 asc
->ctrl_tag
= AGP_AMD64_NVIDIA_PCITAG(pa
->pa_pc
);
273 agp_amd64_nvidia_init(sc
);
274 if (agp_amd64_nvidia_set_aperture(sc
, asc
->initial_aperture
))
278 case PCI_VENDOR_VIATECH
:
279 asc
->via_agp
= agp_amd64_via_match(pa
);
281 asc
->ctrl_tag
= AGP_AMD64_VIA_PCITAG(pa
->pa_pc
);
282 agp_amd64_via_init(sc
);
283 if (agp_amd64_via_set_aperture(sc
,
284 asc
->initial_aperture
))
290 /* Install the gatt and enable aperture. */
291 attbase
= (uint32_t)(gatt
->ag_physical
>> 8) & AGP_AMD64_ATTBASE_MASK
;
292 for (i
= 0; i
< asc
->n_mctrl
; i
++) {
293 pci_conf_write(pa
->pa_pc
, asc
->mctrl_tag
[i
], AGP_AMD64_ATTBASE
,
295 apctrl
= pci_conf_read(pa
->pa_pc
, asc
->mctrl_tag
[i
],
297 apctrl
|= AGP_AMD64_APCTRL_GARTEN
;
299 ~(AGP_AMD64_APCTRL_DISGARTCPU
| AGP_AMD64_APCTRL_DISGARTIO
);
300 pci_conf_write(pa
->pa_pc
, asc
->mctrl_tag
[i
], AGP_AMD64_APCTRL
,
310 static uint32_t agp_amd64_table
[] = {
311 0x02000000, /* 32 MB */
312 0x04000000, /* 64 MB */
313 0x08000000, /* 128 MB */
314 0x10000000, /* 256 MB */
315 0x20000000, /* 512 MB */
316 0x40000000, /* 1024 MB */
317 0x80000000, /* 2048 MB */
320 #define AGP_AMD64_TABLE_SIZE \
321 (sizeof(agp_amd64_table) / sizeof(agp_amd64_table[0]))
324 agp_amd64_get_aperture(struct agp_softc
*sc
)
326 struct agp_amd64_softc
*asc
= sc
->as_chipc
;
329 i
= (pci_conf_read(sc
->as_pc
, asc
->mctrl_tag
[0], AGP_AMD64_APCTRL
) &
330 AGP_AMD64_APCTRL_SIZE_MASK
) >> 1;
332 if (i
>= AGP_AMD64_TABLE_SIZE
)
335 return agp_amd64_table
[i
];
339 agp_amd64_set_aperture(struct agp_softc
*sc
, uint32_t aperture
)
341 struct agp_amd64_softc
*asc
= sc
->as_chipc
;
346 for (i
= 0; i
< AGP_AMD64_TABLE_SIZE
; i
++)
347 if (agp_amd64_table
[i
] == aperture
)
349 if (i
>= AGP_AMD64_TABLE_SIZE
)
352 for (j
= 0; j
< asc
->n_mctrl
; j
++) {
353 apctrl
= pci_conf_read(sc
->as_pc
, asc
->mctrl_tag
[0],
355 pci_conf_write(sc
->as_pc
, asc
->mctrl_tag
[0], AGP_AMD64_APCTRL
,
356 (apctrl
& ~(AGP_AMD64_APCTRL_SIZE_MASK
)) | (i
<< 1));
359 switch (PCI_VENDOR(sc
->as_id
)) {
361 return agp_amd64_uli_set_aperture(sc
, aperture
);
364 case PCI_VENDOR_NVIDIA
:
365 return agp_amd64_nvidia_set_aperture(sc
, aperture
);
368 case PCI_VENDOR_VIATECH
:
370 return agp_amd64_via_set_aperture(sc
, aperture
);
378 agp_amd64_bind_page(struct agp_softc
*sc
, off_t offset
, bus_addr_t physical
)
380 struct agp_amd64_softc
*asc
= sc
->as_chipc
;
382 if (offset
< 0 || offset
>= (asc
->gatt
->ag_entries
<< AGP_PAGE_SHIFT
))
385 asc
->gatt
->ag_virtual
[offset
>> AGP_PAGE_SHIFT
] =
386 (physical
& 0xfffff000) | ((physical
>> 28) & 0x00000ff0) | 3;
392 agp_amd64_unbind_page(struct agp_softc
*sc
, off_t offset
)
394 struct agp_amd64_softc
*asc
= sc
->as_chipc
;
396 if (offset
< 0 || offset
>= (asc
->gatt
->ag_entries
<< AGP_PAGE_SHIFT
))
399 asc
->gatt
->ag_virtual
[offset
>> AGP_PAGE_SHIFT
] = 0;
405 agp_amd64_flush_tlb(struct agp_softc
*sc
)
407 struct agp_amd64_softc
*asc
= sc
->as_chipc
;
411 for (i
= 0; i
< asc
->n_mctrl
; i
++) {
412 cachectrl
= pci_conf_read(sc
->as_pc
, asc
->mctrl_tag
[i
],
413 AGP_AMD64_CACHECTRL
);
414 pci_conf_write(sc
->as_pc
, asc
->mctrl_tag
[i
],
416 cachectrl
| AGP_AMD64_CACHECTRL_INVGART
);
421 agp_amd64_apbase_fixup(struct agp_softc
*sc
)
423 struct agp_amd64_softc
*asc
= sc
->as_chipc
;
427 apbase
= pci_conf_read(sc
->as_pc
, sc
->as_tag
, AGP_APBASE
);
428 asc
->apbase
= PCI_MAPREG_MEM_ADDR(apbase
);
429 apbase
= (asc
->apbase
>> 25) & AGP_AMD64_APBASE_MASK
;
430 for (i
= 0; i
< asc
->n_mctrl
; i
++)
431 pci_conf_write(sc
->as_pc
, asc
->mctrl_tag
[i
], AGP_AMD64_APBASE
,
436 agp_amd64_uli_init(struct agp_softc
*sc
)
438 struct agp_amd64_softc
*asc
= sc
->as_chipc
;
441 agp_amd64_apbase_fixup(sc
);
442 apbase
= pci_conf_read(sc
->as_pc
, sc
->as_tag
, AGP_AMD64_ULI_APBASE
);
443 pci_conf_write(sc
->as_pc
, sc
->as_tag
, AGP_AMD64_ULI_APBASE
,
444 (apbase
& 0x0000000f) | asc
->apbase
);
445 pci_conf_write(sc
->as_pc
, sc
->as_tag
, AGP_AMD64_ULI_HTT_FEATURE
,
450 agp_amd64_uli_set_aperture(struct agp_softc
*sc
, uint32_t aperture
)
452 struct agp_amd64_softc
*asc
= sc
->as_chipc
;
455 case 0x02000000: /* 32 MB */
456 case 0x04000000: /* 64 MB */
457 case 0x08000000: /* 128 MB */
458 case 0x10000000: /* 256 MB */
464 pci_conf_write(sc
->as_pc
, sc
->as_tag
, AGP_AMD64_ULI_ENU_SCR
,
465 asc
->apbase
+ aperture
- 1);
471 agp_amd64_nvidia_init(struct agp_softc
*sc
)
473 struct agp_amd64_softc
*asc
= sc
->as_chipc
;
476 agp_amd64_apbase_fixup(sc
);
478 pci_conf_read(sc
->as_pc
, sc
->as_tag
, AGP_AMD64_NVIDIA_0_APBASE
);
479 pci_conf_write(sc
->as_pc
, sc
->as_tag
, AGP_AMD64_NVIDIA_0_APBASE
,
480 (apbase
& 0x0000000f) | asc
->apbase
);
481 pci_conf_write(sc
->as_pc
, asc
->ctrl_tag
, AGP_AMD64_NVIDIA_1_APBASE1
,
483 pci_conf_write(sc
->as_pc
, asc
->ctrl_tag
, AGP_AMD64_NVIDIA_1_APBASE2
,
488 agp_amd64_nvidia_set_aperture(struct agp_softc
*sc
, uint32_t aperture
)
490 struct agp_amd64_softc
*asc
= sc
->as_chipc
;
494 case 0x02000000: apsize
= 0x0f; break; /* 32 MB */
495 case 0x04000000: apsize
= 0x0e; break; /* 64 MB */
496 case 0x08000000: apsize
= 0x0c; break; /* 128 MB */
497 case 0x10000000: apsize
= 0x08; break; /* 256 MB */
498 case 0x20000000: apsize
= 0x00; break; /* 512 MB */
503 pci_conf_write(sc
->as_pc
, asc
->ctrl_tag
, AGP_AMD64_NVIDIA_1_APSIZE
,
504 (pci_conf_read(sc
->as_pc
, asc
->ctrl_tag
,
505 AGP_AMD64_NVIDIA_1_APSIZE
) & 0xfffffff0) | apsize
);
506 pci_conf_write(sc
->as_pc
, asc
->ctrl_tag
, AGP_AMD64_NVIDIA_1_APLIMIT1
,
507 asc
->apbase
+ aperture
- 1);
508 pci_conf_write(sc
->as_pc
, asc
->ctrl_tag
, AGP_AMD64_NVIDIA_1_APLIMIT2
,
509 asc
->apbase
+ aperture
- 1);
515 agp_amd64_via_init(struct agp_softc
*sc
)
517 struct agp_amd64_softc
*asc
= sc
->as_chipc
;
519 agp_amd64_apbase_fixup(sc
);
520 pci_conf_write(sc
->as_pc
, asc
->ctrl_tag
, AGP3_VIA_ATTBASE
,
521 asc
->gatt
->ag_physical
);
522 pci_conf_write(sc
->as_pc
, asc
->ctrl_tag
, AGP3_VIA_GARTCTRL
,
523 pci_conf_read(sc
->as_pc
, asc
->ctrl_tag
, AGP3_VIA_ATTBASE
) | 0x180);
527 agp_amd64_via_set_aperture(struct agp_softc
*sc
, uint32_t aperture
)
529 struct agp_amd64_softc
*asc
= sc
->as_chipc
;
532 apsize
= ((aperture
- 1) >> 20) ^ 0xff;
533 if ((((apsize
^ 0xff) << 20) | ((1 << 20) - 1)) + 1 != aperture
)
535 pci_conf_write(sc
->as_pc
, asc
->ctrl_tag
, AGP3_VIA_APSIZE
,
536 (pci_conf_read(sc
->as_pc
, asc
->ctrl_tag
, AGP3_VIA_APSIZE
) & ~0xff) |