1 /* $NetBSD: agp_nvidia.c,v 1.1 2026/06/21 18:38:35 andvar Exp $ */ 2 3 /*- 4 * SPDX-License-Identifier: BSD-2-Clause 5 * 6 * Copyright (c) 2003 Matthew N. Dodd <winter (at) jurai.net> 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31 #include <sys/cdefs.h> 32 __KERNEL_RCSID(0, "$NetBSD: agp_nvidia.c,v 1.1 2026/06/21 18:38:35 andvar Exp $"); 33 34 #include <sys/param.h> 35 #include <sys/agpio.h> 36 #include <sys/bus.h> 37 #include <sys/conf.h> 38 #include <sys/device.h> 39 #include <sys/kernel.h> 40 #include <sys/malloc.h> 41 #include <sys/proc.h> 42 #include <sys/systm.h> 43 44 #include <dev/pci/agpreg.h> 45 #include <dev/pci/agpvar.h> 46 #include <dev/pci/pcidevs.h> 47 #include <dev/pci/pcireg.h> 48 #include <dev/pci/pcivar.h> 49 50 #include <machine/cpufunc.h> 51 52 #define AGP_NFORCE_MEMCTLTAG(pc, dev) pci_make_tag(pc, 0, 0, dev) 53 #define AGP_NFORCE_PPBTAG(pc) pci_make_tag(pc, 0, 30, 0) 54 55 #define SYSCFG 0xC0010010 56 #define IORR_BASE0 0xC0010016 57 #define IORR_MASK0 0xC0010017 58 #define AMD_K7_NUM_IORR 2 59 60 struct agp_nvidia_softc { 61 struct agp_softc agp; 62 uint32_t initial_aperture; /* aperture size at startup */ 63 struct agp_gatt * gatt; 64 65 device_t dev; /* AGP Controller */ 66 pcitag_t mc1_tag; /* memory controller func 1 */ 67 pcitag_t mc2_tag; /* memory controller func 2 */ 68 pcitag_t bdev_tag; /* Bridge */ 69 70 uint32_t wbc_mask; 71 int num_dirs; 72 int num_active_entries; 73 off_t pg_offset; 74 }; 75 76 77 static int agp_nvidia_init(struct agp_softc *); 78 static uint32_t agp_nvidia_get_aperture(struct agp_softc *); 79 static int agp_nvidia_set_aperture(struct agp_softc *, uint32_t); 80 static int agp_nvidia_bind_page(struct agp_softc *, off_t, bus_addr_t); 81 static int agp_nvidia_unbind_page(struct agp_softc *, off_t); 82 static void agp_nvidia_flush_tlb(struct agp_softc *); 83 #if 0 84 static int agp_nvidia_detach(struct agp_softc *); 85 #endif 86 static int nvidia_init_iorr(uint32_t, uint32_t); 87 88 89 static struct agp_methods agp_nvidia_methods = { 90 agp_nvidia_get_aperture, 91 agp_nvidia_set_aperture, 92 agp_nvidia_bind_page, 93 agp_nvidia_unbind_page, 94 agp_nvidia_flush_tlb, 95 agp_generic_enable, 96 agp_generic_alloc_memory, 97 agp_generic_free_memory, 98 agp_generic_bind_memory, 99 agp_generic_unbind_memory, 100 }; 101 102 int 103 agp_nvidia_attach(device_t parent, device_t self, void *aux) 104 { 105 struct agp_softc *sc = device_private(self); 106 struct pci_attach_args *pa = aux; 107 struct agp_nvidia_softc *nsc; 108 struct agp_gatt *gatt; 109 110 nsc = malloc(sizeof *nsc, M_AGP, M_WAITOK); 111 112 switch (PCI_PRODUCT(pa->pa_id)) { 113 case PCI_PRODUCT_NVIDIA_NFORCE_PCHB: 114 nsc->wbc_mask = AGP_NVIDIA_NFORCE_WBC_MASK; 115 break; 116 case PCI_PRODUCT_NVIDIA_NFORCE2_PCHB: 117 nsc->wbc_mask = AGP_NVIDIA_NFORCE2_WBC_MASK; 118 break; 119 default: 120 /* Should never happen */ 121 aprint_error_dev(self, "Bad chip id\n"); 122 return ENODEV; 123 } 124 125 sc->as_chipc = nsc; 126 sc->as_methods = &agp_nvidia_methods; 127 nsc->mc1_tag = AGP_NFORCE_MEMCTLTAG(pa->pa_pc, 1); 128 nsc->mc2_tag = AGP_NFORCE_MEMCTLTAG(pa->pa_pc, 2); 129 nsc->bdev_tag = AGP_NFORCE_PPBTAG(pa->pa_pc); 130 131 pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_AGP, &sc->as_capoff, 132 NULL); 133 134 if (agp_map_aperture(pa, sc, AGP_APBASE) != 0) { 135 aprint_error(": can't map aperture\n"); 136 free(nsc, M_AGP); 137 sc->as_chipc = NULL; 138 return ENXIO; 139 } 140 141 nsc->initial_aperture = AGP_GET_APERTURE(sc); 142 143 for (;;) { 144 gatt = agp_alloc_gatt(sc); 145 if (gatt) 146 break; 147 148 /* 149 * Probably contigmalloc failure. Try reducing the 150 * aperture so that the gatt size reduces. 151 */ 152 if (AGP_SET_APERTURE(sc, AGP_GET_APERTURE(sc) / 2)) { 153 agp_generic_detach(sc); 154 aprint_error(": failed to set aperture\n"); 155 return ENOMEM; 156 } 157 } 158 nsc->gatt = gatt; 159 160 return agp_nvidia_init(sc); 161 } 162 163 static int 164 agp_nvidia_init(struct agp_softc *sc) 165 { 166 struct agp_nvidia_softc *nsc = sc->as_chipc; 167 struct agp_gatt *gatt = nsc->gatt; 168 uint32_t apbase; 169 uint32_t aplimit; 170 uint32_t temp; 171 int size, i, error; 172 173 apbase = sc->as_apaddr; 174 aplimit = apbase + AGP_GET_APERTURE(sc) - 1; 175 pci_conf_write(sc->as_pc, nsc->mc2_tag, AGP_NVIDIA_2_APBASE, apbase); 176 pci_conf_write(sc->as_pc, nsc->mc2_tag, AGP_NVIDIA_2_APLIMIT, aplimit); 177 pci_conf_write(sc->as_pc, nsc->bdev_tag, AGP_NVIDIA_3_APBASE, apbase); 178 pci_conf_write(sc->as_pc, nsc->bdev_tag, AGP_NVIDIA_3_APLIMIT, aplimit); 179 180 error = nvidia_init_iorr(apbase, AGP_GET_APERTURE(sc)); 181 error = 0; 182 if (error) { 183 aprint_error_dev(sc->as_dev, "Failed to setup IORRs\n"); 184 agp_generic_detach(sc); 185 return ENOMEM; 186 } 187 188 /* directory size is 64k */ 189 size = AGP_GET_APERTURE(sc) / 1024 / 1024; 190 nsc->num_dirs = size / 64; 191 nsc->num_active_entries = (size == 32) ? 16384 : ((size * 1024) / 4); 192 nsc->pg_offset = 0; 193 if (nsc->num_dirs == 0) { 194 nsc->num_dirs = 1; 195 nsc->num_active_entries /= (64 / size); 196 nsc->pg_offset = rounddown2(apbase & (64 * 1024 * 1024 - 1), 197 AGP_GET_APERTURE(sc)) / PAGE_SIZE; 198 } 199 200 /* (G)ATT Base Address */ 201 for (i = 0; i < 8; i++) { 202 pci_conf_write(sc->as_pc, nsc->mc2_tag, AGP_NVIDIA_2_ATTBASE(i), 203 (gatt->ag_physical + (i % nsc->num_dirs) * 64 * 1024) | 1); 204 } 205 206 /* GTLB Control */ 207 temp = pci_conf_read(sc->as_pc, nsc->mc2_tag, AGP_NVIDIA_2_GARTCTRL); 208 pci_conf_write(sc->as_pc, nsc->mc2_tag, AGP_NVIDIA_2_GARTCTRL, temp | 0x11); 209 210 /* GART Control */ 211 temp = pci_conf_read(sc->as_pc, sc->as_tag, AGP_NVIDIA_0_APSIZE); 212 pci_conf_write(sc->as_pc, sc->as_tag, AGP_NVIDIA_0_APSIZE, temp | 0x100); 213 214 return 0; 215 } 216 217 static uint32_t 218 agp_nvidia_get_aperture(struct agp_softc *sc) 219 { 220 uint8_t apsize; 221 222 apsize = pci_conf_read(sc->as_pc, sc->as_tag, AGP_NVIDIA_0_APSIZE) 223 & AGP_NVIDIA_0_APSIZE_MASK; 224 switch (apsize) { 225 case 0: return (512 * 1024 * 1024); 226 case 8: return (256 * 1024 * 1024); 227 case 12: return (128 * 1024 * 1024); 228 case 14: return (64 * 1024 * 1024); 229 case 15: return (32 * 1024 * 1024); 230 default: 231 aprint_error_dev(sc->as_dev, "Invalid aperture setting 0x%x\n", 232 apsize); 233 return 0; 234 } 235 } 236 237 static int 238 agp_nvidia_set_aperture(struct agp_softc *sc, uint32_t aperture) 239 { 240 uint8_t apsize; 241 pcireg_t reg; 242 243 switch (aperture) { 244 case (512 * 1024 * 1024): apsize = 0; break; 245 case (256 * 1024 * 1024): apsize = 8; break; 246 case (128 * 1024 * 1024): apsize = 12; break; 247 case (64 * 1024 * 1024): apsize = 14; break; 248 case (32 * 1024 * 1024): apsize = 15; break; 249 default: 250 aprint_error_dev(sc->as_dev, "Invalid aperture size (%uMB)\n", 251 aperture / 1024 / 1024); 252 return EINVAL; 253 } 254 255 reg = pci_conf_read(sc->as_pc, sc->as_tag, AGP_NVIDIA_0_APSIZE); 256 reg = (reg & ~AGP_NVIDIA_0_APSIZE_MASK) | apsize; 257 pci_conf_write(sc->as_pc, sc->as_tag, AGP_NVIDIA_0_APSIZE, reg); 258 return 0; 259 } 260 261 static int 262 agp_nvidia_bind_page(struct agp_softc *sc, off_t offset, bus_addr_t physical) 263 { 264 struct agp_nvidia_softc *nsc = sc->as_chipc; 265 uint32_t index; 266 267 if (offset >= (nsc->gatt->ag_entries << AGP_PAGE_SHIFT)) 268 return EINVAL; 269 270 index = (nsc->pg_offset + offset) >> AGP_PAGE_SHIFT; 271 nsc->gatt->ag_virtual[index] = physical | 1; 272 273 return 0; 274 } 275 276 static int 277 agp_nvidia_unbind_page(struct agp_softc *sc, off_t offset) 278 { 279 struct agp_nvidia_softc *nsc = sc->as_chipc; 280 uint32_t index; 281 282 if (offset >= (nsc->gatt->ag_entries << AGP_PAGE_SHIFT)) 283 return EINVAL; 284 285 index = (nsc->pg_offset + offset) >> AGP_PAGE_SHIFT; 286 nsc->gatt->ag_virtual[index] = 0; 287 288 return 0; 289 } 290 291 static void 292 agp_nvidia_flush_tlb(struct agp_softc *sc) 293 { 294 struct agp_nvidia_softc *nsc = sc->as_chipc; 295 uint32_t wbc_reg; 296 volatile uint32_t *ag_virtual; 297 int i, pages; 298 299 if (nsc->wbc_mask) { 300 wbc_reg = pci_conf_read(sc->as_pc, nsc->mc1_tag, AGP_NVIDIA_1_WBC); 301 wbc_reg |= nsc->wbc_mask; 302 pci_conf_write(sc->as_pc, nsc->mc1_tag, AGP_NVIDIA_1_WBC, wbc_reg); 303 304 /* Wait no more than 3 seconds. */ 305 for (i = 0; i < 3000; i++) { 306 wbc_reg = pci_conf_read(sc->as_pc, nsc->mc1_tag, AGP_NVIDIA_1_WBC); 307 308 if ((nsc->wbc_mask & wbc_reg) == 0) 309 break; 310 311 DELAY(1000); 312 preempt_point(); 313 } 314 if (i == 3000) 315 aprint_debug_dev(sc->as_dev, "TLB flush took more than 3 seconds.\n"); 316 } 317 318 ag_virtual = (volatile uint32_t *)nsc->gatt->ag_virtual; 319 320 /* Flush TLB entries. */ 321 pages = nsc->gatt->ag_entries * sizeof(uint32_t) / PAGE_SIZE; 322 for (i = 0; i < pages; i++) 323 (void)ag_virtual[i * PAGE_SIZE / sizeof(uint32_t)]; 324 for (i = 0; i < pages; i++) 325 (void)ag_virtual[i * PAGE_SIZE / sizeof(uint32_t)]; 326 } 327 328 #if 0 329 static int 330 agp_nvidia_detach(struct agp_softc *sc) 331 { 332 int error; 333 uint32_t temp; 334 struct agp_nvidia_softc *nsc = sc->as_chipc; 335 336 error = agp_generic_detach(sc); 337 if (error) 338 return error; 339 340 /* GART Control */ 341 temp = pci_conf_read(sc->as_pc, sc->as_tag, AGP_NVIDIA_0_APSIZE); 342 pci_conf_write(sc->as_pc, sc->as_tag, AGP_NVIDIA_0_APSIZE, temp & ~(0x100)); 343 344 /* GTLB Control */ 345 temp = pci_conf_read(sc->as_pc, nsc->mc2_tag, AGP_NVIDIA_2_GARTCTRL); 346 pci_conf_write(sc->as_pc, nsc->mc2_tag, AGP_NVIDIA_2_GARTCTRL, temp & ~(0x11)); 347 348 /* Put the aperture back the way it started. */ 349 AGP_SET_APERTURE(sc, nsc->initial_aperture); 350 351 /* restore iorr for previous aperture size */ 352 nvidia_init_iorr(AGP_GET_APERTURE(sc), nsc->initial_aperture); 353 354 agp_free_gatt(sc, nsc->gatt); 355 356 return 0; 357 } 358 #endif 359 360 static int 361 nvidia_init_iorr(uint32_t addr, uint32_t size) 362 { 363 uint64_t base, mask, sys; 364 uint32_t iorr_addr, free_iorr_addr; 365 366 /* Find the iorr that is already used for the addr */ 367 /* If not found, determine the uppermost available iorr */ 368 free_iorr_addr = AMD_K7_NUM_IORR; 369 for (iorr_addr = 0; iorr_addr < AMD_K7_NUM_IORR; iorr_addr++) { 370 base = rdmsr(IORR_BASE0 + 2 * iorr_addr); 371 mask = rdmsr(IORR_MASK0 + 2 * iorr_addr); 372 373 if ((base & 0xfffff000ULL) == (addr & 0xfffff000)) 374 break; 375 376 if ((mask & 0x00000800ULL) == 0) 377 free_iorr_addr = iorr_addr; 378 } 379 380 if (iorr_addr >= AMD_K7_NUM_IORR) { 381 iorr_addr = free_iorr_addr; 382 if (iorr_addr >= AMD_K7_NUM_IORR) 383 return EINVAL; 384 } 385 386 base = (addr & ~0xfff) | 0x18; 387 mask = (0xfULL << 32) | rounddown2(0xfffff000, size) | 0x800; 388 wrmsr(IORR_BASE0 + 2 * iorr_addr, base); 389 wrmsr(IORR_MASK0 + 2 * iorr_addr, mask); 390 391 sys = rdmsr(SYSCFG); 392 sys |= 0x00100000ULL; 393 wrmsr(SYSCFG, sys); 394 395 return 0; 396 }