agp_ali.c revision 119288
1285809Sscottl/*- 2285809Sscottl * Copyright (c) 2000 Doug Rabson 3285809Sscottl * All rights reserved. 4285809Sscottl * 5285809Sscottl * Redistribution and use in source and binary forms, with or without 6285809Sscottl * modification, are permitted provided that the following conditions 7285809Sscottl * are met: 8285809Sscottl * 1. Redistributions of source code must retain the above copyright 9285809Sscottl * notice, this list of conditions and the following disclaimer. 10285809Sscottl * 2. Redistributions in binary form must reproduce the above copyright 11285809Sscottl * notice, this list of conditions and the following disclaimer in the 12285809Sscottl * documentation and/or other materials provided with the distribution. 13285809Sscottl * 14285809Sscottl * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15285809Sscottl * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16285809Sscottl * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17285809Sscottl * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18285809Sscottl * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19285809Sscottl * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20285809Sscottl * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21285809Sscottl * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22285809Sscottl * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23285809Sscottl * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24285809Sscottl * SUCH DAMAGE. 25285809Sscottl */ 26285809Sscottl 27285809Sscottl#include <sys/cdefs.h> 28285809Sscottl__FBSDID("$FreeBSD: head/sys/dev/agp/agp_ali.c 119288 2003-08-22 07:20:27Z imp $"); 29285809Sscottl 30285809Sscottl#include "opt_bus.h" 31285809Sscottl 32285809Sscottl#include <sys/param.h> 33285809Sscottl#include <sys/systm.h> 34285809Sscottl#include <sys/malloc.h> 35285809Sscottl#include <sys/kernel.h> 36285809Sscottl#include <sys/bus.h> 37285809Sscottl#include <sys/lock.h> 38285809Sscottl#include <sys/lockmgr.h> 39285809Sscottl#include <sys/mutex.h> 40285809Sscottl#include <sys/proc.h> 41285809Sscottl 42285809Sscottl#include <dev/pci/pcivar.h> 43285809Sscottl#include <dev/pci/pcireg.h> 44285809Sscottl#include <pci/agppriv.h> 45285809Sscottl#include <pci/agpreg.h> 46285809Sscottl 47285809Sscottl#include <vm/vm.h> 48285809Sscottl#include <vm/vm_object.h> 49285809Sscottl#include <vm/pmap.h> 50285809Sscottl 51285809Sscottlstruct agp_ali_softc { 52285809Sscottl struct agp_softc agp; 53285809Sscottl u_int32_t initial_aperture; /* aperture size at startup */ 54285809Sscottl struct agp_gatt *gatt; 55285809Sscottl}; 56285809Sscottl 57285809Sscottlstatic const char* 58285809Sscottlagp_ali_match(device_t dev) 59285809Sscottl{ 60285809Sscottl if (pci_get_class(dev) != PCIC_BRIDGE 61285809Sscottl || pci_get_subclass(dev) != PCIS_BRIDGE_HOST) 62285809Sscottl return NULL; 63285809Sscottl 64285809Sscottl if (agp_find_caps(dev) == 0) 65285809Sscottl return NULL; 66285809Sscottl 67285809Sscottl switch (pci_get_devid(dev)) { 68285809Sscottl case 0x154110b9: 69285809Sscottl return ("Ali M1541 host to AGP bridge"); 70285809Sscottl }; 71285809Sscottl 72285809Sscottl if (pci_get_vendor(dev) == 0x10b9) 73285809Sscottl return ("Ali Generic host to PCI bridge"); 74285809Sscottl 75285809Sscottl return NULL; 76285809Sscottl} 77285809Sscottl 78285809Sscottlstatic int 79285809Sscottlagp_ali_probe(device_t dev) 80285809Sscottl{ 81285809Sscottl const char *desc; 82285809Sscottl 83285809Sscottl desc = agp_ali_match(dev); 84285809Sscottl if (desc) { 85285809Sscottl device_verbose(dev); 86285809Sscottl device_set_desc(dev, desc); 87285809Sscottl return 0; 88285809Sscottl } 89285809Sscottl 90285809Sscottl return ENXIO; 91285809Sscottl} 92285809Sscottl 93285809Sscottlstatic int 94285809Sscottlagp_ali_attach(device_t dev) 95285809Sscottl{ 96285809Sscottl struct agp_ali_softc *sc = device_get_softc(dev); 97285809Sscottl struct agp_gatt *gatt; 98285809Sscottl int error; 99285809Sscottl 100285809Sscottl error = agp_generic_attach(dev); 101285809Sscottl if (error) 102285809Sscottl return error; 103285809Sscottl 104285809Sscottl sc->initial_aperture = AGP_GET_APERTURE(dev); 105285809Sscottl 106285809Sscottl for (;;) { 107285809Sscottl gatt = agp_alloc_gatt(dev); 108285809Sscottl if (gatt) 109285809Sscottl break; 110285809Sscottl 111285809Sscottl /* 112285809Sscottl * Probably contigmalloc failure. Try reducing the 113285809Sscottl * aperture so that the gatt size reduces. 114285809Sscottl */ 115285809Sscottl if (AGP_SET_APERTURE(dev, AGP_GET_APERTURE(dev) / 2)) { 116285809Sscottl agp_generic_detach(dev); 117285809Sscottl return ENOMEM; 118285809Sscottl } 119285809Sscottl } 120285809Sscottl sc->gatt = gatt; 121285809Sscottl 122285809Sscottl /* Install the gatt. */ 123285809Sscottl pci_write_config(dev, AGP_ALI_ATTBASE, 124285809Sscottl (gatt->ag_physical 125285809Sscottl | (pci_read_config(dev, AGP_ALI_ATTBASE, 4) & 0xff)), 126285809Sscottl 4); 127285809Sscottl 128285809Sscottl /* Enable the TLB. */ 129285809Sscottl pci_write_config(dev, AGP_ALI_TLBCTRL, 0x10, 1); 130285809Sscottl 131285809Sscottl return 0; 132285809Sscottl} 133285809Sscottl 134285809Sscottlstatic int 135285809Sscottlagp_ali_detach(device_t dev) 136285809Sscottl{ 137285809Sscottl struct agp_ali_softc *sc = device_get_softc(dev); 138285809Sscottl int error; 139285809Sscottl 140285809Sscottl error = agp_generic_detach(dev); 141285809Sscottl if (error) 142285809Sscottl return error; 143285809Sscottl 144285809Sscottl /* Disable the TLB.. */ 145285809Sscottl pci_write_config(dev, AGP_ALI_TLBCTRL, 0x90, 1); 146285809Sscottl 147285809Sscottl /* Put the aperture back the way it started. */ 148285809Sscottl AGP_SET_APERTURE(dev, sc->initial_aperture); 149285809Sscottl pci_write_config(dev, AGP_ALI_ATTBASE, 150285809Sscottl pci_read_config(dev, AGP_ALI_ATTBASE, 4) & 0xff, 151285809Sscottl 4); 152285809Sscottl 153285809Sscottl agp_free_gatt(sc->gatt); 154285809Sscottl return 0; 155285809Sscottl} 156285809Sscottl 157285809Sscottl#define M 1024*1024 158285809Sscottl 159285809Sscottlstatic u_int32_t agp_ali_table[] = { 160285809Sscottl 0, /* 0 - invalid */ 161285809Sscottl 1, /* 1 - invalid */ 162285809Sscottl 2, /* 2 - invalid */ 163285809Sscottl 4*M, /* 3 - invalid */ 164285809Sscottl 8*M, /* 4 - invalid */ 165285809Sscottl 0, /* 5 - invalid */ 166285809Sscottl 16*M, /* 6 - invalid */ 167285809Sscottl 32*M, /* 7 - invalid */ 168285809Sscottl 64*M, /* 8 - invalid */ 169285809Sscottl 128*M, /* 9 - invalid */ 170285809Sscottl 256*M, /* 10 - invalid */ 171285809Sscottl}; 172285809Sscottl#define agp_ali_table_size (sizeof(agp_ali_table) / sizeof(agp_ali_table[0])) 173285809Sscottl 174285809Sscottlstatic u_int32_t 175285809Sscottlagp_ali_get_aperture(device_t dev) 176285809Sscottl{ 177285809Sscottl /* 178285809Sscottl * The aperture size is derived from the low bits of attbase. 179285809Sscottl * I'm not sure this is correct.. 180285809Sscottl */ 181285809Sscottl int i = pci_read_config(dev, AGP_ALI_ATTBASE, 4) & 0xff; 182285809Sscottl if (i >= agp_ali_table_size) 183285809Sscottl return 0; 184285809Sscottl return agp_ali_table[i]; 185285809Sscottl} 186285809Sscottl 187285809Sscottlstatic int 188285809Sscottlagp_ali_set_aperture(device_t dev, u_int32_t aperture) 189285809Sscottl{ 190285809Sscottl int i; 191285809Sscottl 192285809Sscottl for (i = 0; i < agp_ali_table_size; i++) 193285809Sscottl if (agp_ali_table[i] == aperture) 194285809Sscottl break; 195285809Sscottl if (i == agp_ali_table_size) 196285809Sscottl return EINVAL; 197285809Sscottl 198285809Sscottl pci_write_config(dev, AGP_ALI_ATTBASE, 199285809Sscottl ((pci_read_config(dev, AGP_ALI_ATTBASE, 4) & ~0xff) 200285809Sscottl | i), 4); 201285809Sscottl return 0; 202285809Sscottl} 203285809Sscottl 204285809Sscottlstatic int 205285809Sscottlagp_ali_bind_page(device_t dev, int offset, vm_offset_t physical) 206285809Sscottl{ 207285809Sscottl struct agp_ali_softc *sc = device_get_softc(dev); 208285809Sscottl 209285809Sscottl if (offset < 0 || offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT)) 210285809Sscottl return EINVAL; 211285809Sscottl 212285809Sscottl sc->gatt->ag_virtual[offset >> AGP_PAGE_SHIFT] = physical; 213285809Sscottl return 0; 214285809Sscottl} 215285809Sscottl 216285809Sscottlstatic int 217285809Sscottlagp_ali_unbind_page(device_t dev, int offset) 218285809Sscottl{ 219285809Sscottl struct agp_ali_softc *sc = device_get_softc(dev); 220285809Sscottl 221285809Sscottl if (offset < 0 || offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT)) 222285809Sscottl return EINVAL; 223285809Sscottl 224285809Sscottl sc->gatt->ag_virtual[offset >> AGP_PAGE_SHIFT] = 0; 225285809Sscottl return 0; 226285809Sscottl} 227285809Sscottl 228285809Sscottlstatic void 229285809Sscottlagp_ali_flush_tlb(device_t dev) 230285809Sscottl{ 231285809Sscottl pci_write_config(dev, AGP_ALI_TLBCTRL, 0x90, 1); 232285809Sscottl pci_write_config(dev, AGP_ALI_TLBCTRL, 0x10, 1); 233285809Sscottl} 234285809Sscottl 235285809Sscottlstatic device_method_t agp_ali_methods[] = { 236285809Sscottl /* Device interface */ 237285809Sscottl DEVMETHOD(device_probe, agp_ali_probe), 238285809Sscottl DEVMETHOD(device_attach, agp_ali_attach), 239285809Sscottl DEVMETHOD(device_detach, agp_ali_detach), 240285809Sscottl DEVMETHOD(device_shutdown, bus_generic_shutdown), 241285809Sscottl DEVMETHOD(device_suspend, bus_generic_suspend), 242285809Sscottl DEVMETHOD(device_resume, bus_generic_resume), 243285809Sscottl 244285809Sscottl /* AGP interface */ 245285809Sscottl DEVMETHOD(agp_get_aperture, agp_ali_get_aperture), 246285809Sscottl DEVMETHOD(agp_set_aperture, agp_ali_set_aperture), 247285809Sscottl DEVMETHOD(agp_bind_page, agp_ali_bind_page), 248285809Sscottl DEVMETHOD(agp_unbind_page, agp_ali_unbind_page), 249285809Sscottl DEVMETHOD(agp_flush_tlb, agp_ali_flush_tlb), 250285809Sscottl DEVMETHOD(agp_enable, agp_generic_enable), 251285809Sscottl DEVMETHOD(agp_alloc_memory, agp_generic_alloc_memory), 252285809Sscottl DEVMETHOD(agp_free_memory, agp_generic_free_memory), 253285809Sscottl DEVMETHOD(agp_bind_memory, agp_generic_bind_memory), 254285809Sscottl DEVMETHOD(agp_unbind_memory, agp_generic_unbind_memory), 255285809Sscottl 256285809Sscottl { 0, 0 } 257285809Sscottl}; 258285809Sscottl 259285809Sscottlstatic driver_t agp_ali_driver = { 260285809Sscottl "agp", 261285809Sscottl agp_ali_methods, 262285809Sscottl sizeof(struct agp_ali_softc), 263285809Sscottl}; 264285809Sscottl 265285809Sscottlstatic devclass_t agp_devclass; 266285809Sscottl 267285809SscottlDRIVER_MODULE(agp_ali, pci, agp_ali_driver, agp_devclass, 0, 0); 268285809SscottlMODULE_DEPEND(agp_ali, agp, 1, 1, 1); 269285809SscottlMODULE_DEPEND(agp_ali, pci, 1, 1, 1); 270285809Sscottl