| Commit | Line | Data |
|---|---|---|
| fdc3c5be HT |
1 | /*- |
| 2 | * Copyright (c) 2004, 2005 Jung-uk Kim <jkim@FreeBSD.org> | |
| 3 | * All rights reserved. | |
| 4 | * | |
| 5 | * Redistribution and use in source and binary forms, with or without | |
| 6 | * modification, are permitted provided that the following conditions | |
| 7 | * are met: | |
| 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. | |
| 13 | * | |
| 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 | |
| 24 | * SUCH DAMAGE. | |
| 25 | * | |
| aa31142a SS |
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 $ | |
| fdc3c5be HT |
28 | */ |
| 29 | ||
| 30 | #include "opt_bus.h" | |
| 31 | ||
| 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> | |
| 37 | #include <sys/bus.h> | |
| 38 | #include <sys/lock.h> | |
| 39 | #include <sys/proc.h> | |
| 40 | ||
| 41 | #include <bus/pci/pcivar.h> | |
| 42 | #include <bus/pci/pcireg.h> | |
| 43 | #include "agppriv.h" | |
| 44 | #include "agpreg.h" | |
| 45 | ||
| 46 | #include <vm/vm.h> | |
| 47 | #include <vm/vm_object.h> | |
| 48 | #include <vm/pmap.h> | |
| 49 | #include <sys/rman.h> | |
| 50 | ||
| 51 | /* XXX */ | |
| 52 | extern void pci_cfgregwrite(int, int, int, int, uint32_t, int); | |
| 53 | extern uint32_t pci_cfgregread(int, int, int, int, int); | |
| 54 | ||
| 55 | static void agp_amd64_apbase_fixup(device_t); | |
| 56 | ||
| 57 | static void agp_amd64_uli_init(device_t); | |
| 58 | static int agp_amd64_uli_set_aperture(device_t, uint32_t); | |
| 59 | ||
| 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); | |
| 63 | ||
| 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); | |
| 67 | ||
| 68 | MALLOC_DECLARE(M_AGP); | |
| 69 | ||
| 70 | #define AMD64_MAX_MCTRL 8 | |
| 71 | ||
| 72 | struct agp_amd64_softc { | |
| 73 | struct agp_softc agp; | |
| 74 | uint32_t initial_aperture; | |
| 75 | struct agp_gatt *gatt; | |
| 76 | uint32_t apbase; | |
| 77 | int mctrl[AMD64_MAX_MCTRL]; | |
| 78 | int n_mctrl; | |
| 79 | int via_agp; | |
| 80 | }; | |
| 81 | ||
| 82 | static const char* | |
| 83 | agp_amd64_match(device_t dev) | |
| 84 | { | |
| 85 | if (pci_get_class(dev) != PCIC_BRIDGE || | |
| 86 | pci_get_subclass(dev) != PCIS_BRIDGE_HOST || | |
| 87 | agp_find_caps(dev) == 0) | |
| 88 | return (NULL); | |
| 89 | ||
| 90 | switch (pci_get_devid(dev)) { | |
| 91 | case 0x74541022: | |
| 92 | return ("AMD 8151 AGP graphics tunnel"); | |
| 93 | case 0x07551039: | |
| 94 | return ("SiS 755 host to AGP bridge"); | |
| 95 | case 0x07601039: | |
| 96 | return ("SiS 760 host to AGP bridge"); | |
| 97 | case 0x168910b9: | |
| 98 | return ("ULi M1689 AGP Controller"); | |
| 99 | case 0x00d110de: | |
| 100 | if (agp_amd64_nvidia_match(0x00d2)) | |
| 101 | return (NULL); | |
| 102 | return ("NVIDIA nForce3 AGP Controller"); | |
| 103 | case 0x00e110de: | |
| 104 | if (agp_amd64_nvidia_match(0x00e2)) | |
| 105 | return (NULL); | |
| 106 | return ("NVIDIA nForce3-250 AGP Controller"); | |
| 107 | case 0x02041106: | |
| 108 | return ("VIA 8380 host to PCI bridge"); | |
| 109 | case 0x02381106: | |
| 110 | return ("VIA 3238 host to PCI bridge"); | |
| 111 | case 0x02821106: | |
| 112 | return ("VIA K8T800Pro host to PCI bridge"); | |
| 113 | case 0x31881106: | |
| 114 | return ("VIA 8385 host to PCI bridge"); | |
| 115 | }; | |
| 116 | ||
| 117 | return (NULL); | |
| 118 | } | |
| 119 | ||
| 120 | static int | |
| 121 | agp_amd64_nvidia_match(uint16_t devid) | |
| 122 | { | |
| 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) | |
| 128 | return (ENXIO); | |
| 129 | ||
| 130 | return (0); | |
| 131 | } | |
| 132 | ||
| 133 | static int | |
| 134 | agp_amd64_via_match(void) | |
| 135 | { | |
| 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)) | |
| 142 | return (0); | |
| 143 | ||
| 144 | return (1); | |
| 145 | } | |
| 146 | ||
| 147 | static int | |
| 148 | agp_amd64_probe(device_t dev) | |
| 149 | { | |
| 150 | const char *desc; | |
| 151 | ||
| 152 | if (resource_disabled("agp", device_get_unit(dev))) | |
| 153 | return (ENXIO); | |
| 154 | if ((desc = agp_amd64_match(dev))) { | |
| 155 | device_set_desc(dev, desc); | |
| 156 | return (BUS_PROBE_DEFAULT); | |
| 157 | } | |
| 158 | ||
| 159 | return (ENXIO); | |
| 160 | } | |
| 161 | ||
| 162 | static int | |
| 163 | agp_amd64_attach(device_t dev) | |
| 164 | { | |
| 165 | struct agp_amd64_softc *sc = device_get_softc(dev); | |
| 166 | struct agp_gatt *gatt; | |
| 167 | int i, n, error; | |
| 168 | ||
| 169 | for (i = 0, n = 0; i < PCI_SLOTMAX && n < AMD64_MAX_MCTRL; i++) | |
| 170 | if (pci_cfgregread(0, i, 3, 0, 4) == 0x11031022) { | |
| 171 | sc->mctrl[n] = i; | |
| 172 | n++; | |
| 173 | } | |
| 174 | ||
| 175 | if (n == 0) | |
| 176 | return (ENXIO); | |
| 177 | ||
| 178 | sc->n_mctrl = n; | |
| 179 | ||
| 180 | if (bootverbose) | |
| 181 | device_printf(dev, "%d Miscellaneous Control unit(s) found.\n", | |
| 182 | sc->n_mctrl); | |
| 183 | ||
| 184 | if ((error = agp_generic_attach(dev))) | |
| 185 | return (error); | |
| 186 | ||
| 187 | sc->initial_aperture = AGP_GET_APERTURE(dev); | |
| 188 | if (sc->initial_aperture == 0) { | |
| 189 | device_printf(dev, "bad initial aperture size, disabling\n"); | |
| 190 | return ENXIO; | |
| 191 | } | |
| 192 | ||
| 193 | for (;;) { | |
| 194 | gatt = agp_alloc_gatt(dev); | |
| 195 | if (gatt) | |
| 196 | break; | |
| 197 | ||
| 198 | /* | |
| 199 | * Probably contigmalloc failure. Try reducing the | |
| 200 | * aperture so that the gatt size reduces. | |
| 201 | */ | |
| 202 | if (AGP_SET_APERTURE(dev, AGP_GET_APERTURE(dev) / 2)) { | |
| 203 | agp_generic_detach(dev); | |
| 204 | return (ENOMEM); | |
| 205 | } | |
| 206 | } | |
| 207 | sc->gatt = gatt; | |
| 208 | ||
| 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)) | |
| 213 | return (ENXIO); | |
| 214 | break; | |
| 215 | ||
| 216 | case 0x10de: /* nVidia */ | |
| 217 | agp_amd64_nvidia_init(dev); | |
| 218 | if (agp_amd64_nvidia_set_aperture(dev, sc->initial_aperture)) | |
| 219 | return (ENXIO); | |
| 220 | break; | |
| 221 | ||
| 222 | case 0x1106: /* VIA */ | |
| 223 | sc->via_agp = agp_amd64_via_match(); | |
| 224 | if (sc->via_agp) { | |
| 225 | agp_amd64_via_init(dev); | |
| 226 | if (agp_amd64_via_set_aperture(dev, | |
| 227 | sc->initial_aperture)) | |
| 228 | return (ENXIO); | |
| 229 | } | |
| 230 | break; | |
| 231 | } | |
| 232 | ||
| 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, | |
| 237 | 4); | |
| 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), | |
| 242 | 4); | |
| 243 | } | |
| 244 | ||
| 245 | agp_flush_cache(); | |
| 246 | ||
| 247 | return (0); | |
| 248 | } | |
| 249 | ||
| 250 | static int | |
| 251 | agp_amd64_detach(device_t dev) | |
| 252 | { | |
| 253 | struct agp_amd64_softc *sc = device_get_softc(dev); | |
| 67e2dc5d | 254 | int i; |
| fdc3c5be | 255 | |
| 67e2dc5d | 256 | agp_free_cdev(dev); |
| fdc3c5be HT |
257 | |
| 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); | |
| 262 | ||
| 263 | AGP_SET_APERTURE(dev, sc->initial_aperture); | |
| 264 | agp_free_gatt(sc->gatt); | |
| 67e2dc5d | 265 | agp_free_res(dev); |
| fdc3c5be HT |
266 | |
| 267 | return (0); | |
| 268 | } | |
| 269 | ||
| 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 */ | |
| 278 | }; | |
| 279 | ||
| 280 | #define AGP_AMD64_TABLE_SIZE \ | |
| 281 | (sizeof(agp_amd64_table) / sizeof(agp_amd64_table[0])) | |
| 282 | ||
| 283 | static uint32_t | |
| 284 | agp_amd64_get_aperture(device_t dev) | |
| 285 | { | |
| 286 | struct agp_amd64_softc *sc = device_get_softc(dev); | |
| 287 | uint32_t i; | |
| 288 | ||
| 289 | i = (pci_cfgregread(0, sc->mctrl[0], 3, AGP_AMD64_APCTRL, 4) & | |
| 290 | AGP_AMD64_APCTRL_SIZE_MASK) >> 1; | |
| 291 | ||
| 292 | if (i >= AGP_AMD64_TABLE_SIZE) | |
| 293 | return (0); | |
| 294 | ||
| 295 | return (agp_amd64_table[i]); | |
| 296 | } | |
| 297 | ||
| 298 | static int | |
| 299 | agp_amd64_set_aperture(device_t dev, uint32_t aperture) | |
| 300 | { | |
| 301 | struct agp_amd64_softc *sc = device_get_softc(dev); | |
| 302 | uint32_t i; | |
| 303 | int j; | |
| 304 | ||
| 305 | for (i = 0; i < AGP_AMD64_TABLE_SIZE; i++) | |
| 306 | if (agp_amd64_table[i] == aperture) | |
| 307 | break; | |
| 308 | if (i >= AGP_AMD64_TABLE_SIZE) | |
| 309 | return (EINVAL); | |
| 310 | ||
| 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); | |
| 315 | ||
| 316 | switch (pci_get_vendor(dev)) { | |
| 317 | case 0x10b9: /* ULi */ | |
| 318 | return (agp_amd64_uli_set_aperture(dev, aperture)); | |
| 319 | break; | |
| 320 | ||
| 321 | case 0x10de: /* nVidia */ | |
| 322 | return (agp_amd64_nvidia_set_aperture(dev, aperture)); | |
| 323 | break; | |
| 324 | ||
| 325 | case 0x1106: /* VIA */ | |
| 326 | if (sc->via_agp) | |
| 327 | return (agp_amd64_via_set_aperture(dev, aperture)); | |
| 328 | break; | |
| 329 | } | |
| 330 | ||
| 331 | return (0); | |
| 332 | } | |
| 333 | ||
| 334 | static int | |
| 335 | agp_amd64_bind_page(device_t dev, int offset, vm_offset_t physical) | |
| 336 | { | |
| 337 | struct agp_amd64_softc *sc = device_get_softc(dev); | |
| 338 | ||
| 339 | if (offset < 0 || offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT)) | |
| 340 | return (EINVAL); | |
| 341 | ||
| 342 | sc->gatt->ag_virtual[offset >> AGP_PAGE_SHIFT] = | |
| 343 | (physical & 0xfffff000) | ((physical >> 28) & 0x00000ff0) | 3; | |
| 344 | ||
| 345 | return (0); | |
| 346 | } | |
| 347 | ||
| 348 | static int | |
| 349 | agp_amd64_unbind_page(device_t dev, int offset) | |
| 350 | { | |
| 351 | struct agp_amd64_softc *sc = device_get_softc(dev); | |
| 352 | ||
| 353 | if (offset < 0 || offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT)) | |
| 354 | return (EINVAL); | |
| 355 | ||
| 356 | sc->gatt->ag_virtual[offset >> AGP_PAGE_SHIFT] = 0; | |
| 357 | ||
| 358 | return (0); | |
| 359 | } | |
| 360 | ||
| 361 | static void | |
| 362 | agp_amd64_flush_tlb(device_t dev) | |
| 363 | { | |
| 364 | struct agp_amd64_softc *sc = device_get_softc(dev); | |
| 365 | int i; | |
| 366 | ||
| 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); | |
| 371 | } | |
| 372 | ||
| 373 | static void | |
| 374 | agp_amd64_apbase_fixup(device_t dev) | |
| 375 | { | |
| 376 | struct agp_amd64_softc *sc = device_get_softc(dev); | |
| 377 | uint32_t apbase; | |
| 378 | int i; | |
| 379 | ||
| 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); | |
| 385 | } | |
| 386 | ||
| 387 | static void | |
| 388 | agp_amd64_uli_init(device_t dev) | |
| 389 | { | |
| 390 | struct agp_amd64_softc *sc = device_get_softc(dev); | |
| 391 | ||
| 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) | | |
| 395 | sc->apbase, 4); | |
| 396 | pci_write_config(dev, AGP_AMD64_ULI_HTT_FEATURE, sc->apbase, 4); | |
| 397 | } | |
| 398 | ||
| 399 | static int | |
| 400 | agp_amd64_uli_set_aperture(device_t dev, uint32_t aperture) | |
| 401 | { | |
| 402 | struct agp_amd64_softc *sc = device_get_softc(dev); | |
| 403 | ||
| 404 | switch (aperture) { | |
| 405 | case 0x02000000: /* 32 MB */ | |
| 406 | case 0x04000000: /* 64 MB */ | |
| 407 | case 0x08000000: /* 128 MB */ | |
| 408 | case 0x10000000: /* 256 MB */ | |
| 409 | break; | |
| 410 | default: | |
| 411 | return (EINVAL); | |
| 412 | } | |
| 413 | ||
| 414 | pci_write_config(dev, AGP_AMD64_ULI_ENU_SCR, | |
| 415 | sc->apbase + aperture - 1, 4); | |
| 416 | ||
| 417 | return (0); | |
| 418 | } | |
| 419 | ||
| 420 | static void | |
| 421 | agp_amd64_nvidia_init(device_t dev) | |
| 422 | { | |
| 423 | struct agp_amd64_softc *sc = device_get_softc(dev); | |
| 424 | ||
| 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) | | |
| 428 | sc->apbase, 4); | |
| 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); | |
| 431 | } | |
| 432 | ||
| 433 | static int | |
| 434 | agp_amd64_nvidia_set_aperture(device_t dev, uint32_t aperture) | |
| 435 | { | |
| 436 | struct agp_amd64_softc *sc = device_get_softc(dev); | |
| 437 | uint32_t apsize; | |
| 438 | ||
| 439 | switch (aperture) { | |
| 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 */ | |
| 445 | default: | |
| 446 | return (EINVAL); | |
| 447 | } | |
| 448 | ||
| 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); | |
| 456 | ||
| 457 | return (0); | |
| 458 | } | |
| 459 | ||
| 460 | static void | |
| 461 | agp_amd64_via_init(device_t dev) | |
| 462 | { | |
| 463 | struct agp_amd64_softc *sc = device_get_softc(dev); | |
| 464 | ||
| 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); | |
| 469 | } | |
| 470 | ||
| 471 | static int | |
| 472 | agp_amd64_via_set_aperture(device_t dev, uint32_t aperture) | |
| 473 | { | |
| 474 | uint32_t apsize; | |
| 475 | ||
| 476 | apsize = ((aperture - 1) >> 20) ^ 0xff; | |
| 477 | if ((((apsize ^ 0xff) << 20) | ((1 << 20) - 1)) + 1 != aperture) | |
| 478 | return (EINVAL); | |
| 479 | pci_cfgregwrite(0, 1, 0, AGP3_VIA_APSIZE, apsize, 1); | |
| 480 | ||
| 481 | return (0); | |
| 482 | } | |
| 483 | ||
| 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), | |
| 492 | ||
| 493 | /* AGP interface */ | |
| 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), | |
| 504 | ||
| 505 | { 0, 0 } | |
| 506 | }; | |
| 507 | ||
| 508 | static driver_t agp_amd64_driver = { | |
| 509 | "agp", | |
| 510 | agp_amd64_methods, | |
| 511 | sizeof(struct agp_amd64_softc), | |
| 512 | }; | |
| 513 | ||
| 514 | static devclass_t agp_devclass; | |
| 515 | ||
| 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); |