agp_via.c revision 153572
1238438Sdteske/*- 2238438Sdteske * Copyright (c) 2000 Doug Rabson 3249746Sdteske * All rights reserved. 4238438Sdteske * 5238438Sdteske * Redistribution and use in source and binary forms, with or without 6238438Sdteske * modification, are permitted provided that the following conditions 7238438Sdteske * are met: 8238438Sdteske * 1. Redistributions of source code must retain the above copyright 9238438Sdteske * notice, this list of conditions and the following disclaimer. 10238438Sdteske * 2. Redistributions in binary form must reproduce the above copyright 11238438Sdteske * notice, this list of conditions and the following disclaimer in the 12238438Sdteske * documentation and/or other materials provided with the distribution. 13238438Sdteske * 14238438Sdteske * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15238438Sdteske * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16238438Sdteske * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17238438Sdteske * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18238438Sdteske * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19238438Sdteske * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20238438Sdteske * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21238438Sdteske * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22238438Sdteske * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23238438Sdteske * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24238438Sdteske * SUCH DAMAGE. 25238438Sdteske */ 26238438Sdteske 27238438Sdteske#include <sys/cdefs.h> 28238438Sdteske__FBSDID("$FreeBSD: head/sys/dev/agp/agp_via.c 153572 2005-12-20 21:12:26Z jhb $"); 29238438Sdteske 30238438Sdteske#include "opt_bus.h" 31240684Sdteske 32240684Sdteske#include <sys/param.h> 33244675Sdteske#include <sys/systm.h> 34240684Sdteske#include <sys/malloc.h> 35240684Sdteske#include <sys/kernel.h> 36240684Sdteske#include <sys/module.h> 37240684Sdteske#include <sys/bus.h> 38238438Sdteske#include <sys/lock.h> 39240684Sdteske#include <sys/mutex.h> 40238438Sdteske#include <sys/proc.h> 41238438Sdteske 42243112Sdteske#include <dev/pci/pcivar.h> 43238438Sdteske#include <dev/pci/pcireg.h> 44238438Sdteske#include <pci/agppriv.h> 45238438Sdteske#include <pci/agpreg.h> 46238438Sdteske 47238438Sdteske#include <vm/vm.h> 48238438Sdteske#include <vm/vm_object.h> 49238438Sdteske#include <vm/pmap.h> 50238438Sdteske 51238438Sdteske#define REG_GARTCTRL 0 52238438Sdteske#define REG_APSIZE 1 53238438Sdteske#define REG_ATTBASE 2 54238438Sdteske 55238438Sdteskestruct agp_via_softc { 56238438Sdteske struct agp_softc agp; 57238438Sdteske u_int32_t initial_aperture; /* aperture size at startup */ 58240798Sdteske struct agp_gatt *gatt; 59238438Sdteske int *regs; 60238438Sdteske}; 61238438Sdteske 62238438Sdteskestatic int via_v2_regs[] = { AGP_VIA_GARTCTRL, AGP_VIA_APSIZE, 63238438Sdteske AGP_VIA_ATTBASE }; 64238438Sdteskestatic int via_v3_regs[] = { AGP3_VIA_GARTCTRL, AGP3_VIA_APSIZE, 65238438Sdteske AGP3_VIA_ATTBASE }; 66238438Sdteske 67238438Sdteskestatic const char* 68238438Sdteskeagp_via_match(device_t dev) 69238438Sdteske{ 70238438Sdteske if (pci_get_class(dev) != PCIC_BRIDGE 71238438Sdteske || pci_get_subclass(dev) != PCIS_BRIDGE_HOST) 72238438Sdteske return NULL; 73238438Sdteske 74238438Sdteske if (agp_find_caps(dev) == 0) 75238438Sdteske return NULL; 76238438Sdteske 77238438Sdteske switch (pci_get_devid(dev)) { 78238438Sdteske case 0x01981106: 79238438Sdteske return ("VIA 8763 (P4X600) host to PCI bridge"); 80238438Sdteske case 0x02591106: 81238438Sdteske return ("VIA PM800/PN800/PM880/PN880 host to PCI bridge"); 82238438Sdteske case 0x02691106: 83238438Sdteske return ("VIA KT880 host to PCI bridge"); 84238438Sdteske case 0x02961106: 85238438Sdteske return ("VIA 3296 (P4M800) host to PCI bridge"); 86238438Sdteske case 0x03051106: 87238438Sdteske return ("VIA 82C8363 (Apollo KT133x/KM133) host to PCI bridge"); 88238438Sdteske case 0x03911106: 89238438Sdteske return ("VIA 8371 (Apollo KX133) host to PCI bridge"); 90238438Sdteske case 0x05011106: 91238438Sdteske return ("VIA 8501 (Apollo MVP4) host to PCI bridge"); 92238438Sdteske case 0x05971106: 93238438Sdteske return ("VIA 82C597 (Apollo VP3) host to PCI bridge"); 94238438Sdteske case 0x05981106: 95238438Sdteske return ("VIA 82C598 (Apollo MVP3) host to PCI bridge"); 96238438Sdteske case 0x06011106: 97238438Sdteske return ("VIA 8601 (Apollo ProMedia/PLE133Ta) host to PCI bridge"); 98238438Sdteske case 0x06051106: 99238438Sdteske return ("VIA 82C694X (Apollo Pro 133A) host to PCI bridge"); 100238438Sdteske case 0x06911106: 101238438Sdteske return ("VIA 82C691 (Apollo Pro) host to PCI bridge"); 102238438Sdteske case 0x30911106: 103238438Sdteske return ("VIA 8633 (Pro 266) host to PCI bridge"); 104238438Sdteske case 0x30991106: 105238438Sdteske return ("VIA 8367 (KT266/KY266x/KT333) host to PCI bridge"); 106238438Sdteske case 0x31011106: 107238438Sdteske return ("VIA 8653 (Pro266T) host to PCI bridge"); 108238438Sdteske case 0x31121106: 109238438Sdteske return ("VIA 8361 (KLE133) host to PCI bridge"); 110238438Sdteske case 0x31161106: 111238438Sdteske return ("VIA XM266 (PM266/KM266) host to PCI bridge"); 112238438Sdteske case 0x31231106: 113238438Sdteske return ("VIA 862x (CLE266) host to PCI bridge"); 114238438Sdteske case 0x31281106: 115238438Sdteske return ("VIA 8753 (P4X266) host to PCI bridge"); 116240783Sdteske case 0x31481106: 117240783Sdteske return ("VIA 8703 (P4M266x/P4N266) host to PCI bridge"); 118238438Sdteske case 0x31561106: 119238438Sdteske return ("VIA XN266 (Apollo Pro266) host to PCI bridge"); 120238438Sdteske case 0x31681106: 121238438Sdteske return ("VIA 8754 (PT800) host to PCI bridge"); 122238438Sdteske case 0x31891106: 123238438Sdteske return ("VIA 8377 (Apollo KT400/KT400A/KT600) host to PCI bridge"); 124238438Sdteske case 0x32051106: 125238438Sdteske return ("VIA 8235/8237 (Apollo KM400/KM400A) host to PCI bridge"); 126238438Sdteske case 0x32081106: 127238438Sdteske return ("VIA 8783 (PT890) host to PCI bridge"); 128238438Sdteske case 0x32581106: 129238438Sdteske return ("VIA PT880 host to PCI bridge"); 130238438Sdteske case 0xb1981106: 131238438Sdteske return ("VIA VT83xx/VT87xx/KTxxx/Px8xx host to PCI bridge"); 132238438Sdteske }; 133238438Sdteske 134238438Sdteske return NULL; 135238438Sdteske} 136238438Sdteske 137238438Sdteskestatic int 138238438Sdteskeagp_via_probe(device_t dev) 139238438Sdteske{ 140238438Sdteske const char *desc; 141238438Sdteske 142238438Sdteske if (resource_disabled("agp", device_get_unit(dev))) 143238438Sdteske return (ENXIO); 144238438Sdteske desc = agp_via_match(dev); 145238438Sdteske if (desc) { 146238438Sdteske device_set_desc(dev, desc); 147238438Sdteske return BUS_PROBE_DEFAULT; 148238438Sdteske } 149238438Sdteske 150238438Sdteske return ENXIO; 151238438Sdteske} 152238438Sdteske 153238438Sdteskestatic int 154238438Sdteskeagp_via_attach(device_t dev) 155238438Sdteske{ 156238438Sdteske struct agp_via_softc *sc = device_get_softc(dev); 157238438Sdteske struct agp_gatt *gatt; 158238438Sdteske int error; 159238438Sdteske u_int32_t agpsel; 160238438Sdteske 161238438Sdteske /* XXX: This should be keying off of whether the bridge is AGP3 capable, 162238438Sdteske * rather than a bunch of device ids for chipsets that happen to do 8x. 163238438Sdteske */ 164238438Sdteske switch (pci_get_devid(dev)) { 165238438Sdteske case 0x01981106: 166238438Sdteske case 0x02591106: 167238438Sdteske case 0x02691106: 168238438Sdteske case 0x02961106: 169238438Sdteske case 0x31231106: 170238438Sdteske case 0x31681106: 171238438Sdteske case 0x31891106: 172238438Sdteske case 0x32051106: 173238438Sdteske case 0x32581106: 174238438Sdteske case 0xb1981106: 175238438Sdteske /* The newer VIA chipsets will select the AGP version based on 176238438Sdteske * what AGP versions the card supports. We still have to 177238438Sdteske * program it using the v2 registers if it has chosen to use 178238438Sdteske * compatibility mode. 179240768Sdteske */ 180240768Sdteske agpsel = pci_read_config(dev, AGP_VIA_AGPSEL, 1); 181238438Sdteske if ((agpsel & (1 << 1)) == 0) 182238438Sdteske sc->regs = via_v3_regs; 183238438Sdteske else 184238438Sdteske sc->regs = via_v2_regs; 185238438Sdteske break; 186238438Sdteske default: 187238438Sdteske sc->regs = via_v2_regs; 188238438Sdteske break; 189238438Sdteske } 190238438Sdteske 191240768Sdteske error = agp_generic_attach(dev); 192240768Sdteske if (error) 193240768Sdteske return error; 194240768Sdteske 195240768Sdteske sc->initial_aperture = AGP_GET_APERTURE(dev); 196238438Sdteske 197238438Sdteske for (;;) { 198238438Sdteske gatt = agp_alloc_gatt(dev); 199238438Sdteske if (gatt) 200238438Sdteske break; 201238438Sdteske 202238438Sdteske /* 203238438Sdteske * Probably contigmalloc failure. Try reducing the 204238438Sdteske * aperture so that the gatt size reduces. 205238438Sdteske */ 206238438Sdteske if (AGP_SET_APERTURE(dev, AGP_GET_APERTURE(dev) / 2)) { 207238438Sdteske agp_generic_detach(dev); 208238438Sdteske return ENOMEM; 209238438Sdteske } 210238438Sdteske } 211238438Sdteske sc->gatt = gatt; 212238438Sdteske 213245402Sdteske if (sc->regs == via_v2_regs) { 214238438Sdteske /* Install the gatt. */ 215238438Sdteske pci_write_config(dev, sc->regs[REG_ATTBASE], gatt->ag_physical | 3, 4); 216238438Sdteske 217238438Sdteske /* Enable the aperture. */ 218238438Sdteske pci_write_config(dev, sc->regs[REG_GARTCTRL], 0x0f, 4); 219238438Sdteske } else { 220238438Sdteske u_int32_t gartctrl; 221238438Sdteske 222238438Sdteske /* Install the gatt. */ 223238438Sdteske pci_write_config(dev, sc->regs[REG_ATTBASE], gatt->ag_physical, 4); 224238438Sdteske 225238438Sdteske /* Enable the aperture. */ 226238438Sdteske gartctrl = pci_read_config(dev, sc->regs[REG_ATTBASE], 4); 227238438Sdteske pci_write_config(dev, sc->regs[REG_GARTCTRL], gartctrl | (3 << 7), 4); 228238438Sdteske } 229238438Sdteske 230238438Sdteske return 0; 231238438Sdteske} 232238438Sdteske 233238438Sdteskestatic int 234238438Sdteskeagp_via_detach(device_t dev) 235238438Sdteske{ 236238438Sdteske struct agp_via_softc *sc = device_get_softc(dev); 237238438Sdteske int error; 238238438Sdteske 239238438Sdteske error = agp_generic_detach(dev); 240238438Sdteske if (error) 241238438Sdteske return error; 242238438Sdteske 243238438Sdteske pci_write_config(dev, sc->regs[REG_GARTCTRL], 0, 4); 244238438Sdteske pci_write_config(dev, sc->regs[REG_ATTBASE], 0, 4); 245238438Sdteske AGP_SET_APERTURE(dev, sc->initial_aperture); 246238438Sdteske agp_free_gatt(sc->gatt); 247240768Sdteske 248240768Sdteske return 0; 249238438Sdteske} 250238438Sdteske 251238438Sdteskestatic u_int32_t 252238438Sdteskeagp_via_get_aperture(device_t dev) 253238438Sdteske{ 254238438Sdteske struct agp_via_softc *sc = device_get_softc(dev); 255238438Sdteske u_int32_t apsize; 256238438Sdteske 257240768Sdteske apsize = pci_read_config(dev, sc->regs[REG_APSIZE], 1) & 0x1f; 258240768Sdteske 259240768Sdteske /* 260240768Sdteske * The size is determined by the number of low bits of 261240768Sdteske * register APBASE which are forced to zero. The low 20 bits 262238438Sdteske * are always forced to zero and each zero bit in the apsize 263238438Sdteske * field just read forces the corresponding bit in the 27:20 264238438Sdteske * to be zero. We calculate the aperture size accordingly. 265238438Sdteske */ 266238438Sdteske return (((apsize ^ 0xff) << 20) | ((1 << 20) - 1)) + 1; 267238438Sdteske} 268238438Sdteske 269238438Sdteskestatic int 270238438Sdteskeagp_via_set_aperture(device_t dev, u_int32_t aperture) 271238438Sdteske{ 272249746Sdteske struct agp_via_softc *sc = device_get_softc(dev); 273238438Sdteske u_int32_t apsize; 274238438Sdteske 275238438Sdteske /* 276238438Sdteske * Reverse the magic from get_aperture. 277238438Sdteske */ 278238438Sdteske apsize = ((aperture - 1) >> 20) ^ 0xff; 279238438Sdteske 280238438Sdteske /* 281238438Sdteske * Double check for sanity. 282238438Sdteske */ 283238438Sdteske if ((((apsize ^ 0xff) << 20) | ((1 << 20) - 1)) + 1 != aperture) 284238438Sdteske return EINVAL; 285238438Sdteske 286238438Sdteske pci_write_config(dev, sc->regs[REG_APSIZE], apsize, 1); 287238438Sdteske 288238438Sdteske return 0; 289238438Sdteske} 290238438Sdteske 291238438Sdteskestatic int 292238438Sdteskeagp_via_bind_page(device_t dev, int offset, vm_offset_t physical) 293238438Sdteske{ 294238438Sdteske struct agp_via_softc *sc = device_get_softc(dev); 295238438Sdteske 296238438Sdteske if (offset < 0 || offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT)) 297238438Sdteske return EINVAL; 298238438Sdteske 299238438Sdteske sc->gatt->ag_virtual[offset >> AGP_PAGE_SHIFT] = physical; 300238438Sdteske return 0; 301238438Sdteske} 302238438Sdteske 303238438Sdteskestatic int 304238438Sdteskeagp_via_unbind_page(device_t dev, int offset) 305238438Sdteske{ 306238438Sdteske struct agp_via_softc *sc = device_get_softc(dev); 307238438Sdteske 308238438Sdteske if (offset < 0 || offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT)) 309238438Sdteske return EINVAL; 310238438Sdteske 311238438Sdteske sc->gatt->ag_virtual[offset >> AGP_PAGE_SHIFT] = 0; 312238438Sdteske return 0; 313238438Sdteske} 314238438Sdteske 315238438Sdteskestatic void 316238438Sdteskeagp_via_flush_tlb(device_t dev) 317238438Sdteske{ 318238438Sdteske struct agp_via_softc *sc = device_get_softc(dev); 319238438Sdteske u_int32_t gartctrl; 320238438Sdteske 321245437Sdteske if (sc->regs == via_v2_regs) { 322238438Sdteske pci_write_config(dev, sc->regs[REG_GARTCTRL], 0x8f, 4); 323238438Sdteske pci_write_config(dev, sc->regs[REG_GARTCTRL], 0x0f, 4); 324238438Sdteske } else { 325238438Sdteske gartctrl = pci_read_config(dev, sc->regs[REG_GARTCTRL], 4); 326238438Sdteske pci_write_config(dev, sc->regs[REG_GARTCTRL], gartctrl & 327238438Sdteske ~(1 << 7), 4); 328238438Sdteske pci_write_config(dev, sc->regs[REG_GARTCTRL], gartctrl, 4); 329238438Sdteske } 330238438Sdteske 331238438Sdteske} 332238438Sdteske 333238438Sdteskestatic device_method_t agp_via_methods[] = { 334238438Sdteske /* Device interface */ 335238438Sdteske DEVMETHOD(device_probe, agp_via_probe), 336238438Sdteske DEVMETHOD(device_attach, agp_via_attach), 337238438Sdteske DEVMETHOD(device_detach, agp_via_detach), 338238438Sdteske DEVMETHOD(device_shutdown, bus_generic_shutdown), 339238438Sdteske DEVMETHOD(device_suspend, bus_generic_suspend), 340238438Sdteske DEVMETHOD(device_resume, bus_generic_resume), 341238438Sdteske 342238438Sdteske /* AGP interface */ 343238438Sdteske DEVMETHOD(agp_get_aperture, agp_via_get_aperture), 344238438Sdteske DEVMETHOD(agp_set_aperture, agp_via_set_aperture), 345238438Sdteske DEVMETHOD(agp_bind_page, agp_via_bind_page), 346238438Sdteske DEVMETHOD(agp_unbind_page, agp_via_unbind_page), 347238438Sdteske DEVMETHOD(agp_flush_tlb, agp_via_flush_tlb), 348238438Sdteske DEVMETHOD(agp_enable, agp_generic_enable), 349240798Sdteske DEVMETHOD(agp_alloc_memory, agp_generic_alloc_memory), 350238438Sdteske DEVMETHOD(agp_free_memory, agp_generic_free_memory), 351238438Sdteske DEVMETHOD(agp_bind_memory, agp_generic_bind_memory), 352238438Sdteske DEVMETHOD(agp_unbind_memory, agp_generic_unbind_memory), 353238438Sdteske 354238438Sdteske { 0, 0 } 355238438Sdteske}; 356238438Sdteske 357238438Sdteskestatic driver_t agp_via_driver = { 358238438Sdteske "agp", 359238438Sdteske agp_via_methods, 360238438Sdteske sizeof(struct agp_via_softc), 361238438Sdteske}; 362238438Sdteske 363238438Sdteskestatic devclass_t agp_devclass; 364 365DRIVER_MODULE(agp_via, hostb, agp_via_driver, agp_devclass, 0, 0); 366MODULE_DEPEND(agp_via, agp, 1, 1, 1); 367MODULE_DEPEND(agp_via, pci, 1, 1, 1); 368