File:  [DragonFly] / src / sys / dev / agp / agp_sis.c
Revision 1.4: download - view: text, annotated - select for diffs
Tue Dec 9 19:40:56 2003 UTC (11 years ago) by dillon
Branches: MAIN
CVS tags: HEAD, DragonFly_1_0_RC1
This patch adds a bunch of stuff from FreeBSD5.  It consistantly makes
vendor specific drivers depend on agp, consistantly checks the gart size
!= 0, changes agp_generic_enable to the FreeBSD5 function, initializing
the device as v2 or v3 accordingly, syncs up agpio.h, and adds a couple
PCI Ids from FreeBSD5.

Submitted-by: Craig Dooley <cd5697@albany.edu>

    1: /*-
    2:  * Copyright (c) 2000 Doug Rabson
    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:  *
   26:  *	$FreeBSD: src/sys/pci/agp_sis.c,v 1.1.2.1 2000/07/19 09:48:04 ru Exp $
   27:  *	$DragonFly: src/sys/dev/agp/agp_sis.c,v 1.4 2003/12/09 19:40:56 dillon Exp $
   28:  */
   29: 
   30: #include "opt_bus.h"
   31: #include "opt_pci.h"
   32: 
   33: #include <sys/param.h>
   34: #include <sys/systm.h>
   35: #include <sys/malloc.h>
   36: #include <sys/kernel.h>
   37: #include <sys/bus.h>
   38: #include <sys/lock.h>
   39: 
   40: #include <bus/pci/pcivar.h>
   41: #include <bus/pci/pcireg.h>
   42: #include "agppriv.h"
   43: #include "agpreg.h"
   44: 
   45: #include <vm/vm.h>
   46: #include <vm/vm_object.h>
   47: #include <vm/pmap.h>
   48: 
   49: struct agp_sis_softc {
   50: 	struct agp_softc agp;
   51: 	u_int32_t	initial_aperture; /* aperture size at startup */
   52: 	struct agp_gatt *gatt;
   53: };
   54: 
   55: static const char*
   56: agp_sis_match(device_t dev)
   57: {
   58: 	if (pci_get_class(dev) != PCIC_BRIDGE
   59: 	    || pci_get_subclass(dev) != PCIS_BRIDGE_HOST)
   60: 		return NULL;
   61: 
   62: 	if (agp_find_caps(dev) == 0)
   63: 		return NULL;
   64: 
   65: 	switch (pci_get_devid(dev)) {
   66: 	case 0x00011039:
   67: 		return ("SiS 5591 host to AGP bridge");
   68: 	case 0x06481039:
   69: 		return ("SiS 648 host to AGP bridge");
   70: 	};
   71: 
   72: 	if (pci_get_vendor(dev) == 0x1039)
   73: 		return ("SIS Generic host to PCI bridge");
   74: 
   75: 	return NULL;
   76: }
   77: 
   78: static int
   79: agp_sis_probe(device_t dev)
   80: {
   81: 	const char *desc;
   82: 
   83: 	desc = agp_sis_match(dev);
   84: 	if (desc) {
   85: 		device_verbose(dev);
   86: 		device_set_desc(dev, desc);
   87: 		return 0;
   88: 	}
   89: 
   90: 	return ENXIO;
   91: }
   92: 
   93: static int
   94: agp_sis_attach(device_t dev)
   95: {
   96: 	struct agp_sis_softc *sc = device_get_softc(dev);
   97: 	struct agp_gatt *gatt;
   98: 	int error;
   99: 
  100: 	error = agp_generic_attach(dev);
  101: 	if (error)
  102: 		return error;
  103: 
  104: 	sc->initial_aperture = AGP_GET_APERTURE(dev);
  105: 	if (sc->initial_aperture == 0) {
  106: 		device_printf(dev, "bad initial aperture size, disabling\n");
  107: 		return ENXIO;
  108: 	}
  109: 
  110: 	for (;;) {
  111: 		gatt = agp_alloc_gatt(dev);
  112: 		if (gatt)
  113: 			break;
  114: 
  115: 		/*
  116: 		 * Probably contigmalloc failure. Try reducing the
  117: 		 * aperture so that the gatt size reduces.
  118: 		 */
  119: 		if (AGP_SET_APERTURE(dev, AGP_GET_APERTURE(dev) / 2)) {
  120: 			agp_generic_detach(dev);
  121: 			return ENOMEM;
  122: 		}
  123: 	}
  124: 	sc->gatt = gatt;
  125: 
  126: 	/* Install the gatt. */
  127: 	pci_write_config(dev, AGP_SIS_ATTBASE, gatt->ag_physical, 4);
  128: 	
  129: 	/* Enable the aperture. */
  130: 	pci_write_config(dev, AGP_SIS_WINCTRL,
  131: 			 pci_read_config(dev, AGP_SIS_WINCTRL, 1) | 3, 1);
  132: 
  133: 	/*
  134: 	 * Enable the TLB and make it automatically invalidate entries
  135: 	 * when the GATT is written.
  136: 	 */
  137: 	pci_write_config(dev, AGP_SIS_TLBCTRL, 0x05, 1);
  138: 
  139: 	return 0;
  140: }
  141: 
  142: static int
  143: agp_sis_detach(device_t dev)
  144: {
  145: 	struct agp_sis_softc *sc = device_get_softc(dev);
  146: 	int error;
  147: 
  148: 	error = agp_generic_detach(dev);
  149: 	if (error)
  150: 		return error;
  151: 
  152: 	/* Disable the aperture.. */
  153: 	pci_write_config(dev, AGP_SIS_WINCTRL,
  154: 			 pci_read_config(dev, AGP_SIS_WINCTRL, 1) & ~3, 1);
  155: 
  156: 	/* and the TLB. */
  157: 	pci_write_config(dev, AGP_SIS_TLBCTRL, 0, 1);
  158: 
  159: 	/* Put the aperture back the way it started. */
  160: 	AGP_SET_APERTURE(dev, sc->initial_aperture);
  161: 
  162: 	agp_free_gatt(sc->gatt);
  163: 	return 0;
  164: }
  165: 
  166: static u_int32_t
  167: agp_sis_get_aperture(device_t dev)
  168: {
  169: 	int gws;
  170: 
  171: 	/*
  172: 	 * The aperture size is equal to 4M<<gws.
  173: 	 */
  174: 	gws = (pci_read_config(dev, AGP_SIS_WINCTRL, 1) & 0x70) >> 4;
  175: 	return (4*1024*1024) << gws;
  176: }
  177: 
  178: static int
  179: agp_sis_set_aperture(device_t dev, u_int32_t aperture)
  180: {
  181: 	int gws;
  182: 
  183: 	/*
  184: 	 * Check for a power of two and make sure its within the
  185: 	 * programmable range.
  186: 	 */
  187: 	if (aperture & (aperture - 1)
  188: 	    || aperture < 4*1024*1024
  189: 	    || aperture > 256*1024*1024)
  190: 		return EINVAL;
  191: 
  192: 	gws = ffs(aperture / 4*1024*1024) - 1;
  193: 	
  194: 	pci_write_config(dev, AGP_SIS_WINCTRL,
  195: 			 ((pci_read_config(dev, AGP_SIS_WINCTRL, 1) & ~0x70)
  196: 			  | gws << 4), 1);
  197: 
  198: 	return 0;
  199: }
  200: 
  201: static int
  202: agp_sis_bind_page(device_t dev, int offset, vm_offset_t physical)
  203: {
  204: 	struct agp_sis_softc *sc = device_get_softc(dev);
  205: 
  206: 	if (offset < 0 || offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT))
  207: 		return EINVAL;
  208: 
  209: 	sc->gatt->ag_virtual[offset >> AGP_PAGE_SHIFT] = physical;
  210: 	return 0;
  211: }
  212: 
  213: static int
  214: agp_sis_unbind_page(device_t dev, int offset)
  215: {
  216: 	struct agp_sis_softc *sc = device_get_softc(dev);
  217: 
  218: 	if (offset < 0 || offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT))
  219: 		return EINVAL;
  220: 
  221: 	sc->gatt->ag_virtual[offset >> AGP_PAGE_SHIFT] = 0;
  222: 	return 0;
  223: }
  224: 
  225: static void
  226: agp_sis_flush_tlb(device_t dev)
  227: {
  228: 	pci_write_config(dev, AGP_SIS_TLBFLUSH, 0x02, 1);
  229: }
  230: 
  231: static device_method_t agp_sis_methods[] = {
  232: 	/* Device interface */
  233: 	DEVMETHOD(device_probe,		agp_sis_probe),
  234: 	DEVMETHOD(device_attach,	agp_sis_attach),
  235: 	DEVMETHOD(device_detach,	agp_sis_detach),
  236: 	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
  237: 	DEVMETHOD(device_suspend,	bus_generic_suspend),
  238: 	DEVMETHOD(device_resume,	bus_generic_resume),
  239: 
  240: 	/* AGP interface */
  241: 	DEVMETHOD(agp_get_aperture,	agp_sis_get_aperture),
  242: 	DEVMETHOD(agp_set_aperture,	agp_sis_set_aperture),
  243: 	DEVMETHOD(agp_bind_page,	agp_sis_bind_page),
  244: 	DEVMETHOD(agp_unbind_page,	agp_sis_unbind_page),
  245: 	DEVMETHOD(agp_flush_tlb,	agp_sis_flush_tlb),
  246: 	DEVMETHOD(agp_enable,		agp_generic_enable),
  247: 	DEVMETHOD(agp_alloc_memory,	agp_generic_alloc_memory),
  248: 	DEVMETHOD(agp_free_memory,	agp_generic_free_memory),
  249: 	DEVMETHOD(agp_bind_memory,	agp_generic_bind_memory),
  250: 	DEVMETHOD(agp_unbind_memory,	agp_generic_unbind_memory),
  251: 
  252: 	{ 0, 0 }
  253: };
  254: 
  255: static driver_t agp_sis_driver = {
  256: 	"agp",
  257: 	agp_sis_methods,
  258: 	sizeof(struct agp_sis_softc),
  259: };
  260: 
  261: static devclass_t agp_devclass;
  262: 
  263: DRIVER_MODULE(agp_sis, pci, agp_sis_driver, agp_devclass, 0, 0);
  264: MODULE_DEPEND(agp_sis, agp, 1, 1, 1);
  265: MODULE_DEPEND(agp_sis, pci, 1, 1, 1);