File:  [DragonFly] / src / sys / dev / agp / agp_nvidia.c
Revision 1.2: download - view: text, annotated - select for diffs
Tue Dec 9 19:40:56 2003 UTC (10 years, 8 months 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) 2003 Matthew N. Dodd <winter@jurai.net>
    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:  * Based on FreeBSD v1.2.
   27:  * $DragonFly: src/sys/dev/agp/agp_nvidia.c,v 1.2 2003/12/09 19:40:56 dillon Exp $
   28:  */
   29: 
   30: /*
   31:  * Written using information gleaned from the
   32:  * NVIDIA nForce/nForce2 AGPGART Linux Kernel Patch.
   33:  */
   34: 
   35: #include "opt_bus.h"
   36: #include "opt_pci.h"
   37: 
   38: #include <sys/param.h>
   39: #include <sys/systm.h>
   40: #include <sys/malloc.h>
   41: #include <sys/kernel.h>
   42: #include <sys/bus.h>
   43: #include <sys/lock.h>
   44: 
   45: #include <bus/pci/pcivar.h>
   46: #include <bus/pci/pcireg.h>
   47: #include "agppriv.h"
   48: #include "agpreg.h"
   49: 
   50: #include <vm/vm.h>
   51: #include <vm/vm_object.h>
   52: #include <vm/pmap.h>
   53: 
   54: #include <machine/bus.h>
   55: #include <machine/resource.h>
   56: #include <sys/rman.h>
   57: 
   58: #define	NVIDIA_VENDORID		0x10de
   59: #define	NVIDIA_DEVICEID_NFORCE	0x01a4
   60: #define	NVIDIA_DEVICEID_NFORCE2	0x01e0
   61: 
   62: struct agp_nvidia_softc {
   63: 	struct agp_softc	agp;
   64: 	u_int32_t		initial_aperture; /* aperture size at startup */
   65: 	struct agp_gatt *	gatt;
   66: 
   67: 	device_t		dev;		/* AGP Controller */
   68: 	device_t		mc1_dev;	/* Memory Controller */
   69: 	device_t		mc2_dev;	/* Memory Controller */
   70: 	device_t		bdev;		/* Bridge */
   71: 
   72: 	u_int32_t		wbc_mask;
   73: 	int			num_dirs;
   74: 	int			num_active_entries;
   75: 	off_t			pg_offset;
   76: };
   77: 
   78: static const char *	agp_nvidia_match	(device_t dev);
   79: static int		agp_nvidia_probe	(device_t);
   80: static int		agp_nvidia_attach	(device_t);
   81: static int		agp_nvidia_detach	(device_t);
   82: static u_int32_t	agp_nvidia_get_aperture	(device_t);
   83: static int		agp_nvidia_set_aperture	(device_t, u_int32_t);
   84: static int		agp_nvidia_bind_page	(device_t, int, vm_offset_t);
   85: static int		agp_nvidia_unbind_page	(device_t, int);
   86: 
   87: static int		nvidia_init_iorr	(u_int32_t, u_int32_t);
   88: 
   89: static const char *
   90: agp_nvidia_match (device_t dev)
   91: {
   92: 	if (pci_get_class(dev) != PCIC_BRIDGE ||
   93: 	    pci_get_subclass(dev) != PCIS_BRIDGE_HOST ||
   94: 	    pci_get_vendor(dev) != NVIDIA_VENDORID)
   95: 		return (NULL);
   96: 
   97: 	switch (pci_get_device(dev)) {
   98: 	case NVIDIA_DEVICEID_NFORCE:
   99: 		return ("NVIDIA nForce AGP Controller");
  100: 	case NVIDIA_DEVICEID_NFORCE2:
  101: 		return ("NVIDIA nForce2 AGP Controller");
  102: 	}
  103: 	return ("NVIDIA Generic AGP Controller");
  104: }
  105: 
  106: static int
  107: agp_nvidia_probe (device_t dev)
  108: {
  109: 	const char *desc;
  110: 
  111: 	desc = agp_nvidia_match(dev);
  112: 	if (desc) {
  113: 		device_verbose(dev);
  114: 		device_set_desc(dev, desc);
  115: 		return (0);
  116: 	}
  117: 	return (ENXIO);
  118: }
  119: 
  120: static int
  121: agp_nvidia_attach (device_t dev)
  122: {
  123: 	struct agp_nvidia_softc *sc = device_get_softc(dev);
  124: 	struct agp_gatt *gatt;
  125: 	u_int32_t apbase;
  126: 	u_int32_t aplimit;
  127: 	u_int32_t temp;
  128: 	int size;
  129: 	int i;
  130: 	int error;
  131: 
  132: 	switch (pci_get_device(dev)) {
  133: 	case NVIDIA_DEVICEID_NFORCE:
  134: 		sc->wbc_mask = 0x00010000;
  135: 		break;
  136: 	case NVIDIA_DEVICEID_NFORCE2:
  137: 		sc->wbc_mask = 0x80000000;
  138: 		break;
  139: 	default:
  140: 		sc->wbc_mask = 0;
  141: 		break;
  142: 	}
  143: 
  144: 	/* AGP Controller */
  145: 	sc->dev = dev;
  146: 
  147: 	/* Memory Controller 1 */
  148: 	sc->mc1_dev = pci_find_bsf(pci_get_bus(dev), 0, 1);
  149: 	if (sc->mc1_dev == NULL) {
  150: 		device_printf(dev,
  151: 			"Unable to find NVIDIA Memory Controller 1.\n");
  152: 		return (ENODEV);
  153: 	}
  154: 
  155: 	/* Memory Controller 2 */
  156: 	sc->mc2_dev = pci_find_bsf(pci_get_bus(dev), 0, 2);
  157: 	if (sc->mc2_dev == NULL) {
  158: 		device_printf(dev,
  159: 			"Unable to find NVIDIA Memory Controller 2.\n");
  160: 		return (ENODEV);
  161: 	}
  162: 
  163: 	/* AGP Host to PCI Bridge */
  164: 	sc->bdev = pci_find_bsf(pci_get_bus(dev), 30, 0);
  165: 	if (sc->bdev == NULL) {
  166: 		device_printf(dev,
  167: 			"Unable to find NVIDIA AGP Host to PCI Bridge.\n");
  168: 		return (ENODEV);
  169: 	}
  170: 
  171: 	error = agp_generic_attach(dev);
  172: 	if (error)
  173: 		return (error);
  174: 
  175: 	sc->initial_aperture = AGP_GET_APERTURE(dev);
  176: 	if (sc->initial_aperture == 0) {
  177: 		device_printf(dev, "bad initial aperture size, disabling\n");
  178: 		return ENXIO;
  179: 	}
  180: 
  181: 	for (;;) {
  182: 		gatt = agp_alloc_gatt(dev);
  183: 		if (gatt)
  184: 			break;
  185: 		/*
  186: 		 * Probably contigmalloc failure. Try reducing the
  187: 		 * aperture so that the gatt size reduces.
  188: 		 */
  189: 		if (AGP_SET_APERTURE(dev, AGP_GET_APERTURE(dev) / 2))
  190: 			goto fail;
  191: 	}
  192: 	sc->gatt = gatt;
  193: 
  194: 	apbase = rman_get_start(sc->agp.as_aperture);
  195: 	aplimit = apbase + AGP_GET_APERTURE(dev) - 1;
  196: 	pci_write_config(sc->mc2_dev, AGP_NVIDIA_2_APBASE, apbase, 4);
  197: 	pci_write_config(sc->mc2_dev, AGP_NVIDIA_2_APLIMIT, aplimit, 4);
  198: 	pci_write_config(sc->bdev, AGP_NVIDIA_3_APBASE, apbase, 4);
  199: 	pci_write_config(sc->bdev, AGP_NVIDIA_3_APLIMIT, aplimit, 4);
  200: 
  201: 	error = nvidia_init_iorr(apbase, AGP_GET_APERTURE(dev));
  202: 	if (error) {
  203: 		device_printf(dev, "Failed to setup IORRs\n");
  204: 		goto fail;
  205: 	}
  206: 
  207: 	/* directory size is 64k */
  208: 	size = AGP_GET_APERTURE(dev) / 1024 / 1024;
  209: 	sc->num_dirs = size / 64;
  210: 	sc->num_active_entries = (size == 32) ? 16384 : ((size * 1024) / 4);
  211: 	sc->pg_offset = 0;
  212: 	if (sc->num_dirs == 0) {
  213: 		sc->num_dirs = 1;
  214: 		sc->num_active_entries /= (64 / size);
  215: 		sc->pg_offset = (apbase & (64 * 1024 * 1024 - 1) &
  216: 				 ~(AGP_GET_APERTURE(dev) - 1)) / PAGE_SIZE;
  217: 	}
  218: 
  219: 	/* (G)ATT Base Address */
  220: 	for (i = 0; i < 8; i++) {
  221: 		pci_write_config(sc->mc2_dev, AGP_NVIDIA_2_ATTBASE(i),
  222: 				 (sc->gatt->ag_physical +
  223: 				   (i % sc->num_dirs) * 64 * 1024),
  224: 				 4);
  225: 	}
  226: 
  227: 	/* GTLB Control */
  228: 	temp = pci_read_config(sc->mc2_dev, AGP_NVIDIA_2_GARTCTRL, 4);
  229: 	pci_write_config(sc->mc2_dev, AGP_NVIDIA_2_GARTCTRL, temp | 0x11, 4);
  230: 
  231: 	/* GART Control */
  232: 	temp = pci_read_config(sc->dev, AGP_NVIDIA_0_APSIZE, 4);
  233: 	pci_write_config(sc->dev, AGP_NVIDIA_0_APSIZE, temp | 0x100, 4);
  234: 
  235: 	return (0);
  236: fail:
  237: 	agp_generic_detach(dev);
  238: 	return (ENOMEM);
  239: }
  240: 
  241: static int
  242: agp_nvidia_detach (device_t dev)
  243: {
  244: 	struct agp_nvidia_softc *sc = device_get_softc(dev);
  245: 	int error;
  246: 	u_int32_t temp;
  247: 
  248: 	error = agp_generic_detach(dev);
  249: 	if (error)
  250: 		return (error);
  251: 
  252: 	/* GART Control */
  253: 	temp = pci_read_config(sc->dev, AGP_NVIDIA_0_APSIZE, 4);
  254: 	pci_write_config(sc->dev, AGP_NVIDIA_0_APSIZE, temp & ~(0x100), 4);
  255: 
  256: 	/* GTLB Control */
  257: 	temp = pci_read_config(sc->mc2_dev, AGP_NVIDIA_2_GARTCTRL, 4);
  258: 	pci_write_config(sc->mc2_dev, AGP_NVIDIA_2_GARTCTRL, temp & ~(0x11), 4);
  259: 
  260: 	/* Put the aperture back the way it started. */
  261: 	AGP_SET_APERTURE(dev, sc->initial_aperture);
  262: 
  263: 	/* restore iorr for previous aperture size */
  264: 	nvidia_init_iorr(rman_get_start(sc->agp.as_aperture),
  265: 			 sc->initial_aperture);
  266: 
  267: 	agp_free_gatt(sc->gatt);
  268: 
  269: 	return (0);
  270: }
  271: 
  272: static u_int32_t
  273: agp_nvidia_get_aperture(device_t dev)
  274: {
  275: 	u_int8_t	key;
  276: 
  277: 	key = ffs(pci_read_config(dev, AGP_NVIDIA_0_APSIZE, 1) & 0x0f);
  278: 	return (1 << (24 + (key ? key : 5)));
  279: }
  280: 
  281: static int
  282: agp_nvidia_set_aperture(device_t dev, u_int32_t aperture)
  283: {
  284: 	u_int8_t val;
  285: 	u_int8_t key;
  286: 
  287: 	switch (aperture) {
  288: 	case (512 * 1024 * 1024): key = 0; break;
  289: 	case (256 * 1024 * 1024): key = 8; break;
  290: 	case (128 * 1024 * 1024): key = 12; break;
  291: 	case (64 * 1024 * 1024): key = 14; break;
  292: 	case (32 * 1024 * 1024): key = 15; break;
  293: 	default:
  294: 		device_printf(dev, "Invalid aperture size (%dMb)\n",
  295: 				aperture / 1024 / 1024);
  296: 		return (EINVAL);
  297: 	}
  298: 	val = pci_read_config(dev, AGP_NVIDIA_0_APSIZE, 1);
  299: 	pci_write_config(dev, AGP_NVIDIA_0_APSIZE, ((val & ~0x0f) | key), 1);
  300: 
  301: 	return (0);
  302: }
  303: 
  304: static int
  305: agp_nvidia_bind_page(device_t dev, int offset, vm_offset_t physical)
  306: {
  307: 	struct agp_nvidia_softc *sc = device_get_softc(dev);
  308: 	u_int32_t index;
  309: 
  310: 	if (offset < 0 || offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT))
  311: 		return (EINVAL);
  312: 
  313: 	index = (sc->pg_offset + offset) >> AGP_PAGE_SHIFT;
  314: 	sc->gatt->ag_virtual[index] = physical;
  315: 
  316: 	return (0);
  317: }
  318: 
  319: static int
  320: agp_nvidia_unbind_page(device_t dev, int offset)
  321: {
  322: 	struct agp_nvidia_softc *sc = device_get_softc(dev);
  323: 	u_int32_t index;
  324: 
  325: 	if (offset < 0 || offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT))
  326: 		return (EINVAL);
  327: 
  328: 	index = (sc->pg_offset + offset) >> AGP_PAGE_SHIFT;
  329: 	sc->gatt->ag_virtual[index] = 0;
  330: 
  331: 	return (0);
  332: }
  333: 
  334: static int
  335: agp_nvidia_flush_tlb (device_t dev, int offset)
  336: {
  337: 	struct agp_nvidia_softc *sc;
  338: 	u_int32_t wbc_reg, temp;
  339: 	int i;
  340: 
  341: 	sc = (struct agp_nvidia_softc *)device_get_softc(dev);
  342: 
  343: 	if (sc->wbc_mask) {
  344: 		wbc_reg = pci_read_config(sc->mc1_dev, AGP_NVIDIA_1_WBC, 4);
  345: 		wbc_reg |= sc->wbc_mask;
  346: 		pci_write_config(sc->mc1_dev, AGP_NVIDIA_1_WBC, wbc_reg, 4);
  347: 
  348: 		/* Wait no more than 3 seconds. */
  349: 		for (i = 0; i < 3000; i++) {
  350: 			wbc_reg = pci_read_config(sc->mc1_dev,
  351: 						  AGP_NVIDIA_1_WBC, 4);
  352: 			if ((sc->wbc_mask & wbc_reg) == 0)
  353: 				break;
  354: 			else
  355: 				DELAY(1000);
  356: 		}
  357: 		if (i == 3000)
  358: 			device_printf(dev,
  359: 				"TLB flush took more than 3 seconds.\n");
  360: 	}
  361: 
  362: 	/* Flush TLB entries. */
  363: 	for(i = 0; i < 32 + 1; i++)
  364: 		temp = sc->gatt->ag_virtual[i * PAGE_SIZE / sizeof(u_int32_t)];
  365: 	for(i = 0; i < 32 + 1; i++)
  366: 		temp = sc->gatt->ag_virtual[i * PAGE_SIZE / sizeof(u_int32_t)];
  367: 
  368: 	return (0);
  369: }
  370: 
  371: #define	SYSCFG		0xC0010010
  372: #define	IORR_BASE0	0xC0010016
  373: #define	IORR_MASK0	0xC0010017
  374: #define	AMD_K7_NUM_IORR	2
  375: 
  376: static int
  377: nvidia_init_iorr(u_int32_t addr, u_int32_t size)
  378: {
  379: 	quad_t base, mask, sys;
  380: 	u_int32_t iorr_addr, free_iorr_addr;
  381: 
  382: 	/* Find the iorr that is already used for the addr */
  383: 	/* If not found, determine the uppermost available iorr */
  384: 	free_iorr_addr = AMD_K7_NUM_IORR;
  385: 	for(iorr_addr = 0; iorr_addr < AMD_K7_NUM_IORR; iorr_addr++) {
  386: 		base = rdmsr(IORR_BASE0 + 2 * iorr_addr);
  387: 		mask = rdmsr(IORR_MASK0 + 2 * iorr_addr);
  388: 
  389: 		if ((base & 0xfffff000ULL) == (addr & 0xfffff000))
  390: 			break;
  391: 
  392: 		if ((mask & 0x00000800ULL) == 0)
  393: 			free_iorr_addr = iorr_addr;
  394: 	}
  395: 
  396: 	if (iorr_addr >= AMD_K7_NUM_IORR) {
  397: 		iorr_addr = free_iorr_addr;
  398: 		if (iorr_addr >= AMD_K7_NUM_IORR)
  399: 			return (EINVAL);
  400: 	}
  401: 
  402: 	base = (addr & ~0xfff) | 0x18;
  403: 	mask = (0xfULL << 32) | ((~(size - 1)) & 0xfffff000) | 0x800;
  404: 	wrmsr(IORR_BASE0 + 2 * iorr_addr, base);
  405: 	wrmsr(IORR_MASK0 + 2 * iorr_addr, mask);
  406: 
  407: 	sys = rdmsr(SYSCFG);
  408: 	sys |= 0x00100000ULL;
  409: 	wrmsr(SYSCFG, sys);
  410: 
  411: 	return (0);
  412: }
  413: 
  414: static device_method_t agp_nvidia_methods[] = {
  415: 	/* Device interface */
  416: 	DEVMETHOD(device_probe,		agp_nvidia_probe),
  417: 	DEVMETHOD(device_attach,	agp_nvidia_attach),
  418: 	DEVMETHOD(device_detach,	agp_nvidia_detach),
  419: 	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
  420: 	DEVMETHOD(device_suspend,	bus_generic_suspend),
  421: 	DEVMETHOD(device_resume,	bus_generic_resume),
  422: 
  423: 	/* AGP interface */
  424: 	DEVMETHOD(agp_get_aperture,	agp_nvidia_get_aperture),
  425: 	DEVMETHOD(agp_set_aperture,	agp_nvidia_set_aperture),
  426: 	DEVMETHOD(agp_bind_page,	agp_nvidia_bind_page),
  427: 	DEVMETHOD(agp_unbind_page,	agp_nvidia_unbind_page),
  428: 	DEVMETHOD(agp_flush_tlb,	agp_nvidia_flush_tlb),
  429: 
  430: 	DEVMETHOD(agp_enable,		agp_generic_enable),
  431: 	DEVMETHOD(agp_alloc_memory,	agp_generic_alloc_memory),
  432: 	DEVMETHOD(agp_free_memory,	agp_generic_free_memory),
  433: 	DEVMETHOD(agp_bind_memory,	agp_generic_bind_memory),
  434: 	DEVMETHOD(agp_unbind_memory,	agp_generic_unbind_memory),
  435: 
  436: 	{ 0, 0 }
  437: };
  438: 
  439: static driver_t agp_nvidia_driver = {
  440: 	"agp",
  441: 	agp_nvidia_methods,
  442: 	sizeof(struct agp_nvidia_softc),
  443: };
  444: 
  445: static devclass_t agp_devclass;
  446: 
  447: DRIVER_MODULE(agp_nvidia, pci, agp_nvidia_driver, agp_devclass, 0, 0);
  448: MODULE_DEPEND(agp_nvidia, agp, 1, 1, 1);
  449: MODULE_DEPEND(agp_nvidia, pci, 1, 1, 1);