[PATCH] Bring in the latest agp code from FreeBSD HEAD
Hasso Tepper
hasso at estpak.ee
Mon Sep 10 01:12:57 PDT 2007
# HG changeset patch
# User Hasso Tepper <hasso at estpak.ee>
# Date 1189411506 -10800
# Branch HEAD
# Node ID 68e1e6cb72a19d13e3e85d688e6257b5d870f93f
# Parent 238f78b197db9a89d87a68446eeb1033a7b14558
Bring in the latest agp code from FreeBSD HEAD.
It allows various X11 acceleration methods (like XVideo) to work on a
newer hardware and makes easier to update the drm code (any volunteers?).
Only the Intel Q965 onboard video is tested so far and I don't have a
hardware to test anything else.
There is one related bug I discovered so far - mplayer crashes if I try to
play the video with 1280x720 resolution on the 1280x1024 display with
message:
X11 error: BadAlloc (insufficient resources for operation)?,?% 0 0
All other (smaller) videos play OK. And due to lack of hardware I can even
test if it's a regression, a bug in the agp code, abug in the X11 driver
(i810) or a bug in the mplayer. Brief gooling seems to point to the buggy
X11 driver, but I'm not very sure yet.
So, any testing is more than welcome. If no serious regressions appear,
I'll commit it in Wednesday.
diff --git a/sys/conf/files b/sys/conf/files
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -1045,7 +1045,9 @@ dev/agp/agp_sis.c optional agp
dev/agp/agp_sis.c optional agp
dev/agp/agp_ali.c optional agp
dev/agp/agp_amd.c optional agp
+dev/agp/agp_amd64.c optional agp
dev/agp/agp_i810.c optional agp
+dev/agp/agp_ati.c optional agp
dev/agp/agp_if.m optional agp
dev/disk/amd/amd.c optional amd
dev/netif/awi/am79c930.c optional awi
diff --git a/sys/dev/agp/Makefile b/sys/dev/agp/Makefile
--- a/sys/dev/agp/Makefile
+++ b/sys/dev/agp/Makefile
@@ -3,8 +3,8 @@
KMOD = agp
SRCS = agp.c
-SRCS += agp_i810.c agp_ali.c agp_amd.c agp_nvidia.c agp_intel.c
-SRCS += agp_sis.c agp_via.c
+SRCS += agp_i810.c agp_ali.c agp_amd.c agp_amd64.c agp_ati.c agp_nvidia.c
+SRCS += agp_intel.c agp_sis.c agp_via.c
SRCS += agp_if.c device_if.h bus_if.h agp_if.h pci_if.h
SRCS += opt_bus.h opt_pci.h
MFILES = kern/device_if.m kern/bus_if.m dev/agp/agp_if.m bus/pci/pci_if.m
diff --git a/sys/dev/agp/agp.c b/sys/dev/agp/agp.c
--- a/sys/dev/agp/agp.c
+++ b/sys/dev/agp/agp.c
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/sys/pci/agp.c,v 1.3.2.4 2002/08/11 19:58:12 alc Exp $
+ * $FreeBSD: src/sys/pci/agp.c,v 1.56 2007/07/13 16:28:11 anholt Exp $
* $DragonFly: src/sys/dev/agp/agp.c,v 1.26 2006/12/22 23:26:14 swildner Exp $
*/
@@ -84,7 +84,7 @@ void
void
agp_flush_cache(void)
{
-#ifdef __i386__
+#if defined(__i386__) || defined(__amd64__)
wbinvd();
#endif
}
@@ -172,7 +172,7 @@ agp_alloc_gatt(device_t dev)
gatt = kmalloc(sizeof(struct agp_gatt), M_AGP, M_INTWAIT);
gatt->ag_entries = entries;
- gatt->ag_virtual = contigmalloc(entries * sizeof(u_int32_t), M_AGP,
+ gatt->ag_virtual = contigmalloc(entries * sizeof(u_int32_t), M_AGP,
M_WAITOK, 0, ~0, PAGE_SIZE, 0);
if (!gatt->ag_virtual) {
if (bootverbose)
@@ -195,7 +195,7 @@ agp_free_gatt(struct agp_gatt *gatt)
kfree(gatt, M_AGP);
}
-static int agp_max[][2] = {
+static u_int agp_max[][2] = {
{0, 0},
{32, 4},
{64, 28},
@@ -208,18 +208,36 @@ static int agp_max[][2] = {
};
#define agp_max_size (sizeof(agp_max) / sizeof(agp_max[0]))
+/**
+ * Sets the PCI resource which represents the AGP aperture.
+ *
+ * If not called, the default AGP aperture resource of AGP_APBASE will
+ * be used. Must be called before agp_generic_attach().
+ */
+void
+agp_set_aperture_resource(device_t dev, int rid)
+{
+ struct agp_softc *sc = device_get_softc(dev);
+
+ sc->as_aperture_rid = rid;
+}
+
int
agp_generic_attach(device_t dev)
{
struct agp_softc *sc = device_get_softc(dev);
- int rid, memsize, i;
-
- /*
- * Find and map the aperture.
- */
- rid = AGP_APBASE;
- sc->as_aperture = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid,
- 0, ~0, 1, RF_ACTIVE);
+ int i;
+ u_int memsize;
+
+ /*
+ * Find and map the aperture, RF_SHAREABLE for DRM but not RF_ACTIVE
+ * because the kernel doesn't need to map it.
+ */
+ if (sc->as_aperture_rid == 0)
+ sc->as_aperture_rid = AGP_APBASE;
+
+ sc->as_aperture = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+ &sc->as_aperture_rid, RF_SHAREABLE);
if (!sc->as_aperture)
return ENOMEM;
@@ -264,6 +282,34 @@ agp_generic_detach(device_t dev)
agp_flush_cache();
dev_ops_remove(&agp_ops, -1, device_get_unit(dev));
return 0;
+}
+
+/**
+ * Default AGP aperture size detection which simply returns the size of
+ * the aperture's PCI resource.
+ */
+int
+agp_generic_get_aperture(device_t dev)
+{
+ struct agp_softc *sc = device_get_softc(dev);
+
+ return rman_get_size(sc->as_aperture);
+}
+
+/**
+ * Default AGP aperture size setting function, which simply doesn't allow
+ * changes to resource size.
+ */
+int
+agp_generic_set_aperture(device_t dev, u_int32_t aperture)
+{
+ u_int32_t current_aperture;
+
+ current_aperture = AGP_GET_APERTURE(dev);
+ if (current_aperture != aperture)
+ return EINVAL;
+ else
+ return 0;
}
/*
@@ -324,12 +370,14 @@ agp_v3_enable(device_t dev, device_t mde
pci_write_config(dev, agp_find_caps(dev) + AGP_COMMAND, 0, 4);
/* Construct the new mode word and tell the hardware */
+ command = 0;
command = AGP_MODE_SET_RQ(0, rq);
command = AGP_MODE_SET_ARQSZ(command, arqsz);
command = AGP_MODE_SET_CAL(command, cal);
command = AGP_MODE_SET_SBA(command, sba);
command = AGP_MODE_SET_FW(command, fw);
command = AGP_MODE_SET_RATE(command, rate);
+ command = AGP_MODE_SET_MODE_3(command, 1);
command = AGP_MODE_SET_AGP(command, 1);
pci_write_config(dev, agp_find_caps(dev) + AGP_COMMAND, command, 4);
pci_write_config(mdev, agp_find_caps(mdev) + AGP_COMMAND, command, 4);
@@ -378,6 +426,7 @@ agp_v2_enable(device_t dev, device_t mde
device_printf(dev, "Setting AGP v2 mode %d\n", rate);
/* Construct the new mode word and tell the hardware */
+ command = 0;
command = AGP_MODE_SET_RQ(0, rq);
command = AGP_MODE_SET_SBA(command, sba);
command = AGP_MODE_SET_FW(command, fw);
@@ -411,7 +460,9 @@ agp_generic_enable(device_t dev, u_int32
* but should work fine for a classic single AGP slot system
* with AGP v3.
*/
- if (AGP_MODE_GET_MODE_3(tstatus) && AGP_MODE_GET_MODE_3(mstatus))
+ if (AGP_MODE_GET_MODE_3(mode) &&
+ AGP_MODE_GET_MODE_3(tstatus) &&
+ AGP_MODE_GET_MODE_3(mstatus))
return (agp_v3_enable(dev, mdev, mode));
else
return (agp_v2_enable(dev, mdev, mode));
@@ -431,7 +482,7 @@ agp_generic_alloc_memory(device_t dev, i
if (type != 0) {
kprintf("agp_generic_alloc_memory: unsupported type %d\n",
- type);
+ type);
return 0;
}
@@ -806,7 +857,7 @@ agp_mmap(struct dev_mmap_args *ap)
if (ap->a_offset > AGP_GET_APERTURE(dev))
return EINVAL;
ap->a_result = atop(rman_get_start(sc->as_aperture) + ap->a_offset);
- return(0);
+ return 0;
}
/* Implementation of the kernel api */
@@ -814,9 +865,22 @@ device_t
device_t
agp_find_device(void)
{
+ device_t *children, child;
+ int i, count;
+
if (!agp_devclass)
- return 0;
- return devclass_get_device(agp_devclass, 0);
+ return NULL;
+ if (devclass_get_devices(agp_devclass, &children, &count) != 0)
+ return NULL;
+ child = NULL;
+ for (i = 0; i < count; i++) {
+ if (device_is_attached(children[i])) {
+ child = children[i];
+ break;
+ }
+ }
+ kfree(children, M_TEMP);
+ return child;
}
enum agp_acquire_state
@@ -834,9 +898,7 @@ agp_get_info(device_t dev, struct agp_in
info->ai_mode =
pci_read_config(dev, agp_find_caps(dev) + AGP_STATUS, 4);
info->ai_aperture_base = rman_get_start(sc->as_aperture);
- info->ai_aperture_size = (rman_get_end(sc->as_aperture)
- - rman_get_start(sc->as_aperture)) + 1;
- info->ai_aperture_va = (vm_offset_t) rman_get_virtual(sc->as_aperture);
+ info->ai_aperture_size = rman_get_size(sc->as_aperture);
info->ai_memory_allowed = sc->as_maxmem;
info->ai_memory_used = sc->as_allocated;
}
diff --git a/sys/dev/agp/agp_ali.c b/sys/dev/agp/agp_ali.c
--- a/sys/dev/agp/agp_ali.c
+++ b/sys/dev/agp/agp_ali.c
@@ -23,12 +23,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/sys/pci/agp_ali.c,v 1.1.2.1 2000/07/19 09:48:04 ru Exp $
+ * $FreeBSD: src/sys/pci/agp_ali.c,v 1.18 2005/12/20 21:12:26 jhb Exp $
* $DragonFly: src/sys/dev/agp/agp_ali.c,v 1.5 2004/10/10 18:59:02 dillon Exp $
*/
#include "opt_bus.h"
-#include "opt_pci.h"
#include <sys/param.h>
#include <sys/systm.h>
@@ -63,13 +62,14 @@ agp_ali_match(device_t dev)
return NULL;
switch (pci_get_devid(dev)) {
+ case 0x167110b9:
+ return ("Ali M1671 host to AGP bridge");
case 0x154110b9:
return ("Ali M1541 host to AGP bridge");
+ case 0x162110b9:
+ return ("Ali M1621 host to AGP bridge");
};
- if (pci_get_vendor(dev) == 0x10b9)
- return ("Ali Generic host to PCI bridge");
-
return NULL;
}
@@ -78,11 +78,13 @@ agp_ali_probe(device_t dev)
{
const char *desc;
+ if (resource_disabled("agp", device_get_unit(dev)))
+ return (ENXIO);
desc = agp_ali_match(dev);
if (desc) {
device_verbose(dev);
device_set_desc(dev, desc);
- return 0;
+ return BUS_PROBE_DEFAULT;
}
return ENXIO;
@@ -94,6 +96,7 @@ agp_ali_attach(device_t dev)
struct agp_ali_softc *sc = device_get_softc(dev);
struct agp_gatt *gatt;
int error;
+ u_int32_t attbase;
error = agp_generic_attach(dev);
if (error)
@@ -123,10 +126,9 @@ agp_ali_attach(device_t dev)
sc->gatt = gatt;
/* Install the gatt. */
- pci_write_config(dev, AGP_ALI_ATTBASE,
- (gatt->ag_physical
- | (pci_read_config(dev, AGP_ALI_ATTBASE, 4) & 0xff)),
- 4);
+ attbase = pci_read_config(dev, AGP_ALI_ATTBASE, 4);
+ pci_write_config(dev, AGP_ALI_ATTBASE, gatt->ag_physical |
+ (attbase & 0xfff), 4);
/* Enable the TLB. */
pci_write_config(dev, AGP_ALI_TLBCTRL, 0x10, 1);
@@ -139,6 +141,7 @@ agp_ali_detach(device_t dev)
{
struct agp_ali_softc *sc = device_get_softc(dev);
int error;
+ u_int32_t attbase;
error = agp_generic_detach(dev);
if (error)
@@ -149,9 +152,8 @@ agp_ali_detach(device_t dev)
/* Put the aperture back the way it started. */
AGP_SET_APERTURE(dev, sc->initial_aperture);
- pci_write_config(dev, AGP_ALI_ATTBASE,
- pci_read_config(dev, AGP_ALI_ATTBASE, 4) & 0xff,
- 4);
+ attbase = pci_read_config(dev, AGP_ALI_ATTBASE, 4);
+ pci_write_config(dev, AGP_ALI_ATTBASE, attbase & 0xfff, 4);
agp_free_gatt(sc->gatt);
return 0;
@@ -181,7 +183,7 @@ agp_ali_get_aperture(device_t dev)
* The aperture size is derived from the low bits of attbase.
* I'm not sure this is correct..
*/
- int i = pci_read_config(dev, AGP_ALI_ATTBASE, 4) & 0xff;
+ int i = pci_read_config(dev, AGP_ALI_ATTBASE, 4) & 0xf;
if (i >= agp_ali_table_size)
return 0;
return agp_ali_table[i];
@@ -191,6 +193,7 @@ agp_ali_set_aperture(device_t dev, u_int
agp_ali_set_aperture(device_t dev, u_int32_t aperture)
{
int i;
+ u_int32_t attbase;
for (i = 0; i < agp_ali_table_size; i++)
if (agp_ali_table[i] == aperture)
@@ -198,9 +201,8 @@ agp_ali_set_aperture(device_t dev, u_int
if (i == agp_ali_table_size)
return EINVAL;
- pci_write_config(dev, AGP_ALI_ATTBASE,
- ((pci_read_config(dev, AGP_ALI_ATTBASE, 4) & ~0xff)
- | i), 4);
+ attbase = pci_read_config(dev, AGP_ALI_ATTBASE, 4);
+ pci_write_config(dev, AGP_ALI_ATTBASE, (attbase & ~0xf) | i, 4);
return 0;
}
diff --git a/sys/dev/agp/agp_amd.c b/sys/dev/agp/agp_amd.c
--- a/sys/dev/agp/agp_amd.c
+++ b/sys/dev/agp/agp_amd.c
@@ -23,12 +23,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/sys/pci/agp_amd.c,v 1.3.2.4 2002/04/25 23:41:36 cokane Exp $
+ * $FreeBSD: src/sys/pci/agp_amd.c,v 1.23 2005/12/20 21:12:26 jhb Exp $
* $DragonFly: src/sys/dev/agp/agp_amd.c,v 1.8 2006/10/25 20:55:52 dillon Exp $
*/
#include "opt_bus.h"
-#include "opt_pci.h"
#include <sys/param.h>
#include <sys/systm.h>
@@ -46,7 +45,6 @@
#include <vm/vm.h>
#include <vm/vm_object.h>
#include <vm/pmap.h>
-#include <machine/clock.h>
MALLOC_DECLARE(M_AGP);
@@ -64,12 +62,12 @@ struct agp_amd_gatt {
};
struct agp_amd_softc {
- struct agp_softc agp;
- struct resource *regs; /* memory mapped control registers */
- bus_space_tag_t bst; /* bus_space tag */
- bus_space_handle_t bsh; /* bus_space handle */
- u_int32_t initial_aperture; /* aperture size at startup */
- struct agp_amd_gatt *gatt;
+ struct agp_softc agp;
+ struct resource *regs; /* memory mapped control registers */
+ bus_space_tag_t bst; /* bus_space tag */
+ bus_space_handle_t bsh; /* bus_space handle */
+ u_int32_t initial_aperture; /* aperture size at startup */
+ struct agp_amd_gatt *gatt;
};
static struct agp_amd_gatt *
@@ -101,10 +99,11 @@ agp_amd_alloc_gatt(device_t dev)
* Allocate the page directory.
*/
gatt->ag_vdir = kmalloc(AGP_PAGE_SIZE, M_AGP, M_INTWAIT | M_ZERO);
+
gatt->ag_pdir = vtophys((vm_offset_t) gatt->ag_vdir);
if(bootverbose)
- device_printf(dev, "gatt -> ag_pdir %8x\n",
- (vm_offset_t)gatt->ag_pdir);
+ device_printf(dev, "gatt -> ag_pdir %#lx\n",
+ (u_long)gatt->ag_pdir);
/*
* Allocate the gatt pages
*/
@@ -112,6 +111,7 @@ agp_amd_alloc_gatt(device_t dev)
if(bootverbose)
device_printf(dev, "allocating GATT for %d AGP page entries\n",
gatt->ag_entries);
+
gatt->ag_physical = vtophys((vm_offset_t) gatt->ag_virtual);
/*
@@ -164,16 +164,12 @@ agp_amd_match(device_t dev)
return NULL;
switch (pci_get_devid(dev)) {
-
case 0x70061022:
return ("AMD 751 host to AGP bridge");
-
case 0x700e1022:
return ("AMD 761 host to AGP bridge");
-
case 0x700c1022:
return ("AMD 762 host to AGP bridge");
-
};
return NULL;
@@ -184,11 +180,13 @@ agp_amd_probe(device_t dev)
{
const char *desc;
+ if (resource_disabled("agp", device_get_unit(dev)))
+ return (ENXIO);
desc = agp_amd_match(dev);
if (desc) {
device_verbose(dev);
device_set_desc(dev, desc);
- return 0;
+ return BUS_PROBE_DEFAULT;
}
return ENXIO;
@@ -206,8 +204,8 @@ agp_amd_attach(device_t dev)
return error;
rid = AGP_AMD751_REGISTERS;
- sc->regs = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid,
- 0, ~0, 1, RF_ACTIVE);
+ sc->regs = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
if (!sc->regs) {
agp_generic_detach(dev);
return ENOMEM;
diff --git a/sys/dev/agp/agp_amd64.c b/sys/dev/agp/agp_amd64.c
new file mode 100644
--- /dev/null
+++ b/sys/dev/agp/agp_amd64.c
@@ -0,0 +1,518 @@
+/*-
+ * Copyright (c) 2004, 2005 Jung-uk Kim <jkim at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/pci/agp_amd64.c,v 1.14 2006/10/09 20:26:32 jkim Exp $
+ * $DragonFly$
+ */
+
+#include "opt_bus.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/lock.h>
+#include <sys/proc.h>
+
+#include <bus/pci/pcivar.h>
+#include <bus/pci/pcireg.h>
+#include "agppriv.h"
+#include "agpreg.h"
+
+#include <vm/vm.h>
+#include <vm/vm_object.h>
+#include <vm/pmap.h>
+#include <sys/rman.h>
+
+/* XXX */
+extern void pci_cfgregwrite(int, int, int, int, uint32_t, int);
+extern uint32_t pci_cfgregread(int, int, int, int, int);
+
+static void agp_amd64_apbase_fixup(device_t);
+
+static void agp_amd64_uli_init(device_t);
+static int agp_amd64_uli_set_aperture(device_t, uint32_t);
+
+static int agp_amd64_nvidia_match(uint16_t);
+static void agp_amd64_nvidia_init(device_t);
+static int agp_amd64_nvidia_set_aperture(device_t, uint32_t);
+
+static int agp_amd64_via_match(void);
+static void agp_amd64_via_init(device_t);
+static int agp_amd64_via_set_aperture(device_t, uint32_t);
+
+MALLOC_DECLARE(M_AGP);
+
+#define AMD64_MAX_MCTRL 8
+
+struct agp_amd64_softc {
+ struct agp_softc agp;
+ uint32_t initial_aperture;
+ struct agp_gatt *gatt;
+ uint32_t apbase;
+ int mctrl[AMD64_MAX_MCTRL];
+ int n_mctrl;
+ int via_agp;
+};
+
+static const char*
+agp_amd64_match(device_t dev)
+{
+ if (pci_get_class(dev) != PCIC_BRIDGE ||
+ pci_get_subclass(dev) != PCIS_BRIDGE_HOST ||
+ agp_find_caps(dev) == 0)
+ return (NULL);
+
+ switch (pci_get_devid(dev)) {
+ case 0x74541022:
+ return ("AMD 8151 AGP graphics tunnel");
+ case 0x07551039:
+ return ("SiS 755 host to AGP bridge");
+ case 0x07601039:
+ return ("SiS 760 host to AGP bridge");
+ case 0x168910b9:
+ return ("ULi M1689 AGP Controller");
+ case 0x00d110de:
+ if (agp_amd64_nvidia_match(0x00d2))
+ return (NULL);
+ return ("NVIDIA nForce3 AGP Controller");
+ case 0x00e110de:
+ if (agp_amd64_nvidia_match(0x00e2))
+ return (NULL);
+ return ("NVIDIA nForce3-250 AGP Controller");
+ case 0x02041106:
+ return ("VIA 8380 host to PCI bridge");
+ case 0x02381106:
+ return ("VIA 3238 host to PCI bridge");
+ case 0x02821106:
+ return ("VIA K8T800Pro host to PCI bridge");
+ case 0x31881106:
+ return ("VIA 8385 host to PCI bridge");
+ };
+
+ return (NULL);
+}
+
+static int
+agp_amd64_nvidia_match(uint16_t devid)
+{
+ /* XXX nForce3 requires secondary AGP bridge at 0:11:0. */
+ if (pci_cfgregread(0, 11, 0, PCIR_CLASS, 1) != PCIC_BRIDGE ||
+ pci_cfgregread(0, 11, 0, PCIR_SUBCLASS, 1) != PCIS_BRIDGE_PCI ||
+ pci_cfgregread(0, 11, 0, PCIR_VENDOR, 2) != 0x10de ||
+ pci_cfgregread(0, 11, 0, PCIR_DEVICE, 2) != devid)
+ return (ENXIO);
+
+ return (0);
+}
+
+static int
+agp_amd64_via_match(void)
+{
+ /* XXX Some VIA bridge requires secondary AGP bridge at 0:1:0. */
+ if (pci_cfgregread(0, 1, 0, PCIR_CLASS, 1) != PCIC_BRIDGE ||
+ pci_cfgregread(0, 1, 0, PCIR_SUBCLASS, 1) != PCIS_BRIDGE_PCI ||
+ pci_cfgregread(0, 1, 0, PCIR_VENDOR, 2) != 0x1106 ||
+ pci_cfgregread(0, 1, 0, PCIR_DEVICE, 2) != 0xb188 ||
+ (pci_cfgregread(0, 1, 0, AGP_VIA_AGPSEL, 1) & 2))
+ return (0);
+
+ return (1);
+}
+
+static int
+agp_amd64_probe(device_t dev)
+{
+ const char *desc;
+
+ if (resource_disabled("agp", device_get_unit(dev)))
+ return (ENXIO);
+ if ((desc = agp_amd64_match(dev))) {
+ device_set_desc(dev, desc);
+ return (BUS_PROBE_DEFAULT);
+ }
+
+ return (ENXIO);
+}
+
+static int
+agp_amd64_attach(device_t dev)
+{
+ struct agp_amd64_softc *sc = device_get_softc(dev);
+ struct agp_gatt *gatt;
+ int i, n, error;
+
+ for (i = 0, n = 0; i < PCI_SLOTMAX && n < AMD64_MAX_MCTRL; i++)
+ if (pci_cfgregread(0, i, 3, 0, 4) == 0x11031022) {
+ sc->mctrl[n] = i;
+ n++;
+ }
+
+ if (n == 0)
+ return (ENXIO);
+
+ sc->n_mctrl = n;
+
+ if (bootverbose)
+ device_printf(dev, "%d Miscellaneous Control unit(s) found.\n",
+ sc->n_mctrl);
+
+ if ((error = agp_generic_attach(dev)))
+ return (error);
+
+ sc->initial_aperture = AGP_GET_APERTURE(dev);
+ if (sc->initial_aperture == 0) {
+ device_printf(dev, "bad initial aperture size, disabling\n");
+ return ENXIO;
+ }
+
+ for (;;) {
+ gatt = agp_alloc_gatt(dev);
+ if (gatt)
+ break;
+
+ /*
+ * Probably contigmalloc failure. Try reducing the
+ * aperture so that the gatt size reduces.
+ */
+ if (AGP_SET_APERTURE(dev, AGP_GET_APERTURE(dev) / 2)) {
+ agp_generic_detach(dev);
+ return (ENOMEM);
+ }
+ }
+ sc->gatt = gatt;
+
+ switch (pci_get_vendor(dev)) {
+ case 0x10b9: /* ULi */
+ agp_amd64_uli_init(dev);
+ if (agp_amd64_uli_set_aperture(dev, sc->initial_aperture))
+ return (ENXIO);
+ break;
+
+ case 0x10de: /* nVidia */
+ agp_amd64_nvidia_init(dev);
+ if (agp_amd64_nvidia_set_aperture(dev, sc->initial_aperture))
+ return (ENXIO);
+ break;
+
+ case 0x1106: /* VIA */
+ sc->via_agp = agp_amd64_via_match();
+ if (sc->via_agp) {
+ agp_amd64_via_init(dev);
+ if (agp_amd64_via_set_aperture(dev,
+ sc->initial_aperture))
+ return (ENXIO);
+ }
+ break;
+ }
+
+ /* Install the gatt and enable aperture. */
+ for (i = 0; i < sc->n_mctrl; i++) {
+ pci_cfgregwrite(0, sc->mctrl[i], 3, AGP_AMD64_ATTBASE,
+ (uint32_t)(gatt->ag_physical >> 8) & AGP_AMD64_ATTBASE_MASK,
+ 4);
+ pci_cfgregwrite(0, sc->mctrl[i], 3, AGP_AMD64_APCTRL,
+ (pci_cfgregread(0, sc->mctrl[i], 3, AGP_AMD64_APCTRL, 4) |
+ AGP_AMD64_APCTRL_GARTEN) &
+ ~(AGP_AMD64_APCTRL_DISGARTCPU | AGP_AMD64_APCTRL_DISGARTIO),
+ 4);
+ }
+
+ agp_flush_cache();
+
+ return (0);
+}
+
+static int
+agp_amd64_detach(device_t dev)
+{
+ struct agp_amd64_softc *sc = device_get_softc(dev);
+ int i, error;
+
+ if ((error = agp_generic_detach(dev)))
+ return (error);
+
+ for (i = 0; i < sc->n_mctrl; i++)
+ pci_cfgregwrite(0, sc->mctrl[i], 3, AGP_AMD64_APCTRL,
+ pci_cfgregread(0, sc->mctrl[i], 3, AGP_AMD64_APCTRL, 4) &
+ ~AGP_AMD64_APCTRL_GARTEN, 4);
+
+ AGP_SET_APERTURE(dev, sc->initial_aperture);
+ agp_free_gatt(sc->gatt);
+
+ return (0);
+}
+
+static uint32_t agp_amd64_table[] = {
+ 0x02000000, /* 32 MB */
+ 0x04000000, /* 64 MB */
+ 0x08000000, /* 128 MB */
+ 0x10000000, /* 256 MB */
+ 0x20000000, /* 512 MB */
+ 0x40000000, /* 1024 MB */
+ 0x80000000, /* 2048 MB */
+};
+
+#define AGP_AMD64_TABLE_SIZE \
+ (sizeof(agp_amd64_table) / sizeof(agp_amd64_table[0]))
+
+static uint32_t
+agp_amd64_get_aperture(device_t dev)
+{
+ struct agp_amd64_softc *sc = device_get_softc(dev);
+ uint32_t i;
+
+ i = (pci_cfgregread(0, sc->mctrl[0], 3, AGP_AMD64_APCTRL, 4) &
+ AGP_AMD64_APCTRL_SIZE_MASK) >> 1;
+
+ if (i >= AGP_AMD64_TABLE_SIZE)
+ return (0);
+
+ return (agp_amd64_table[i]);
+}
+
+static int
+agp_amd64_set_aperture(device_t dev, uint32_t aperture)
+{
+ struct agp_amd64_softc *sc = device_get_softc(dev);
+ uint32_t i;
+ int j;
+
+ for (i = 0; i < AGP_AMD64_TABLE_SIZE; i++)
+ if (agp_amd64_table[i] == aperture)
+ break;
+ if (i >= AGP_AMD64_TABLE_SIZE)
+ return (EINVAL);
+
+ for (j = 0; j < sc->n_mctrl; j++)
+ pci_cfgregwrite(0, sc->mctrl[j], 3, AGP_AMD64_APCTRL,
+ (pci_cfgregread(0, sc->mctrl[j], 3, AGP_AMD64_APCTRL, 4) &
+ ~(AGP_AMD64_APCTRL_SIZE_MASK)) | (i << 1), 4);
+
+ switch (pci_get_vendor(dev)) {
+ case 0x10b9: /* ULi */
+ return (agp_amd64_uli_set_aperture(dev, aperture));
+ break;
+
+ case 0x10de: /* nVidia */
+ return (agp_amd64_nvidia_set_aperture(dev, aperture));
+ break;
+
+ case 0x1106: /* VIA */
+ if (sc->via_agp)
+ return (agp_amd64_via_set_aperture(dev, aperture));
+ break;
+ }
+
+ return (0);
+}
+
+static int
+agp_amd64_bind_page(device_t dev, int offset, vm_offset_t physical)
+{
+ struct agp_amd64_softc *sc = device_get_softc(dev);
+
+ if (offset < 0 || offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT))
+ return (EINVAL);
+
+ sc->gatt->ag_virtual[offset >> AGP_PAGE_SHIFT] =
+ (physical & 0xfffff000) | ((physical >> 28) & 0x00000ff0) | 3;
+
+ return (0);
+}
+
+static int
+agp_amd64_unbind_page(device_t dev, int offset)
+{
+ struct agp_amd64_softc *sc = device_get_softc(dev);
+
+ if (offset < 0 || offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT))
+ return (EINVAL);
+
+ sc->gatt->ag_virtual[offset >> AGP_PAGE_SHIFT] = 0;
+
+ return (0);
+}
+
+static void
+agp_amd64_flush_tlb(device_t dev)
+{
+ struct agp_amd64_softc *sc = device_get_softc(dev);
+ int i;
+
+ for (i = 0; i < sc->n_mctrl; i++)
+ pci_cfgregwrite(0, sc->mctrl[i], 3, AGP_AMD64_CACHECTRL,
+ pci_cfgregread(0, sc->mctrl[i], 3, AGP_AMD64_CACHECTRL, 4) |
+ AGP_AMD64_CACHECTRL_INVGART, 4);
+}
+
+static void
+agp_amd64_apbase_fixup(device_t dev)
+{
+ struct agp_amd64_softc *sc = device_get_softc(dev);
+ uint32_t apbase;
+ int i;
+
+ sc->apbase = rman_get_start(sc->agp.as_aperture);
+ apbase = (sc->apbase >> 25) & AGP_AMD64_APBASE_MASK;
+ for (i = 0; i < sc->n_mctrl; i++)
+ pci_cfgregwrite(0, sc->mctrl[i], 3,
+ AGP_AMD64_APBASE, apbase, 4);
+}
+
+static void
+agp_amd64_uli_init(device_t dev)
+{
+ struct agp_amd64_softc *sc = device_get_softc(dev);
+
+ agp_amd64_apbase_fixup(dev);
+ pci_write_config(dev, AGP_AMD64_ULI_APBASE,
+ (pci_read_config(dev, AGP_AMD64_ULI_APBASE, 4) & 0x0000000f) |
+ sc->apbase, 4);
+ pci_write_config(dev, AGP_AMD64_ULI_HTT_FEATURE, sc->apbase, 4);
+}
+
+static int
+agp_amd64_uli_set_aperture(device_t dev, uint32_t aperture)
+{
+ struct agp_amd64_softc *sc = device_get_softc(dev);
+
+ switch (aperture) {
+ case 0x02000000: /* 32 MB */
+ case 0x04000000: /* 64 MB */
+ case 0x08000000: /* 128 MB */
+ case 0x10000000: /* 256 MB */
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ pci_write_config(dev, AGP_AMD64_ULI_ENU_SCR,
+ sc->apbase + aperture - 1, 4);
+
+ return (0);
+}
+
+static void
+agp_amd64_nvidia_init(device_t dev)
+{
+ struct agp_amd64_softc *sc = device_get_softc(dev);
+
+ agp_amd64_apbase_fixup(dev);
+ pci_write_config(dev, AGP_AMD64_NVIDIA_0_APBASE,
+ (pci_read_config(dev, AGP_AMD64_NVIDIA_0_APBASE, 4) & 0x0000000f) |
+ sc->apbase, 4);
+ pci_cfgregwrite(0, 11, 0, AGP_AMD64_NVIDIA_1_APBASE1, sc->apbase, 4);
+ pci_cfgregwrite(0, 11, 0, AGP_AMD64_NVIDIA_1_APBASE2, sc->apbase, 4);
+}
+
+static int
+agp_amd64_nvidia_set_aperture(device_t dev, uint32_t aperture)
+{
+ struct agp_amd64_softc *sc = device_get_softc(dev);
+ uint32_t apsize;
+
+ switch (aperture) {
+ case 0x02000000: apsize = 0x0f; break; /* 32 MB */
+ case 0x04000000: apsize = 0x0e; break; /* 64 MB */
+ case 0x08000000: apsize = 0x0c; break; /* 128 MB */
+ case 0x10000000: apsize = 0x08; break; /* 256 MB */
+ case 0x20000000: apsize = 0x00; break; /* 512 MB */
+ default:
+ return (EINVAL);
+ }
+
+ pci_cfgregwrite(0, 11, 0, AGP_AMD64_NVIDIA_1_APSIZE,
+ (pci_cfgregread(0, 11, 0, AGP_AMD64_NVIDIA_1_APSIZE, 4) &
+ 0xfffffff0) | apsize, 4);
+ pci_cfgregwrite(0, 11, 0, AGP_AMD64_NVIDIA_1_APLIMIT1,
+ sc->apbase + aperture - 1, 4);
+ pci_cfgregwrite(0, 11, 0, AGP_AMD64_NVIDIA_1_APLIMIT2,
+ sc->apbase + aperture - 1, 4);
+
+ return (0);
+}
+static void
+agp_amd64_via_init(device_t dev)
+{
+ struct agp_amd64_softc *sc = device_get_softc(dev);
+
+ agp_amd64_apbase_fixup(dev);
+ pci_cfgregwrite(0, 1, 0, AGP3_VIA_ATTBASE, sc->gatt->ag_physical, 4);
+ pci_cfgregwrite(0, 1, 0, AGP3_VIA_GARTCTRL,
+ pci_cfgregread(0, 1, 0, AGP3_VIA_ATTBASE, 4) | 0x180, 4);
+}
+
+static int
+agp_amd64_via_set_aperture(device_t dev, uint32_t aperture)
+{
+ uint32_t apsize;
+
+ apsize = ((aperture - 1) >> 20) ^ 0xff;
+ if ((((apsize ^ 0xff) << 20) | ((1 << 20) - 1)) + 1 != aperture)
+ return (EINVAL);
+ pci_cfgregwrite(0, 1, 0, AGP3_VIA_APSIZE, apsize, 1);
+
+ return (0);
+}
+
+static device_method_t agp_amd64_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, agp_amd64_probe),
+ DEVMETHOD(device_attach, agp_amd64_attach),
+ DEVMETHOD(device_detach, agp_amd64_detach),
+ DEVMETHOD(device_shutdown, bus_generic_shutdown),
+ DEVMETHOD(device_suspend, bus_generic_suspend),
+ DEVMETHOD(device_resume, bus_generic_resume),
+
+ /* AGP interface */
+ DEVMETHOD(agp_get_aperture, agp_amd64_get_aperture),
+ DEVMETHOD(agp_set_aperture, agp_amd64_set_aperture),
+ DEVMETHOD(agp_bind_page, agp_amd64_bind_page),
+ DEVMETHOD(agp_unbind_page, agp_amd64_unbind_page),
+ DEVMETHOD(agp_flush_tlb, agp_amd64_flush_tlb),
+ DEVMETHOD(agp_enable, agp_generic_enable),
+ DEVMETHOD(agp_alloc_memory, agp_generic_alloc_memory),
+ DEVMETHOD(agp_free_memory, agp_generic_free_memory),
+ DEVMETHOD(agp_bind_memory, agp_generic_bind_memory),
+ DEVMETHOD(agp_unbind_memory, agp_generic_unbind_memory),
+
+ { 0, 0 }
+};
+
+static driver_t agp_amd64_driver = {
+ "agp",
+ agp_amd64_methods,
+ sizeof(struct agp_amd64_softc),
+};
+
+static devclass_t agp_devclass;
+
+DRIVER_MODULE(agp_amd64, pci, agp_amd64_driver, agp_devclass, 0, 0);
+MODULE_DEPEND(agp_amd64, agp, 1, 1, 1);
+MODULE_DEPEND(agp_amd64, pci, 1, 1, 1);
diff --git a/sys/dev/agp/agp_ati.c b/sys/dev/agp/agp_ati.c
new file mode 100644
--- /dev/null
+++ b/sys/dev/agp/agp_ati.c
@@ -0,0 +1,393 @@
+/*-
+ * Copyright (c) 2005 Eric Anholt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Based on reading the Linux 2.6.8.1 driver by Dave Jones.
+ *
+ * $FreeBSD: src/sys/pci/agp_ati.c,v 1.3 2006/09/01 02:22:17 anholt Exp $
+ * $DragonFly$
+ */
+
+#include <sys/cdefs.h>
+
+#include "opt_bus.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/lock.h>
+#include <sys/proc.h>
+
+#include <bus/pci/pcivar.h>
+#include <bus/pci/pcireg.h>
+#include "agppriv.h"
+#include "agpreg.h"
+
+#include <vm/vm.h>
+#include <vm/vm_object.h>
+#include <vm/pmap.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+
+MALLOC_DECLARE(M_AGP);
+
+#define READ4(off) bus_space_read_4(sc->bst, sc->bsh, off)
+#define WRITE4(off,v) bus_space_write_4(sc->bst, sc->bsh, off, v)
+
+struct agp_ati_softc {
+ struct agp_softc agp;
+ struct resource *regs; /* memory mapped control registers */
+ bus_space_tag_t bst; /* bus_space tag */
+ bus_space_handle_t bsh; /* bus_space handle */
+ u_int32_t initial_aperture; /* aperture size at startup */
+ char is_rs300;
+
+ /* The GATT */
+ u_int32_t ag_entries;
+ u_int32_t *ag_virtual; /* virtual address of gatt */
+ u_int32_t *ag_vdir; /* virtual address of page dir */
+ vm_offset_t ag_pdir; /* physical address of page dir */
+};
+
+
+static const char*
+agp_ati_match(device_t dev)
+{
+ if (pci_get_class(dev) != PCIC_BRIDGE ||
+ pci_get_subclass(dev) != PCIS_BRIDGE_HOST)
+ return NULL;
+
+ if (agp_find_caps(dev) == 0)
+ return NULL;
+
+ switch (pci_get_devid(dev)) {
+ case 0xcab01002:
+ return ("ATI RS100 AGP bridge");
+ case 0xcab21002:
+ return ("ATI RS200 AGP bridge");
+ case 0xcbb21002:
+ return ("ATI RS200M AGP bridge");
+ case 0xcab31002:
+ return ("ATI RS250 AGP bridge");
+ case 0x58301002:
+ return ("ATI RS300_100 AGP bridge");
+ case 0x58311002:
+ return ("ATI RS300_133 AGP bridge");
+ case 0x58321002:
+ return ("ATI RS300_166 AGP bridge");
+ case 0x58331002:
+ return ("ATI RS300_200 AGP bridge");
+ };
+
+ return NULL;
+}
+
+static int
+agp_ati_probe(device_t dev)
+{
+ const char *desc;
+
+ desc = agp_ati_match(dev);
+ if (desc) {
+ device_verbose(dev);
+ device_set_desc(dev, desc);
+ return 0;
+ }
+
+ return ENXIO;
+}
+
+static int
+agp_ati_alloc_gatt(device_t dev)
+{
+ struct agp_ati_softc *sc = device_get_softc(dev);
+ u_int32_t apsize = AGP_GET_APERTURE(dev);
+ u_int32_t entries = apsize >> AGP_PAGE_SHIFT;
+ u_int32_t apbase_offset;
+ int i;
+
+ /* Alloc the GATT -- pointers to pages of AGP memory */
+ sc->ag_entries = entries;
+ sc->ag_virtual = kmalloc(entries * sizeof(u_int32_t), M_AGP,
+ M_NOWAIT | M_ZERO);
+ if (sc->ag_virtual == NULL) {
+ if (bootverbose)
+ device_printf(dev, "aperture allocation failed\n");
+ return ENOMEM;
+ }
+
+ /* Alloc the page directory -- pointers to each page of the GATT */
+ sc->ag_vdir = kmalloc(AGP_PAGE_SIZE, M_AGP, M_NOWAIT | M_ZERO);
+ if (sc->ag_vdir == NULL) {
+ if (bootverbose)
+ device_printf(dev, "pagedir allocation failed\n");
+ kfree(sc->ag_virtual, M_AGP);
+ return ENOMEM;
+ }
+ sc->ag_pdir = vtophys((vm_offset_t)sc->ag_vdir);
+
+ apbase_offset = pci_read_config(dev, AGP_APBASE, 4) >> 22;
+ /* Fill in the pagedir's pointers to GATT pages */
+ for (i = 0; i < sc->ag_entries / 1024; i++) {
+ vm_offset_t va;
+ vm_offset_t pa;
+
+ va = ((vm_offset_t)sc->ag_virtual) + i * AGP_PAGE_SIZE;
+ pa = vtophys(va);
+ sc->ag_vdir[apbase_offset + i] = pa | 1;
+ }
+
+ /*
+ * Make sure the chipset can see everything.
+ */
+ agp_flush_cache();
+
+ return 0;
+}
+
+
+static int
+agp_ati_attach(device_t dev)
+{
+ struct agp_ati_softc *sc = device_get_softc(dev);
+ int error, rid;
+ u_int32_t temp;
+ u_int32_t apsize_reg, agpmode_reg;
+
+ error = agp_generic_attach(dev);
+ if (error)
+ return error;
+
+ switch (pci_get_devid(dev)) {
+ case 0xcab01002: /* ATI RS100 AGP bridge */
+ case 0xcab21002: /* ATI RS200 AGP bridge */
+ case 0xcbb21002: /* ATI RS200M AGP bridge */
+ case 0xcab31002: /* ATI RS250 AGP bridge */
+ sc->is_rs300 = 0;
+ apsize_reg = ATI_RS100_APSIZE;
+ agpmode_reg = ATI_RS100_IG_AGPMODE;
+ break;
+ case 0x58301002: /* ATI RS300_100 AGP bridge */
+ case 0x58311002: /* ATI RS300_133 AGP bridge */
+ case 0x58321002: /* ATI RS300_166 AGP bridge */
+ case 0x58331002: /* ATI RS300_200 AGP bridge */
+ sc->is_rs300 = 1;
+ apsize_reg = ATI_RS300_APSIZE;
+ agpmode_reg = ATI_RS300_IG_AGPMODE;
+ break;
+ default:
+ /* Unknown chipset */
+ return EINVAL;
+ };
+
+ rid = ATI_GART_MMADDR;
+ sc->regs = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
+ if (!sc->regs) {
+ agp_generic_detach(dev);
+ return ENOMEM;
+ }
+
+ sc->bst = rman_get_bustag(sc->regs);
+ sc->bsh = rman_get_bushandle(sc->regs);
+
+ sc->initial_aperture = AGP_GET_APERTURE(dev);
+ if (sc->initial_aperture == 0) {
+ device_printf(dev, "bad initial aperture size, disabling\n");
+ return ENXIO;
+ }
+
+ for (;;) {
+ if (agp_ati_alloc_gatt(dev) == 0)
+ break;
+
+ /*
+ * Probably contigmalloc failure. Try reducing the
+ * aperture so that the gatt size reduces.
+ */
+ if (AGP_SET_APERTURE(dev, AGP_GET_APERTURE(dev) / 2))
+ return ENOMEM;
+ }
+
+ temp = pci_read_config(dev, apsize_reg, 4);
+ pci_write_config(dev, apsize_reg, temp | 1, 4);
+
+ pci_write_config(dev, agpmode_reg, 0x20000, 4);
+
+ WRITE4(ATI_GART_FEATURE_ID, 0x00060000);
+
+ temp = pci_read_config(dev, 4, 4); /* XXX: Magic reg# */
+ pci_write_config(dev, 4, temp | (1 << 14), 4);
+
+ WRITE4(ATI_GART_BASE, sc->ag_pdir);
+
+ AGP_FLUSH_TLB(dev);
+
+ return 0;
+}
+
+static int
+agp_ati_detach(device_t dev)
+{
+ struct agp_ati_softc *sc = device_get_softc(dev);
+ int error;
+ u_int32_t apsize_reg, temp;
+
+ if (sc->is_rs300)
+ apsize_reg = ATI_RS300_APSIZE;
+ else
+ apsize_reg = ATI_RS100_APSIZE;
+
+ error = agp_generic_detach(dev);
+ if (error)
+ return error;
+
+ /* Clear the GATT base */
+ WRITE4(ATI_GART_BASE, 0);
+
+ /* Put the aperture back the way it started. */
+ AGP_SET_APERTURE(dev, sc->initial_aperture);
+
+ temp = pci_read_config(dev, apsize_reg, 4);
+ pci_write_config(dev, apsize_reg, temp & ~1, 4);
+
+ kfree(sc->ag_vdir, M_AGP);
+ kfree(sc->ag_virtual, M_AGP);
+
+ bus_release_resource(dev, SYS_RES_MEMORY, ATI_GART_MMADDR, sc->regs);
+
+ return 0;
+}
+
+static u_int32_t
+agp_ati_get_aperture(device_t dev)
+{
+ struct agp_ati_softc *sc = device_get_softc(dev);
+ int size_value;
+
+ if (sc->is_rs300)
+ size_value = pci_read_config(dev, ATI_RS300_APSIZE, 4);
+ else
+ size_value = pci_read_config(dev, ATI_RS100_APSIZE, 4);
+
+ size_value = (size_value & 0x0000000e) >> 1;
+ size_value = (32 * 1024 * 1024) << size_value;
+
+ return size_value;
+}
+
+static int
+agp_ati_set_aperture(device_t dev, u_int32_t aperture)
+{
+ struct agp_ati_softc *sc = device_get_softc(dev);
+ int size_value;
+ u_int32_t apsize_reg;
+
+ if (sc->is_rs300)
+ apsize_reg = ATI_RS300_APSIZE;
+ else
+ apsize_reg = ATI_RS100_APSIZE;
+
+ size_value = pci_read_config(dev, apsize_reg, 4);
+
+ size_value &= ~0x0000000e;
+ size_value |= (ffs(aperture / (32 * 1024 * 1024)) - 1) << 1;
+
+ pci_write_config(dev, apsize_reg, size_value, 4);
+
+ return 0;
+}
+
+static int
+agp_ati_bind_page(device_t dev, int offset, vm_offset_t physical)
+{
+ struct agp_ati_softc *sc = device_get_softc(dev);
+
+ if (offset < 0 || offset >= (sc->ag_entries << AGP_PAGE_SHIFT))
+ return EINVAL;
+
+ sc->ag_virtual[offset >> AGP_PAGE_SHIFT] = physical | 1;
+
+ return 0;
+}
+
+static int
+agp_ati_unbind_page(device_t dev, int offset)
+{
+ struct agp_ati_softc *sc = device_get_softc(dev);
+
+ if (offset < 0 || offset >= (sc->ag_entries << AGP_PAGE_SHIFT))
+ return EINVAL;
+
+ sc->ag_virtual[offset >> AGP_PAGE_SHIFT] = 0;
+ return 0;
+}
+
+static void
+agp_ati_flush_tlb(device_t dev)
+{
+ struct agp_ati_softc *sc = device_get_softc(dev);
+
+ /* Set the cache invalidate bit and wait for the chipset to clear */
+ WRITE4(ATI_GART_CACHE_CNTRL, 1);
+ (void)READ4(ATI_GART_CACHE_CNTRL);
+}
+
+static device_method_t agp_ati_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, agp_ati_probe),
+ DEVMETHOD(device_attach, agp_ati_attach),
+ DEVMETHOD(device_detach, agp_ati_detach),
+ DEVMETHOD(device_shutdown, bus_generic_shutdown),
+ DEVMETHOD(device_suspend, bus_generic_suspend),
+ DEVMETHOD(device_resume, bus_generic_resume),
+
+ /* AGP interface */
+ DEVMETHOD(agp_get_aperture, agp_ati_get_aperture),
+ DEVMETHOD(agp_set_aperture, agp_ati_set_aperture),
+ DEVMETHOD(agp_bind_page, agp_ati_bind_page),
+ DEVMETHOD(agp_unbind_page, agp_ati_unbind_page),
+ DEVMETHOD(agp_flush_tlb, agp_ati_flush_tlb),
+ DEVMETHOD(agp_enable, agp_generic_enable),
+ DEVMETHOD(agp_alloc_memory, agp_generic_alloc_memory),
+ DEVMETHOD(agp_free_memory, agp_generic_free_memory),
+ DEVMETHOD(agp_bind_memory, agp_generic_bind_memory),
+ DEVMETHOD(agp_unbind_memory, agp_generic_unbind_memory),
+
+ { 0, 0 }
+};
+
+static driver_t agp_ati_driver = {
+ "agp",
+ agp_ati_methods,
+ sizeof(struct agp_ati_softc),
+};
+
+static devclass_t agp_devclass;
+
+DRIVER_MODULE(agp_ati, pci, agp_ati_driver, agp_devclass, 0, 0);
+MODULE_DEPEND(agp_ati, agp, 1, 1, 1);
+MODULE_DEPEND(agp_ati, pci, 1, 1, 1);
diff --git a/sys/dev/agp/agp_i810.c b/sys/dev/agp/agp_i810.c
--- a/sys/dev/agp/agp_i810.c
+++ b/sys/dev/agp/agp_i810.c
@@ -24,16 +24,16 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/sys/pci/agp_i810.c,v 1.1.2.5 2002/09/15 08:45:41 anholt Exp $
+ * $FreeBSD: src/sys/pci/agp_i810.c,v 1.40 2007/07/13 16:28:12 anholt Exp $
* $DragonFly: src/sys/dev/agp/agp_i810.c,v 1.11 2006/12/22 23:26:14 swildner Exp $
*/
/*
* Fixes for 830/845G support: David Dawes <dawes at xfree86.org>
+ * 852GM/855GM/865G support added by David Dawes <dawes at xfree86.org>
*/
#include "opt_bus.h"
-#include "opt_pci.h"
#include <sys/param.h>
#include <sys/systm.h>
@@ -54,15 +54,47 @@
#include <vm/vm_pageout.h>
#include <vm/pmap.h>
+#include <machine/md_var.h>
+
+#define bus_read_1(r, o) \
+ bus_space_read_1((r)->r_bustag, (r)->r_bushandle, (o))
+#define bus_read_4(r, o) \
+ bus_space_read_4((r)->r_bustag, (r)->r_bushandle, (o))
+#define bus_write_4(r, o, v) \
+ bus_space_write_4((r)->r_bustag, (r)->r_bushandle, (o), (v))
+
MALLOC_DECLARE(M_AGP);
-#define READ1(off) bus_space_read_1(sc->bst, sc->bsh, off)
-#define READ4(off) bus_space_read_4(sc->bst, sc->bsh, off)
-#define WRITE4(off,v) bus_space_write_4(sc->bst, sc->bsh, off, v)
-
-#define CHIP_I810 0 /* i810/i815 */
-#define CHIP_I830 1 /* 830M/845G */
-#define CHIP_I855 2 /* 852GM/855GM/865G */
+enum {
+ CHIP_I810, /* i810/i815 */
+ CHIP_I830, /* 830M/845G */
+ CHIP_I855, /* 852GM/855GM/865G */
+ CHIP_I915, /* 915G/915GM */
+ CHIP_I965, /* G965 */
+ CHIP_G33, /* G33/Q33/Q35 */
+};
+
+/* The i810 through i855 have the registers at BAR 1, and the GATT gets
+ * allocated by us. The i915 has registers in BAR 0 and the GATT is at the
+ * start of the stolen memory, and should only be accessed by the OS through
+ * BAR 3. The G965 has registers and GATT in the same BAR (0) -- first 512KB
+ * is registers, second 512KB is GATT.
+ */
+static struct resource_spec agp_i810_res_spec[] = {
+ { SYS_RES_MEMORY, AGP_I810_MMADR, RF_ACTIVE | RF_SHAREABLE },
+ { -1, 0 }
+};
+
+static struct resource_spec agp_i915_res_spec[] = {
+ { SYS_RES_MEMORY, AGP_I915_MMADR, RF_ACTIVE | RF_SHAREABLE },
+ { SYS_RES_MEMORY, AGP_I915_GTTADR, RF_ACTIVE | RF_SHAREABLE },
+ { -1, 0 }
+};
+
+static struct resource_spec agp_i965_res_spec[] = {
+ { SYS_RES_MEMORY, AGP_I965_GTTMMADR, RF_ACTIVE | RF_SHAREABLE },
+ { -1, 0 }
+};
struct agp_i810_softc {
struct agp_softc agp;
@@ -72,61 +104,89 @@ struct agp_i810_softc {
u_int32_t dcache_size; /* i810 only */
u_int32_t stolen; /* number of i830/845 gtt entries for stolen memory */
device_t bdev; /* bridge device */
- struct resource *regs; /* memory mapped GC registers */
- bus_space_tag_t bst; /* bus_space tag */
- bus_space_handle_t bsh; /* bus_space handle */
+
+ void *argb_cursor; /* contigmalloc area for ARGB cursor */
+
+ struct resource_spec * sc_res_spec;
+ struct resource *sc_res[2];
};
-static const char*
+/* For adding new devices, devid is the id of the graphics controller
+ * (pci:0:2:0, for example). The placeholder (usually at pci:0:2:1) for the
+ * second head should never be added. The bridge_offset is the offset to
+ * subtract from devid to get the id of the hostb that the device is on.
+ */
+static const struct agp_i810_match {
+ int devid;
+ int chiptype;
+ int bridge_offset;
+ char *name;
+} agp_i810_matches[] = {
+ {0x71218086, CHIP_I810, 0x00010000,
+ "Intel 82810 (i810 GMCH) SVGA controller"},
+ {0x71238086, CHIP_I810, 0x00010000,
+ "Intel 82810-DC100 (i810-DC100 GMCH) SVGA controller"},
+ {0x71258086, CHIP_I810, 0x00010000,
+ "Intel 82810E (i810E GMCH) SVGA controller"},
+ {0x11328086, CHIP_I810, 0x00020000,
+ "Intel 82815 (i815 GMCH) SVGA controller"},
+ {0x35778086, CHIP_I830, 0x00020000,
+ "Intel 82830M (830M GMCH) SVGA controller"},
+ {0x35828086, CHIP_I855, 0x00020000,
+ "Intel 82852/5"},
+ {0x25728086, CHIP_I855, 0x00020000,
+ "Intel 82865G (865G GMCH) SVGA controller"},
+ {0x25828086, CHIP_I915, 0x00020000,
+ "Intel 82915G (915G GMCH) SVGA controller"},
+ {0x25928086, CHIP_I915, 0x00020000,
+ "Intel 82915GM (915GM GMCH) SVGA controller"},
+ {0x27728086, CHIP_I915, 0x00020000,
+ "Intel 82945G (945G GMCH) SVGA controller"},
+ {0x27A28086, CHIP_I915, 0x00020000,
+ "Intel 82945GM (945GM GMCH) SVGA controller"},
+ {0x27A28086, CHIP_I915, 0x00020000,
+ "Intel 945GME SVGA controller"},
+ {0x29728086, CHIP_I965, 0x00020000,
+ "Intel 946GZ SVGA controller"},
+ {0x29828086, CHIP_I965, 0x00020000,
+ "Intel G965 SVGA controller"},
+ {0x29928086, CHIP_I965, 0x00020000,
+ "Intel Q965 SVGA controller"},
+ {0x29a28086, CHIP_I965, 0x00020000,
+ "Intel G965 SVGA controller"},
+/*
+ {0x29b28086, CHIP_G33, 0x00020000,
+ "Intel Q35 SVGA controller"},
+ {0x29c28086, CHIP_G33, 0x00020000,
+ "Intel G33 SVGA controller"},
+ {0x29d28086, CHIP_G33, 0x00020000,
+ "Intel Q33 SVGA controller"},
+*/
+ {0x2a028086, CHIP_I965, 0x00020000,
+ "Intel GM965 SVGA controller"},
+ {0x2a128086, CHIP_I965, 0x00020000,
+ "Intel GME965 SVGA controller"},
+ {0, 0, 0, NULL}
+};
+
+static const struct agp_i810_match*
agp_i810_match(device_t dev)
{
+ int i, devid;
+
if (pci_get_class(dev) != PCIC_DISPLAY
|| pci_get_subclass(dev) != PCIS_DISPLAY_VGA)
return NULL;
- switch (pci_get_devid(dev)) {
- case 0x71218086:
- return ("Intel 82810 (i810 GMCH) SVGA controller");
-
- case 0x71238086:
- return ("Intel 82810-DC100 (i810-DC100 GMCH) SVGA controller");
-
- case 0x71258086:
- return ("Intel 82810E (i810E GMCH) SVGA controller");
-
- case 0x11328086:
- return ("Intel 82815 (i815 GMCH) SVGA controller");
-
- case 0x35778086:
- return ("Intel 82830M (i830M GMCH) SVGA controller");
-
- case 0x25628086:
- return ("Intel 82845G (i845 GMCH) SVGA controller");
-
- case 0x25728086:
- return ("Intel 82865G (i865 GMCH) SVGA controller");
-
- case 0x35828086:
- switch (pci_read_config(dev, AGP_I85X_CAPID, 1)) {
- case AGP_I855_GME:
- return ("Intel 82855GME (855GME GMCH) SVGA controller");
-
- case AGP_I855_GM:
- return ("Intel 82855GM (855GM GMCH) SVGA controller");
-
- case AGP_I852_GME:
- return ("Intel 82852GME (852GME GMCH) SVGA controller");
-
- case AGP_I852_GM:
- return ("Intel 82852GM (852GM GMCH) SVGA controller");
-
- default:
- return ("Intel 8285xM (85xGM GMCH) SVGA controller");
- }
- /* not reached */
- };
-
- return NULL;
+ devid = pci_get_devid(dev);
+ for (i = 0; agp_i810_matches[i].devid != 0; i++) {
+ if (agp_i810_matches[i].devid == devid)
+ break;
+ }
+ if (agp_i810_matches[i].devid == 0)
+ return NULL;
+ else
+ return &agp_i810_matches[i];
}
/*
@@ -138,25 +198,11 @@ agp_i810_find_bridge(device_t dev)
device_t *children, child;
int nchildren, i;
u_int32_t devid;
-
- /*
- * Calculate bridge device's ID.
- */
- devid = pci_get_devid(dev);
- switch (devid) {
- case 0x71218086:
- case 0x71238086:
- case 0x71258086:
- devid -= 0x10000;
- break;
-
- case 0x11328086:
- case 0x35778086:
- case 0x25628086:
- case 0x25728086:
- devid -= 0x20000;
- break;
- };
+ const struct agp_i810_match *match;
+
+ match = agp_i810_match(dev);
+ devid = match->devid - match->bridge_offset;
+
if (device_get_children(device_get_parent(dev), &children, &nchildren))
return 0;
@@ -172,64 +218,135 @@ agp_i810_find_bridge(device_t dev)
return 0;
}
+static void
+agp_i810_identify(driver_t *driver, device_t parent)
+{
+
+ if (device_find_child(parent, "agp", -1) == NULL &&
+ agp_i810_match(parent))
+ device_add_child(parent, "agp", -1);
+}
+
static int
agp_i810_probe(device_t dev)
{
- const char *desc;
-
- desc = agp_i810_match(dev);
- if (desc) {
- device_t bdev;
- u_int8_t smram;
- unsigned int gcc1;
- int devid = pci_get_devid(dev);
-
- bdev = agp_i810_find_bridge(dev);
- if (!bdev) {
+ device_t bdev;
+ const struct agp_i810_match *match;
+ u_int8_t smram;
+ int gcc1, deven;
+
+ if (resource_disabled("agp", device_get_unit(dev)))
+ return (ENXIO);
+ match = agp_i810_match(dev);
+ if (match == NULL)
+ return ENXIO;
+
+ bdev = agp_i810_find_bridge(dev);
+ if (!bdev) {
+ if (bootverbose)
+ kprintf("I810: can't find bridge device\n");
+ return ENXIO;
+ }
+
+ /*
+ * checking whether internal graphics device has been activated.
+ */
+ switch (match->chiptype) {
+ case CHIP_I810:
+ smram = pci_read_config(bdev, AGP_I810_SMRAM, 1);
+ if ((smram & AGP_I810_SMRAM_GMS) ==
+ AGP_I810_SMRAM_GMS_DISABLED) {
if (bootverbose)
- kprintf("I810: can't find bridge device\n");
+ kprintf("I810: disabled, not probing\n");
return ENXIO;
}
-
- /*
- * checking whether internal graphics device has been activated.
- */
- switch(devid) {
- case 0x71218086:
- case 0x71238086:
- case 0x71258086:
- case 0x11328086:
- /* i810 */
- smram = pci_read_config(bdev, AGP_I810_SMRAM, 1);
- if ((smram & AGP_I810_SMRAM_GMS)
- == AGP_I810_SMRAM_GMS_DISABLED) {
- if (bootverbose)
- kprintf("I810: disabled, not probing\n");
- return ENXIO;
- }
- break;
- case 0x35778086:
- case 0x35828086:
- case 0x25628086:
- case 0x25728086:
- /* i830 */
- gcc1 = pci_read_config(bdev, AGP_I830_GCC1, 1);
- if ((gcc1 & AGP_I830_GCC1_DEV2) == AGP_I830_GCC1_DEV2_DISABLED) {
- if (bootverbose)
- kprintf("I830: disabled, not probing\n");
- return ENXIO;
- }
+ break;
+ case CHIP_I830:
+ case CHIP_I855:
+ gcc1 = pci_read_config(bdev, AGP_I830_GCC1, 1);
+ if ((gcc1 & AGP_I830_GCC1_DEV2) ==
+ AGP_I830_GCC1_DEV2_DISABLED) {
+ if (bootverbose)
+ kprintf("I830: disabled, not probing\n");
+ return ENXIO;
+ }
+ break;
+ case CHIP_I915:
+ case CHIP_I965:
+ case CHIP_G33:
+ deven = pci_read_config(bdev, AGP_I915_DEVEN, 4);
+ if ((deven & AGP_I915_DEVEN_D2F0) ==
+ AGP_I915_DEVEN_D2F0_DISABLED) {
+ if (bootverbose)
+ kprintf("I915: disabled, not probing\n");
+ return ENXIO;
+ }
+ break;
+ }
+
+ device_verbose(dev);
+ if (match->devid == 0x35828086) {
+ switch (pci_read_config(dev, AGP_I85X_CAPID, 1)) {
+ case AGP_I855_GME:
+ device_set_desc(dev,
+ "Intel 82855GME (855GME GMCH) SVGA controller");
+ break;
+ case AGP_I855_GM:
+ device_set_desc(dev,
+ "Intel 82855GM (855GM GMCH) SVGA controller");
+ break;
+ case AGP_I852_GME:
+ device_set_desc(dev,
+ "Intel 82852GME (852GME GMCH) SVGA controller");
+ break;
+ case AGP_I852_GM:
+ device_set_desc(dev,
+ "Intel 82852GM (852GM GMCH) SVGA controller");
break;
default:
- return ENXIO;
- }
-
- device_verbose(dev);
- device_set_desc(dev, desc);
- return 0;
- }
-
- return ENXIO;
+ device_set_desc(dev,
+ "Intel 8285xM (85xGM GMCH) SVGA controller");
+ break;
+ }
+ } else {
+ device_set_desc(dev, match->name);
+ }
+
+ return BUS_PROBE_DEFAULT;
+}
+
+static void
+agp_i810_dump_regs(device_t dev)
+{
+ struct agp_i810_softc *sc = device_get_softc(dev);
+
+ device_printf(dev, "AGP_I810_PGTBL_CTL: %08x\n",
+ bus_read_4(sc->sc_res[0], AGP_I810_PGTBL_CTL));
+
+ switch (sc->chiptype) {
+ case CHIP_I810:
+ device_printf(dev, "AGP_I810_MISCC: 0x%04x\n",
+ pci_read_config(sc->bdev, AGP_I810_MISCC, 2));
+ break;
+ case CHIP_I830:
+ device_printf(dev, "AGP_I830_GCC1: 0x%02x\n",
+ pci_read_config(sc->bdev, AGP_I830_GCC1, 1));
+ break;
+ case CHIP_I855:
+ device_printf(dev, "AGP_I855_GCC1: 0x%02x\n",
+ pci_read_config(sc->bdev, AGP_I855_GCC1, 1));
+ break;
+ case CHIP_I915:
+ case CHIP_I965:
+ case CHIP_G33:
+ device_printf(dev, "AGP_I855_GCC1: 0x%02x\n",
+ pci_read_config(sc->bdev, AGP_I855_GCC1, 1));
+ device_printf(dev, "AGP_I915_MSAC: 0x%02x\n",
+ pci_read_config(sc->bdev, AGP_I915_MSAC, 1));
+ break;
+ }
+ device_printf(dev, "Aperture resource size: %d bytes\n",
+ AGP_GET_APERTURE(dev));
}
static int
@@ -237,43 +354,50 @@ agp_i810_attach(device_t dev)
{
struct agp_i810_softc *sc = device_get_softc(dev);
struct agp_gatt *gatt;
- int error, rid;
+ const struct agp_i810_match *match;
+ int error;
sc->bdev = agp_i810_find_bridge(dev);
if (!sc->bdev)
return ENOENT;
+ match = agp_i810_match(dev);
+ sc->chiptype = match->chiptype;
+
+ switch (sc->chiptype) {
+ case CHIP_I810:
+ case CHIP_I830:
+ case CHIP_I855:
+ sc->sc_res_spec = agp_i810_res_spec;
+ agp_set_aperture_resource(dev, AGP_APBASE);
+ break;
+ case CHIP_I915:
+ case CHIP_G33:
+ sc->sc_res_spec = agp_i915_res_spec;
+ agp_set_aperture_resource(dev, AGP_I915_GMADR);
+ break;
+ case CHIP_I965:
+ sc->sc_res_spec = agp_i965_res_spec;
+ agp_set_aperture_resource(dev, AGP_I915_GMADR);
+ break;
+ }
+
error = agp_generic_attach(dev);
if (error)
return error;
- switch (pci_get_devid(dev)) {
- case 0x71218086:
- case 0x71238086:
- case 0x71258086:
- case 0x11328086:
- sc->chiptype = CHIP_I810;
- break;
- case 0x35778086:
- case 0x25628086:
- sc->chiptype = CHIP_I830;
- break;
- case 0x25728086:
- case 0x35828086:
- sc->chiptype = CHIP_I855;
- break;
- };
-
- /* Same for i810 and i830 */
- rid = AGP_I810_MMADR;
- sc->regs = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid,
- 0, ~0, 1, RF_ACTIVE);
- if (!sc->regs) {
+ if (sc->chiptype != CHIP_I965 && sc->chiptype != CHIP_G33 &&
+ ptoa((vm_paddr_t)Maxmem) > 0xfffffffful)
+ {
+ device_printf(dev, "agp_i810.c does not support physical "
+ "memory above 4GB.\n");
+ return ENOENT;
+ }
+
+ if (bus_alloc_resources(dev, sc->sc_res_spec, sc->sc_res)) {
agp_generic_detach(dev);
- return ENOMEM;
- }
- sc->bst = rman_get_bustag(sc->regs);
- sc->bsh = rman_get_bushandle(sc->regs);
+ return ENODEV;
+ }
sc->initial_aperture = AGP_GET_APERTURE(dev);
if (sc->initial_aperture == 0) {
@@ -288,7 +412,8 @@ agp_i810_attach(device_t dev)
if ( sc->chiptype == CHIP_I810 ) {
/* Some i810s have on-chip memory called dcache */
- if (READ1(AGP_I810_DRT) & AGP_I810_DRT_POPULATED)
+ if (bus_read_1(sc->sc_res[0], AGP_I810_DRT) &
+ AGP_I810_DRT_POPULATED)
sc->dcache_size = 4 * 1024 * 1024;
else
sc->dcache_size = 0;
@@ -299,6 +424,8 @@ agp_i810_attach(device_t dev)
if (!gatt->ag_virtual) {
if (bootverbose)
device_printf(dev, "contiguous allocation failed\n");
+ bus_release_resources(dev, sc->sc_res_spec,
+ sc->sc_res);
kfree(gatt, M_AGP);
agp_generic_detach(dev);
return ENOMEM;
@@ -308,8 +435,9 @@ agp_i810_attach(device_t dev)
gatt->ag_physical = vtophys((vm_offset_t) gatt->ag_virtual);
agp_flush_cache();
/* Install the GATT. */
- WRITE4(AGP_I810_PGTBL_CTL, gatt->ag_physical | 1);
- } else if (sc->chiptype == CHIP_I830) {
+ bus_write_4(sc->sc_res[0], AGP_I810_PGTBL_CTL,
+ gatt->ag_physical | 1);
+ } else if ( sc->chiptype == CHIP_I830 ) {
/* The i830 automatically initializes the 128k gatt on boot. */
unsigned int gcc1, pgtblctl;
@@ -327,63 +455,126 @@ agp_i810_attach(device_t dev)
default:
device_printf(dev, "unknown memory configuration, disabling\n");
+ bus_release_resources(dev, sc->sc_res_spec,
+ sc->sc_res);
+ kfree(gatt, M_AGP);
agp_generic_detach(dev);
return EINVAL;
}
if (sc->stolen > 0) {
- device_printf(dev,
- "detected %dk stolen memory\n", sc->stolen * 4);
- }
- device_printf(dev, "aperture size is %dM\n", sc->initial_aperture / 1024 / 1024);
+ device_printf(dev, "detected %dk stolen memory\n",
+ sc->stolen * 4);
+ }
+ device_printf(dev, "aperture size is %dM\n",
+ sc->initial_aperture / 1024 / 1024);
/* GATT address is already in there, make sure it's enabled */
- pgtblctl = READ4(AGP_I810_PGTBL_CTL);
+ pgtblctl = bus_read_4(sc->sc_res[0], AGP_I810_PGTBL_CTL);
pgtblctl |= 1;
- WRITE4(AGP_I810_PGTBL_CTL, pgtblctl);
+ bus_write_4(sc->sc_res[0], AGP_I810_PGTBL_CTL, pgtblctl);
gatt->ag_physical = pgtblctl & ~1;
- } else { /* CHIP_I855 */
- /* The i855 automatically initializes the 128k gatt on boot. */
- unsigned int gcc1, pgtblctl;
-
+ } else if (sc->chiptype == CHIP_I855 || sc->chiptype == CHIP_I915 ||
+ sc->chiptype == CHIP_I965 || sc->chiptype == CHIP_G33) {
+ unsigned int gcc1, pgtblctl, stolen, gtt_size;
+
+ /* Stolen memory is set up at the beginning of the aperture by
+ * the BIOS, consisting of the GATT followed by 4kb for the
+ * BIOS display.
+ */
+ switch (sc->chiptype) {
+ case CHIP_I855:
+ gtt_size = 128;
+ break;
+ case CHIP_I915:
+ gtt_size = 256;
+ break;
+ case CHIP_I965:
+ case CHIP_G33:
+ switch (bus_read_4(sc->sc_res[0], AGP_I810_PGTBL_CTL) &
+ AGP_I810_PGTBL_SIZE_MASK) {
+ case AGP_I810_PGTBL_SIZE_128KB:
+ gtt_size = 128;
+ break;
+ case AGP_I810_PGTBL_SIZE_256KB:
+ gtt_size = 256;
+ break;
+ case AGP_I810_PGTBL_SIZE_512KB:
+ gtt_size = 512;
+ break;
+ default:
+ device_printf(dev, "Bad PGTBL size\n");
+ bus_release_resources(dev, sc->sc_res_spec,
+ sc->sc_res);
+ kfree(gatt, M_AGP);
+ agp_generic_detach(dev);
+ return EINVAL;
+ }
+ break;
+ default:
+ device_printf(dev, "Bad chiptype\n");
+ bus_release_resources(dev, sc->sc_res_spec,
+ sc->sc_res);
+ kfree(gatt, M_AGP);
+ agp_generic_detach(dev);
+ return EINVAL;
+ }
+
+ /* GCC1 is called MGGC on i915+ */
gcc1 = pci_read_config(sc->bdev, AGP_I855_GCC1, 1);
switch (gcc1 & AGP_I855_GCC1_GMS) {
case AGP_I855_GCC1_GMS_STOLEN_1M:
- sc->stolen = (1024 - 132) * 1024 / 4096;
+ stolen = 1024;
break;
case AGP_I855_GCC1_GMS_STOLEN_4M:
- sc->stolen = (4096 - 132) * 1024 / 4096;
+ stolen = 4096;
break;
case AGP_I855_GCC1_GMS_STOLEN_8M:
- sc->stolen = (8192 - 132) * 1024 / 4096;
+ stolen = 8192;
break;
case AGP_I855_GCC1_GMS_STOLEN_16M:
- sc->stolen = (16384 - 132) * 1024 / 4096;
+ stolen = 16384;
break;
case AGP_I855_GCC1_GMS_STOLEN_32M:
- sc->stolen = (32768 - 132) * 1024 / 4096;
+ stolen = 32768;
+ break;
+ case AGP_I915_GCC1_GMS_STOLEN_48M:
+ stolen = 49152;
+ break;
+ case AGP_I915_GCC1_GMS_STOLEN_64M:
+ stolen = 65536;
+ break;
+ case AGP_G33_GCC1_GMS_STOLEN_128M:
+ stolen = 128 * 1024;
+ break;
+ case AGP_G33_GCC1_GMS_STOLEN_256M:
+ stolen = 256 * 1024;
break;
default:
- sc->stolen = 0;
- device_printf(dev,
- "unknown memory configuration, disabling\n");
+ device_printf(dev, "unknown memory configuration, "
+ "disabling\n");
+ bus_release_resources(dev, sc->sc_res_spec,
+ sc->sc_res);
+ kfree(gatt, M_AGP);
agp_generic_detach(dev);
return EINVAL;
}
- if (sc->stolen > 0) {
- device_printf(dev, "detected %dk stolen memory\n",
- sc->stolen * 4);
- }
- device_printf(dev, "aperture size is %dM\n",
- sc->initial_aperture / 1024 / 1024);
+ sc->stolen = (stolen - gtt_size - 4) * 1024 / 4096;
+ if (sc->stolen > 0)
+ device_printf(dev, "detected %dk stolen memory\n", sc->stolen * 4);
+ device_printf(dev, "aperture size is %dM\n", sc->initial_aperture / 1024 / 1024);
/* GATT address is already in there, make sure it's enabled */
- pgtblctl = READ4(AGP_I810_PGTBL_CTL);
+ pgtblctl = bus_read_4(sc->sc_res[0], AGP_I810_PGTBL_CTL);
pgtblctl |= 1;
- WRITE4(AGP_I810_PGTBL_CTL, pgtblctl);
+ bus_write_4(sc->sc_res[0], AGP_I810_PGTBL_CTL, pgtblctl);
gatt->ag_physical = pgtblctl & ~1;
- }
+ }
+
+ if (0)
+ agp_i810_dump_regs(dev);
+
return 0;
}
@@ -399,12 +590,12 @@ agp_i810_detach(device_t dev)
/* Clear the GATT base. */
if ( sc->chiptype == CHIP_I810 ) {
- WRITE4(AGP_I810_PGTBL_CTL, 0);
+ bus_write_4(sc->sc_res[0], AGP_I810_PGTBL_CTL, 0);
} else {
unsigned int pgtblctl;
- pgtblctl = READ4(AGP_I810_PGTBL_CTL);
+ pgtblctl = bus_read_4(sc->sc_res[0], AGP_I810_PGTBL_CTL);
pgtblctl &= ~1;
- WRITE4(AGP_I810_PGTBL_CTL, pgtblctl);
+ bus_write_4(sc->sc_res[0], AGP_I810_PGTBL_CTL, pgtblctl);
}
/* Put the aperture back the way it started. */
@@ -415,42 +606,28 @@ agp_i810_detach(device_t dev)
}
kfree(sc->gatt, M_AGP);
- bus_release_resource(dev, SYS_RES_MEMORY,
- AGP_I810_MMADR, sc->regs);
+ bus_release_resources(dev, sc->sc_res_spec, sc->sc_res);
return 0;
}
-static u_int32_t
-agp_i810_get_aperture(device_t dev)
-{
- struct agp_i810_softc *sc = device_get_softc(dev);
-
- if ( sc->chiptype == CHIP_I810 ) {
- u_int16_t miscc;
- miscc = pci_read_config(sc->bdev, AGP_I810_MISCC, 2);
- if ((miscc & AGP_I810_MISCC_WINSIZE) == AGP_I810_MISCC_WINSIZE_32)
- return 32 * 1024 * 1024;
- else
- return 64 * 1024 * 1024;
- } else { /* I830 */
- unsigned int gcc1;
-
- gcc1 = pci_read_config(sc->bdev, AGP_I830_GCC1, 2);
- if ((gcc1 & AGP_I830_GCC1_GMASIZE) == AGP_I830_GCC1_GMASIZE_64)
- return 64 * 1024 * 1024;
- else
- return 128 * 1024 * 1024;
- }
-}
-
+/**
+ * Sets the PCI resource size of the aperture on i830-class and below chipsets,
+ * while returning failure on later chipsets when an actual change is
+ * requested.
+ *
+ * This whole function is likely bogus, as the kernel would probably need to
+ * reconfigure the placement of the AGP aperture if a larger size is requested,
+ * which doesn't happen currently.
+ */
static int
agp_i810_set_aperture(device_t dev, u_int32_t aperture)
{
struct agp_i810_softc *sc = device_get_softc(dev);
- u_int16_t miscc;
-
- if ( sc->chiptype == CHIP_I810 ) {
+ u_int16_t miscc, gcc1;
+
+ switch (sc->chiptype) {
+ case CHIP_I810:
/*
* Double check for sanity.
*/
@@ -458,7 +635,7 @@ agp_i810_set_aperture(device_t dev, u_in
device_printf(dev, "bad aperture size %d\n", aperture);
return EINVAL;
}
-
+
miscc = pci_read_config(sc->bdev, AGP_I810_MISCC, 2);
miscc &= ~AGP_I810_MISCC_WINSIZE;
if (aperture == 32 * 1024 * 1024)
@@ -467,10 +644,10 @@ agp_i810_set_aperture(device_t dev, u_in
miscc |= AGP_I810_MISCC_WINSIZE_64;
pci_write_config(sc->bdev, AGP_I810_MISCC, miscc, 2);
- } else { /* I830 */
- unsigned int gcc1;
-
- if (aperture != 64 * 1024 * 1024 && aperture != 128 * 1024 * 1024) {
+ break;
+ case CHIP_I830:
+ if (aperture != 64 * 1024 * 1024 &&
+ aperture != 128 * 1024 * 1024) {
device_printf(dev, "bad aperture size %d\n", aperture);
return EINVAL;
}
@@ -482,9 +659,57 @@ agp_i810_set_aperture(device_t dev, u_in
gcc1 |= AGP_I830_GCC1_GMASIZE_128;
pci_write_config(sc->bdev, AGP_I830_GCC1, gcc1, 2);
+ break;
+ case CHIP_I855:
+ case CHIP_I915:
+ case CHIP_I965:
+ case CHIP_G33:
+ return agp_generic_set_aperture(dev, aperture);
}
return 0;
+}
+
+/**
+ * Writes a GTT entry mapping the page at the given offset from the beginning
+ * of the aperture to the given physical address.
+ */
+static void
+agp_i810_write_gtt_entry(device_t dev, int offset, vm_offset_t physical,
+ int enabled)
+{
+ struct agp_i810_softc *sc = device_get_softc(dev);
+ u_int32_t pte;
+
+ pte = (u_int32_t)physical | 1;
+ if (sc->chiptype == CHIP_I965 || sc->chiptype == CHIP_G33) {
+ pte |= (physical & 0x0000000f00000000ull) >> 28;
+ } else {
+ /* If we do actually have memory above 4GB on an older system,
+ * crash cleanly rather than scribble on system memory,
+ * so we know we need to fix it.
+ */
+ KASSERT((pte & 0x0000000f00000000ull) == 0,
+ (">4GB physical address in agp"));
+ }
+
+ switch (sc->chiptype) {
+ case CHIP_I810:
+ case CHIP_I830:
+ case CHIP_I855:
+ bus_write_4(sc->sc_res[0],
+ AGP_I810_GTT + (offset >> AGP_PAGE_SHIFT) * 4, pte);
+ break;
+ case CHIP_I915:
+ case CHIP_G33:
+ bus_write_4(sc->sc_res[1],
+ (offset >> AGP_PAGE_SHIFT) * 4, pte);
+ break;
+ case CHIP_I965:
+ bus_write_4(sc->sc_res[0],
+ (offset >> AGP_PAGE_SHIFT) * 4 + (512 * 1024), pte);
+ break;
+ }
}
static int
@@ -497,14 +722,15 @@ agp_i810_bind_page(device_t dev, int off
return EINVAL;
}
- if ( sc->chiptype == CHIP_I830 ) {
+ if ( sc->chiptype != CHIP_I810 ) {
if ( (offset >> AGP_PAGE_SHIFT) < sc->stolen ) {
device_printf(dev, "trying to bind into stolen memory");
return EINVAL;
}
}
- WRITE4(AGP_I810_GTT + (offset >> AGP_PAGE_SHIFT) * 4, physical | 1);
+ agp_i810_write_gtt_entry(dev, offset, physical, 1);
+
return 0;
}
@@ -516,14 +742,15 @@ agp_i810_unbind_page(device_t dev, int o
if (offset < 0 || offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT))
return EINVAL;
- if ( sc->chiptype == CHIP_I830 ) {
+ if ( sc->chiptype != CHIP_I810 ) {
if ( (offset >> AGP_PAGE_SHIFT) < sc->stolen ) {
device_printf(dev, "trying to unbind from stolen memory");
return EINVAL;
}
}
- WRITE4(AGP_I810_GTT + (offset >> AGP_PAGE_SHIFT) * 4, 0);
+ agp_i810_write_gtt_entry(dev, offset, 0, 0);
+
return 0;
}
@@ -558,41 +785,61 @@ agp_i810_alloc_memory(device_t dev, int
/*
* Mapping local DRAM into GATT.
*/
- if ( sc->chiptype == CHIP_I830 )
+ if ( sc->chiptype != CHIP_I810 )
return 0;
if (size != sc->dcache_size)
return 0;
} else if (type == 2) {
/*
- * Bogus mapping of a single page for the hardware cursor.
+ * Type 2 is the contiguous physical memory type, that hands
+ * back a physical address. This is used for cursors on i810.
+ * Hand back as many single pages with physical as the user
+ * wants, but only allow one larger allocation (ARGB cursor)
+ * for simplicity.
*/
- if (size != AGP_PAGE_SIZE)
- return 0;
+ if (size != AGP_PAGE_SIZE) {
+ if (sc->argb_cursor != NULL)
+ return 0;
+
+ /* Allocate memory for ARGB cursor, if we can. */
+ sc->argb_cursor = contigmalloc(size, M_AGP,
+ 0, 0, ~0, PAGE_SIZE, 0);
+ if (sc->argb_cursor == NULL)
+ return 0;
+ }
}
mem = kmalloc(sizeof *mem, M_AGP, M_INTWAIT);
mem->am_id = sc->agp.as_nextid++;
mem->am_size = size;
mem->am_type = type;
- if (type != 1)
+ if (type != 1 && (type != 2 || size == AGP_PAGE_SIZE))
mem->am_obj = vm_object_allocate(OBJT_DEFAULT,
atop(round_page(size)));
else
mem->am_obj = 0;
if (type == 2) {
- /*
- * Allocate and wire down the page now so that we can
- * get its physical address.
- */
- vm_page_t m;
- m = vm_page_grab(mem->am_obj, 0,
- VM_ALLOC_NORMAL|VM_ALLOC_ZERO|VM_ALLOC_RETRY);
- if ((m->flags & PG_ZERO) == 0)
- vm_page_zero_fill(m);
- vm_page_wire(m);
- mem->am_physical = VM_PAGE_TO_PHYS(m);
- vm_page_wakeup(m);
+ if (size == AGP_PAGE_SIZE) {
+ /*
+ * Allocate and wire down the page now so that we can
+ * get its physical address.
+ */
+ vm_page_t m;
+
+ m = vm_page_grab(mem->am_obj, 0,
+ VM_ALLOC_NORMAL|VM_ALLOC_ZERO|VM_ALLOC_RETRY);
+ if ((m->flags & PG_ZERO) == 0)
+ vm_page_zero_fill(m);
+ vm_page_wire(m);
+ mem->am_physical = VM_PAGE_TO_PHYS(m);
+ vm_page_wakeup(m);
+ } else {
+ /* Our allocation is already nicely wired down for us.
+ * Just grab the physical address.
+ */
+ mem->am_physical = vtophys(sc->argb_cursor);
+ }
} else {
mem->am_physical = 0;
}
@@ -614,11 +861,16 @@ agp_i810_free_memory(device_t dev, struc
return EBUSY;
if (mem->am_type == 2) {
- /*
- * Unwire the page which we wired in alloc_memory.
- */
- vm_page_t m = vm_page_lookup(mem->am_obj, 0);
- vm_page_unwire(m, 0);
+ if (mem->am_size == AGP_PAGE_SIZE) {
+ /*
+ * Unwire the page which we wired in alloc_memory.
+ */
+ vm_page_t m = vm_page_lookup(mem->am_obj, 0);
+ vm_page_unwire(m, 0);
+ } else {
+ contigfree(sc->argb_cursor, mem->am_size, M_AGP);
+ sc->argb_cursor = NULL;
+ }
}
sc->agp.as_allocated -= mem->am_size;
@@ -636,15 +888,41 @@ agp_i810_bind_memory(device_t dev, struc
struct agp_i810_softc *sc = device_get_softc(dev);
vm_offset_t i;
+ /* Do some sanity checks first. */
+ if (offset < 0 || (offset & (AGP_PAGE_SIZE - 1)) != 0 ||
+ offset + mem->am_size > AGP_GET_APERTURE(dev)) {
+ device_printf(dev, "binding memory at bad offset %#x\n",
+ (int)offset);
+ return EINVAL;
+ }
+
+ if (mem->am_type == 2 && mem->am_size != AGP_PAGE_SIZE) {
+ lockmgr(&sc->agp.as_lock, LK_EXCLUSIVE);
+ if (mem->am_is_bound) {
+ lockmgr(&sc->agp.as_lock, LK_RELEASE);
+ return EINVAL;
+ }
+ /* The memory's already wired down, just stick it in the GTT. */
+ for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) {
+ agp_i810_write_gtt_entry(dev, offset + i,
+ mem->am_physical + i, 1);
+ }
+ agp_flush_cache();
+ mem->am_offset = offset;
+ mem->am_is_bound = 1;
+ lockmgr(&sc->agp.as_lock, LK_RELEASE);
+ return 0;
+ }
+
if (mem->am_type != 1)
return agp_generic_bind_memory(dev, mem, offset);
- if ( sc->chiptype == CHIP_I830 )
+ if ( sc->chiptype != CHIP_I810 )
return EINVAL;
for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) {
- WRITE4(AGP_I810_GTT + (offset >> AGP_PAGE_SHIFT) * 4,
- i | 3);
+ bus_write_4(sc->sc_res[0],
+ AGP_I810_GTT + (i >> AGP_PAGE_SHIFT) * 4, i | 3);
}
return 0;
@@ -656,29 +934,46 @@ agp_i810_unbind_memory(device_t dev, str
struct agp_i810_softc *sc = device_get_softc(dev);
vm_offset_t i;
+ if (mem->am_type == 2 && mem->am_size != AGP_PAGE_SIZE) {
+ lockmgr(&sc->agp.as_lock, LK_EXCLUSIVE);
+ if (!mem->am_is_bound) {
+ lockmgr(&sc->agp.as_lock, LK_RELEASE);
+ return EINVAL;
+ }
+
+ for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) {
+ agp_i810_write_gtt_entry(dev, mem->am_offset + i,
+ 0, 0);
+ }
+ agp_flush_cache();
+ mem->am_is_bound = 0;
+ lockmgr(&sc->agp.as_lock, LK_RELEASE);
+ return 0;
+ }
+
if (mem->am_type != 1)
return agp_generic_unbind_memory(dev, mem);
- if ( sc->chiptype == CHIP_I830 )
+ if ( sc->chiptype != CHIP_I810 )
return EINVAL;
- for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE)
- WRITE4(AGP_I810_GTT + (i >> AGP_PAGE_SHIFT) * 4, 0);
+ for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) {
+ bus_write_4(sc->sc_res[0],
+ AGP_I810_GTT + (i >> AGP_PAGE_SHIFT) * 4, 0);
+ }
return 0;
}
static device_method_t agp_i810_methods[] = {
/* Device interface */
+ DEVMETHOD(device_identify, agp_i810_identify),
DEVMETHOD(device_probe, agp_i810_probe),
DEVMETHOD(device_attach, agp_i810_attach),
DEVMETHOD(device_detach, agp_i810_detach),
- DEVMETHOD(device_shutdown, bus_generic_shutdown),
- DEVMETHOD(device_suspend, bus_generic_suspend),
- DEVMETHOD(device_resume, bus_generic_resume),
/* AGP interface */
- DEVMETHOD(agp_get_aperture, agp_i810_get_aperture),
+ DEVMETHOD(agp_get_aperture, agp_generic_get_aperture),
DEVMETHOD(agp_set_aperture, agp_i810_set_aperture),
DEVMETHOD(agp_bind_page, agp_i810_bind_page),
DEVMETHOD(agp_unbind_page, agp_i810_unbind_page),
diff --git a/sys/dev/agp/agp_if.m b/sys/dev/agp/agp_if.m
--- a/sys/dev/agp/agp_if.m
+++ b/sys/dev/agp/agp_if.m
@@ -23,7 +23,7 @@
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
-# $FreeBSD: src/sys/pci/agp_if.m,v 1.1.2.2 2003/04/12 20:38:37 murray Exp $
+# $FreeBSD: src/sys/pci/agp_if.m,v 1.3 2005/01/07 02:29:18 imp Exp $
# $DragonFly: src/sys/dev/agp/agp_if.m,v 1.2 2003/06/17 04:28:56 dillon Exp $
#
diff --git a/sys/dev/agp/agp_intel.c b/sys/dev/agp/agp_intel.c
--- a/sys/dev/agp/agp_intel.c
+++ b/sys/dev/agp/agp_intel.c
@@ -23,12 +23,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/sys/pci/agp_intel.c,v 1.1.2.5 2003/06/02 17:38:19 jhb Exp $
+ * $FreeBSD: src/sys/pci/agp_intel.c,v 1.34 2007/01/06 08:31:31 takawata Exp $
* $DragonFly: src/sys/dev/agp/agp_intel.c,v 1.7 2006/12/22 23:26:14 swildner Exp $
*/
#include "opt_bus.h"
-#include "opt_pci.h"
#include <sys/param.h>
#include <sys/systm.h>
@@ -53,6 +52,7 @@ struct agp_intel_softc {
u_int32_t initial_aperture; /* aperture size at startup */
struct agp_gatt *gatt;
u_int aperture_mask;
+ u_int32_t current_aperture; /* current aperture size */
};
static const char*
@@ -60,64 +60,53 @@ agp_intel_match(device_t dev)
{
if (pci_get_class(dev) != PCIC_BRIDGE
|| pci_get_subclass(dev) != PCIS_BRIDGE_HOST)
- return NULL;
+ return (NULL);
if (agp_find_caps(dev) == 0)
- return NULL;
+ return (NULL);
switch (pci_get_devid(dev)) {
/* Intel -- vendor 0x8086 */
case 0x71808086:
return ("Intel 82443LX (440 LX) host to PCI bridge");
-
case 0x71908086:
return ("Intel 82443BX (440 BX) host to PCI bridge");
-
case 0x71a08086:
return ("Intel 82443GX host to PCI bridge");
-
case 0x71a18086:
return ("Intel 82443GX host to AGP bridge");
-
case 0x11308086:
return ("Intel 82815 (i815 GMCH) host to PCI bridge");
-
case 0x25008086:
case 0x25018086:
return ("Intel 82820 host to AGP bridge");
-
case 0x35758086:
return ("Intel 82830 host to AGP bridge");
-
case 0x1a218086:
return ("Intel 82840 host to AGP bridge");
-
case 0x1a308086:
return ("Intel 82845 host to AGP bridge");
-
case 0x25308086:
return ("Intel 82850 host to AGP bridge");
-
case 0x33408086:
return ("Intel 82855 host to AGP bridge");
-
case 0x25318086:
return ("Intel 82860 host to AGP bridge");
-
case 0x25708086:
return ("Intel 82865 host to AGP bridge");
-
+ case 0x255d8086:
+ return ("Intel E7205 host to AGP bridge");
+ case 0x25508086:
+ return ("Intel E7505 host to AGP bridge");
case 0x25788086:
return ("Intel 82875P host to AGP bridge");
-
- case 0x25608086: /* i845G */
+ case 0x25608086:
return ("Intel 82845G host to AGP bridge");
+ case 0x35808086:
+ return ("Intel 82855GM host to AGP bridge");
};
- if (pci_get_vendor(dev) == 0x8086)
- return ("Intel Generic host to PCI bridge");
-
- return NULL;
+ return (NULL);
}
static int
@@ -125,28 +114,117 @@ agp_intel_probe(device_t dev)
{
const char *desc;
+ if (resource_disabled("agp", device_get_unit(dev)))
+ return (ENXIO);
desc = agp_intel_match(dev);
if (desc) {
device_verbose(dev);
device_set_desc(dev, desc);
- return 0;
- }
-
- return ENXIO;
+ return (BUS_PROBE_DEFAULT);
+ }
+
+ return (ENXIO);
+}
+
+static void
+agp_intel_commit_gatt(device_t dev)
+{
+ struct agp_intel_softc *sc;
+ u_int32_t type;
+ u_int32_t value;
+
+ sc = device_get_softc(dev);
+ type = pci_get_devid(dev);
+
+ /* Install the gatt. */
+ pci_write_config(dev, AGP_INTEL_ATTBASE, sc->gatt->ag_physical, 4);
+
+ /* Enable the GLTB and setup the control register. */
+ switch (type) {
+ case 0x71908086: /* 440LX/EX */
+ pci_write_config(dev, AGP_INTEL_AGPCTRL, 0x2080, 4);
+ break;
+ case 0x71808086: /* 440BX */
+ /*
+ * XXX: Should be 0xa080? Bit 9 is undefined, and
+ * bit 13 being on and bit 15 being clear is illegal.
+ */
+ pci_write_config(dev, AGP_INTEL_AGPCTRL, 0x2280, 4);
+ break;
+ default:
+ value = pci_read_config(dev, AGP_INTEL_AGPCTRL, 4);
+ pci_write_config(dev, AGP_INTEL_AGPCTRL, value | 0x80, 4);
+ }
+
+ /* Enable aperture accesses. */
+ switch (type) {
+ case 0x25008086: /* i820 */
+ case 0x25018086: /* i820 */
+ pci_write_config(dev, AGP_INTEL_I820_RDCR,
+ (pci_read_config(dev, AGP_INTEL_I820_RDCR, 1)
+ | (1 << 1)), 1);
+ break;
+ case 0x1a308086: /* i845 */
+ case 0x25608086: /* i845G */
+ case 0x33408086: /* i855 */
+ case 0x35808086: /* i855GM */
+ case 0x25708086: /* i865 */
+ case 0x25788086: /* i875P */
+ pci_write_config(dev, AGP_INTEL_I845_AGPM,
+ (pci_read_config(dev, AGP_INTEL_I845_AGPM, 1)
+ | (1 << 1)), 1);
+ break;
+ case 0x1a218086: /* i840 */
+ case 0x25308086: /* i850 */
+ case 0x25318086: /* i860 */
+ case 0x255d8086: /* E7205 */
+ case 0x25508086: /* E7505 */
+ pci_write_config(dev, AGP_INTEL_MCHCFG,
+ (pci_read_config(dev, AGP_INTEL_MCHCFG, 2)
+ | (1 << 9)), 2);
+ break;
+ default: /* Intel Generic (maybe) */
+ pci_write_config(dev, AGP_INTEL_NBXCFG,
+ (pci_read_config(dev, AGP_INTEL_NBXCFG, 4)
+ & ~(1 << 10)) | (1 << 9), 4);
+ }
+
+ /* Clear errors. */
+ switch (type) {
+ case 0x1a218086: /* i840 */
+ pci_write_config(dev, AGP_INTEL_I8XX_ERRSTS, 0xc000, 2);
+ break;
+ case 0x25008086: /* i820 */
+ case 0x25018086: /* i820 */
+ case 0x1a308086: /* i845 */
+ case 0x25608086: /* i845G */
+ case 0x25308086: /* i850 */
+ case 0x33408086: /* i855 */
+ case 0x25318086: /* i860 */
+ case 0x25708086: /* i865 */
+ case 0x25788086: /* i875P */
+ case 0x255d8086: /* E7205 */
+ case 0x25508086: /* E7505 */
+ pci_write_config(dev, AGP_INTEL_I8XX_ERRSTS, 0x00ff, 2);
+ break;
+ default: /* Intel Generic (maybe) */
+ pci_write_config(dev, AGP_INTEL_ERRSTS + 1, 7, 1);
+ }
}
static int
agp_intel_attach(device_t dev)
{
- struct agp_intel_softc *sc = device_get_softc(dev);
+ struct agp_intel_softc *sc;
struct agp_gatt *gatt;
- u_int32_t type = pci_get_devid(dev);
u_int32_t value;
int error;
+ sc = device_get_softc(dev);
+
error = agp_generic_attach(dev);
if (error)
- return error;
+ return (error);
/* Determine maximum supported aperture size. */
value = pci_read_config(dev, AGP_INTEL_APSIZE, 1);
@@ -154,7 +232,11 @@ agp_intel_attach(device_t dev)
sc->aperture_mask = pci_read_config(dev, AGP_INTEL_APSIZE, 1) &
MAX_APSIZE;
pci_write_config(dev, AGP_INTEL_APSIZE, value, 1);
- sc->initial_aperture = AGP_GET_APERTURE(dev);
+ sc->current_aperture = sc->initial_aperture = AGP_GET_APERTURE(dev);
+ if (sc->initial_aperture == 0) {
+ device_printf(dev, "bad initial aperture size, disabling\n");
+ return ENXIO;
+ }
for (;;) {
gatt = agp_alloc_gatt(dev);
@@ -167,151 +249,86 @@ agp_intel_attach(device_t dev)
*/
if (AGP_SET_APERTURE(dev, AGP_GET_APERTURE(dev) / 2)) {
agp_generic_detach(dev);
- return ENOMEM;
+ return (ENOMEM);
}
}
sc->gatt = gatt;
- /* Install the gatt. */
- pci_write_config(dev, AGP_INTEL_ATTBASE, gatt->ag_physical, 4);
-
- /* Enable the GLTB and setup the control register. */
- switch (type) {
- case 0x71908086: /* 440LX/EX */
- pci_write_config(dev, AGP_INTEL_AGPCTRL, 0x2080, 4);
- break;
- case 0x71808086: /* 440BX */
- /*
- * XXX: Should be 0xa080? Bit 9 is undefined, and
- * bit 13 being on and bit 15 being clear is illegal.
- */
- pci_write_config(dev, AGP_INTEL_AGPCTRL, 0x2280, 4);
- break;
- default:
- value = pci_read_config(dev, AGP_INTEL_AGPCTRL, 4);
- pci_write_config(dev, AGP_INTEL_AGPCTRL, value | 0x80, 4);
- }
-
- /* Enable things, clear errors etc. */
- switch (type) {
+ agp_intel_commit_gatt(dev);
+
+ return (0);
+}
+
+static int
+agp_intel_detach(device_t dev)
+{
+ struct agp_intel_softc *sc;
+ u_int32_t reg;
+ int error;
+
+ sc = device_get_softc(dev);
+
+ error = agp_generic_detach(dev);
+ if (error)
+ return (error);
+
+ /* Disable aperture accesses. */
+ switch (pci_get_devid(dev)) {
+ case 0x25008086: /* i820 */
+ case 0x25018086: /* i820 */
+ reg = pci_read_config(dev, AGP_INTEL_I820_RDCR, 1) & ~(1 << 1);
+ kprintf("%s: set RDCR to %02x\n", __func__, reg & 0xff);
+ pci_write_config(dev, AGP_INTEL_I820_RDCR, reg, 1);
+ break;
+ case 0x1a308086: /* i845 */
+ case 0x25608086: /* i845G */
+ case 0x33408086: /* i855 */
+ case 0x35808086: /* i855GM */
+ case 0x25708086: /* i865 */
+ case 0x25788086: /* i875P */
+ reg = pci_read_config(dev, AGP_INTEL_I845_AGPM, 1) & ~(1 << 1);
+ kprintf("%s: set AGPM to %02x\n", __func__, reg & 0xff);
+ pci_write_config(dev, AGP_INTEL_I845_AGPM, reg, 1);
+ break;
case 0x1a218086: /* i840 */
case 0x25308086: /* i850 */
case 0x25318086: /* i860 */
- pci_write_config(dev, AGP_INTEL_MCHCFG,
- (pci_read_config(dev, AGP_INTEL_MCHCFG, 2)
- | (1 << 9)), 2);
- break;
-
- case 0x25008086: /* i820 */
- case 0x25018086: /* i820 */
- pci_write_config(dev, AGP_INTEL_I820_RDCR,
- (pci_read_config(dev, AGP_INTEL_I820_RDCR, 1)
- | (1 << 1)), 1);
- break;
-
- case 0x1a308086: /* i845 */
- case 0x33408086: /* i855 */
- case 0x25708086: /* i865 */
- case 0x25788086: /* i875P */
- case 0x25608086: /* i845G */
- pci_write_config(dev, AGP_INTEL_I845_MCHCFG,
- (pci_read_config(dev, AGP_INTEL_I845_MCHCFG, 1)
- | (1 << 1)), 1);
- break;
-
+ case 0x255d8086: /* E7205 */
+ case 0x25508086: /* E7505 */
+ reg = pci_read_config(dev, AGP_INTEL_MCHCFG, 2) & ~(1 << 9);
+ kprintf("%s: set MCHCFG to %x04\n", __func__, reg & 0xffff);
+ pci_write_config(dev, AGP_INTEL_MCHCFG, reg, 2);
+ break;
default: /* Intel Generic (maybe) */
- pci_write_config(dev, AGP_INTEL_NBXCFG,
- (pci_read_config(dev, AGP_INTEL_NBXCFG, 4)
- & ~(1 << 10)) | (1 << 9), 4);
- }
-
- switch (type) {
- case 0x1a218086: /* i840 */
- pci_write_config(dev, AGP_INTEL_I8XX_ERRSTS, 0xc000, 2);
- break;
-
- case 0x25008086: /* i820 */
- case 0x25018086: /* i820 */
- case 0x1a308086: /* i845 */
- case 0x25308086: /* i850 */
- case 0x33408086: /* i855 */
- case 0x25318086: /* i860 */
- case 0x25708086: /* i865 */
- case 0x25788086: /* i875P */
- case 0x25608086: /* i845G */
- pci_write_config(dev, AGP_INTEL_I8XX_ERRSTS, 0x00ff, 2);
- break;
-
- default: /* Intel Generic (maybe) */
- pci_write_config(dev, AGP_INTEL_ERRSTS + 1, 7, 1);
- }
-
- return 0;
-}
-
-static int
-agp_intel_detach(device_t dev)
-{
- struct agp_intel_softc *sc = device_get_softc(dev);
- u_int32_t type = pci_get_devid(dev);
- int error;
-
- error = agp_generic_detach(dev);
- if (error)
- return error;
-
- switch (type) {
- case 0x1a218086: /* i840 */
- case 0x25308086: /* i850 */
- case 0x25318086: /* i860 */
- kprintf("%s: set MCHCFG to %x\n", __func__, (unsigned)
- (pci_read_config(dev, AGP_INTEL_MCHCFG, 2)
- & ~(1 << 9)));
- pci_write_config(dev, AGP_INTEL_MCHCFG,
- (pci_read_config(dev, AGP_INTEL_MCHCFG, 2)
- & ~(1 << 9)), 2);
-
- case 0x25008086: /* i820 */
- case 0x25018086: /* i820 */
- kprintf("%s: set RDCR to %x\n", __func__, (unsigned)
- (pci_read_config(dev, AGP_INTEL_I820_RDCR, 1)
- & ~(1 << 1)));
- pci_write_config(dev, AGP_INTEL_I820_RDCR,
- (pci_read_config(dev, AGP_INTEL_I820_RDCR, 1)
- & ~(1 << 1)), 1);
-
- case 0x1a308086: /* i845 */
- case 0x25608086: /* i845G */
- case 0x33408086: /* i855 */
- case 0x25708086: /* i865 */
- case 0x25788086: /* i875P */
- kprintf("%s: set MCHCFG to %x\n", __func__, (unsigned)
- (pci_read_config(dev, AGP_INTEL_I845_MCHCFG, 1)
- & ~(1 << 1)));
- pci_write_config(dev, AGP_INTEL_MCHCFG,
- (pci_read_config(dev, AGP_INTEL_I845_MCHCFG, 1)
- & ~(1 << 1)), 1);
-
- default: /* Intel Generic (maybe) */
- kprintf("%s: set NBXCFG to %x\n", __func__,
- (pci_read_config(dev, AGP_INTEL_NBXCFG, 4)
- & ~(1 << 9)));
- pci_write_config(dev, AGP_INTEL_NBXCFG,
- (pci_read_config(dev, AGP_INTEL_NBXCFG, 4)
- & ~(1 << 9)), 4);
+ reg = pci_read_config(dev, AGP_INTEL_NBXCFG, 4) & ~(1 << 9);
+ kprintf("%s: set NBXCFG to %08x\n", __func__, reg);
+ pci_write_config(dev, AGP_INTEL_NBXCFG, reg, 4);
}
pci_write_config(dev, AGP_INTEL_ATTBASE, 0, 4);
AGP_SET_APERTURE(dev, sc->initial_aperture);
agp_free_gatt(sc->gatt);
- return 0;
+ return (0);
+}
+
+static int
+agp_intel_resume(device_t dev)
+{
+ struct agp_intel_softc *sc;
+ sc = device_get_softc(dev);
+
+ AGP_SET_APERTURE(dev, sc->current_aperture);
+ agp_intel_commit_gatt(dev);
+ return (bus_generic_resume(dev));
}
static u_int32_t
agp_intel_get_aperture(device_t dev)
{
- struct agp_intel_softc *sc = device_get_softc(dev);
+ struct agp_intel_softc *sc;
+
+ sc = device_get_softc(dev);
apsize = pci_read_config(dev, AGP_INTEL_APSIZE, 1) & sc->aperture_mask;
@@ -322,14 +339,16 @@ agp_intel_get_aperture(device_t dev)
* field just read forces the corresponding bit in the 27:22
* to be zero. We calculate the aperture size accordingly.
*/
- return (((apsize ^ sc->aperture_mask) << 22) | ((1 << 22) - 1)) + 1;
+ return ((((apsize ^ sc->aperture_mask) << 22) | ((1 << 22) - 1)) + 1);
}
static int
agp_intel_set_aperture(device_t dev, u_int32_t aperture)
{
- struct agp_intel_softc *sc = device_get_softc(dev);
+ struct agp_intel_softc *sc;
u_int32_t apsize;
+
+ sc = device_get_softc(dev);
/*
* Reverse the magic from get_aperture.
@@ -340,35 +359,41 @@ agp_intel_set_aperture(device_t dev, u_i
* Double check for sanity.
*/
if ((((apsize ^ sc->aperture_mask) << 22) | ((1 << 22) - 1)) + 1 != aperture)
- return EINVAL;
+ return (EINVAL);
+
+ sc->current_aperture = apsize;
pci_write_config(dev, AGP_INTEL_APSIZE, apsize, 1);
- return 0;
+ return (0);
}
static int
agp_intel_bind_page(device_t dev, int offset, vm_offset_t physical)
{
- struct agp_intel_softc *sc = device_get_softc(dev);
+ struct agp_intel_softc *sc;
+
+ sc = device_get_softc(dev);
if (offset < 0 || offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT))
- return EINVAL;
+ return (EINVAL);
sc->gatt->ag_virtual[offset >> AGP_PAGE_SHIFT] = physical | 0x17;
- return 0;
+ return (0);
}
static int
agp_intel_unbind_page(device_t dev, int offset)
{
- struct agp_intel_softc *sc = device_get_softc(dev);
+ struct agp_intel_softc *sc;
+
+ sc = device_get_softc(dev);
if (offset < 0 || offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT))
- return EINVAL;
+ return (EINVAL);
sc->gatt->ag_virtual[offset >> AGP_PAGE_SHIFT] = 0;
- return 0;
+ return (0);
}
static void
@@ -388,7 +413,7 @@ static device_method_t agp_intel_methods
DEVMETHOD(device_detach, agp_intel_detach),
DEVMETHOD(device_shutdown, bus_generic_shutdown),
DEVMETHOD(device_suspend, bus_generic_suspend),
- DEVMETHOD(device_resume, bus_generic_resume),
+ DEVMETHOD(device_resume, agp_intel_resume),
/* AGP interface */
DEVMETHOD(agp_get_aperture, agp_intel_get_aperture),
diff --git a/sys/dev/agp/agp_nvidia.c b/sys/dev/agp/agp_nvidia.c
--- a/sys/dev/agp/agp_nvidia.c
+++ b/sys/dev/agp/agp_nvidia.c
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * Based on FreeBSD v1.2.
+ * $FreeBSD: src/sys/pci/agp_nvidia.c,v 1.11 2005/12/20 21:12:26 jhb Exp $
* $DragonFly: src/sys/dev/agp/agp_nvidia.c,v 1.4 2006/10/25 20:55:52 dillon Exp $
*/
@@ -33,7 +33,6 @@
*/
#include "opt_bus.h"
-#include "opt_pci.h"
#include <sys/param.h>
#include <sys/systm.h>
@@ -72,16 +71,16 @@ struct agp_nvidia_softc {
off_t pg_offset;
};
-static const char * agp_nvidia_match (device_t dev);
-static int agp_nvidia_probe (device_t);
-static int agp_nvidia_attach (device_t);
-static int agp_nvidia_detach (device_t);
-static u_int32_t agp_nvidia_get_aperture (device_t);
-static int agp_nvidia_set_aperture (device_t, u_int32_t);
-static int agp_nvidia_bind_page (device_t, int, vm_offset_t);
-static int agp_nvidia_unbind_page (device_t, int);
-
-static int nvidia_init_iorr (u_int32_t, u_int32_t);
+static const char *agp_nvidia_match(device_t dev);
+static int agp_nvidia_probe(device_t);
+static int agp_nvidia_attach(device_t);
+static int agp_nvidia_detach(device_t);
+static u_int32_t agp_nvidia_get_aperture(device_t);
+static int agp_nvidia_set_aperture(device_t, u_int32_t);
+static int agp_nvidia_bind_page(device_t, int, vm_offset_t);
+static int agp_nvidia_unbind_page(device_t, int);
+
+static int nvidia_init_iorr(u_int32_t, u_int32_t);
static const char *
agp_nvidia_match (device_t dev)
@@ -97,7 +96,7 @@ agp_nvidia_match (device_t dev)
case NVIDIA_DEVICEID_NFORCE2:
return ("NVIDIA nForce2 AGP Controller");
}
- return ("NVIDIA Generic AGP Controller");
+ return (NULL);
}
static int
@@ -105,11 +104,13 @@ agp_nvidia_probe (device_t dev)
{
const char *desc;
+ if (resource_disabled("agp", device_get_unit(dev)))
+ return (ENXIO);
desc = agp_nvidia_match(dev);
if (desc) {
device_verbose(dev);
device_set_desc(dev, desc);
- return (0);
+ return (BUS_PROBE_DEFAULT);
}
return (ENXIO);
}
@@ -134,8 +135,8 @@ agp_nvidia_attach (device_t dev)
sc->wbc_mask = 0x80000000;
break;
default:
- sc->wbc_mask = 0;
- break;
+ device_printf(dev, "Bad chip id\n");
+ return (ENODEV);
}
/* AGP Controller */
@@ -170,6 +171,10 @@ agp_nvidia_attach (device_t dev)
return (error);
sc->initial_aperture = AGP_GET_APERTURE(dev);
+ if (sc->initial_aperture == 0) {
+ device_printf(dev, "bad initial aperture size, disabling\n");
+ return ENXIO;
+ }
for (;;) {
gatt = agp_alloc_gatt(dev);
@@ -213,8 +218,7 @@ agp_nvidia_attach (device_t dev)
for (i = 0; i < 8; i++) {
pci_write_config(sc->mc2_dev, AGP_NVIDIA_2_ATTBASE(i),
(sc->gatt->ag_physical +
- (i % sc->num_dirs) * 64 * 1024),
- 4);
+ (i % sc->num_dirs) * 64 * 1024) | 1, 4);
}
/* GTLB Control */
@@ -265,10 +269,17 @@ static u_int32_t
static u_int32_t
agp_nvidia_get_aperture(device_t dev)
{
- u_int8_t key;
-
- key = ffs(pci_read_config(dev, AGP_NVIDIA_0_APSIZE, 1) & 0x0f);
- return (1 << (24 + (key ? key : 5)));
+ switch (pci_read_config(dev, AGP_NVIDIA_0_APSIZE, 1) & 0x0f) {
+ case 0: return (512 * 1024 * 1024); break;
+ case 8: return (256 * 1024 * 1024); break;
+ case 12: return (128 * 1024 * 1024); break;
+ case 14: return (64 * 1024 * 1024); break;
+ case 15: return (32 * 1024 * 1024); break;
+ default:
+ device_printf(dev, "Invalid aperture setting 0x%x",
+ pci_read_config(dev, AGP_NVIDIA_0_APSIZE, 1));
+ return 0;
+ }
}
static int
@@ -304,7 +315,7 @@ agp_nvidia_bind_page(device_t dev, int o
return (EINVAL);
index = (sc->pg_offset + offset) >> AGP_PAGE_SHIFT;
- sc->gatt->ag_virtual[index] = physical;
+ sc->gatt->ag_virtual[index] = physical | 1;
return (0);
}
@@ -329,6 +340,7 @@ agp_nvidia_flush_tlb (device_t dev, int
{
struct agp_nvidia_softc *sc;
u_int32_t wbc_reg, temp;
+ volatile u_int32_t *ag_virtual;
int i;
sc = (struct agp_nvidia_softc *)device_get_softc(dev);
@@ -352,11 +364,13 @@ agp_nvidia_flush_tlb (device_t dev, int
"TLB flush took more than 3 seconds.\n");
}
+ ag_virtual = (volatile u_int32_t *)sc->gatt->ag_virtual;
+
/* Flush TLB entries. */
for(i = 0; i < 32 + 1; i++)
- temp = sc->gatt->ag_virtual[i * PAGE_SIZE / sizeof(u_int32_t)];
+ temp = ag_virtual[i * PAGE_SIZE / sizeof(u_int32_t)];
for(i = 0; i < 32 + 1; i++)
- temp = sc->gatt->ag_virtual[i * PAGE_SIZE / sizeof(u_int32_t)];
+ temp = ag_virtual[i * PAGE_SIZE / sizeof(u_int32_t)];
return (0);
}
diff --git a/sys/dev/agp/agp_sis.c b/sys/dev/agp/agp_sis.c
--- a/sys/dev/agp/agp_sis.c
+++ b/sys/dev/agp/agp_sis.c
@@ -23,12 +23,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/sys/pci/agp_sis.c,v 1.1.2.1 2000/07/19 09:48:04 ru Exp $
+ * $FreeBSD: src/sys/pci/agp_sis.c,v 1.20 2006/05/30 18:41:26 jkim Exp $
* $DragonFly: src/sys/dev/agp/agp_sis.c,v 1.5 2004/07/04 00:24:52 dillon Exp $
*/
#include "opt_bus.h"
-#include "opt_pci.h"
#include <sys/param.h>
#include <sys/systm.h>
@@ -101,13 +100,8 @@ agp_sis_match(device_t dev)
return ("SiS 745 host to AGP bridge");
case 0x07461039:
return ("SiS 746 host to AGP bridge");
- case 0x07601039:
- return ("SiS 760 host to AGP bridge");
};
- if (pci_get_vendor(dev) == 0x1039)
- return ("SIS Generic host to PCI bridge");
-
return NULL;
}
@@ -116,11 +110,13 @@ agp_sis_probe(device_t dev)
{
const char *desc;
+ if (resource_disabled("agp", device_get_unit(dev)))
+ return (ENXIO);
desc = agp_sis_match(dev);
if (desc) {
device_verbose(dev);
device_set_desc(dev, desc);
- return 0;
+ return BUS_PROBE_DEFAULT;
}
return ENXIO;
diff --git a/sys/dev/agp/agp_via.c b/sys/dev/agp/agp_via.c
--- a/sys/dev/agp/agp_via.c
+++ b/sys/dev/agp/agp_via.c
@@ -23,12 +23,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/sys/pci/agp_via.c,v 1.1.2.2 2001/10/04 09:53:04 ru Exp $
+ * $FreeBSD: src/sys/pci/agp_via.c,v 1.23 2005/12/20 21:12:26 jhb Exp $
* $DragonFly: src/sys/dev/agp/agp_via.c,v 1.5 2004/07/04 00:24:52 dillon Exp $
*/
#include "opt_bus.h"
-#include "opt_pci.h"
#include <sys/param.h>
#include <sys/systm.h>
@@ -46,9 +45,9 @@
#include <vm/vm_object.h>
#include <vm/pmap.h>
-#define REG_GARTCTRL 0
-#define REG_APSIZE 1
-#define REG_ATTBASE 2
+#define REG_GARTCTRL 0
+#define REG_APSIZE 1
+#define REG_ATTBASE 2
struct agp_via_softc {
struct agp_softc agp;
@@ -58,9 +57,9 @@ struct agp_via_softc {
};
static int via_v2_regs[] = { AGP_VIA_GARTCTRL, AGP_VIA_APSIZE,
- AGP_VIA_ATTBASE };
+ AGP_VIA_ATTBASE };
static int via_v3_regs[] = { AGP3_VIA_GARTCTRL, AGP3_VIA_APSIZE,
- AGP3_VIA_ATTBASE };
+ AGP3_VIA_ATTBASE };
static const char*
agp_via_match(device_t dev)
@@ -73,25 +72,62 @@ agp_via_match(device_t dev)
return NULL;
switch (pci_get_devid(dev)) {
+ case 0x01981106:
+ return ("VIA 8763 (P4X600) host to PCI bridge");
+ case 0x02591106:
+ return ("VIA PM800/PN800/PM880/PN880 host to PCI bridge");
+ case 0x02691106:
+ return ("VIA KT880 host to PCI bridge");
+ case 0x02961106:
+ return ("VIA 3296 (P4M800) host to PCI bridge");
case 0x03051106:
- return ("VIA 82C8363 (Apollo KT133A) host to PCI bridge");
+ return ("VIA 82C8363 (Apollo KT133x/KM133) host to PCI bridge");
+ case 0x03911106:
+ return ("VIA 8371 (Apollo KX133) host to PCI bridge");
case 0x05011106:
return ("VIA 8501 (Apollo MVP4) host to PCI bridge");
case 0x05971106:
return ("VIA 82C597 (Apollo VP3) host to PCI bridge");
case 0x05981106:
return ("VIA 82C598 (Apollo MVP3) host to PCI bridge");
+ case 0x06011106:
+ return ("VIA 8601 (Apollo ProMedia/PLE133Ta) host to PCI bridge");
case 0x06051106:
return ("VIA 82C694X (Apollo Pro 133A) host to PCI bridge");
case 0x06911106:
return ("VIA 82C691 (Apollo Pro) host to PCI bridge");
- case 0x31881106:
- return ("VIA 8385 host to PCI bridge");
+ case 0x30911106:
+ return ("VIA 8633 (Pro 266) host to PCI bridge");
+ case 0x30991106:
+ return ("VIA 8367 (KT266/KY266x/KT333) host to PCI bridge");
+ case 0x31011106:
+ return ("VIA 8653 (Pro266T) host to PCI bridge");
+ case 0x31121106:
+ return ("VIA 8361 (KLE133) host to PCI bridge");
+ case 0x31161106:
+ return ("VIA XM266 (PM266/KM266) host to PCI bridge");
+ case 0x31231106:
+ return ("VIA 862x (CLE266) host to PCI bridge");
+ case 0x31281106:
+ return ("VIA 8753 (P4X266) host to PCI bridge");
+ case 0x31481106:
+ return ("VIA 8703 (P4M266x/P4N266) host to PCI bridge");
+ case 0x31561106:
+ return ("VIA XN266 (Apollo Pro266) host to PCI bridge");
+ case 0x31681106:
+ return ("VIA 8754 (PT800) host to PCI bridge");
+ case 0x31891106:
+ return ("VIA 8377 (Apollo KT400/KT400A/KT600) host to PCI bridge");
+ case 0x32051106:
+ return ("VIA 8235/8237 (Apollo KM400/KM400A) host to PCI bridge");
+ case 0x32081106:
+ return ("VIA 8783 (PT890) host to PCI bridge");
+ case 0x32581106:
+ return ("VIA PT880 host to PCI bridge");
+ case 0xb1981106:
+ return ("VIA VT83xx/VT87xx/KTxxx/Px8xx host to PCI bridge");
};
- if (pci_get_vendor(dev) == 0x1106)
- return ("VIA Generic host to PCI bridge");
-
return NULL;
}
@@ -100,11 +136,13 @@ agp_via_probe(device_t dev)
{
const char *desc;
+ if (resource_disabled("agp", device_get_unit(dev)))
+ return (ENXIO);
desc = agp_via_match(dev);
if (desc) {
device_verbose(dev);
device_set_desc(dev, desc);
- return 0;
+ return BUS_PROBE_DEFAULT;
}
return ENXIO;
@@ -116,21 +154,47 @@ agp_via_attach(device_t dev)
struct agp_via_softc *sc = device_get_softc(dev);
struct agp_gatt *gatt;
int error;
-
+ u_int32_t agpsel;
+
+ /* XXX: This should be keying off of whether the bridge is AGP3 capable,
+ * rather than a bunch of device ids for chipsets that happen to do 8x.
+ */
switch (pci_get_devid(dev)) {
- case 0x31881106:
- sc->regs = via_v3_regs;
+ case 0x01981106:
+ case 0x02591106:
+ case 0x02691106:
+ case 0x02961106:
+ case 0x31231106:
+ case 0x31681106:
+ case 0x31891106:
+ case 0x32051106:
+ case 0x32581106:
+ case 0xb1981106:
+ /* The newer VIA chipsets will select the AGP version based on
+ * what AGP versions the card supports. We still have to
+ * program it using the v2 registers if it has chosen to use
+ * compatibility mode.
+ */
+ agpsel = pci_read_config(dev, AGP_VIA_AGPSEL, 1);
+ if ((agpsel & (1 << 1)) == 0)
+ sc->regs = via_v3_regs;
+ else
+ sc->regs = via_v2_regs;
break;
default:
sc->regs = via_v2_regs;
break;
}
-
+
error = agp_generic_attach(dev);
if (error)
return error;
sc->initial_aperture = AGP_GET_APERTURE(dev);
+ if (sc->initial_aperture == 0) {
+ device_printf(dev, "bad initial aperture size, disabling\n");
+ return ENXIO;
+ }
for (;;) {
gatt = agp_alloc_gatt(dev);
@@ -148,11 +212,22 @@ agp_via_attach(device_t dev)
}
sc->gatt = gatt;
- /* Install the gatt. */
- pci_write_config(dev, sc->regs[REG_ATTBASE], gatt->ag_physical | 3, 4);
-
- /* Enable the aperture. */
- pci_write_config(dev, sc->regs[REG_GARTCTRL], 0x0f, 4);
+ if (sc->regs == via_v2_regs) {
+ /* Install the gatt. */
+ pci_write_config(dev, sc->regs[REG_ATTBASE], gatt->ag_physical | 3, 4);
+
+ /* Enable the aperture. */
+ pci_write_config(dev, sc->regs[REG_GARTCTRL], 0x0f, 4);
+ } else {
+ u_int32_t gartctrl;
+
+ /* Install the gatt. */
+ pci_write_config(dev, sc->regs[REG_ATTBASE], gatt->ag_physical, 4);
+
+ /* Enable the aperture. */
+ gartctrl = pci_read_config(dev, sc->regs[REG_ATTBASE], 4);
+ pci_write_config(dev, sc->regs[REG_GARTCTRL], gartctrl | (3 << 7), 4);
+ }
return 0;
}
@@ -243,9 +318,18 @@ agp_via_flush_tlb(device_t dev)
agp_via_flush_tlb(device_t dev)
{
struct agp_via_softc *sc = device_get_softc(dev);
-
- pci_write_config(dev, sc->regs[REG_GARTCTRL], 0x8f, 4);
- pci_write_config(dev, sc->regs[REG_GARTCTRL], 0x0f, 4);
+ u_int32_t gartctrl;
+
+ if (sc->regs == via_v2_regs) {
+ pci_write_config(dev, sc->regs[REG_GARTCTRL], 0x8f, 4);
+ pci_write_config(dev, sc->regs[REG_GARTCTRL], 0x0f, 4);
+ } else {
+ gartctrl = pci_read_config(dev, sc->regs[REG_GARTCTRL], 4);
+ pci_write_config(dev, sc->regs[REG_GARTCTRL], gartctrl &
+ ~(1 << 7), 4);
+ pci_write_config(dev, sc->regs[REG_GARTCTRL], gartctrl, 4);
+ }
+
}
static device_method_t agp_via_methods[] = {
diff --git a/sys/dev/agp/agppriv.h b/sys/dev/agp/agppriv.h
--- a/sys/dev/agp/agppriv.h
+++ b/sys/dev/agp/agppriv.h
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/sys/pci/agppriv.h,v 1.3.2.1 2000/07/19 09:48:04 ru Exp $
+ * $FreeBSD: src/sys/pci/agppriv.h,v 1.6 2007/07/13 16:28:12 anholt Exp $
* $DragonFly: src/sys/dev/agp/agppriv.h,v 1.5 2006/12/22 23:26:15 swildner Exp $
*/
@@ -41,8 +41,8 @@
#ifdef AGP_DEBUG
#define AGP_DPF(x...) do { \
- kprintf("agp: "); \
- kprintf(##x); \
+ printf("agp: "); \
+ printf(##x); \
} while (0)
#else
#define AGP_DPF(x...) do {} while (0)
@@ -70,12 +70,14 @@ struct agp_memory {
*/
struct agp_softc {
struct resource *as_aperture; /* location of aperture */
+ int as_aperture_rid;
u_int32_t as_maxmem; /* allocation upper bound */
u_int32_t as_allocated; /* amount allocated */
enum agp_acquire_state as_state;
struct agp_memory_list as_memory; /* list of allocated memory */
int as_nextid; /* next memory block id */
int as_isopen; /* user device is open */
+ struct cdev *as_devnode; /* from make_dev */
struct lock as_lock; /* lock for access to GATT */
};
@@ -88,9 +90,13 @@ void agp_flush_cache(void);
void agp_flush_cache(void);
u_int8_t agp_find_caps(device_t dev);
struct agp_gatt *agp_alloc_gatt(device_t dev);
+void agp_set_aperture_resource(device_t dev, int rid);
void agp_free_gatt(struct agp_gatt *gatt);
int agp_generic_attach(device_t dev);
int agp_generic_detach(device_t dev);
+int agp_generic_get_aperture(device_t dev);
+int agp_generic_set_aperture(device_t dev,
+ u_int32_t aperture);
int agp_generic_enable(device_t dev, u_int32_t mode);
struct agp_memory *agp_generic_alloc_memory(device_t dev, int type,
vm_size_t size);
diff --git a/sys/dev/agp/agpreg.h b/sys/dev/agp/agpreg.h
--- a/sys/dev/agp/agpreg.h
+++ b/sys/dev/agp/agpreg.h
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/sys/pci/agpreg.h,v 1.3.2.5 2003/06/02 17:38:19 jhb Exp $
+ * $FreeBSD: src/sys/pci/agpreg.h,v 1.19 2007/07/13 16:28:12 anholt Exp $
* $DragonFly: src/sys/dev/agp/agpreg.h,v 1.5 2004/07/04 00:24:52 dillon Exp $
*/
@@ -40,9 +40,9 @@
* Offsets from the AGP Capability pointer.
*/
#define AGP_CAPID 0x0
-#define AGP_CAPID_GET_MAJOR(x) (((x) & 0x00f00000U) >> 20)
-#define AGP_CAPID_GET_MINOR(x) (((x) & 0x000f0000U) >> 16)
-#define AGP_CAPID_GET_NEXT_PTR(x) (((x) & 0x0000ff00U) >> 8)
+#define AGP_CAPID_GET_MAJOR(x) (((x) & 0x00f00000U) >> 20)
+#define AGP_CAPID_GET_MINOR(x) (((x) & 0x000f0000U) >> 16)
+#define AGP_CAPID_GET_NEXT_PTR(x) (((x) & 0x0000ff00U) >> 8)
#define AGP_CAPID_GET_CAP_ID(x) (((x) & 0x000000ffU) >> 0)
#define AGP_STATUS 0x4
@@ -61,7 +61,7 @@
#define AGP_STATUS_HTRANS 0x0040
#define AGP_STATUS_64BIT 0x0020
#define AGP_STATUS_FW 0x0010
-#define AGP_COMMAND_RQ_MASK 0xff000000
+#define AGP_COMMAND_RQ_MASK 0xff000000
#define AGP_COMMAND_ARQSZ_MASK 0xe000
#define AGP_COMMAND_CAL_MASK 0x1c00
#define AGP_COMMAND_SBA 0x0200
@@ -70,7 +70,6 @@
#define AGP_COMMAND_64BIT 0x0020
#define AGP_COMMAND_FW 0x0010
-
/*
* Config offsets for Intel AGP chipsets.
*/
@@ -81,15 +80,15 @@
#define AGP_INTEL_ATTBASE 0xb8
/*
- * Config offsets for Intel i820/i840/i845/i850/i860/i865 AGP chipsets.
+ * Config offsets for Intel i8xx/E7xxx AGP chipsets.
*/
#define AGP_INTEL_MCHCFG 0x50
#define AGP_INTEL_I820_RDCR 0x51
-#define AGP_INTEL_I845_MCHCFG 0x51
+#define AGP_INTEL_I845_AGPM 0x51
#define AGP_INTEL_I8XX_ERRSTS 0xc8
/*
- * Config offsets for VIA AGP chipsets.
+ * Config offsets for VIA AGP 2.x chipsets.
*/
#define AGP_VIA_GARTCTRL 0x80
#define AGP_VIA_APSIZE 0x84
@@ -98,9 +97,10 @@
/*
* Config offsets for VIA AGP 3.0 chipsets.
*/
-#define AGP3_VIA_GARTCTRL 0x90
-#define AGP3_VIA_APSIZE 0x94
-#define AGP3_VIA_ATTBASE 0x98
+#define AGP3_VIA_GARTCTRL 0x90
+#define AGP3_VIA_APSIZE 0x94
+#define AGP3_VIA_ATTBASE 0x98
+#define AGP_VIA_AGPSEL 0xfd
/*
* Config offsets for SiS AGP chipsets.
@@ -187,11 +187,19 @@
* Memory mapped register offsets for i810 chipset.
*/
#define AGP_I810_PGTBL_CTL 0x2020
+/**
+ * This field determines the actual size of the global GTT on the 965
+ * and G33
+ */
+#define AGP_I810_PGTBL_SIZE_MASK 0x0000000e
+#define AGP_I810_PGTBL_SIZE_512KB (0 << 1)
+#define AGP_I810_PGTBL_SIZE_256KB (1 << 1)
+#define AGP_I810_PGTBL_SIZE_128KB (2 << 1)
#define AGP_I810_DRT 0x3000
#define AGP_I810_DRT_UNPOPULATED 0x00
#define AGP_I810_DRT_POPULATED 0x01
#define AGP_I810_GTT 0x10000
-
+
/*
* Config registers for i830MG device 0
*/
@@ -199,7 +207,7 @@
#define AGP_I830_GCC1_DEV2 0x08
#define AGP_I830_GCC1_DEV2_ENABLED 0x00
#define AGP_I830_GCC1_DEV2_DISABLED 0x08
-#define AGP_I830_GCC1_GMS 0x70
+#define AGP_I830_GCC1_GMS 0xf0 /* Top bit reserved pre-G33 */
#define AGP_I830_GCC1_GMS_STOLEN_512 0x20
#define AGP_I830_GCC1_GMS_STOLEN_1024 0x30
#define AGP_I830_GCC1_GMS_STOLEN_8192 0x40
@@ -234,6 +242,38 @@
#define AGP_I852_GM 0x5
/*
+ * 915G registers
+ */
+#define AGP_I915_GMADR 0x18
+#define AGP_I915_MMADR 0x10
+#define AGP_I915_GTTADR 0x1C
+#define AGP_I915_GCC1_GMS_STOLEN_48M 0x60
+#define AGP_I915_GCC1_GMS_STOLEN_64M 0x70
+#define AGP_I915_DEVEN 0x54
+#define AGP_I915_DEVEN_D2F0 0x08
+#define AGP_I915_DEVEN_D2F0_ENABLED 0x08
+#define AGP_I915_DEVEN_D2F0_DISABLED 0x00
+#define AGP_I915_MSAC 0x62
+#define AGP_I915_MSAC_GMASIZE 0x02
+#define AGP_I915_MSAC_GMASIZE_128 0x02
+#define AGP_I915_MSAC_GMASIZE_256 0x00
+
+/*
+ * G965 registers
+ */
+#define AGP_I965_GTTMMADR 0x10
+#define AGP_I965_MSAC 0x62
+#define AGP_I965_MSAC_GMASIZE_128 0x00
+#define AGP_I965_MSAC_GMASIZE_256 0x02
+#define AGP_I965_MSAC_GMASIZE_512 0x06
+
+/*
+ * G33 registers
+ */
+#define AGP_G33_GCC1_GMS_STOLEN_128M 0x80
+#define AGP_G33_GCC1_GMS_STOLEN_256M 0x90
+
+/*
* NVIDIA nForce/nForce2 registers
*/
#define AGP_NVIDIA_0_APBASE 0x10
@@ -246,4 +286,50 @@
#define AGP_NVIDIA_3_APBASE 0x50
#define AGP_NVIDIA_3_APLIMIT 0x54
+/*
+ * AMD64 GART registers
+ */
+#define AGP_AMD64_APCTRL 0x90
+#define AGP_AMD64_APBASE 0x94
+#define AGP_AMD64_ATTBASE 0x98
+#define AGP_AMD64_CACHECTRL 0x9c
+#define AGP_AMD64_APCTRL_GARTEN 0x00000001
+#define AGP_AMD64_APCTRL_SIZE_MASK 0x0000000e
+#define AGP_AMD64_APCTRL_DISGARTCPU 0x00000010
+#define AGP_AMD64_APCTRL_DISGARTIO 0x00000020
+#define AGP_AMD64_APCTRL_DISWLKPRB 0x00000040
+#define AGP_AMD64_APBASE_MASK 0x00007fff
+#define AGP_AMD64_ATTBASE_MASK 0xfffffff0
+#define AGP_AMD64_CACHECTRL_INVGART 0x00000001
+#define AGP_AMD64_CACHECTRL_PTEERR 0x00000002
+
+/*
+ * NVIDIA nForce3 registers
+ */
+#define AGP_AMD64_NVIDIA_0_APBASE 0x10
+#define AGP_AMD64_NVIDIA_1_APBASE1 0x50
+#define AGP_AMD64_NVIDIA_1_APLIMIT1 0x54
+#define AGP_AMD64_NVIDIA_1_APSIZE 0xa8
+#define AGP_AMD64_NVIDIA_1_APBASE2 0xd8
+#define AGP_AMD64_NVIDIA_1_APLIMIT2 0xdc
+
+/*
+ * ULi M1689 registers
+ */
+#define AGP_AMD64_ULI_APBASE 0x10
+#define AGP_AMD64_ULI_HTT_FEATURE 0x50
+#define AGP_AMD64_ULI_ENU_SCR 0x54
+
+/*
+ * ATI IGP registers
+ */
+#define ATI_GART_MMADDR 0x14
+#define ATI_RS100_APSIZE 0xac
+#define ATI_RS100_IG_AGPMODE 0xb0
+#define ATI_RS300_APSIZE 0xf8
+#define ATI_RS300_IG_AGPMODE 0xfc
+#define ATI_GART_FEATURE_ID 0x00
+#define ATI_GART_BASE 0x04
+#define ATI_GART_CACHE_CNTRL 0x0c
+
#endif /* !_PCI_AGPREG_H_ */
diff --git a/sys/dev/agp/agpvar.h b/sys/dev/agp/agpvar.h
--- a/sys/dev/agp/agpvar.h
+++ b/sys/dev/agp/agpvar.h
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/sys/pci/agpvar.h,v 1.1.2.2 2002/01/10 12:07:08 mdodd Exp $
+ * $FreeBSD: src/sys/pci/agpvar.h,v 1.3 2005/12/20 20:05:21 jhb Exp $
* $DragonFly: src/sys/dev/agp/agpvar.h,v 1.2 2003/06/17 04:28:56 dillon Exp $
*/
@@ -48,7 +48,6 @@ struct agp_info {
u_int32_t ai_mode;
vm_offset_t ai_aperture_base;
vm_size_t ai_aperture_size;
- vm_offset_t ai_aperture_va;
vm_size_t ai_memory_allowed;
vm_size_t ai_memory_used;
u_int32_t ai_devid;
diff --git a/sys/sys/agpio.h b/sys/sys/agpio.h
--- a/sys/sys/agpio.h
+++ b/sys/sys/agpio.h
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/sys/sys/agpio.h,v 1.1.2.2 2001/12/20 10:36:57 ru Exp $
+ * $FreeBSD: src/sys/sys/agpio.h,v 1.4 2003/10/23 18:08:56 jhb Exp $
* $DragonFly: src/sys/sys/agpio.h,v 1.4 2006/05/20 02:42:13 dillon Exp $
*/
More information about the Submit
mailing list