summaryrefslogtreecommitdiff
path: root/sys/dev/pci
diff options
context:
space:
mode:
authorTodd C. Miller <millert@cvs.openbsd.org>2003-03-19 20:06:29 +0000
committerTodd C. Miller <millert@cvs.openbsd.org>2003-03-19 20:06:29 +0000
commit61b746adad97e1f6dc83c56e64043edcc4fd024d (patch)
treeddbd9f1f89a17103369afcf87d5e3b76456b4e9e /sys/dev/pci
parentb140dd8b1a36d6a61ba86b34f51790597280bc5e (diff)
Add i830 support from NetBSD via patch in kernel/3150.
Verified to not break i81[05] and tested on two i830s.
Diffstat (limited to 'sys/dev/pci')
-rw-r--r--sys/dev/pci/agp_i810.c279
-rw-r--r--sys/dev/pci/agpreg.h18
2 files changed, 230 insertions, 67 deletions
diff --git a/sys/dev/pci/agp_i810.c b/sys/dev/pci/agp_i810.c
index 3a1abb9b9b5..1bcf5f1dab1 100644
--- a/sys/dev/pci/agp_i810.c
+++ b/sys/dev/pci/agp_i810.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: agp_i810.c,v 1.4 2003/02/13 20:07:33 mickey Exp $ */
-/* $NetBSD: agp_i810.c,v 1.8 2001/09/20 20:00:16 fvdl Exp $ */
+/* $OpenBSD: agp_i810.c,v 1.5 2003/03/19 20:06:28 millert Exp $ */
+/* $NetBSD: agp_i810.c,v 1.15 2003/01/31 00:07:39 thorpej Exp $ */
/*-
* Copyright (c) 2000 Doug Rabson
@@ -46,20 +46,26 @@
#include <dev/pci/pcidevs.h>
#include <dev/pci/agpvar.h>
#include <dev/pci/agpreg.h>
-
#include <dev/pci/vga_pcivar.h>
#include <machine/bus.h>
#define READ1(off) bus_space_read_1(isc->bst, isc->bsh, off)
+#define READ4(off) bus_space_read_4(isc->bst, isc->bsh, off)
#define WRITE4(off,v) bus_space_write_4(isc->bst, isc->bsh, off, v)
+#define CHIP_I810 0 /* i810/i815 */
+#define CHIP_I830 1 /* i830/i845 */
+
struct agp_i810_softc {
- u_int32_t initial_aperture; /* aperture size at startup */
struct agp_gatt *gatt;
- u_int32_t dcache_size;
- bus_space_tag_t bst; /* bus_space tag */
- bus_space_handle_t bsh; /* bus_space handle */
+ int chiptype; /* i810-like or i830 */
+ u_int32_t dcache_size; /* i810 only */
+ u_int32_t stolen; /* number of i830/845 gtt entries
+ for stolen memory */
+ bus_space_tag_t bst; /* bus_space tag */
+ bus_space_handle_t bsh; /* bus_space handle */
+ struct pci_attach_args bridge_pa;
};
u_int32_t agp_i810_get_aperture(struct vga_pci_softc *);
@@ -88,9 +94,8 @@ struct agp_methods agp_i810_methods = {
agp_i810_unbind_memory,
};
-
int
-agp_i810_attach(struct vga_pci_softc* sc, struct pci_attach_args *pa,
+agp_i810_attach(struct vga_pci_softc *sc, struct pci_attach_args *pa,
struct pci_attach_args *pchb_pa)
{
struct agp_i810_softc *isc;
@@ -105,7 +110,7 @@ agp_i810_attach(struct vga_pci_softc* sc, struct pci_attach_args *pa,
memset(isc, 0, sizeof *isc);
sc->sc_chipc = isc;
sc->sc_methods = &agp_i810_methods;
- sc->sc_dmat = pa->pa_dmat; /* XXX fvdl */
+ memcpy(&isc->bridge_pa, pchb_pa, sizeof *pchb_pa);
if ((error = agp_map_aperture(sc))) {
printf(": can't map aperture\n");
@@ -113,6 +118,19 @@ agp_i810_attach(struct vga_pci_softc* sc, struct pci_attach_args *pa,
return (error);
}
+ switch (PCI_PRODUCT(pa->pa_id)) {
+ case PCI_PRODUCT_INTEL_82810_GC:
+ case PCI_PRODUCT_INTEL_82810_DC100_GC:
+ case PCI_PRODUCT_INTEL_82810E_GC:
+ case PCI_PRODUCT_INTEL_82815_FULL_GRAPH:
+ isc->chiptype = CHIP_I810;
+ break;
+ case PCI_PRODUCT_INTEL_82830MP_IV:
+ case PCI_PRODUCT_INTEL_82845G_IGD:
+ isc->chiptype = CHIP_I830;
+ break;
+ }
+
error = pci_mapreg_map(pa, AGP_I810_MMADR,
PCI_MAPREG_TYPE_MEM, 0, &isc->bst, &isc->bsh, NULL, NULL, 0);
if (error != 0) {
@@ -120,31 +138,78 @@ agp_i810_attach(struct vga_pci_softc* sc, struct pci_attach_args *pa,
return (error);
}
- isc->initial_aperture = AGP_GET_APERTURE(sc);
+ gatt = malloc(sizeof(struct agp_gatt), M_DEVBUF, M_NOWAIT);
+ if (!gatt) {
+ agp_generic_detach(sc);
+ return (ENOMEM);
+ }
+ isc->gatt = gatt;
- if (READ1(AGP_I810_DRT) & AGP_I810_DRT_POPULATED)
- isc->dcache_size = 4 * 1024 * 1024;
- else
- isc->dcache_size = 0;
+ gatt->ag_entries = AGP_GET_APERTURE(sc) >> AGP_PAGE_SHIFT;
+
+ if (isc->chiptype == CHIP_I810) {
+ int dummyseg;
+ /* Some i810s have on-chip memory called dcache */
+ if (READ1(AGP_I810_DRT) & AGP_I810_DRT_POPULATED)
+ isc->dcache_size = 4 * 1024 * 1024;
+ else
+ isc->dcache_size = 0;
+
+ /* According to the specs the gatt on the i810 must be 64k */
+ if (agp_alloc_dmamem(sc->sc_dmat, 64 * 1024,
+ 0, &gatt->ag_dmamap, (caddr_t *)&gatt->ag_virtual,
+ &gatt->ag_physical, &gatt->ag_dmaseg, 1, &dummyseg) != 0) {
+ free(gatt, M_DEVBUF);
+ agp_generic_detach(sc);
+ return (ENOMEM);
+ }
- for (;;) {
- gatt = agp_alloc_gatt(sc);
- if (gatt)
+ gatt->ag_size = gatt->ag_entries * sizeof(u_int32_t);
+ memset(gatt->ag_virtual, 0, gatt->ag_size);
+
+ agp_flush_cache();
+ /* Install the GATT. */
+ WRITE4(AGP_I810_PGTBL_CTL, gatt->ag_physical | 1);
+ } else {
+ /* The i830 automatically initializes the 128k gatt on boot. */
+ pcireg_t reg;
+ u_int32_t pgtblctl;
+ u_int16_t gcc1;
+
+ reg = pci_conf_read(isc->bridge_pa.pa_pc,
+ isc->bridge_pa.pa_tag, AGP_I830_GCC1);
+ gcc1 = (u_int16_t)(reg >> 16);
+ switch (gcc1 & AGP_I830_GCC1_GMS) {
+ case AGP_I830_GCC1_GMS_STOLEN_512:
+ isc->stolen = (512 - 132) * 1024 / 4096;
break;
-
- /*
- * Probably contigmalloc failure. Try reducing the
- * aperture so that the gatt size reduces.
- */
- if (AGP_SET_APERTURE(sc, AGP_GET_APERTURE(sc) / 2)) {
+ case AGP_I830_GCC1_GMS_STOLEN_1024:
+ isc->stolen = (1024 - 132) * 1024 / 4096;
+ break;
+ case AGP_I830_GCC1_GMS_STOLEN_8192:
+ isc->stolen = (8192 - 132) * 1024 / 4096;
+ break;
+ default:
+ isc->stolen = 0;
+ printf(
+ ": unknown memory configuration, disabling\n");
agp_generic_detach(sc);
- return (ENOMEM);
+ return (EINVAL);
}
- }
- isc->gatt = gatt;
+#ifdef DEBUG
+ if (isc->stolen > 0) {
+ printf(": detected %dk stolen memory",
+ isc->stolen * 4);
+ }
+#endif
- /* Install the GATT. */
- WRITE4(AGP_I810_PGTBL_CTL, gatt->ag_physical | 1);
+ /* GATT address is already in there, make sure it's enabled */
+ pgtblctl = READ4(AGP_I810_PGTBL_CTL);
+ pgtblctl |= 1;
+ WRITE4(AGP_I810_PGTBL_CTL, pgtblctl);
+
+ gatt->ag_physical = pgtblctl & ~1;
+ }
/*
* Make sure the chipset can see everything.
@@ -157,54 +222,115 @@ agp_i810_attach(struct vga_pci_softc* sc, struct pci_attach_args *pa,
u_int32_t
agp_i810_get_aperture(struct vga_pci_softc *sc)
{
- u_int16_t miscc;
-
- miscc = pci_conf_read(sc->sc_pc, sc->sc_pcitag, AGP_I810_SMRAM) >> 16;
- if ((miscc & AGP_I810_MISCC_WINSIZE) == AGP_I810_MISCC_WINSIZE_32)
- return (32 * 1024 * 1024);
- else
- return (64 * 1024 * 1024);
+ struct agp_i810_softc *isc = sc->sc_chipc;
+ pcireg_t reg;
+
+ if (isc->chiptype == CHIP_I810) {
+ u_int16_t miscc;
+
+ reg = pci_conf_read(isc->bridge_pa.pa_pc,
+ isc->bridge_pa.pa_tag, AGP_I810_SMRAM);
+ miscc = (u_int16_t)(reg >> 16);
+ if ((miscc & AGP_I810_MISCC_WINSIZE) ==
+ AGP_I810_MISCC_WINSIZE_32)
+ return (32 * 1024 * 1024);
+ else
+ return (64 * 1024 * 1024);
+ } else { /* I830 */
+ u_int16_t gcc1;
+
+ reg = pci_conf_read(isc->bridge_pa.pa_pc,
+ isc->bridge_pa.pa_tag, AGP_I830_GCC0);
+ gcc1 = (u_int16_t)(reg >> 16);
+ if ((gcc1 & AGP_I830_GCC1_GMASIZE) == AGP_I830_GCC1_GMASIZE_64)
+ return (64 * 1024 * 1024);
+ else
+ return (128 * 1024 * 1024);
+ }
}
int
agp_i810_set_aperture(struct vga_pci_softc *sc, u_int32_t aperture)
{
- pcireg_t reg, miscc;
+ struct agp_i810_softc *isc = sc->sc_chipc;
+ pcireg_t reg;
- /*
- * Double check for sanity.
- */
- if (aperture != 32 * 1024 * 1024 && aperture != 64 * 1024 * 1024) {
- printf("AGP: bad aperture size %d\n", aperture);
- return (EINVAL);
- }
+ if (isc->chiptype == CHIP_I810) {
+ u_int16_t miscc;
- reg = pci_conf_read(sc->sc_pc, sc->sc_pcitag, AGP_I810_SMRAM);
- miscc = reg >> 16;
- miscc &= ~AGP_I810_MISCC_WINSIZE;
- if (aperture == 32 * 1024 * 1024)
- miscc |= AGP_I810_MISCC_WINSIZE_32;
- else
- miscc |= AGP_I810_MISCC_WINSIZE_64;
+ /*
+ * Double check for sanity.
+ */
+ if (aperture != (32 * 1024 * 1024) &&
+ aperture != (64 * 1024 * 1024)) {
+ printf("agp: bad aperture size %d\n", aperture);
+ return (EINVAL);
+ }
- reg &= 0x0000ffff;
- reg |= (miscc << 16);
- pci_conf_write(sc->sc_pc, sc->sc_pcitag, AGP_I810_SMRAM, miscc);
+ reg = pci_conf_read(isc->bridge_pa.pa_pc,
+ isc->bridge_pa.pa_tag, AGP_I810_SMRAM);
+ miscc = (u_int16_t)(reg >> 16);
+ miscc &= ~AGP_I810_MISCC_WINSIZE;
+ if (aperture == 32 * 1024 * 1024)
+ miscc |= AGP_I810_MISCC_WINSIZE_32;
+ else
+ miscc |= AGP_I810_MISCC_WINSIZE_64;
+
+ reg &= 0x0000ffff;
+ reg |= ((pcireg_t)miscc) << 16;
+ pci_conf_write(isc->bridge_pa.pa_pc,
+ isc->bridge_pa.pa_tag, AGP_I810_SMRAM, reg);
+ } else { /* I830 */
+ u_int16_t gcc1;
+
+ if (aperture != (64 * 1024 * 1024) &&
+ aperture != (128 * 1024 * 1024)) {
+ printf("agp: bad aperture size %d\n", aperture);
+ return (EINVAL);
+ }
+ reg = pci_conf_read(isc->bridge_pa.pa_pc,
+ isc->bridge_pa.pa_tag, AGP_I830_GCC0);
+ gcc1 = (u_int16_t)(reg >> 16);
+ gcc1 &= ~AGP_I830_GCC1_GMASIZE;
+ if (aperture == 64 * 1024 * 1024)
+ gcc1 |= AGP_I830_GCC1_GMASIZE_64;
+ else
+ gcc1 |= AGP_I830_GCC1_GMASIZE_128;
+
+ reg &= 0x0000ffff;
+ reg |= ((pcireg_t)gcc1) << 16;
+ pci_conf_write(isc->bridge_pa.pa_pc,
+ isc->bridge_pa.pa_tag, AGP_I830_GCC0, reg);
+ }
return (0);
}
int
-agp_i810_bind_page(struct vga_pci_softc *sc, off_t offset, bus_addr_t pa)
+agp_i810_bind_page(struct vga_pci_softc *sc, off_t offset, bus_addr_t physical)
{
struct agp_i810_softc *isc = sc->sc_chipc;
- if (offset < 0 || offset >= (isc->gatt->ag_entries << AGP_PAGE_SHIFT))
+ if (offset < 0 || offset >= (isc->gatt->ag_entries << AGP_PAGE_SHIFT)) {
+#ifdef DEBUG
+ printf("agp: failed: offset 0x%08x, shift %d, entries %d\n",
+ (int)offset, AGP_PAGE_SHIFT,
+ isc->gatt->ag_entries);
+#endif
return (EINVAL);
+ }
- WRITE4(AGP_I810_GTT + (u_int32_t)(offset >> AGP_PAGE_SHIFT) * 4,
- pa | 1);
+ if (isc->chiptype == CHIP_I810) {
+ if ((offset >> AGP_PAGE_SHIFT) < isc->stolen) {
+#ifdef DEBUG
+ printf("agp: trying to bind into stolen memory\n");
+#endif
+ return (EINVAL);
+ }
+ }
+ WRITE4(AGP_I810_GTT + (u_int32_t)(offset >> AGP_PAGE_SHIFT) * 4,
+ physical | 1);
return (0);
}
@@ -216,6 +342,15 @@ agp_i810_unbind_page(struct vga_pci_softc *sc, off_t offset)
if (offset < 0 || offset >= (isc->gatt->ag_entries << AGP_PAGE_SHIFT))
return (EINVAL);
+ if (isc->chiptype == CHIP_I830 ) {
+ if ((offset >> AGP_PAGE_SHIFT) < isc->stolen) {
+#ifdef DEBUG
+ printf("agp: trying to unbind from stolen memory\n");
+#endif
+ return (EINVAL);
+ }
+ }
+
WRITE4(AGP_I810_GTT + (u_int32_t)(offset >> AGP_PAGE_SHIFT) * 4, 0);
return (0);
}
@@ -245,6 +380,8 @@ agp_i810_alloc_memory(struct vga_pci_softc *sc, int type, vsize_t size)
/*
* Mapping local DRAM into GATT.
*/
+ if (isc->chiptype == CHIP_I830 )
+ return (NULL);
if (size != isc->dcache_size)
return (NULL);
} else if (type == 2) {
@@ -260,11 +397,14 @@ agp_i810_alloc_memory(struct vga_pci_softc *sc, int type, vsize_t size)
mem->am_id = sc->sc_nextid++;
mem->am_size = size;
mem->am_type = type;
-
+
if (type == 2) {
+ /*
+ * Allocate and wire down the page now so that we can
+ * get its physical address.
+ */
mem->am_dmaseg = malloc(sizeof *mem->am_dmaseg, M_DEVBUF,
M_WAITOK);
-
if ((error = agp_alloc_dmamem(sc->sc_dmat, size, 0,
&mem->am_dmamap, &mem->am_virtual, &mem->am_physical,
mem->am_dmaseg, 1, &mem->am_nseg)) != 0) {
@@ -294,7 +434,7 @@ agp_i810_free_memory(struct vga_pci_softc *sc, struct agp_memory *mem)
{
if (mem->am_is_bound)
return (EBUSY);
-
+
if (mem->am_type == 2) {
agp_free_dmamem(sc->sc_dmat, mem->am_size, mem->am_dmamap,
mem->am_virtual, mem->am_dmaseg, mem->am_nseg);
@@ -322,7 +462,7 @@ agp_i810_bind_memory(struct vga_pci_softc *sc, struct agp_memory *mem,
*/
regval = bus_space_read_4(isc->bst, isc->bsh, AGP_I810_PGTBL_CTL);
if (regval != (isc->gatt->ag_physical | 1)) {
-#if 0
+#if DEBUG
printf("agp_i810_bind_memory: PGTBL_CTL is 0x%x - fixing\n",
regval);
#endif
@@ -339,12 +479,16 @@ agp_i810_bind_memory(struct vga_pci_softc *sc, struct agp_memory *mem,
}
if (mem->am_type != 1)
- return agp_generic_bind_memory(sc, mem, offset);
+ return (agp_generic_bind_memory(sc, mem, offset));
- for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE)
+ if (isc->chiptype == CHIP_I830)
+ return (EINVAL);
+
+ for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) {
WRITE4(AGP_I810_GTT +
(u_int32_t)(offset >> AGP_PAGE_SHIFT) * 4, i | 3);
-
+ }
+ mem->am_is_bound = 1;
return (0);
}
@@ -365,8 +509,11 @@ agp_i810_unbind_memory(struct vga_pci_softc *sc, struct agp_memory *mem)
if (mem->am_type != 1)
return (agp_generic_unbind_memory(sc, mem));
+ if (isc->chiptype == CHIP_I830)
+ return (EINVAL);
+
for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE)
WRITE4(AGP_I810_GTT + (i >> AGP_PAGE_SHIFT) * 4, 0);
-
+ mem->am_is_bound = 0;
return (0);
}
diff --git a/sys/dev/pci/agpreg.h b/sys/dev/pci/agpreg.h
index df3dd955be0..5e25b463832 100644
--- a/sys/dev/pci/agpreg.h
+++ b/sys/dev/pci/agpreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: agpreg.h,v 1.1 2002/07/12 20:17:03 mickey Exp $ */
+/* $OpenBSD: agpreg.h,v 1.2 2003/03/19 20:06:28 millert Exp $ */
/* $NetBSD: agpreg.h,v 1.1 2001/09/10 10:01:02 fvdl Exp $ */
/*-
@@ -154,4 +154,20 @@
#define AGP_I810_DRT_POPULATED 0x01
#define AGP_I810_GTT 0x10000
+/*
+ * Config registers for i830MG device 0
+ */
+#define AGP_I830_GCC0 0x50
+#define AGP_I830_GCC1 0x52
+#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_STOLEN_512 0x20
+#define AGP_I830_GCC1_GMS_STOLEN_1024 0x30
+#define AGP_I830_GCC1_GMS_STOLEN_8192 0x40
+#define AGP_I830_GCC1_GMASIZE 0x01
+#define AGP_I830_GCC1_GMASIZE_64 0x01
+#define AGP_I830_GCC1_GMASIZE_128 0x00
+
#endif /* !_PCI_AGPREG_H_ */