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.16 2007/11/12 21:51:36 jhb Exp $
27 * $DragonFly: src/sys/dev/agp/agp_amd64.c,v 1.3 2008/01/07 01:34:58 corecode Exp $
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/malloc.h>
35 #include <sys/kernel.h>
36 #include <sys/module.h>
41 #include <bus/pci/pcivar.h>
42 #include <bus/pci/pcireg.h>
47 #include <vm/vm_object.h>
52 extern void pci_cfgregwrite(int, int, int, int, uint32_t, int);
53 extern uint32_t pci_cfgregread(int, int, int, int, int);
55 static void agp_amd64_apbase_fixup(device_t
);
57 static void agp_amd64_uli_init(device_t
);
58 static int agp_amd64_uli_set_aperture(device_t
, uint32_t);
60 static int agp_amd64_nvidia_match(uint16_t);
61 static void agp_amd64_nvidia_init(device_t
);
62 static int agp_amd64_nvidia_set_aperture(device_t
, uint32_t);
64 static int agp_amd64_via_match(void);
65 static void agp_amd64_via_init(device_t
);
66 static int agp_amd64_via_set_aperture(device_t
, uint32_t);
68 MALLOC_DECLARE(M_AGP
);
70 #define AMD64_MAX_MCTRL 8
72 struct agp_amd64_softc
{
74 uint32_t initial_aperture
;
75 struct agp_gatt
*gatt
;
77 int mctrl
[AMD64_MAX_MCTRL
];
83 agp_amd64_match(device_t dev
)
85 if (pci_get_class(dev
) != PCIC_BRIDGE
||
86 pci_get_subclass(dev
) != PCIS_BRIDGE_HOST
||
87 agp_find_caps(dev
) == 0)
90 switch (pci_get_devid(dev
)) {
92 return ("AMD 8151 AGP graphics tunnel");
94 return ("SiS 755 host to AGP bridge");
96 return ("SiS 760 host to AGP bridge");
98 return ("ULi M1689 AGP Controller");
100 if (agp_amd64_nvidia_match(0x00d2))
102 return ("NVIDIA nForce3 AGP Controller");
104 if (agp_amd64_nvidia_match(0x00e2))
106 return ("NVIDIA nForce3-250 AGP Controller");
108 return ("VIA 8380 host to PCI bridge");
110 return ("VIA 3238 host to PCI bridge");
112 return ("VIA K8T800Pro host to PCI bridge");
114 return ("VIA 8385 host to PCI bridge");
121 agp_amd64_nvidia_match(uint16_t devid
)
123 /* XXX nForce3 requires secondary AGP bridge at 0:11:0. */
124 if (pci_cfgregread(0, 11, 0, PCIR_CLASS
, 1) != PCIC_BRIDGE
||
125 pci_cfgregread(0, 11, 0, PCIR_SUBCLASS
, 1) != PCIS_BRIDGE_PCI
||
126 pci_cfgregread(0, 11, 0, PCIR_VENDOR
, 2) != 0x10de ||
127 pci_cfgregread(0, 11, 0, PCIR_DEVICE
, 2) != devid
)
134 agp_amd64_via_match(void)
136 /* XXX Some VIA bridge requires secondary AGP bridge at 0:1:0. */
137 if (pci_cfgregread(0, 1, 0, PCIR_CLASS
, 1) != PCIC_BRIDGE
||
138 pci_cfgregread(0, 1, 0, PCIR_SUBCLASS
, 1) != PCIS_BRIDGE_PCI
||
139 pci_cfgregread(0, 1, 0, PCIR_VENDOR
, 2) != 0x1106 ||
140 pci_cfgregread(0, 1, 0, PCIR_DEVICE
, 2) != 0xb188 ||
141 (pci_cfgregread(0, 1, 0, AGP_VIA_AGPSEL
, 1) & 2))
148 agp_amd64_probe(device_t dev
)
152 if (resource_disabled("agp", device_get_unit(dev
)))
154 if ((desc
= agp_amd64_match(dev
))) {
155 device_set_desc(dev
, desc
);
156 return (BUS_PROBE_DEFAULT
);
163 agp_amd64_attach(device_t dev
)
165 struct agp_amd64_softc
*sc
= device_get_softc(dev
);
166 struct agp_gatt
*gatt
;
169 for (i
= 0, n
= 0; i
< PCI_SLOTMAX
&& n
< AMD64_MAX_MCTRL
; i
++)
170 if (pci_cfgregread(0, i
, 3, 0, 4) == 0x11031022) {
181 device_printf(dev
, "%d Miscellaneous Control unit(s) found.\n",
184 if ((error
= agp_generic_attach(dev
)))
187 sc
->initial_aperture
= AGP_GET_APERTURE(dev
);
188 if (sc
->initial_aperture
== 0) {
189 device_printf(dev
, "bad initial aperture size, disabling\n");
194 gatt
= agp_alloc_gatt(dev
);
199 * Probably contigmalloc failure. Try reducing the
200 * aperture so that the gatt size reduces.
202 if (AGP_SET_APERTURE(dev
, AGP_GET_APERTURE(dev
) / 2)) {
203 agp_generic_detach(dev
);
209 switch (pci_get_vendor(dev
)) {
210 case 0x10b9: /* ULi */
211 agp_amd64_uli_init(dev
);
212 if (agp_amd64_uli_set_aperture(dev
, sc
->initial_aperture
))
216 case 0x10de: /* nVidia */
217 agp_amd64_nvidia_init(dev
);
218 if (agp_amd64_nvidia_set_aperture(dev
, sc
->initial_aperture
))
222 case 0x1106: /* VIA */
223 sc
->via_agp
= agp_amd64_via_match();
225 agp_amd64_via_init(dev
);
226 if (agp_amd64_via_set_aperture(dev
,
227 sc
->initial_aperture
))
233 /* Install the gatt and enable aperture. */
234 for (i
= 0; i
< sc
->n_mctrl
; i
++) {
235 pci_cfgregwrite(0, sc
->mctrl
[i
], 3, AGP_AMD64_ATTBASE
,
236 (uint32_t)(gatt
->ag_physical
>> 8) & AGP_AMD64_ATTBASE_MASK
,
238 pci_cfgregwrite(0, sc
->mctrl
[i
], 3, AGP_AMD64_APCTRL
,
239 (pci_cfgregread(0, sc
->mctrl
[i
], 3, AGP_AMD64_APCTRL
, 4) |
240 AGP_AMD64_APCTRL_GARTEN
) &
241 ~(AGP_AMD64_APCTRL_DISGARTCPU
| AGP_AMD64_APCTRL_DISGARTIO
),
251 agp_amd64_detach(device_t dev
)
253 struct agp_amd64_softc
*sc
= device_get_softc(dev
);
258 for (i
= 0; i
< sc
->n_mctrl
; i
++)
259 pci_cfgregwrite(0, sc
->mctrl
[i
], 3, AGP_AMD64_APCTRL
,
260 pci_cfgregread(0, sc
->mctrl
[i
], 3, AGP_AMD64_APCTRL
, 4) &
261 ~AGP_AMD64_APCTRL_GARTEN
, 4);
263 AGP_SET_APERTURE(dev
, sc
->initial_aperture
);
264 agp_free_gatt(sc
->gatt
);
270 static uint32_t agp_amd64_table
[] = {
271 0x02000000, /* 32 MB */
272 0x04000000, /* 64 MB */
273 0x08000000, /* 128 MB */
274 0x10000000, /* 256 MB */
275 0x20000000, /* 512 MB */
276 0x40000000, /* 1024 MB */
277 0x80000000, /* 2048 MB */
280 #define AGP_AMD64_TABLE_SIZE \
281 (sizeof(agp_amd64_table) / sizeof(agp_amd64_table[0]))
284 agp_amd64_get_aperture(device_t dev
)
286 struct agp_amd64_softc
*sc
= device_get_softc(dev
);
289 i
= (pci_cfgregread(0, sc
->mctrl
[0], 3, AGP_AMD64_APCTRL
, 4) &
290 AGP_AMD64_APCTRL_SIZE_MASK
) >> 1;
292 if (i
>= AGP_AMD64_TABLE_SIZE
)
295 return (agp_amd64_table
[i
]);
299 agp_amd64_set_aperture(device_t dev
, uint32_t aperture
)
301 struct agp_amd64_softc
*sc
= device_get_softc(dev
);
305 for (i
= 0; i
< AGP_AMD64_TABLE_SIZE
; i
++)
306 if (agp_amd64_table
[i
] == aperture
)
308 if (i
>= AGP_AMD64_TABLE_SIZE
)
311 for (j
= 0; j
< sc
->n_mctrl
; j
++)
312 pci_cfgregwrite(0, sc
->mctrl
[j
], 3, AGP_AMD64_APCTRL
,
313 (pci_cfgregread(0, sc
->mctrl
[j
], 3, AGP_AMD64_APCTRL
, 4) &
314 ~(AGP_AMD64_APCTRL_SIZE_MASK
)) | (i
<< 1), 4);
316 switch (pci_get_vendor(dev
)) {
317 case 0x10b9: /* ULi */
318 return (agp_amd64_uli_set_aperture(dev
, aperture
));
321 case 0x10de: /* nVidia */
322 return (agp_amd64_nvidia_set_aperture(dev
, aperture
));
325 case 0x1106: /* VIA */
327 return (agp_amd64_via_set_aperture(dev
, aperture
));
335 agp_amd64_bind_page(device_t dev
, int offset
, vm_offset_t physical
)
337 struct agp_amd64_softc
*sc
= device_get_softc(dev
);
339 if (offset
< 0 || offset
>= (sc
->gatt
->ag_entries
<< AGP_PAGE_SHIFT
))
342 sc
->gatt
->ag_virtual
[offset
>> AGP_PAGE_SHIFT
] =
343 (physical
& 0xfffff000) | ((physical
>> 28) & 0x00000ff0) | 3;
349 agp_amd64_unbind_page(device_t dev
, int offset
)
351 struct agp_amd64_softc
*sc
= device_get_softc(dev
);
353 if (offset
< 0 || offset
>= (sc
->gatt
->ag_entries
<< AGP_PAGE_SHIFT
))
356 sc
->gatt
->ag_virtual
[offset
>> AGP_PAGE_SHIFT
] = 0;
362 agp_amd64_flush_tlb(device_t dev
)
364 struct agp_amd64_softc
*sc
= device_get_softc(dev
);
367 for (i
= 0; i
< sc
->n_mctrl
; i
++)
368 pci_cfgregwrite(0, sc
->mctrl
[i
], 3, AGP_AMD64_CACHECTRL
,
369 pci_cfgregread(0, sc
->mctrl
[i
], 3, AGP_AMD64_CACHECTRL
, 4) |
370 AGP_AMD64_CACHECTRL_INVGART
, 4);
374 agp_amd64_apbase_fixup(device_t dev
)
376 struct agp_amd64_softc
*sc
= device_get_softc(dev
);
380 sc
->apbase
= rman_get_start(sc
->agp
.as_aperture
);
381 apbase
= (sc
->apbase
>> 25) & AGP_AMD64_APBASE_MASK
;
382 for (i
= 0; i
< sc
->n_mctrl
; i
++)
383 pci_cfgregwrite(0, sc
->mctrl
[i
], 3,
384 AGP_AMD64_APBASE
, apbase
, 4);
388 agp_amd64_uli_init(device_t dev
)
390 struct agp_amd64_softc
*sc
= device_get_softc(dev
);
392 agp_amd64_apbase_fixup(dev
);
393 pci_write_config(dev
, AGP_AMD64_ULI_APBASE
,
394 (pci_read_config(dev
, AGP_AMD64_ULI_APBASE
, 4) & 0x0000000f) |
396 pci_write_config(dev
, AGP_AMD64_ULI_HTT_FEATURE
, sc
->apbase
, 4);
400 agp_amd64_uli_set_aperture(device_t dev
, uint32_t aperture
)
402 struct agp_amd64_softc
*sc
= device_get_softc(dev
);
405 case 0x02000000: /* 32 MB */
406 case 0x04000000: /* 64 MB */
407 case 0x08000000: /* 128 MB */
408 case 0x10000000: /* 256 MB */
414 pci_write_config(dev
, AGP_AMD64_ULI_ENU_SCR
,
415 sc
->apbase
+ aperture
- 1, 4);
421 agp_amd64_nvidia_init(device_t dev
)
423 struct agp_amd64_softc
*sc
= device_get_softc(dev
);
425 agp_amd64_apbase_fixup(dev
);
426 pci_write_config(dev
, AGP_AMD64_NVIDIA_0_APBASE
,
427 (pci_read_config(dev
, AGP_AMD64_NVIDIA_0_APBASE
, 4) & 0x0000000f) |
429 pci_cfgregwrite(0, 11, 0, AGP_AMD64_NVIDIA_1_APBASE1
, sc
->apbase
, 4);
430 pci_cfgregwrite(0, 11, 0, AGP_AMD64_NVIDIA_1_APBASE2
, sc
->apbase
, 4);
434 agp_amd64_nvidia_set_aperture(device_t dev
, uint32_t aperture
)
436 struct agp_amd64_softc
*sc
= device_get_softc(dev
);
440 case 0x02000000: apsize
= 0x0f; break; /* 32 MB */
441 case 0x04000000: apsize
= 0x0e; break; /* 64 MB */
442 case 0x08000000: apsize
= 0x0c; break; /* 128 MB */
443 case 0x10000000: apsize
= 0x08; break; /* 256 MB */
444 case 0x20000000: apsize
= 0x00; break; /* 512 MB */
449 pci_cfgregwrite(0, 11, 0, AGP_AMD64_NVIDIA_1_APSIZE
,
450 (pci_cfgregread(0, 11, 0, AGP_AMD64_NVIDIA_1_APSIZE
, 4) &
451 0xfffffff0) | apsize
, 4);
452 pci_cfgregwrite(0, 11, 0, AGP_AMD64_NVIDIA_1_APLIMIT1
,
453 sc
->apbase
+ aperture
- 1, 4);
454 pci_cfgregwrite(0, 11, 0, AGP_AMD64_NVIDIA_1_APLIMIT2
,
455 sc
->apbase
+ aperture
- 1, 4);
461 agp_amd64_via_init(device_t dev
)
463 struct agp_amd64_softc
*sc
= device_get_softc(dev
);
465 agp_amd64_apbase_fixup(dev
);
466 pci_cfgregwrite(0, 1, 0, AGP3_VIA_ATTBASE
, sc
->gatt
->ag_physical
, 4);
467 pci_cfgregwrite(0, 1, 0, AGP3_VIA_GARTCTRL
,
468 pci_cfgregread(0, 1, 0, AGP3_VIA_ATTBASE
, 4) | 0x180, 4);
472 agp_amd64_via_set_aperture(device_t dev
, uint32_t aperture
)
476 apsize
= ((aperture
- 1) >> 20) ^ 0xff;
477 if ((((apsize
^ 0xff) << 20) | ((1 << 20) - 1)) + 1 != aperture
)
479 pci_cfgregwrite(0, 1, 0, AGP3_VIA_APSIZE
, apsize
, 1);
484 static device_method_t agp_amd64_methods
[] = {
485 /* Device interface */
486 DEVMETHOD(device_probe
, agp_amd64_probe
),
487 DEVMETHOD(device_attach
, agp_amd64_attach
),
488 DEVMETHOD(device_detach
, agp_amd64_detach
),
489 DEVMETHOD(device_shutdown
, bus_generic_shutdown
),
490 DEVMETHOD(device_suspend
, bus_generic_suspend
),
491 DEVMETHOD(device_resume
, bus_generic_resume
),
494 DEVMETHOD(agp_get_aperture
, agp_amd64_get_aperture
),
495 DEVMETHOD(agp_set_aperture
, agp_amd64_set_aperture
),
496 DEVMETHOD(agp_bind_page
, agp_amd64_bind_page
),
497 DEVMETHOD(agp_unbind_page
, agp_amd64_unbind_page
),
498 DEVMETHOD(agp_flush_tlb
, agp_amd64_flush_tlb
),
499 DEVMETHOD(agp_enable
, agp_generic_enable
),
500 DEVMETHOD(agp_alloc_memory
, agp_generic_alloc_memory
),
501 DEVMETHOD(agp_free_memory
, agp_generic_free_memory
),
502 DEVMETHOD(agp_bind_memory
, agp_generic_bind_memory
),
503 DEVMETHOD(agp_unbind_memory
, agp_generic_unbind_memory
),
508 static driver_t agp_amd64_driver
= {
511 sizeof(struct agp_amd64_softc
),
514 static devclass_t agp_devclass
;
516 DRIVER_MODULE(agp_amd64
, pci
, agp_amd64_driver
, agp_devclass
, 0, 0);
517 MODULE_DEPEND(agp_amd64
, agp
, 1, 1, 1);
518 MODULE_DEPEND(agp_amd64
, pci
, 1, 1, 1);