aboutsummaryrefslogtreecommitdiff
path: root/sys/pci
diff options
context:
space:
mode:
Diffstat (limited to 'sys/pci')
-rw-r--r--sys/pci/agp_amd64.c166
-rw-r--r--sys/pci/agpreg.h17
2 files changed, 175 insertions, 8 deletions
diff --git a/sys/pci/agp_amd64.c b/sys/pci/agp_amd64.c
index efa71a506738..a8f36d6d2ba6 100644
--- a/sys/pci/agp_amd64.c
+++ b/sys/pci/agp_amd64.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2004 Jung-uk Kim
+ * Copyright (c) 2004, 2005 Jung-uk Kim <jkim@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -55,16 +55,26 @@ __FBSDID("$FreeBSD$");
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);
+
MALLOC_DECLARE(M_AGP);
#define AMD64_MAX_MCTRL 8
struct agp_amd64_softc {
struct agp_softc agp;
- uint32_t initial_aperture; /* aperture size at startup */
- struct agp_gatt *gatt;
- int mctrl[AMD64_MAX_MCTRL];
- int n_mctrl;
+ uint32_t initial_aperture;
+ struct agp_gatt *gatt;
+ uint32_t apbase;
+ int mctrl[AMD64_MAX_MCTRL];
+ int n_mctrl;
};
static const char*
@@ -82,22 +92,45 @@ agp_amd64_match(device_t dev)
return ("AMD 8151 AGP graphics tunnel");
case 0x07551039:
return ("SiS 755 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");
+ case 0xb1881106:
+ return ("VIA 838X 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_probe(device_t dev)
{
const char *desc;
@@ -131,14 +164,34 @@ agp_amd64_attach(device_t dev)
sc->n_mctrl = n;
- if (bootverbose)
- printf("AMD64: %d Misc. Control unit(s) found.\n", sc->n_mctrl);
+ if (bootverbose) {
+ device_printf(dev, "%d Miscellaneous Control unit(s) found.\n",
+ sc->n_mctrl);
+ for (i = 0; i < sc->n_mctrl; i++)
+ device_printf(dev, "Aperture Base[%d]: 0x%08x\n", i,
+ pci_cfgregread(0, sc->mctrl[i], 3,
+ AGP_AMD64_APBASE, 4) & AGP_AMD64_APBASE_MASK);
+ }
if ((error = agp_generic_attach(dev)))
return error;
sc->initial_aperture = AGP_GET_APERTURE(dev);
+ 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;
+ }
+
for (;;) {
gatt = agp_alloc_gatt(dev);
if (gatt)
@@ -230,7 +283,7 @@ agp_amd64_set_aperture(device_t dev, uint32_t aperture)
for (i = 0; i < AGP_AMD64_TABLE_SIZE; i++)
if (agp_amd64_table[i] == aperture)
break;
- if (i == AGP_AMD64_TABLE_SIZE)
+ if (i >= AGP_AMD64_TABLE_SIZE)
return EINVAL;
for (j = 0; j < sc->n_mctrl; j++)
@@ -238,6 +291,16 @@ agp_amd64_set_aperture(device_t dev, uint32_t aperture)
(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;
+ }
+
return 0;
}
@@ -277,6 +340,93 @@ agp_amd64_flush_tlb(device_t dev)
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;
+
+ apbase = pci_cfgregread(0, sc->mctrl[0], 3, AGP_AMD64_APBASE, 4);
+ for (i = 0; i < sc->n_mctrl; i++)
+ pci_cfgregwrite(0, sc->mctrl[i], 3, AGP_AMD64_APBASE,
+ apbase & ~(AGP_AMD64_APBASE_MASK & ~(uint32_t)0x7f), 4);
+ sc->apbase = apbase << 25;
+}
+
+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 device_method_t agp_amd64_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, agp_amd64_probe),
diff --git a/sys/pci/agpreg.h b/sys/pci/agpreg.h
index eb5053d20ca4..55c145ff1e87 100644
--- a/sys/pci/agpreg.h
+++ b/sys/pci/agpreg.h
@@ -263,6 +263,23 @@
#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