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
26 * $FreeBSD: src/sys/dev/agp/agp_amd64.c,v 1.17 2009/01/12 16:07:03 jkim Exp $
29 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <sys/malloc.h>
32 #include <sys/kernel.h>
33 #include <sys/module.h>
38 #include <bus/pci/pcivar.h>
39 #include <bus/pci/pcireg.h>
44 #include <vm/vm_object.h>
49 extern void pci_cfgregwrite(int, int, int, int, uint32_t, int);
50 extern uint32_t pci_cfgregread(int, int, int, int, int);
52 static void agp_amd64_apbase_fixup(device_t
);
54 static void agp_amd64_uli_init(device_t
);
55 static int agp_amd64_uli_set_aperture(device_t
, uint32_t);
57 static int agp_amd64_nvidia_match(uint16_t);
58 static void agp_amd64_nvidia_init(device_t
);
59 static int agp_amd64_nvidia_set_aperture(device_t
, uint32_t);
61 static int agp_amd64_via_match(void);
62 static void agp_amd64_via_init(device_t
);
63 static int agp_amd64_via_set_aperture(device_t
, uint32_t);
65 MALLOC_DECLARE(M_AGP
);
67 #define AMD64_MAX_MCTRL 8
69 struct agp_amd64_softc
{
71 uint32_t initial_aperture
;
72 struct agp_gatt
*gatt
;
74 int mctrl
[AMD64_MAX_MCTRL
];
80 agp_amd64_match(device_t dev
)
82 if (pci_get_class(dev
) != PCIC_BRIDGE
||
83 pci_get_subclass(dev
) != PCIS_BRIDGE_HOST
||
84 agp_find_caps(dev
) == 0)
87 switch (pci_get_devid(dev
)) {
89 return ("AMD 8151 AGP graphics tunnel");
91 return ("SiS 755 host to AGP bridge");
93 return ("SiS 760 host to AGP bridge");
95 return ("ULi M1689 AGP Controller");
97 if (agp_amd64_nvidia_match(0x00d2))
99 return ("NVIDIA nForce3 AGP Controller");
101 if (agp_amd64_nvidia_match(0x00e2))
103 return ("NVIDIA nForce3-250 AGP Controller");
105 return ("VIA 8380 host to PCI bridge");
107 return ("VIA 3238 host to PCI bridge");
109 return ("VIA K8T800Pro host to PCI bridge");
111 return ("VIA 8385 host to PCI bridge");
118 agp_amd64_nvidia_match(uint16_t devid
)
120 /* XXX nForce3 requires secondary AGP bridge at 0:11:0. */
121 if (pci_cfgregread(0, 11, 0, PCIR_CLASS
, 1) != PCIC_BRIDGE
||
122 pci_cfgregread(0, 11, 0, PCIR_SUBCLASS
, 1) != PCIS_BRIDGE_PCI
||
123 pci_cfgregread(0, 11, 0, PCIR_VENDOR
, 2) != 0x10de ||
124 pci_cfgregread(0, 11, 0, PCIR_DEVICE
, 2) != devid
)
131 agp_amd64_via_match(void)
133 /* XXX Some VIA bridge requires secondary AGP bridge at 0:1:0. */
134 if (pci_cfgregread(0, 1, 0, PCIR_CLASS
, 1) != PCIC_BRIDGE
||
135 pci_cfgregread(0, 1, 0, PCIR_SUBCLASS
, 1) != PCIS_BRIDGE_PCI
||
136 pci_cfgregread(0, 1, 0, PCIR_VENDOR
, 2) != 0x1106 ||
137 pci_cfgregread(0, 1, 0, PCIR_DEVICE
, 2) != 0xb188 ||
138 (pci_cfgregread(0, 1, 0, AGP_VIA_AGPSEL
, 1) & 2))
145 agp_amd64_probe(device_t dev
)
149 if (resource_disabled("agp", device_get_unit(dev
)))
151 if ((desc
= agp_amd64_match(dev
))) {
152 device_set_desc(dev
, desc
);
153 return (BUS_PROBE_DEFAULT
);
160 agp_amd64_attach(device_t dev
)
162 struct agp_amd64_softc
*sc
= device_get_softc(dev
);
163 struct agp_gatt
*gatt
;
167 for (i
= 0, n
= 0; i
< PCI_SLOTMAX
&& n
< AMD64_MAX_MCTRL
; i
++) {
168 devid
= pci_cfgregread(0, i
, 3, 0, 4);
169 if (devid
== 0x11031022 || devid
== 0x12031022) {
180 device_printf(dev
, "%d Miscellaneous Control unit(s) found.\n",
183 if ((error
= agp_generic_attach(dev
)))
186 sc
->initial_aperture
= AGP_GET_APERTURE(dev
);
189 gatt
= agp_alloc_gatt(dev
);
194 * Probably contigmalloc failure. Try reducing the
195 * aperture so that the gatt size reduces.
197 if (AGP_SET_APERTURE(dev
, AGP_GET_APERTURE(dev
) / 2)) {
198 agp_generic_detach(dev
);
204 switch (pci_get_vendor(dev
)) {
205 case 0x10b9: /* ULi */
206 agp_amd64_uli_init(dev
);
207 if (agp_amd64_uli_set_aperture(dev
, sc
->initial_aperture
))
211 case 0x10de: /* nVidia */
212 agp_amd64_nvidia_init(dev
);
213 if (agp_amd64_nvidia_set_aperture(dev
, sc
->initial_aperture
))
217 case 0x1106: /* VIA */
218 sc
->via_agp
= agp_amd64_via_match();
220 agp_amd64_via_init(dev
);
221 if (agp_amd64_via_set_aperture(dev
,
222 sc
->initial_aperture
))
228 /* Install the gatt and enable aperture. */
229 for (i
= 0; i
< sc
->n_mctrl
; i
++) {
230 pci_cfgregwrite(0, sc
->mctrl
[i
], 3, AGP_AMD64_ATTBASE
,
231 (uint32_t)(gatt
->ag_physical
>> 8) & AGP_AMD64_ATTBASE_MASK
,
233 pci_cfgregwrite(0, sc
->mctrl
[i
], 3, AGP_AMD64_APCTRL
,
234 (pci_cfgregread(0, sc
->mctrl
[i
], 3, AGP_AMD64_APCTRL
, 4) |
235 AGP_AMD64_APCTRL_GARTEN
) &
236 ~(AGP_AMD64_APCTRL_DISGARTCPU
| AGP_AMD64_APCTRL_DISGARTIO
),
246 agp_amd64_detach(device_t dev
)
248 struct agp_amd64_softc
*sc
= device_get_softc(dev
);
253 for (i
= 0; i
< sc
->n_mctrl
; i
++)
254 pci_cfgregwrite(0, sc
->mctrl
[i
], 3, AGP_AMD64_APCTRL
,
255 pci_cfgregread(0, sc
->mctrl
[i
], 3, AGP_AMD64_APCTRL
, 4) &
256 ~AGP_AMD64_APCTRL_GARTEN
, 4);
258 AGP_SET_APERTURE(dev
, sc
->initial_aperture
);
259 agp_free_gatt(sc
->gatt
);
265 static uint32_t agp_amd64_table
[] = {
266 0x02000000, /* 32 MB */
267 0x04000000, /* 64 MB */
268 0x08000000, /* 128 MB */
269 0x10000000, /* 256 MB */
270 0x20000000, /* 512 MB */
271 0x40000000, /* 1024 MB */
272 0x80000000, /* 2048 MB */
275 #define AGP_AMD64_TABLE_SIZE NELEM(agp_amd64_table)
278 agp_amd64_get_aperture(device_t dev
)
280 struct agp_amd64_softc
*sc
= device_get_softc(dev
);
283 i
= (pci_cfgregread(0, sc
->mctrl
[0], 3, AGP_AMD64_APCTRL
, 4) &
284 AGP_AMD64_APCTRL_SIZE_MASK
) >> 1;
286 if (i
>= AGP_AMD64_TABLE_SIZE
)
289 return (agp_amd64_table
[i
]);
293 agp_amd64_set_aperture(device_t dev
, uint32_t aperture
)
295 struct agp_amd64_softc
*sc
= device_get_softc(dev
);
299 for (i
= 0; i
< AGP_AMD64_TABLE_SIZE
; i
++)
300 if (agp_amd64_table
[i
] == aperture
)
302 if (i
>= AGP_AMD64_TABLE_SIZE
)
305 for (j
= 0; j
< sc
->n_mctrl
; j
++)
306 pci_cfgregwrite(0, sc
->mctrl
[j
], 3, AGP_AMD64_APCTRL
,
307 (pci_cfgregread(0, sc
->mctrl
[j
], 3, AGP_AMD64_APCTRL
, 4) &
308 ~(AGP_AMD64_APCTRL_SIZE_MASK
)) | (i
<< 1), 4);
310 switch (pci_get_vendor(dev
)) {
311 case 0x10b9: /* ULi */
312 return (agp_amd64_uli_set_aperture(dev
, aperture
));
315 case 0x10de: /* nVidia */
316 return (agp_amd64_nvidia_set_aperture(dev
, aperture
));
319 case 0x1106: /* VIA */
321 return (agp_amd64_via_set_aperture(dev
, aperture
));
329 agp_amd64_bind_page(device_t dev
, vm_offset_t offset
, vm_offset_t physical
)
331 struct agp_amd64_softc
*sc
= device_get_softc(dev
);
333 if (offset
>= (sc
->gatt
->ag_entries
<< AGP_PAGE_SHIFT
))
336 sc
->gatt
->ag_virtual
[offset
>> AGP_PAGE_SHIFT
] =
337 (physical
& 0xfffff000) | ((physical
>> 28) & 0x00000ff0) | 3;
343 agp_amd64_unbind_page(device_t dev
, vm_offset_t offset
)
345 struct agp_amd64_softc
*sc
= device_get_softc(dev
);
347 if (offset
>= (sc
->gatt
->ag_entries
<< AGP_PAGE_SHIFT
))
350 sc
->gatt
->ag_virtual
[offset
>> AGP_PAGE_SHIFT
] = 0;
356 agp_amd64_flush_tlb(device_t dev
)
358 struct agp_amd64_softc
*sc
= device_get_softc(dev
);
361 for (i
= 0; i
< sc
->n_mctrl
; i
++)
362 pci_cfgregwrite(0, sc
->mctrl
[i
], 3, AGP_AMD64_CACHECTRL
,
363 pci_cfgregread(0, sc
->mctrl
[i
], 3, AGP_AMD64_CACHECTRL
, 4) |
364 AGP_AMD64_CACHECTRL_INVGART
, 4);
368 agp_amd64_apbase_fixup(device_t dev
)
370 struct agp_amd64_softc
*sc
= device_get_softc(dev
);
374 sc
->apbase
= rman_get_start(sc
->agp
.as_aperture
);
375 apbase
= (sc
->apbase
>> 25) & AGP_AMD64_APBASE_MASK
;
376 for (i
= 0; i
< sc
->n_mctrl
; i
++)
377 pci_cfgregwrite(0, sc
->mctrl
[i
], 3,
378 AGP_AMD64_APBASE
, apbase
, 4);
382 agp_amd64_uli_init(device_t dev
)
384 struct agp_amd64_softc
*sc
= device_get_softc(dev
);
386 agp_amd64_apbase_fixup(dev
);
387 pci_write_config(dev
, AGP_AMD64_ULI_APBASE
,
388 (pci_read_config(dev
, AGP_AMD64_ULI_APBASE
, 4) & 0x0000000f) |
390 pci_write_config(dev
, AGP_AMD64_ULI_HTT_FEATURE
, sc
->apbase
, 4);
394 agp_amd64_uli_set_aperture(device_t dev
, uint32_t aperture
)
396 struct agp_amd64_softc
*sc
= device_get_softc(dev
);
399 case 0x02000000: /* 32 MB */
400 case 0x04000000: /* 64 MB */
401 case 0x08000000: /* 128 MB */
402 case 0x10000000: /* 256 MB */
408 pci_write_config(dev
, AGP_AMD64_ULI_ENU_SCR
,
409 sc
->apbase
+ aperture
- 1, 4);
415 agp_amd64_nvidia_init(device_t dev
)
417 struct agp_amd64_softc
*sc
= device_get_softc(dev
);
419 agp_amd64_apbase_fixup(dev
);
420 pci_write_config(dev
, AGP_AMD64_NVIDIA_0_APBASE
,
421 (pci_read_config(dev
, AGP_AMD64_NVIDIA_0_APBASE
, 4) & 0x0000000f) |
423 pci_cfgregwrite(0, 11, 0, AGP_AMD64_NVIDIA_1_APBASE1
, sc
->apbase
, 4);
424 pci_cfgregwrite(0, 11, 0, AGP_AMD64_NVIDIA_1_APBASE2
, sc
->apbase
, 4);
428 agp_amd64_nvidia_set_aperture(device_t dev
, uint32_t aperture
)
430 struct agp_amd64_softc
*sc
= device_get_softc(dev
);
434 case 0x02000000: apsize
= 0x0f; break; /* 32 MB */
435 case 0x04000000: apsize
= 0x0e; break; /* 64 MB */
436 case 0x08000000: apsize
= 0x0c; break; /* 128 MB */
437 case 0x10000000: apsize
= 0x08; break; /* 256 MB */
438 case 0x20000000: apsize
= 0x00; break; /* 512 MB */
443 pci_cfgregwrite(0, 11, 0, AGP_AMD64_NVIDIA_1_APSIZE
,
444 (pci_cfgregread(0, 11, 0, AGP_AMD64_NVIDIA_1_APSIZE
, 4) &
445 0xfffffff0) | apsize
, 4);
446 pci_cfgregwrite(0, 11, 0, AGP_AMD64_NVIDIA_1_APLIMIT1
,
447 sc
->apbase
+ aperture
- 1, 4);
448 pci_cfgregwrite(0, 11, 0, AGP_AMD64_NVIDIA_1_APLIMIT2
,
449 sc
->apbase
+ aperture
- 1, 4);
455 agp_amd64_via_init(device_t dev
)
457 struct agp_amd64_softc
*sc
= device_get_softc(dev
);
459 agp_amd64_apbase_fixup(dev
);
460 pci_cfgregwrite(0, 1, 0, AGP3_VIA_ATTBASE
, sc
->gatt
->ag_physical
, 4);
461 pci_cfgregwrite(0, 1, 0, AGP3_VIA_GARTCTRL
,
462 pci_cfgregread(0, 1, 0, AGP3_VIA_ATTBASE
, 4) | 0x180, 4);
466 agp_amd64_via_set_aperture(device_t dev
, uint32_t aperture
)
470 apsize
= ((aperture
- 1) >> 20) ^ 0xff;
471 if ((((apsize
^ 0xff) << 20) | ((1 << 20) - 1)) + 1 != aperture
)
473 pci_cfgregwrite(0, 1, 0, AGP3_VIA_APSIZE
, apsize
, 1);
478 static device_method_t agp_amd64_methods
[] = {
479 /* Device interface */
480 DEVMETHOD(device_probe
, agp_amd64_probe
),
481 DEVMETHOD(device_attach
, agp_amd64_attach
),
482 DEVMETHOD(device_detach
, agp_amd64_detach
),
483 DEVMETHOD(device_shutdown
, bus_generic_shutdown
),
484 DEVMETHOD(device_suspend
, bus_generic_suspend
),
485 DEVMETHOD(device_resume
, bus_generic_resume
),
488 DEVMETHOD(agp_get_aperture
, agp_amd64_get_aperture
),
489 DEVMETHOD(agp_set_aperture
, agp_amd64_set_aperture
),
490 DEVMETHOD(agp_bind_page
, agp_amd64_bind_page
),
491 DEVMETHOD(agp_unbind_page
, agp_amd64_unbind_page
),
492 DEVMETHOD(agp_flush_tlb
, agp_amd64_flush_tlb
),
493 DEVMETHOD(agp_enable
, agp_generic_enable
),
494 DEVMETHOD(agp_alloc_memory
, agp_generic_alloc_memory
),
495 DEVMETHOD(agp_free_memory
, agp_generic_free_memory
),
496 DEVMETHOD(agp_bind_memory
, agp_generic_bind_memory
),
497 DEVMETHOD(agp_unbind_memory
, agp_generic_unbind_memory
),
502 static driver_t agp_amd64_driver
= {
505 sizeof(struct agp_amd64_softc
),
508 static devclass_t agp_devclass
;
510 DRIVER_MODULE(agp_amd64
, pci
, agp_amd64_driver
, agp_devclass
, NULL
, NULL
);
511 MODULE_DEPEND(agp_amd64
, agp
, 1, 1, 1);
512 MODULE_DEPEND(agp_amd64
, pci
, 1, 1, 1);