summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorMichael Shalayeff <mickey@cvs.openbsd.org>2002-07-12 20:17:04 +0000
committerMichael Shalayeff <mickey@cvs.openbsd.org>2002-07-12 20:17:04 +0000
commit5865d6a998391648e294e7a7d4670166fb810364 (patch)
treef676c2582d4801871f0dcc11309adaa318343ddc /sys/dev
parentb7951dd4c58d1d7d1cbd884949af928addaa1330 (diff)
support for the agp gart on various agp chipsets.
only i810 driver was tested though. based on the netbsd's lkm, initially ported by hunter@dg.net.ua and later made into shape by mickey. testing by art@ and millert@ .
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/ic/i82810reg.h82
-rw-r--r--sys/dev/ic/vga.c14
-rw-r--r--sys/dev/ic/vgavar.h12
-rw-r--r--sys/dev/pci/agp_ali.c247
-rw-r--r--sys/dev/pci/agp_amd.c326
-rw-r--r--sys/dev/pci/agp_i810.c375
-rw-r--r--sys/dev/pci/agp_intel.c236
-rw-r--r--sys/dev/pci/agp_sis.c224
-rw-r--r--sys/dev/pci/agp_via.c219
-rw-r--r--sys/dev/pci/agpreg.h157
-rw-r--r--sys/dev/pci/agpvar.h138
-rw-r--r--sys/dev/pci/files.pci8
-rw-r--r--sys/dev/pci/pcivar.h13
-rw-r--r--sys/dev/pci/vga_pci.c779
-rw-r--r--sys/dev/pci/vga_pcivar.h72
15 files changed, 2851 insertions, 51 deletions
diff --git a/sys/dev/ic/i82810reg.h b/sys/dev/ic/i82810reg.h
new file mode 100644
index 00000000000..b20f4e6a137
--- /dev/null
+++ b/sys/dev/ic/i82810reg.h
@@ -0,0 +1,82 @@
+/* $OpenBSD: i82810reg.h,v 1.1 2002/07/12 20:17:03 mickey Exp $ */
+
+/*
+ * Copyright (c) 2000 Michael Shalayeff
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Michael Shalayeff.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 HIS RELATIVES 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 MIND, 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.
+ */
+
+
+/*
+ * Intel i82810/810E memory and graphics controller
+ * http://
+ */
+
+/* Host-Hub Interface Bridge/DRAM Controller Device Registers (Device 0) */
+#define I82810_SMRAM 0x70
+#define I82810_SMRAM_GMS_DIS 0x00
+#define I82810_SMRAM_GMS_RSRVD 0x40
+#define I82810_SMRAM_GMS_512 0x80
+#define I82810_SMRAM_GMS_1024 0xc0
+#define I82810_SMRAM_USMM_DIS 0x00
+#define I82810_SMRAM_USMM_TDHE 0x10
+#define I82810_SMRAM_USMM_T5HE 0x20
+#define I82810_SMRAM_USMM_T1HE 0x30
+#define I82810_SMRAM_LSMM_DIS 0x00
+#define I82810_SMRAM_LSMM_GSM 0x04
+#define I82810_SMRAM_LSMM_CRSH 0x08
+#define I82810_SMRAM_D_LCK 0x02
+#define I82810_SMRAM_E_SMERR 0x01
+#define I82810_MISCC 0x72
+#define I82810_MISCC_GDCWS 0x0001
+#define I82810_MISCC_P_LCK 0x0008
+#define I82810_MISCC_WPTHC_NO 0x0000
+#define I82810_MISCC_WPTHC_625 0x0010
+#define I82810_MISCC_WPTHC_500 0x0020
+#define I82810_MISCC_WPTHC_375 0x0030
+#define I82810_MISCC_RPTHC_NO 0x0000
+#define I82810_MISCC_RPTHC_625 0x0040
+#define I82810_MISCC_RPTHC_500 0x0080
+#define I82810_MISCC_RPTHC_375 0x00c0
+
+/* Graphics Device Registers (Device 1) */
+#define I82810_GMADR 0x10
+#define I82810_MMADR 0x14
+
+#define I82810_DRT 0x3000
+#define I82810_DRT_DP 0x01
+#define I82810_DRAMCL 0x3001
+#define I82810_DRAMCL_RPT 0x01
+#define I82810_DRAMCL_RT 0x02
+#define I82810_DRAMCL_CL 0x04
+#define I82810_DRAMCL_RCO 0x08
+#define I82810_DRAMCL_PMC 0x10
+#define I82810_DRAMCH 0x3002
+#define I82810_DRAMCH_SMS 0x07
+#define I82810_DRAMCH_DRR 0x18
+#define I82810_GTT 0x10000
diff --git a/sys/dev/ic/vga.c b/sys/dev/ic/vga.c
index 1dc3f035154..373226c8d09 100644
--- a/sys/dev/ic/vga.c
+++ b/sys/dev/ic/vga.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vga.c,v 1.29 2002/03/14 03:16:05 millert Exp $ */
+/* $OpenBSD: vga.c,v 1.30 2002/07/12 20:17:03 mickey Exp $ */
/* $NetBSD: vga.c,v 1.28.2.1 2000/06/30 16:27:47 simonb Exp $ */
/*
@@ -497,7 +497,6 @@ vga_common_attach(self, iot, memt, type)
bus_space_tag_t iot, memt;
int type;
{
-#ifdef arc
vga_extended_attach(self, iot, memt, type, NULL);
}
@@ -506,9 +505,8 @@ vga_extended_attach(self, iot, memt, type, map)
struct device *self;
bus_space_tag_t iot, memt;
int type;
- int (*map)(void *, vaddr_t, int);
+ paddr_t (*map)(void *, off_t, int);
{
-#endif /* arc */
int console;
struct vga_config *vc;
struct wsemuldisplaydev_attach_args aa;
@@ -528,9 +526,7 @@ vga_extended_attach(self, iot, memt, type, map)
vc->vc_softc = self;
vc->vc_type = type;
-#ifdef arc
vc->vc_mmap = map;
-#endif
aa.console = console;
aa.scrdata = (vc->hdl.vh_mono ? &vga_screenlist_mono : &vga_screenlist);
@@ -628,15 +624,11 @@ vga_mmap(v, offset, prot)
off_t offset;
int prot;
{
-
-#ifdef arc
struct vga_config *vc = v;
if (vc->vc_mmap != NULL)
return (*vc->vc_mmap)(v, offset, prot);
-#else
- /* XXX */
-#endif
+
return -1;
}
diff --git a/sys/dev/ic/vgavar.h b/sys/dev/ic/vgavar.h
index 5a5db102d10..7bac3e67bbc 100644
--- a/sys/dev/ic/vgavar.h
+++ b/sys/dev/ic/vgavar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: vgavar.h,v 1.7 2002/03/14 03:16:05 millert Exp $ */
+/* $OpenBSD: vgavar.h,v 1.8 2002/07/12 20:17:03 mickey Exp $ */
/* $NetBSD: vgavar.h,v 1.4 2000/06/17 07:11:50 soda Exp $ */
/*
@@ -57,9 +57,7 @@ struct vga_config {
void (*switchcb)(void *, int, int);
void *switchcbarg;
-#ifdef arc
paddr_t (*vc_mmap)(void *, off_t, int);
-#endif
struct timeout vc_switch_timeout;
};
@@ -164,14 +162,10 @@ static inline void _vga_gdc_write(vh, reg, val)
int vga_common_probe(bus_space_tag_t, bus_space_tag_t);
void vga_common_attach(struct device *, bus_space_tag_t,
- bus_space_tag_t, int);
-#ifdef arc
+ bus_space_tag_t, int);
void vga_extended_attach(struct device *, bus_space_tag_t,
- bus_space_tag_t, int,
- int (*)(void *, off_t, int));
-#endif
+ bus_space_tag_t, int, paddr_t (*)(void *, off_t, int));
int vga_is_console(bus_space_tag_t, int);
-
int vga_cnattach(bus_space_tag_t, bus_space_tag_t, int, int);
struct wsscreen_descr;
diff --git a/sys/dev/pci/agp_ali.c b/sys/dev/pci/agp_ali.c
new file mode 100644
index 00000000000..58cec9ee1c3
--- /dev/null
+++ b/sys/dev/pci/agp_ali.c
@@ -0,0 +1,247 @@
+/* $OpenBSD: agp_ali.c,v 1.1 2002/07/12 20:17:03 mickey Exp $ */
+/* $NetBSD: agp_ali.c,v 1.2 2001/09/15 00:25:00 thorpej Exp $ */
+
+
+/*-
+ * Copyright (c) 2000 Doug Rabson
+ * 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_ali.c,v 1.3 2001/07/05 21:28:46 jhb Exp $
+ */
+
+
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/conf.h>
+#include <sys/device.h>
+#include <sys/lock.h>
+#include <sys/agpio.h>
+
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+#include <dev/pci/vga_pcivar.h>
+#include <dev/pci/agpvar.h>
+#include <dev/pci/agpreg.h>
+
+#include <machine/bus.h>
+
+struct agp_ali_softc {
+ u_int32_t initial_aperture; /* aperture size at startup */
+ struct agp_gatt *gatt;
+};
+
+u_int32_t agp_ali_get_aperture(struct vga_pci_softc *);
+int agp_ali_set_aperture(struct vga_pci_softc *sc, u_int32_t);
+int agp_ali_bind_page(struct vga_pci_softc *, off_t, bus_addr_t);
+int agp_ali_unbind_page(struct vga_pci_softc *, off_t);
+void agp_ali_flush_tlb(struct vga_pci_softc *);
+
+struct agp_methods agp_ali_methods = {
+ agp_ali_get_aperture,
+ agp_ali_set_aperture,
+ agp_ali_bind_page,
+ agp_ali_unbind_page,
+ agp_ali_flush_tlb,
+ agp_generic_enable,
+ agp_generic_alloc_memory,
+ agp_generic_free_memory,
+ agp_generic_bind_memory,
+ agp_generic_unbind_memory,
+};
+
+int
+agp_ali_attach(struct vga_pci_softc *sc, struct pci_attach_args *pa, struct pci_attach_args *pchb_pa)
+{
+ struct agp_ali_softc *asc;
+ struct agp_gatt *gatt;
+ pcireg_t reg;
+
+ asc = malloc(sizeof *asc, M_DEVBUF, M_NOWAIT);
+ if (asc == NULL) {
+ printf(": failed to allocate softc\n");
+ return ENOMEM;
+ }
+ sc->sc_chipc = asc;
+ sc->sc_methods = &agp_ali_methods;
+
+ if (agp_map_aperture(sc) != 0) {
+ printf(": failed to map aperture\n");
+ free(asc, M_DEVBUF);
+ return ENXIO;
+ }
+
+ asc->initial_aperture = agp_ali_get_aperture(sc);
+
+ for (;;) {
+ gatt = agp_alloc_gatt(sc);
+ if (gatt != NULL)
+ break;
+
+ /*
+ * Probably contigmalloc failure. Try reducing the
+ * aperture so that the gatt size reduces.
+ */
+ if (AGP_SET_APERTURE(sc, AGP_GET_APERTURE(sc) / 2)) {
+ agp_generic_detach(sc);
+ printf(": failed to set aperture\n");
+ return ENOMEM;
+ }
+ }
+ asc->gatt = gatt;
+
+ /* Install the gatt. */
+ reg = pci_conf_read(sc->sc_pc, sc->sc_pcitag, AGP_ALI_ATTBASE);
+ reg = (reg & 0xff) | gatt->ag_physical;
+ pci_conf_write(sc->sc_pc, sc->sc_pcitag, AGP_ALI_ATTBASE, reg);
+
+ /* Enable the TLB. */
+ reg = pci_conf_read(sc->sc_pc, sc->sc_pcitag, AGP_ALI_TLBCTRL);
+ reg = (reg & ~0xff) | 0x10;
+ pci_conf_write(sc->sc_pc, sc->sc_pcitag, AGP_ALI_TLBCTRL, reg);
+
+ return 0;
+}
+
+#if 0
+int
+agp_ali_detach(struct vga_pci_softc *sc)
+{
+ int error;
+ pcireg_t reg;
+ struct agp_ali_softc *asc = sc->sc_chipc;
+
+ error = agp_generic_detach(sc);
+ if (error)
+ return error;
+
+ /* Disable the TLB.. */
+ reg = pci_conf_read(sc->sc_pc, sc->sc_pcitag, AGP_ALI_TLBCTRL);
+ reg &= ~0xff;
+ reg |= 0x90;
+ pci_conf_write(sc->sc_pc, sc->sc_pcitag, AGP_ALI_TLBCTRL, reg);
+
+ /* Put the aperture back the way it started. */
+ AGP_SET_APERTURE(sc, asc->initial_aperture);
+ reg = pci_conf_read(sc->sc_pc, sc->sc_pcitag, AGP_ALI_ATTBASE);
+ reg &= 0xff;
+ pci_conf_write(sc->sc_pc, sc->sc_pcitag, AGP_ALI_ATTBASE, reg);
+
+ agp_free_gatt(sc, asc->gatt);
+ return 0;
+}
+#endif
+
+#define M 1024*1024
+
+static const u_int32_t agp_ali_table[] = {
+ 0, /* 0 - invalid */
+ 1, /* 1 - invalid */
+ 2, /* 2 - invalid */
+ 4*M, /* 3 - invalid */
+ 8*M, /* 4 - invalid */
+ 0, /* 5 - invalid */
+ 16*M, /* 6 - invalid */
+ 32*M, /* 7 - invalid */
+ 64*M, /* 8 - invalid */
+ 128*M, /* 9 - invalid */
+ 256*M, /* 10 - invalid */
+};
+#define agp_ali_table_size (sizeof(agp_ali_table) / sizeof(agp_ali_table[0]))
+
+u_int32_t
+agp_ali_get_aperture(struct vga_pci_softc *sc)
+{
+ int i;
+
+ /*
+ * The aperture size is derived from the low bits of attbase.
+ * I'm not sure this is correct..
+ */
+ i = (int)pci_conf_read(sc->sc_pc, sc->sc_pcitag, AGP_ALI_ATTBASE) & 0xff;
+ if (i >= agp_ali_table_size)
+ return 0;
+ return agp_ali_table[i];
+}
+
+int
+agp_ali_set_aperture(struct vga_pci_softc *sc, u_int32_t aperture)
+{
+ int i;
+ pcireg_t reg;
+
+ for (i = 0; i < agp_ali_table_size; i++)
+ if (agp_ali_table[i] == aperture)
+ break;
+ if (i == agp_ali_table_size)
+ return EINVAL;
+
+ reg = pci_conf_read(sc->sc_pc, sc->sc_pcitag, AGP_ALI_ATTBASE);
+ reg &= ~0xff;
+ reg |= i;
+ pci_conf_write(sc->sc_pc, sc->sc_pcitag, AGP_ALI_ATTBASE, reg);
+ return 0;
+}
+
+int
+agp_ali_bind_page(struct vga_pci_softc *sc, off_t offset, bus_addr_t physical)
+{
+ struct agp_ali_softc *asc = sc->sc_chipc;
+
+ if (offset < 0 || offset >= (asc->gatt->ag_entries << AGP_PAGE_SHIFT))
+ return EINVAL;
+
+ asc->gatt->ag_virtual[offset >> AGP_PAGE_SHIFT] = physical;
+ return 0;
+}
+
+int
+agp_ali_unbind_page(struct vga_pci_softc *sc, off_t offset)
+{
+ struct agp_ali_softc *asc = sc->sc_chipc;
+
+ if (offset < 0 || offset >= (asc->gatt->ag_entries << AGP_PAGE_SHIFT))
+ return EINVAL;
+
+ asc->gatt->ag_virtual[offset >> AGP_PAGE_SHIFT] = 0;
+ return 0;
+}
+
+void
+agp_ali_flush_tlb(struct vga_pci_softc *sc)
+{
+ pcireg_t reg;
+
+ reg = pci_conf_read(sc->sc_pc, sc->sc_pcitag, AGP_ALI_TLBCTRL);
+ reg &= ~0xff;
+ reg |= 0x90;
+ pci_conf_write(sc->sc_pc, sc->sc_pcitag, AGP_ALI_TLBCTRL, reg);
+ reg &= ~0xff;
+ reg |= 0x10;
+ pci_conf_write(sc->sc_pc, sc->sc_pcitag, AGP_ALI_TLBCTRL, reg);
+}
+
diff --git a/sys/dev/pci/agp_amd.c b/sys/dev/pci/agp_amd.c
new file mode 100644
index 00000000000..c17a49f045b
--- /dev/null
+++ b/sys/dev/pci/agp_amd.c
@@ -0,0 +1,326 @@
+/* $OpenBSD: agp_amd.c,v 1.1 2002/07/12 20:17:03 mickey Exp $ */
+/* $NetBSD: agp_amd.c,v 1.6 2001/10/06 02:48:50 thorpej Exp $ */
+
+
+/*-
+ * Copyright (c) 2000 Doug Rabson
+ * 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_amd.c,v 1.6 2001/07/05 21:28:46 jhb Exp $
+ */
+
+
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/proc.h>
+#include <sys/conf.h>
+#include <sys/device.h>
+#include <sys/agpio.h>
+
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+#include <dev/pci/vga_pcivar.h>
+#include <dev/pci/agpvar.h>
+#include <dev/pci/agpreg.h>
+
+#include <dev/pci/pcidevs.h>
+
+#define READ2(off) bus_space_read_2(asc->iot, asc->ioh, off)
+#define READ4(off) bus_space_read_4(asc->iot, asc->ioh, off)
+#define WRITE2(off,v) bus_space_write_2(asc->iot, asc->ioh, off, v)
+#define WRITE4(off,v) bus_space_write_4(asc->iot, asc->ioh, off, v)
+
+struct agp_amd_gatt {
+ bus_dmamap_t ag_dmamap;
+ bus_dma_segment_t ag_dmaseg;
+ int ag_nseg;
+ u_int32_t ag_entries;
+ u_int32_t *ag_vdir; /* virtual address of page dir */
+ bus_addr_t ag_pdir; /* bus address of page dir */
+ u_int32_t *ag_virtual; /* virtual address of gatt */
+ bus_addr_t ag_physical; /* bus address of gatt */
+ size_t ag_size;
+};
+
+struct agp_amd_softc {
+ u_int32_t initial_aperture; /* aperture size at startup */
+ struct agp_amd_gatt *gatt;
+ bus_space_handle_t ioh;
+ bus_space_tag_t iot;
+};
+
+static u_int32_t agp_amd_get_aperture(struct vga_pci_softc *);
+static int agp_amd_set_aperture(struct vga_pci_softc *, u_int32_t);
+static int agp_amd_bind_page(struct vga_pci_softc *, off_t, bus_addr_t);
+static int agp_amd_unbind_page(struct vga_pci_softc *, off_t);
+static void agp_amd_flush_tlb(struct vga_pci_softc *);
+
+
+struct agp_methods agp_amd_methods = {
+ agp_amd_get_aperture,
+ agp_amd_set_aperture,
+ agp_amd_bind_page,
+ agp_amd_unbind_page,
+ agp_amd_flush_tlb,
+ agp_generic_enable,
+ agp_generic_alloc_memory,
+ agp_generic_free_memory,
+ agp_generic_bind_memory,
+ agp_generic_unbind_memory,
+};
+
+
+static struct agp_amd_gatt *
+agp_amd_alloc_gatt(struct vga_pci_softc *sc)
+{
+ u_int32_t apsize = AGP_GET_APERTURE(sc);
+ u_int32_t entries = apsize >> AGP_PAGE_SHIFT;
+ struct agp_amd_gatt *gatt;
+ int i, npages;
+ caddr_t vdir;
+
+ gatt = malloc(sizeof(struct agp_amd_gatt), M_DEVBUF, M_NOWAIT);
+ if (!gatt)
+ return 0;
+
+ if (agp_alloc_dmamem(sc->sc_dmat,
+ AGP_PAGE_SIZE + entries * sizeof(u_int32_t), 0,
+ &gatt->ag_dmamap, &vdir, &gatt->ag_pdir,
+ &gatt->ag_dmaseg, 1, &gatt->ag_nseg) != 0) {
+ printf("failed to allocate GATT\n");
+ free(gatt, M_DEVBUF);
+ return NULL;
+ }
+
+ gatt->ag_vdir = (u_int32_t *)vdir;
+ gatt->ag_entries = entries;
+ gatt->ag_virtual = (u_int32_t *)(vdir + AGP_PAGE_SIZE);
+ gatt->ag_physical = gatt->ag_pdir + AGP_PAGE_SIZE;
+ gatt->ag_size = AGP_PAGE_SIZE + entries * sizeof(u_int32_t);
+
+ memset(gatt->ag_vdir, 0, AGP_PAGE_SIZE);
+ memset(gatt->ag_virtual, 0, entries * sizeof(u_int32_t));
+
+ /*
+ * Map the pages of the GATT into the page directory.
+ */
+ npages = ((entries * sizeof(u_int32_t) + AGP_PAGE_SIZE - 1)
+ >> AGP_PAGE_SHIFT);
+
+ for (i = 0; i < npages; i++)
+ gatt->ag_vdir[i] = (gatt->ag_physical + i * AGP_PAGE_SIZE) | 1;
+
+ /*
+ * Make sure the chipset can see everything.
+ */
+ agp_flush_cache();
+
+ return gatt;
+}
+
+#if 0
+static void
+agp_amd_free_gatt(struct vga_pci_softc *sc, struct agp_amd_gatt *gatt)
+{
+ agp_free_dmamem(sc->sc_dmat, gatt->ag_size,
+ gatt->ag_dmamap, (caddr_t)gatt->ag_virtual, &gatt->ag_dmaseg,
+ gatt->ag_nseg);
+ free(gatt, M_DEVBUF);
+}
+#endif
+
+int
+agp_amd_attach(struct vga_pci_softc *sc, struct pci_attach_args *pa, struct pci_attach_args *pchb_pa)
+{
+ struct agp_amd_softc *asc;
+ struct agp_amd_gatt *gatt;
+ pcireg_t reg;
+ int error;
+
+ asc = malloc(sizeof *asc, M_DEVBUF, M_NOWAIT);
+ if (asc == NULL) {
+ printf(": can't allocate softc\n");
+ /* agp_generic_detach(sc) */
+ return ENOMEM;
+ }
+ memset(asc, 0, sizeof *asc);
+
+ error = pci_mapreg_map(pchb_pa, AGP_AMD751_REGISTERS,
+ PCI_MAPREG_TYPE_MEM,0, &asc->iot, &asc->ioh, NULL, NULL, 0);
+ if (error != 0) {
+ printf(": can't map AGP registers\n");
+ agp_generic_detach(sc);
+ return error;
+ }
+
+ if (agp_map_aperture(sc) != 0) {
+ printf(": can't map aperture\n");
+ agp_generic_detach(sc);
+ free(asc, M_DEVBUF);
+ return ENXIO;
+ }
+ sc->sc_methods = &agp_amd_methods;
+ sc->sc_chipc = asc;
+ asc->initial_aperture = AGP_GET_APERTURE(sc);
+
+ for (;;) {
+ gatt = agp_amd_alloc_gatt(sc);
+ if (gatt)
+ break;
+
+ /*
+ * Probably contigmalloc failure. Try reducing the
+ * aperture so that the gatt size reduces.
+ */
+ if (AGP_SET_APERTURE(sc, AGP_GET_APERTURE(sc) / 2)) {
+ printf(": can't set aperture\n");
+ return ENOMEM;
+ }
+ }
+ asc->gatt = gatt;
+
+ /* Install the gatt. */
+ WRITE4(AGP_AMD751_ATTBASE, gatt->ag_physical);
+
+ /* Enable synchronisation between host and agp. */
+ reg = pci_conf_read(sc->sc_pc, sc->sc_pcitag, AGP_AMD751_MODECTRL);
+ reg &= ~0x00ff00ff;
+ reg |= (AGP_AMD751_MODECTRL_SYNEN) | (AGP_AMD751_MODECTRL2_GPDCE << 16);
+ pci_conf_write(sc->sc_pc, sc->sc_pcitag, AGP_AMD751_MODECTRL, reg);
+ /* Enable the TLB and flush */
+ WRITE2(AGP_AMD751_STATUS,
+ READ2(AGP_AMD751_STATUS) | AGP_AMD751_STATUS_GCE);
+ AGP_FLUSH_TLB(sc);
+
+ return 0;
+}
+
+#if 0
+static int
+agp_amd_detach(struct vga_pci_softc *sc)
+{
+ pcireg_t reg;
+ struct agp_amd_softc *asc = sc->sc_chipc;
+
+ /* Disable the TLB.. */
+ WRITE2(AGP_AMD751_STATUS,
+ READ2(AGP_AMD751_STATUS) & ~AGP_AMD751_STATUS_GCE);
+
+ /* Disable host-agp sync */
+ reg = pci_conf_read(sc->sc_pc, sc->sc_pcitag, AGP_AMD751_MODECTRL);
+ reg &= 0xffffff00;
+ pci_conf_write(sc->sc_pc, sc->sc_pcitag, AGP_AMD751_MODECTRL, reg);
+
+ /* Clear the GATT base */
+ WRITE4(AGP_AMD751_ATTBASE, 0);
+
+ /* Put the aperture back the way it started. */
+ AGP_SET_APERTURE(sc, asc->initial_aperture);
+
+ agp_amd_free_gatt(sc, asc->gatt);
+
+ /* XXXfvdl no pci_mapreg_unmap */
+
+ return 0;
+}
+#endif
+
+static u_int32_t
+agp_amd_get_aperture(struct vga_pci_softc *sc)
+{
+ int vas;
+
+ vas = (pci_conf_read(sc->sc_pc, sc->sc_pcitag, AGP_AMD751_APCTRL) & 0x06);
+ vas >>= 1;
+ /*
+ * The aperture size is equal to 32M<<vas.
+ */
+ return (32*1024*1024) << vas;
+}
+
+static int
+agp_amd_set_aperture(struct vga_pci_softc *sc, u_int32_t aperture)
+{
+ int vas;
+ pcireg_t reg;
+
+ /*
+ * Check for a power of two and make sure its within the
+ * programmable range.
+ */
+ if (aperture & (aperture - 1)
+ || aperture < 32*1024*1024
+ || aperture > 2U*1024*1024*1024)
+ return EINVAL;
+
+ vas = ffs(aperture / 32*1024*1024) - 1;
+
+ reg = pci_conf_read(sc->sc_pc, sc->sc_pcitag, AGP_AMD751_APCTRL);
+ reg = (reg & ~0x06) | (vas << 1);
+ pci_conf_write(sc->sc_pc, sc->sc_pcitag, AGP_AMD751_APCTRL, reg);
+
+ return 0;
+}
+
+static int
+agp_amd_bind_page(struct vga_pci_softc *sc, off_t offset, bus_addr_t physical)
+{
+ struct agp_amd_softc *asc = sc->sc_chipc;
+
+ if (offset < 0 || offset >= (asc->gatt->ag_entries << AGP_PAGE_SHIFT))
+ return EINVAL;
+
+ asc->gatt->ag_virtual[offset >> AGP_PAGE_SHIFT] = physical | 1;
+ return 0;
+}
+
+static int
+agp_amd_unbind_page(struct vga_pci_softc *sc, off_t offset)
+{
+ struct agp_amd_softc *asc = sc->sc_chipc;
+
+ if (offset < 0 || offset >= (asc->gatt->ag_entries << AGP_PAGE_SHIFT))
+ return EINVAL;
+
+ asc->gatt->ag_virtual[offset >> AGP_PAGE_SHIFT] = 0;
+ return 0;
+}
+
+static void
+agp_amd_flush_tlb(struct vga_pci_softc *sc)
+{
+ struct agp_amd_softc *asc = sc->sc_chipc;
+
+ /* Set the cache invalidate bit and wait for the chipset to clear */
+ WRITE4(AGP_AMD751_TLBCTRL, 1);
+ do {
+ DELAY(1);
+ } while (READ4(AGP_AMD751_TLBCTRL));
+}
+
+
diff --git a/sys/dev/pci/agp_i810.c b/sys/dev/pci/agp_i810.c
new file mode 100644
index 00000000000..db623c5f6fb
--- /dev/null
+++ b/sys/dev/pci/agp_i810.c
@@ -0,0 +1,375 @@
+/* $OpenBSD: agp_i810.c,v 1.1 2002/07/12 20:17:03 mickey Exp $ */
+/* $NetBSD: agp_i810.c,v 1.8 2001/09/20 20:00:16 fvdl Exp $ */
+
+/*-
+ * Copyright (c) 2000 Doug Rabson
+ * Copyright (c) 2000 Ruslan Ermilov
+ * 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_i810.c,v 1.4 2001/07/05 21:28:47 jhb Exp $
+ */
+
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/proc.h>
+#include <sys/device.h>
+#include <sys/conf.h>
+#include <sys/agpio.h>
+
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+#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 WRITE4(off,v) bus_space_write_4(isc->bst, isc->bsh, off, v)
+
+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 */
+};
+
+u_int32_t agp_i810_get_aperture(struct vga_pci_softc *);
+int agp_i810_set_aperture(struct vga_pci_softc *, u_int32_t);
+int agp_i810_bind_page(struct vga_pci_softc *, off_t, bus_addr_t);
+int agp_i810_unbind_page(struct vga_pci_softc *, off_t);
+void agp_i810_flush_tlb(struct vga_pci_softc *);
+int agp_i810_enable(struct vga_pci_softc *, u_int32_t mode);
+struct agp_memory *agp_i810_alloc_memory(struct vga_pci_softc *, int, vsize_t);
+int agp_i810_free_memory(struct vga_pci_softc *, struct agp_memory *);
+int agp_i810_bind_memory(struct vga_pci_softc *, struct agp_memory *, off_t);
+int agp_i810_unbind_memory(struct vga_pci_softc *, struct agp_memory *);
+
+struct agp_methods agp_i810_methods = {
+ agp_i810_get_aperture,
+ agp_i810_set_aperture,
+ agp_i810_bind_page,
+ agp_i810_unbind_page,
+ agp_i810_flush_tlb,
+ agp_i810_enable,
+ agp_i810_alloc_memory,
+ agp_i810_free_memory,
+ agp_i810_bind_memory,
+ agp_i810_unbind_memory,
+};
+
+
+int
+agp_i810_attach(struct vga_pci_softc* sc, struct pci_attach_args *pa, struct pci_attach_args *pchb_pa)
+{
+ struct agp_i810_softc *isc;
+ struct agp_gatt *gatt;
+ int error;
+
+ isc = malloc(sizeof *isc, M_DEVBUF, M_NOWAIT);
+ if (isc == NULL) {
+ printf(": can't allocate chipset-specific softc\n");
+ return ENOMEM;
+ }
+ memset(isc, 0, sizeof *isc);
+ sc->sc_chipc = isc;
+ sc->sc_methods = &agp_i810_methods;
+ sc->sc_dmat = pa->pa_dmat; /* XXX fvdl */
+
+ if ((error = agp_map_aperture(sc))) {
+ printf(": can't map aperture\n");
+ free(isc, M_DEVBUF);
+ return error;
+ }
+
+ error = pci_mapreg_map(pa, AGP_I810_MMADR,
+ PCI_MAPREG_TYPE_MEM, 0, &isc->bst, &isc->bsh, NULL, NULL, 0);
+ if (error != 0) {
+ printf(": can't map mmadr registers\n");
+ return error;
+ }
+
+ isc->initial_aperture = AGP_GET_APERTURE(sc);
+
+ if (READ1(AGP_I810_DRT) & AGP_I810_DRT_POPULATED)
+ isc->dcache_size = 4 * 1024 * 1024;
+ else
+ isc->dcache_size = 0;
+
+ for (;;) {
+ gatt = agp_alloc_gatt(sc);
+ if (gatt)
+ break;
+
+ /*
+ * Probably contigmalloc failure. Try reducing the
+ * aperture so that the gatt size reduces.
+ */
+ if (AGP_SET_APERTURE(sc, AGP_GET_APERTURE(sc) / 2)) {
+ agp_generic_detach(sc);
+ return ENOMEM;
+ }
+ }
+ isc->gatt = gatt;
+
+ /* Install the GATT. */
+ WRITE4(AGP_I810_PGTBL_CTL, gatt->ag_physical | 1);
+
+ /*
+ * Make sure the chipset can see everything.
+ */
+ agp_flush_cache();
+
+ return 0;
+}
+
+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;
+}
+
+int
+agp_i810_set_aperture(struct vga_pci_softc *sc, u_int32_t aperture)
+{
+ pcireg_t reg, miscc;
+
+ /*
+ * Double check for sanity.
+ */
+ if (aperture != 32 * 1024 * 1024 && aperture != 64 * 1024 * 1024) {
+ printf("AGP: bad aperture size %d\n", aperture);
+ return EINVAL;
+ }
+
+ 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;
+
+ reg &= 0x0000ffff;
+ reg |= (miscc << 16);
+ pci_conf_write(sc->sc_pc, sc->sc_pcitag, AGP_I810_SMRAM, miscc);
+
+ return 0;
+}
+
+int
+agp_i810_bind_page(struct vga_pci_softc *sc, off_t offset, bus_addr_t pa)
+{
+ struct agp_i810_softc *isc = sc->sc_chipc;
+
+ if (offset < 0 || offset >= (isc->gatt->ag_entries << AGP_PAGE_SHIFT))
+ return EINVAL;
+
+ WRITE4(AGP_I810_GTT + (u_int32_t)(offset >> AGP_PAGE_SHIFT) * 4,
+ pa | 1);
+
+ return 0;
+}
+
+int
+agp_i810_unbind_page(struct vga_pci_softc *sc, off_t offset)
+{
+ struct agp_i810_softc *isc = sc->sc_chipc;
+
+ if (offset < 0 || offset >= (isc->gatt->ag_entries << AGP_PAGE_SHIFT))
+ return EINVAL;
+
+ WRITE4(AGP_I810_GTT + (u_int32_t)(offset >> AGP_PAGE_SHIFT) * 4, 0);
+ return 0;
+}
+
+/*
+ * Writing via memory mapped registers already flushes all TLBs.
+ */
+void
+agp_i810_flush_tlb(struct vga_pci_softc *sc)
+{
+}
+
+int
+agp_i810_enable(struct vga_pci_softc *sc, u_int32_t mode)
+{
+
+ return 0;
+}
+
+struct agp_memory *
+agp_i810_alloc_memory(struct vga_pci_softc *sc, int type, vsize_t size)
+{
+ struct agp_i810_softc *isc = sc->sc_chipc;
+ struct agp_memory *mem;
+ int error;
+
+ if (type == 1) {
+ /*
+ * Mapping local DRAM into GATT.
+ */
+ if (size != isc->dcache_size)
+{ printf("agp: size(%d) != isc->dcache_size(%d)\n", size, isc->dcache_size);
+ return NULL;
+}
+ } else if (type == 2) {
+ /*
+ * Bogus mapping of a single page for the hardware cursor.
+ */
+ if (size != AGP_PAGE_SIZE)
+{ printf("agp: size(%d) != AGP_PAGE_SIZE(%d)\n", size, AGP_PAGE_SIZE);
+ return NULL;
+}
+ }
+
+ if ((mem = malloc(sizeof *mem, M_DEVBUF, M_WAITOK)) == NULL)
+ return NULL;
+ bzero(mem, sizeof *mem);
+ mem->am_id = sc->sc_nextid++;
+ mem->am_size = size;
+ mem->am_type = type;
+
+ if (type == 2) {
+ mem->am_dmaseg = malloc(sizeof *mem->am_dmaseg, M_DEVBUF, M_WAITOK);
+ if (mem->am_dmaseg == NULL) {
+ free(mem, M_DEVBUF);
+printf("agp: no memory for the segments\n");
+ return NULL;
+ }
+ 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) {
+ free(mem, M_DEVBUF);
+ free(mem->am_dmaseg, M_DEVBUF);
+printf("agp: agp_alloc_dmamem(%d)\n", error);
+ return NULL;
+ }
+ } else if (type != 1) {
+ if ((error = bus_dmamap_create(sc->sc_dmat, size, size / PAGE_SIZE + 1,
+ size, 0, BUS_DMA_NOWAIT, &mem->am_dmamap)) != 0) {
+ free(mem, M_DEVBUF);
+printf("agp: bus_dmamap_create(%d)\n", error);
+ return NULL;
+ }
+ }
+
+ TAILQ_INSERT_TAIL(&sc->sc_memory, mem, am_link);
+ sc->sc_allocated += size;
+
+ return mem;
+}
+
+int
+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);
+ free(mem->am_dmaseg, M_DEVBUF);
+ }
+
+ sc->sc_allocated -= mem->am_size;
+ TAILQ_REMOVE(&sc->sc_memory, mem, am_link);
+ free(mem, M_DEVBUF);
+ return 0;
+}
+
+int
+agp_i810_bind_memory(struct vga_pci_softc *sc, struct agp_memory *mem,
+ off_t offset)
+{
+ struct agp_i810_softc *isc = sc->sc_chipc;
+ u_int32_t regval, i;
+
+ /*
+ * XXX evil hack: the PGTBL_CTL appearently gets overwritten by the
+ * X server for mysterious reasons which leads to crashes if we write
+ * to the GTT through the MMIO window.
+ * Until the issue is solved, simply restore it.
+ */
+ regval = bus_space_read_4(isc->bst, isc->bsh, AGP_I810_PGTBL_CTL);
+ if (regval != (isc->gatt->ag_physical | 1)) {
+ printf("agp_i810_bind_memory: PGTBL_CTL is 0x%x - fixing\n",
+ regval);
+ bus_space_write_4(isc->bst, isc->bsh, AGP_I810_PGTBL_CTL,
+ isc->gatt->ag_physical | 1);
+ }
+
+ if (mem->am_type == 2) {
+ WRITE4(AGP_I810_GTT + (u_int32_t)(offset >> AGP_PAGE_SHIFT) * 4,
+ mem->am_physical | 1);
+ mem->am_offset = offset;
+ mem->am_is_bound = 1;
+ return 0;
+ }
+
+ if (mem->am_type != 1)
+ return agp_generic_bind_memory(sc, mem, offset);
+
+ 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);
+
+ return 0;
+}
+
+int
+agp_i810_unbind_memory(struct vga_pci_softc *sc, struct agp_memory *mem)
+{
+ struct agp_i810_softc *isc = sc->sc_chipc;
+ u_int32_t i;
+
+ if (mem->am_type == 2) {
+ WRITE4(AGP_I810_GTT +
+ (u_int32_t)(mem->am_offset >> AGP_PAGE_SHIFT) * 4, 0);
+ mem->am_offset = 0;
+ mem->am_is_bound = 0;
+ return 0;
+ }
+
+ if (mem->am_type != 1)
+ return agp_generic_unbind_memory(sc, mem);
+
+ for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE)
+ WRITE4(AGP_I810_GTT + (i >> AGP_PAGE_SHIFT) * 4, 0);
+
+ return 0;
+}
diff --git a/sys/dev/pci/agp_intel.c b/sys/dev/pci/agp_intel.c
new file mode 100644
index 00000000000..653adaf4c9e
--- /dev/null
+++ b/sys/dev/pci/agp_intel.c
@@ -0,0 +1,236 @@
+/* $OpentBSD: agp_intel.c,v 1.1 2001/10/25 21:44:00 thorpej Exp $ */
+/* $NetBSD: agp_intel.c,v 1.3 2001/09/15 00:25:00 thorpej Exp $ */
+
+/*-
+ * Copyright (c) 2000 Doug Rabson
+ * 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_intel.c,v 1.4 2001/07/05 21:28:47 jhb Exp $
+ */
+
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/proc.h>
+#include <sys/agpio.h>
+#include <sys/device.h>
+#include <sys/agpio.h>
+
+
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+#include <dev/pci/vga_pcivar.h>
+#include <dev/pci/agpvar.h>
+#include <dev/pci/agpreg.h>
+
+#include <machine/bus.h>
+
+struct agp_intel_softc {
+ u_int32_t initial_aperture; /* aperture size at startup */
+ struct agp_gatt *gatt;
+};
+
+
+static u_int32_t agp_intel_get_aperture(struct vga_pci_softc *);
+static int agp_intel_set_aperture(struct vga_pci_softc *, u_int32_t);
+static int agp_intel_bind_page(struct vga_pci_softc *, off_t, bus_addr_t);
+static int agp_intel_unbind_page(struct vga_pci_softc *, off_t);
+static void agp_intel_flush_tlb(struct vga_pci_softc *);
+
+struct agp_methods agp_intel_methods = {
+ agp_intel_get_aperture,
+ agp_intel_set_aperture,
+ agp_intel_bind_page,
+ agp_intel_unbind_page,
+ agp_intel_flush_tlb,
+ agp_generic_enable,
+ agp_generic_alloc_memory,
+ agp_generic_free_memory,
+ agp_generic_bind_memory,
+ agp_generic_unbind_memory,
+};
+
+int
+agp_intel_attach(struct vga_pci_softc *sc, struct pci_attach_args *pa, struct pci_attach_args *pchb_pa)
+{
+ struct agp_intel_softc *isc;
+ struct agp_gatt *gatt;
+ pcireg_t reg;
+
+ isc = malloc(sizeof *isc, M_DEVBUF, M_NOWAIT);
+ if (isc == NULL) {
+ printf(": can't allocate chipset-specific softc\n");
+ return ENOMEM;
+ }
+ memset(isc, 0, sizeof *isc);
+
+ sc->sc_methods = &agp_intel_methods;
+ sc->sc_chipc = isc;
+
+ if (agp_map_aperture(sc) != 0) {
+ printf(": can't map aperture\n");
+ free(isc, M_DEVBUF);
+ sc->sc_chipc = NULL;
+ return ENXIO;
+ }
+
+ isc->initial_aperture = AGP_GET_APERTURE(sc);
+
+ for (;;) {
+ gatt = agp_alloc_gatt(sc);
+ if (gatt)
+ break;
+
+ /*
+ * Probably contigmalloc failure. Try reducing the
+ * aperture so that the gatt size reduces.
+ */
+ if (AGP_SET_APERTURE(sc, AGP_GET_APERTURE(sc) / 2)) {
+ agp_generic_detach(sc);
+ printf(": failed to set aperture\n");
+ return ENOMEM;
+ }
+ }
+ isc->gatt = gatt;
+
+ /* Install the gatt. */
+ pci_conf_write(sc->sc_pc, sc->sc_pcitag, AGP_INTEL_ATTBASE,
+ gatt->ag_physical);
+
+ /* Enable things, clear errors etc. */
+ /* XXXfvdl get rid of the magic constants */
+ pci_conf_write(sc->sc_pc, sc->sc_pcitag, AGP_INTEL_AGPCTRL, 0x2280);
+ reg = pci_conf_read(sc->sc_pc, sc->sc_pcitag, AGP_INTEL_NBXCFG);
+ reg &= ~(1 << 10);
+ reg |= (1 << 9);
+ pci_conf_write(sc->sc_pc, sc->sc_pcitag, AGP_INTEL_NBXCFG, reg);
+
+ reg = pci_conf_read(sc->sc_pc, sc->sc_pcitag, AGP_INTEL_STS);
+ reg &= ~0x00ff0000;
+ reg |= (7 << 16);
+ pci_conf_write(sc->sc_pc, sc->sc_pcitag, AGP_INTEL_STS, reg);
+
+ return 0;
+}
+
+#if 0
+static int
+agp_intel_detach(struct vga_pci_softc *sc)
+{
+ int error;
+ pcireg_t reg;
+ struct agp_intel_softc *isc = sc->sc_chipc;
+
+ error = agp_generic_detach(sc);
+ if (error)
+ return error;
+
+ reg = pci_conf_read(sc->sc_pc, sc->sc_pcitag, AGP_INTEL_NBXCFG);
+ reg &= ~(1 << 9);
+ printf("%s: set NBXCFG to %x\n", __FUNCTION__, reg);
+ pci_conf_write(sc->sc_pc, sc->sc_pcitag, AGP_INTEL_NBXCFG, reg);
+ pci_conf_write(sc->sc_pc, sc->sc_pcitag, AGP_INTEL_ATTBASE, 0);
+ AGP_SET_APERTURE(sc, isc->initial_aperture);
+ agp_free_gatt(sc, isc->gatt);
+
+ return 0;
+}
+#endif
+
+static u_int32_t
+agp_intel_get_aperture(struct vga_pci_softc *sc)
+{
+ u_int32_t apsize;
+
+ apsize = pci_conf_read(sc->sc_pc, sc->sc_pcitag, AGP_INTEL_APSIZE) & 0x1f;
+
+ /*
+ * The size is determined by the number of low bits of
+ * register APBASE which are forced to zero. The low 22 bits
+ * are always forced to zero and each zero bit in the apsize
+ * field just read forces the corresponding bit in the 27:22
+ * to be zero. We calculate the aperture size accordingly.
+ */
+ return (((apsize ^ 0x1f) << 22) | ((1 << 22) - 1)) + 1;
+}
+
+static int
+agp_intel_set_aperture(struct vga_pci_softc *sc, u_int32_t aperture)
+{
+ u_int32_t apsize;
+ pcireg_t reg;
+
+ /*
+ * Reverse the magic from get_aperture.
+ */
+ apsize = ((aperture - 1) >> 22) ^ 0x1f;
+
+ /*
+ * Double check for sanity.
+ */
+ if ((((apsize ^ 0x1f) << 22) | ((1 << 22) - 1)) + 1 != aperture)
+ return EINVAL;
+
+ reg = pci_conf_read(sc->sc_pc, sc->sc_pcitag, AGP_INTEL_APSIZE);
+ reg = (reg & 0xffffff00) | apsize;
+ pci_conf_write(sc->sc_pc, sc->sc_pcitag, AGP_INTEL_APSIZE, reg);
+
+ return 0;
+}
+
+static int
+agp_intel_bind_page(struct vga_pci_softc *sc, off_t offset, bus_addr_t physical)
+{
+ struct agp_intel_softc *isc = sc->sc_chipc;
+
+ if (offset < 0 || offset >= (isc->gatt->ag_entries << AGP_PAGE_SHIFT))
+ return EINVAL;
+
+ isc->gatt->ag_virtual[offset >> AGP_PAGE_SHIFT] = physical | 0x17;
+ return 0;
+}
+
+static int
+agp_intel_unbind_page(struct vga_pci_softc *sc, off_t offset)
+{
+ struct agp_intel_softc *isc = sc->sc_chipc;
+
+ if (offset < 0 || offset >= (isc->gatt->ag_entries << AGP_PAGE_SHIFT))
+ return EINVAL;
+
+ isc->gatt->ag_virtual[offset >> AGP_PAGE_SHIFT] = 0;
+ return 0;
+}
+
+static void
+agp_intel_flush_tlb(struct vga_pci_softc *sc)
+{
+ pci_conf_write(sc->sc_pc, sc->sc_pcitag, AGP_INTEL_AGPCTRL, 0x2200);
+ pci_conf_write(sc->sc_pc, sc->sc_pcitag, AGP_INTEL_AGPCTRL, 0x2280);
+}
+
+
diff --git a/sys/dev/pci/agp_sis.c b/sys/dev/pci/agp_sis.c
new file mode 100644
index 00000000000..bf510cffd9f
--- /dev/null
+++ b/sys/dev/pci/agp_sis.c
@@ -0,0 +1,224 @@
+/* $OpenBSD: agp_sis.c,v 1.1 2002/07/12 20:17:03 mickey Exp $ */
+/* $NetBSD: agp_sis.c,v 1.2 2001/09/15 00:25:00 thorpej Exp $ */
+
+/*-
+ * Copyright (c) 2000 Doug Rabson
+ * 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_sis.c,v 1.3 2001/07/05 21:28:47 jhb Exp $
+ */
+
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/proc.h>
+#include <sys/conf.h>
+#include <sys/device.h>
+#include <sys/agpio.h>
+
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+#include <dev/pci/vga_pcivar.h>
+#include <dev/pci/agpvar.h>
+#include <dev/pci/agpreg.h>
+
+#include <machine/bus.h>
+
+struct agp_sis_softc {
+ u_int32_t initial_aperture; /* aperture size at startup */
+ struct agp_gatt *gatt;
+};
+
+static u_int32_t agp_sis_get_aperture(struct vga_pci_softc *);
+static int agp_sis_set_aperture(struct vga_pci_softc *, u_int32_t);
+static int agp_sis_bind_page(struct vga_pci_softc *, off_t, bus_addr_t);
+static int agp_sis_unbind_page(struct vga_pci_softc *, off_t);
+static void agp_sis_flush_tlb(struct vga_pci_softc *);
+
+struct agp_methods agp_sis_methods = {
+ agp_sis_get_aperture,
+ agp_sis_set_aperture,
+ agp_sis_bind_page,
+ agp_sis_unbind_page,
+ agp_sis_flush_tlb,
+ agp_generic_enable,
+ agp_generic_alloc_memory,
+ agp_generic_free_memory,
+ agp_generic_bind_memory,
+ agp_generic_unbind_memory,
+};
+
+
+int
+agp_sis_attach(struct vga_pci_softc *sc, struct pci_attach_args *pa, struct pci_attach_args *pchb_pa)
+{
+ struct agp_sis_softc *ssc;
+ struct agp_gatt *gatt;
+ pcireg_t reg;
+
+ ssc = malloc(sizeof *ssc, M_DEVBUF, M_NOWAIT);
+ if (ssc == NULL) {
+ printf(": can't allocate chipset-specific softc\n");
+ return ENOMEM;
+ }
+ sc->sc_methods = &agp_sis_methods;
+ sc->sc_chipc = ssc;
+
+ if (agp_map_aperture(sc) != 0) {
+ printf(": can't map aperture\n");
+ free(ssc, M_DEVBUF);
+ return ENXIO;
+ }
+
+ ssc->initial_aperture = AGP_GET_APERTURE(sc);
+
+ for (;;) {
+ gatt = agp_alloc_gatt(sc);
+ if (gatt)
+ break;
+
+ /*
+ * Probably contigmalloc failure. Try reducing the
+ * aperture so that the gatt size reduces.
+ */
+ if (AGP_SET_APERTURE(sc, AGP_GET_APERTURE(sc) / 2)) {
+ agp_generic_detach(sc);
+ printf(": failed to set aperture\n");
+ return ENOMEM;
+ }
+ }
+ ssc->gatt = gatt;
+
+ /* Install the gatt. */
+ pci_conf_write(sc->sc_pc, sc->sc_pcitag, AGP_SIS_ATTBASE,
+ gatt->ag_physical);
+
+ /* Enable the aperture and auto-tlb-inval */
+ reg = pci_conf_read(sc->sc_pc, sc->sc_pcitag, AGP_SIS_WINCTRL);
+ reg |= (0x05 << 24) | 3;
+ pci_conf_write(sc->sc_pc, sc->sc_pcitag, AGP_SIS_WINCTRL, reg);
+
+ return 0;
+}
+
+#if 0
+static int
+agp_sis_detach(struct vga_pci_softc *sc)
+{
+ struct agp_sis_softc *ssc = sc->sc_chipc;
+ pcireg_t reg;
+ int error;
+
+ error = agp_generic_detach(sc);
+ if (error)
+ return error;
+
+ reg = pci_conf_read(sc->sc_pc, sc->sc_pcitag, AGP_SIS_WINCTRL);
+ reg &= ~3;
+ reg &= 0x00ffffff;
+ pci_conf_write(sc->sc_pc, sc->sc_pcitag, AGP_SIS_WINCTRL, reg);
+
+ /* Put the aperture back the way it started. */
+ AGP_SET_APERTURE(sc, ssc->initial_aperture);
+
+ agp_free_gatt(sc, ssc->gatt);
+ return 0;
+}
+#endif
+
+static u_int32_t
+agp_sis_get_aperture(struct vga_pci_softc *sc)
+{
+ int gws;
+
+ /*
+ * The aperture size is equal to 4M<<gws.
+ */
+ gws = (pci_conf_read(sc->sc_pc, sc->sc_pcitag, AGP_SIS_WINCTRL)&0x70) >> 4;
+ return (4*1024*1024) << gws;
+}
+
+static int
+agp_sis_set_aperture(struct vga_pci_softc *sc, u_int32_t aperture)
+{
+ int gws;
+ pcireg_t reg;
+
+ /*
+ * Check for a power of two and make sure its within the
+ * programmable range.
+ */
+ if (aperture & (aperture - 1)
+ || aperture < 4*1024*1024
+ || aperture > 256*1024*1024)
+ return EINVAL;
+
+ gws = ffs(aperture / 4*1024*1024) - 1;
+
+ reg = pci_conf_read(sc->sc_pc, sc->sc_pcitag, AGP_SIS_WINCTRL);
+ reg &= ~0x00000070;
+ reg |= gws << 4;
+ pci_conf_write(sc->sc_pc, sc->sc_pcitag, AGP_SIS_WINCTRL, reg);
+
+ return 0;
+}
+
+static int
+agp_sis_bind_page(struct vga_pci_softc *sc, off_t offset, bus_addr_t physical)
+{
+ struct agp_sis_softc *ssc = sc->sc_chipc;
+
+ if (offset < 0 || offset >= (ssc->gatt->ag_entries << AGP_PAGE_SHIFT))
+ return EINVAL;
+
+ ssc->gatt->ag_virtual[offset >> AGP_PAGE_SHIFT] = physical;
+ return 0;
+}
+
+static int
+agp_sis_unbind_page(struct vga_pci_softc *sc, off_t offset)
+{
+ struct agp_sis_softc *ssc = sc->sc_chipc;
+
+ if (offset < 0 || offset >= (ssc->gatt->ag_entries << AGP_PAGE_SHIFT))
+ return EINVAL;
+
+ ssc->gatt->ag_virtual[offset >> AGP_PAGE_SHIFT] = 0;
+ return 0;
+}
+
+static void
+agp_sis_flush_tlb(struct vga_pci_softc *sc)
+{
+ pcireg_t reg;
+
+ reg = pci_conf_read(sc->sc_pc, sc->sc_pcitag, AGP_SIS_TLBFLUSH);
+ reg &= 0xffffff00;
+ reg |= 0x02;
+ pci_conf_write(sc->sc_pc, sc->sc_pcitag, AGP_SIS_TLBFLUSH, reg);
+}
+
diff --git a/sys/dev/pci/agp_via.c b/sys/dev/pci/agp_via.c
new file mode 100644
index 00000000000..dd5e7dc4cf1
--- /dev/null
+++ b/sys/dev/pci/agp_via.c
@@ -0,0 +1,219 @@
+/* $OpenBSD: agp_via.c,v 1.1 2002/07/12 20:17:03 mickey Exp $ */
+/* $NetBSD: agp_via.c,v 1.2 2001/09/15 00:25:00 thorpej Exp $ */
+
+/*-
+ * Copyright (c) 2000 Doug Rabson
+ * 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_via.c,v 1.3 2001/07/05 21:28:47 jhb Exp $
+ */
+
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/proc.h>
+#include <sys/conf.h>
+#include <sys/device.h>
+#include <sys/agpio.h>
+
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+#include <dev/pci/vga_pcivar.h>
+#include <dev/pci/agpvar.h>
+#include <dev/pci/agpreg.h>
+
+#include <machine/bus.h>
+
+static u_int32_t agp_via_get_aperture(struct vga_pci_softc *);
+static int agp_via_set_aperture(struct vga_pci_softc *, u_int32_t);
+static int agp_via_bind_page(struct vga_pci_softc *, off_t, bus_addr_t);
+static int agp_via_unbind_page(struct vga_pci_softc *, off_t);
+static void agp_via_flush_tlb(struct vga_pci_softc *);
+
+struct agp_methods agp_via_methods = {
+ agp_via_get_aperture,
+ agp_via_set_aperture,
+ agp_via_bind_page,
+ agp_via_unbind_page,
+ agp_via_flush_tlb,
+ agp_generic_enable,
+ agp_generic_alloc_memory,
+ agp_generic_free_memory,
+ agp_generic_bind_memory,
+ agp_generic_unbind_memory,
+};
+
+struct agp_via_softc {
+ u_int32_t initial_aperture; /* aperture size at startup */
+ struct agp_gatt *gatt;
+};
+
+
+int
+agp_via_attach(struct vga_pci_softc *sc, struct pci_attach_args *pa, struct pci_attach_args *pchb_pa)
+{
+ struct agp_via_softc *asc;
+ struct agp_gatt *gatt;
+
+ asc = malloc(sizeof *asc, M_DEVBUF, M_NOWAIT);
+ if (asc == NULL) {
+ printf(": can't allocate chipset-specific softc\n");
+ return ENOMEM;
+ }
+ memset(asc, 0, sizeof *asc);
+ sc->sc_chipc = asc;
+ sc->sc_methods = &agp_via_methods;
+
+ if (agp_map_aperture(sc) != 0) {
+ printf(": can't map aperture\n");
+ free(asc, M_DEVBUF);
+ return ENXIO;
+ }
+
+ asc->initial_aperture = AGP_GET_APERTURE(sc);
+
+ for (;;) {
+ gatt = agp_alloc_gatt(sc);
+ if (gatt)
+ break;
+
+ /*
+ * Probably contigmalloc failure. Try reducing the
+ * aperture so that the gatt size reduces.
+ */
+ if (AGP_SET_APERTURE(sc, AGP_GET_APERTURE(sc) / 2)) {
+ agp_generic_detach(sc);
+ printf(": can't set aperture size\n");
+ return ENOMEM;
+ }
+ }
+ asc->gatt = gatt;
+
+ /* Install the gatt. */
+ pci_conf_write(sc->sc_pc, sc->sc_pcitag, AGP_VIA_ATTBASE,
+ gatt->ag_physical | 3);
+
+ /* Enable the aperture. */
+ pci_conf_write(sc->sc_pc, sc->sc_pcitag, AGP_VIA_GARTCTRL, 0x0000000f);
+
+ return 0;
+}
+
+#if 0
+static int
+agp_via_detach(struct vga_pci_softc *sc)
+{
+ struct agp_via_softc *asc = sc->sc_chipc;
+ int error;
+
+ error = agp_generic_detach(sc);
+ if (error)
+ return error;
+
+ pci_conf_write(sc->sc_pc, sc->sc_pcitag, AGP_VIA_GARTCTRL, 0);
+ pci_conf_write(sc->sc_pc, sc->sc_pcitag, AGP_VIA_ATTBASE, 0);
+ AGP_SET_APERTURE(sc, asc->initial_aperture);
+ agp_free_gatt(sc, asc->gatt);
+
+ return 0;
+}
+#endif
+
+static u_int32_t
+agp_via_get_aperture(struct vga_pci_softc *sc)
+{
+ u_int32_t apsize;
+
+ apsize = pci_conf_read(sc->sc_pc, sc->sc_pcitag, AGP_VIA_APSIZE) & 0x1f;
+
+ /*
+ * The size is determined by the number of low bits of
+ * register APBASE which are forced to zero. The low 20 bits
+ * are always forced to zero and each zero bit in the apsize
+ * field just read forces the corresponding bit in the 27:20
+ * to be zero. We calculate the aperture size accordingly.
+ */
+ return (((apsize ^ 0xff) << 20) | ((1 << 20) - 1)) + 1;
+}
+
+static int
+agp_via_set_aperture(struct vga_pci_softc *sc, u_int32_t aperture)
+{
+ u_int32_t apsize;
+ pcireg_t reg;
+
+ /*
+ * Reverse the magic from get_aperture.
+ */
+ apsize = ((aperture - 1) >> 20) ^ 0xff;
+
+ /*
+ * Double check for sanity.
+ */
+ if ((((apsize ^ 0xff) << 20) | ((1 << 20) - 1)) + 1 != aperture)
+ return EINVAL;
+
+ reg = pci_conf_read(sc->sc_pc, sc->sc_pcitag, AGP_VIA_APSIZE);
+ reg &= ~0xff;
+ reg |= apsize;
+ pci_conf_write(sc->sc_pc, sc->sc_pcitag, AGP_VIA_APSIZE, reg);
+
+ return 0;
+}
+
+static int
+agp_via_bind_page(struct vga_pci_softc *sc, off_t offset, bus_addr_t physical)
+{
+ struct agp_via_softc *asc = sc->sc_chipc;
+
+ if (offset < 0 || offset >= (asc->gatt->ag_entries << AGP_PAGE_SHIFT))
+ return EINVAL;
+
+ asc->gatt->ag_virtual[offset >> AGP_PAGE_SHIFT] = physical;
+ return 0;
+}
+
+static int
+agp_via_unbind_page(struct vga_pci_softc *sc, off_t offset)
+{
+ struct agp_via_softc *asc = sc->sc_chipc;
+
+ if (offset < 0 || offset >= (asc->gatt->ag_entries << AGP_PAGE_SHIFT))
+ return EINVAL;
+
+ asc->gatt->ag_virtual[offset >> AGP_PAGE_SHIFT] = 0;
+ return 0;
+}
+
+static void
+agp_via_flush_tlb(struct vga_pci_softc *sc)
+{
+ pci_conf_write(sc->sc_pc, sc->sc_pcitag, AGP_VIA_GARTCTRL, 0x8f);
+ pci_conf_write(sc->sc_pc, sc->sc_pcitag, AGP_VIA_GARTCTRL, 0x0f);
+}
+
+
diff --git a/sys/dev/pci/agpreg.h b/sys/dev/pci/agpreg.h
new file mode 100644
index 00000000000..df3dd955be0
--- /dev/null
+++ b/sys/dev/pci/agpreg.h
@@ -0,0 +1,157 @@
+/* $OpenBSD: agpreg.h,v 1.1 2002/07/12 20:17:03 mickey Exp $ */
+/* $NetBSD: agpreg.h,v 1.1 2001/09/10 10:01:02 fvdl Exp $ */
+
+/*-
+ * Copyright (c) 2000 Doug Rabson
+ * 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/agpreg.h,v 1.3 2000/07/12 10:13:04 dfr Exp $
+ */
+
+#ifndef _PCI_AGPREG_H_
+#define _PCI_AGPREG_H_
+
+/*
+ * Offsets for various AGP configuration registers.
+ */
+#define AGP_APBASE 0x10
+
+/*
+ * Offsets from the AGP Capability pointer.
+ */
+#define AGP_CAPID 0x02
+#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
+#define AGP_COMMAND 0x8
+
+/*
+ * Config offsets for Intel AGP chipsets.
+ */
+#define AGP_INTEL_NBXCFG 0x50
+#define AGP_INTEL_STS 0x90
+#define AGP_INTEL_AGPCTRL 0xb0
+#define AGP_INTEL_APSIZE 0xb4
+#define AGP_INTEL_ATTBASE 0xb8
+
+/*
+ * Config offsets for VIA AGP chipsets.
+ */
+#define AGP_VIA_GARTCTRL 0x80
+#define AGP_VIA_APSIZE 0x84
+#define AGP_VIA_ATTBASE 0x88
+
+/*
+ * Config offsets for SiS AGP chipsets.
+ */
+#define AGP_SIS_ATTBASE 0x90
+#define AGP_SIS_WINCTRL 0x94
+#define AGP_SIS_TLBCTRL 0x97
+#define AGP_SIS_TLBFLUSH 0x98
+
+/*
+ * Config offsets for Ali AGP chipsets.
+ */
+#define AGP_ALI_AGPCTRL 0xb8
+#define AGP_ALI_ATTBASE 0xbc
+#define AGP_ALI_TLBCTRL 0xc0
+
+/*
+ * Config offsets for the AMD 751 chipset.
+ */
+#define AGP_AMD751_REGISTERS 0x14
+#define AGP_AMD751_APCTRL 0xac
+#define AGP_AMD751_MODECTRL 0xb0
+#define AGP_AMD751_MODECTRL_SYNEN 0x80
+#define AGP_AMD751_MODECTRL2 0xb2
+#define AGP_AMD751_MODECTRL2_G1LM 0x01
+#define AGP_AMD751_MODECTRL2_GPDCE 0x02
+#define AGP_AMD751_MODECTRL2_NGSE 0x08
+
+/*
+ * Memory mapped register offsets for AMD 751 chipset.
+ */
+#define AGP_AMD751_CAPS 0x00
+#define AGP_AMD751_CAPS_EHI 0x0800
+#define AGP_AMD751_CAPS_P2P 0x0400
+#define AGP_AMD751_CAPS_MPC 0x0200
+#define AGP_AMD751_CAPS_VBE 0x0100
+#define AGP_AMD751_CAPS_REV 0x00ff
+#define AGP_AMD751_STATUS 0x02
+#define AGP_AMD751_STATUS_P2PS 0x0800
+#define AGP_AMD751_STATUS_GCS 0x0400
+#define AGP_AMD751_STATUS_MPS 0x0200
+#define AGP_AMD751_STATUS_VBES 0x0100
+#define AGP_AMD751_STATUS_P2PE 0x0008
+#define AGP_AMD751_STATUS_GCE 0x0004
+#define AGP_AMD751_STATUS_VBEE 0x0001
+#define AGP_AMD751_ATTBASE 0x04
+#define AGP_AMD751_TLBCTRL 0x0c
+
+/*
+ * Config registers for i810 device 0
+ */
+#define AGP_I810_SMRAM 0x70
+#define AGP_I810_SMRAM_GMS 0xc0
+#define AGP_I810_SMRAM_GMS_DISABLED 0x00
+#define AGP_I810_SMRAM_GMS_ENABLED_0 0x40
+#define AGP_I810_SMRAM_GMS_ENABLED_512 0x80
+#define AGP_I810_SMRAM_GMS_ENABLED_1024 0xc0
+#define AGP_I810_MISCC 0x72
+#define AGP_I810_MISCC_WINSIZE 0x0001
+#define AGP_I810_MISCC_WINSIZE_64 0x0000
+#define AGP_I810_MISCC_WINSIZE_32 0x0001
+#define AGP_I810_MISCC_PLCK 0x0008
+#define AGP_I810_MISCC_PLCK_UNLOCKED 0x0000
+#define AGP_I810_MISCC_PLCK_LOCKED 0x0008
+#define AGP_I810_MISCC_WPTC 0x0030
+#define AGP_I810_MISCC_WPTC_NOLIMIT 0x0000
+#define AGP_I810_MISCC_WPTC_62 0x0010
+#define AGP_I810_MISCC_WPTC_50 0x0020
+#define AGP_I810_MISCC_WPTC_37 0x0030
+#define AGP_I810_MISCC_RPTC 0x00c0
+#define AGP_I810_MISCC_RPTC_NOLIMIT 0x0000
+#define AGP_I810_MISCC_RPTC_62 0x0040
+#define AGP_I810_MISCC_RPTC_50 0x0080
+#define AGP_I810_MISCC_RPTC_37 0x00c0
+
+/*
+ * Config registers for i810 device 1
+ */
+#define AGP_I810_GMADR 0x10
+#define AGP_I810_MMADR 0x14
+
+/*
+ * Memory mapped register offsets for i810 chipset.
+ */
+#define AGP_I810_PGTBL_CTL 0x2020
+#define AGP_I810_DRT 0x3000
+#define AGP_I810_DRT_UNPOPULATED 0x00
+#define AGP_I810_DRT_POPULATED 0x01
+#define AGP_I810_GTT 0x10000
+
+#endif /* !_PCI_AGPREG_H_ */
diff --git a/sys/dev/pci/agpvar.h b/sys/dev/pci/agpvar.h
new file mode 100644
index 00000000000..4bad2ff97da
--- /dev/null
+++ b/sys/dev/pci/agpvar.h
@@ -0,0 +1,138 @@
+/* $OpenBSD: agpvar.h,v 1.1 2002/07/12 20:17:03 mickey Exp $ */
+/* $NetBSD: agpvar.h,v 1.4 2001/10/01 21:54:48 fvdl Exp $ */
+
+/*-
+ * Copyright (c) 2000 Doug Rabson
+ * 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/agppriv.h,v 1.3 2000/07/12 10:13:04 dfr Exp $
+ */
+
+#ifndef _PCI_AGPVAR_H_
+#define _PCI_AGPVAR_H_
+
+#include <sys/lock.h>
+#include <dev/pci/vga_pcivar.h>
+
+/*
+ * This structure is used to query the state of the AGP system.
+ */
+struct agp_info {
+ u_int32_t ai_mode;
+ bus_addr_t ai_aperture_base;
+ bus_size_t ai_aperture_size;
+ vsize_t ai_memory_allowed;
+ vsize_t ai_memory_used;
+ u_int32_t ai_devid;
+};
+
+struct agp_memory_info {
+ vsize_t ami_size; /* size in bytes */
+ bus_addr_t ami_physical; /* bogus hack for i810 */
+ off_t ami_offset; /* page offset if bound */
+ int ami_is_bound; /* non-zero if bound */
+};
+
+#define AGP_DEBUG
+#ifdef AGP_DEBUG
+#define AGP_DPF(x...) do { \
+ printf("agp: "); \
+ printf(##x); \
+} while (0)
+#else
+#define AGP_DPF(x...) do {} while (0)
+#endif
+
+#define AGPUNIT(x) minor(x)
+
+struct agp_methods {
+ u_int32_t (*get_aperture)(struct vga_pci_softc *);
+ int (*set_aperture)(struct vga_pci_softc *, u_int32_t);
+ int (*bind_page)(struct vga_pci_softc *, off_t, bus_addr_t);
+ int (*unbind_page)(struct vga_pci_softc *, off_t);
+ void (*flush_tlb)(struct vga_pci_softc *);
+ int (*enable)(struct vga_pci_softc *, u_int32_t mode);
+ struct agp_memory *(*alloc_memory)(struct vga_pci_softc *, int, vsize_t);
+ int (*free_memory)(struct vga_pci_softc *, struct agp_memory *);
+ int (*bind_memory)(struct vga_pci_softc *, struct agp_memory *, off_t);
+ int (*unbind_memory)(struct vga_pci_softc *, struct agp_memory *);
+};
+
+#define AGP_GET_APERTURE(sc) ((sc)->sc_methods->get_aperture(sc))
+#define AGP_SET_APERTURE(sc,a) ((sc)->sc_methods->set_aperture((sc),(a)))
+#define AGP_BIND_PAGE(sc,o,p) ((sc)->sc_methods->bind_page((sc),(o),(p)))
+#define AGP_UNBIND_PAGE(sc,o) ((sc)->sc_methods->unbind_page((sc), (o)))
+#define AGP_FLUSH_TLB(sc) ((sc)->sc_methods->flush_tlb(sc))
+#define AGP_ENABLE(sc,m) ((sc)->sc_methods->enable((sc),(m)))
+#define AGP_ALLOC_MEMORY(sc,t,s) ((sc)->sc_methods->alloc_memory((sc),(t),(s)))
+#define AGP_FREE_MEMORY(sc,m) ((sc)->sc_methods->free_memory((sc),(m)))
+#define AGP_BIND_MEMORY(sc,m,o) ((sc)->sc_methods->bind_memory((sc),(m),(o)))
+#define AGP_UNBIND_MEMORY(sc,m) ((sc)->sc_methods->unbind_memory((sc),(m)))
+
+/*
+ * All chipset drivers must have this at the start of their softc.
+ */
+
+struct agp_gatt {
+ u_int32_t ag_entries;
+ u_int32_t *ag_virtual;
+ bus_addr_t ag_physical;
+ bus_dmamap_t ag_dmamap;
+ bus_dma_segment_t ag_dmaseg;
+ size_t ag_size;
+};
+
+
+/*
+ * Functions private to the AGP code.
+ */
+
+int agp_find_caps(pci_chipset_tag_t pct, pcitag_t pt);
+int agp_map_aperture(struct vga_pci_softc *sc);
+struct agp_gatt *agp_alloc_gatt(struct vga_pci_softc *sc);
+void agp_free_gatt(struct vga_pci_softc *sc, struct agp_gatt *gatt);
+void agp_flush_cache(void);
+int agp_generic_attach(struct vga_pci_softc *sc);
+int agp_generic_detach(struct vga_pci_softc *sc);
+int agp_generic_enable(struct vga_pci_softc *sc, u_int32_t mode);
+struct agp_memory *agp_generic_alloc_memory(struct vga_pci_softc *sc, int type,
+ vsize_t size);
+int agp_generic_free_memory(struct vga_pci_softc *sc, struct agp_memory *mem);
+int agp_generic_bind_memory(struct vga_pci_softc *sc, struct agp_memory *mem,
+ off_t offset);
+int agp_generic_unbind_memory(struct vga_pci_softc *sc, struct agp_memory *mem);
+
+int agp_ali_attach(struct vga_pci_softc *sc, struct pci_attach_args *pa, struct pci_attach_args *p);
+int agp_amd_attach(struct vga_pci_softc *sc, struct pci_attach_args *pa, struct pci_attach_args *p);
+int agp_i810_attach(struct vga_pci_softc *sc, struct pci_attach_args *pa, struct pci_attach_args *p);
+int agp_intel_attach(struct vga_pci_softc *sc, struct pci_attach_args *pa, struct pci_attach_args *p);
+int agp_via_attach(struct vga_pci_softc *sc, struct pci_attach_args *pa, struct pci_attach_args *p);
+int agp_sis_attach(struct vga_pci_softc *sc, struct pci_attach_args *pa, struct pci_attach_args *p);
+
+int agp_alloc_dmamem(bus_dma_tag_t, size_t, int, bus_dmamap_t *, caddr_t *,
+ bus_addr_t *, bus_dma_segment_t *, int, int *);
+void agp_free_dmamem(bus_dma_tag_t tag, size_t size, bus_dmamap_t map,
+ caddr_t vaddr, bus_dma_segment_t *seg, int nseg) ;
+
+#endif /* !_PCI_AGPVAR_H_ */
diff --git a/sys/dev/pci/files.pci b/sys/dev/pci/files.pci
index 3bb790bb290..ed700af7c2e 100644
--- a/sys/dev/pci/files.pci
+++ b/sys/dev/pci/files.pci
@@ -1,4 +1,4 @@
-# $OpenBSD: files.pci,v 1.140 2002/06/26 00:18:03 itojun Exp $
+# $OpenBSD: files.pci,v 1.141 2002/07/12 20:17:03 mickey Exp $
# $NetBSD: files.pci,v 1.20 1996/09/24 17:47:15 christos Exp $
#
# Config file and device description for machine-independent PCI code.
@@ -15,6 +15,12 @@ file dev/pci/pci_subr.c pci
# Generic VGA
attach vga at pci with vga_pci
file dev/pci/vga_pci.c vga_pci
+file dev/pci/agp_ali.c pciagp
+file dev/pci/agp_amd.c pciagp
+file dev/pci/agp_i810.c pciagp
+file dev/pci/agp_intel.c pciagp
+file dev/pci/agp_sis.c pciagp
+file dev/pci/agp_via.c pciagp
device tga: wsemuldisplaydev, rasops8, rasops32
attach tga at pci
diff --git a/sys/dev/pci/pcivar.h b/sys/dev/pci/pcivar.h
index c9419191ede..dc68945d121 100644
--- a/sys/dev/pci/pcivar.h
+++ b/sys/dev/pci/pcivar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pcivar.h,v 1.24 2002/03/14 03:16:06 millert Exp $ */
+/* $OpenBSD: pcivar.h,v 1.25 2002/07/12 20:17:03 mickey Exp $ */
/* $NetBSD: pcivar.h,v 1.23 1997/06/06 23:48:05 thorpej Exp $ */
/*
@@ -185,14 +185,11 @@ int pci_get_capability(pci_chipset_tag_t, pcitag_t, int,
/*
* Helper functions for autoconfiguration.
*/
+const char *pci_findvendor(pcireg_t);
void pci_devinfo(pcireg_t, pcireg_t, int, char *);
void set_pci_isa_bridge_callback(void (*)(void *), void *);
-const struct pci_quirkdata *pci_lookup_quirkdata(pci_vendor_id_t,
- pci_product_id_t);
-
-/*
- * Misc.
- */
-const char *pci_findvendor(pcireg_t);
+const struct pci_quirkdata *
+ pci_lookup_quirkdata(pci_vendor_id_t, pci_product_id_t);
+void pciagp_set_pchb(struct pci_attach_args *);
#endif /* _DEV_PCI_PCIVAR_H_ */
diff --git a/sys/dev/pci/vga_pci.c b/sys/dev/pci/vga_pci.c
index dc1b323da24..e087c24748c 100644
--- a/sys/dev/pci/vga_pci.c
+++ b/sys/dev/pci/vga_pci.c
@@ -1,22 +1,83 @@
-/* $OpenBSD: vga_pci.c,v 1.11 2002/03/14 01:27:00 millert Exp $ */
+/* $OpenBSD: vga_pci.c,v 1.12 2002/07/12 20:17:03 mickey Exp $ */
/* $NetBSD: vga_pci.c,v 1.3 1998/06/08 06:55:58 thorpej Exp $ */
+/*-
+ * Copyright (c) 2000 Doug Rabson
+ * 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.c,v 1.12 2001/05/19 01:28:07 alfred Exp $
+ */
+/*
+ * Copyright (c) 2001 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Frank van der Linden for Wasabi Systems, Inc.
+ *
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC
+ * 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.
+ */
/*
* Copyright (c) 1995, 1996 Carnegie-Mellon University.
* All rights reserved.
*
* Author: Chris G. Demetriou
- *
+ *
* Permission to use, copy, modify and distribute this software and
* its documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
- *
- * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
* FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
+ *
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
@@ -35,6 +96,11 @@
#include <sys/kernel.h>
#include <sys/device.h>
#include <sys/malloc.h>
+#include <sys/agpio.h>
+
+#include <uvm/uvm.h>
+
+#include <machine/bus.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
@@ -46,25 +112,32 @@
#include <dev/ic/vgavar.h>
#include <dev/pci/vga_pcivar.h>
-#include <dev/wscons/wsconsio.h>
-#include <dev/wscons/wsdisplayvar.h>
+#ifdef PCIAGP
+#include <sys/fcntl.h>
-struct vga_pci_softc {
- struct device sc_dev;
-
- pcitag_t sc_pcitag; /* PCI tag, in case we need it. */
-#if 0
- struct vga_config *sc_vc; /* VGA configuration */
+#include <dev/pci/agpvar.h>
+#include <dev/pci/agpreg.h>
#endif
-};
+
+#include <dev/wscons/wsconsio.h>
+#include <dev/wscons/wsdisplayvar.h>
int vga_pci_match(struct device *, void *, void *);
void vga_pci_attach(struct device *, struct device *, void *);
+paddr_t vga_pci_mmap(void* v, off_t off, int prot);
struct cfattach vga_pci_ca = {
sizeof(struct vga_pci_softc), vga_pci_match, vga_pci_attach,
};
+#ifdef PCIAGP
+struct agp_memory *agp_find_memory(struct vga_pci_softc *sc, int id);
+const struct agp_product *agp_lookup(struct pci_attach_args *pa);
+
+struct pci_attach_args agp_pchb_pa;
+int agp_pchb_pa_set = 0;
+#endif
+
int
vga_pci_match(parent, match, aux)
struct device *parent;
@@ -115,16 +188,92 @@ vga_pci_attach(parent, self, aux)
void *aux;
{
struct pci_attach_args *pa = aux;
+#ifdef PCIAGP
struct vga_pci_softc *sc = (struct vga_pci_softc *)self;
- char devinfo[256];
+ const struct agp_product *ap;
+ u_int memsize;
+ int i, ret;
+#endif
- sc->sc_pcitag = pa->pa_tag;
+#ifdef PCIAGP
+ ap = agp_lookup(pa);
+ if (ap) {
+ static const int agp_max[][2] = {
+ {0, 0},
+ {32, 4},
+ {64, 28},
+ {128, 96},
+ {256, 204},
+ {512, 440},
+ {1024, 942},
+ {2048, 1920},
+ {4096, 3932}
+ };
+#define agp_max_size (sizeof(agp_max)/sizeof(agp_max[0]))
- pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo);
- printf("\n");
+ /*
+ * Work out an upper bound for agp memory allocation. This
+ * uses a heurisitc table from the Linux driver.
+ */
+ memsize = ptoa(physmem) >> 20;
+
+ for (i = 0; i < agp_max_size && memsize > agp_max[i][0]; i++)
+ ;
+ if (i == agp_max_size)
+ i = agp_max_size - 1;
+ sc->sc_maxmem = agp_max[i][1] << 20;
+
+ /*
+ * The lock is used to prevent re-entry to
+ * agp_generic_bind_memory() since that function can sleep.
+ */
+ lockinit(&sc->sc_lock, PZERO|PCATCH, "agplk", 0, 0);
+
+ TAILQ_INIT(&sc->sc_memory);
+
+ sc->sc_pcitag = pa->pa_tag;
+ sc->sc_pc = pa->pa_pc;
+ sc->sc_id = pa->pa_id;
+ sc->sc_dmat = pa->pa_dmat;
+
+ pci_get_capability(sc->sc_pc, sc->sc_pcitag, PCI_CAP_AGP,
+ &sc->sc_capoff, NULL);
+
+ ret = (*ap->ap_attach)(sc, pa, &agp_pchb_pa);
+ if (ret == 0)
+ printf(": aperture at 0x%lx, size 0x%lx",
+ (u_long)sc->sc_apaddr,
+ (u_long)AGP_GET_APERTURE(sc));
+ else {
+ sc->sc_chipc = NULL;
+ printf(": AGP GART");
+ }
+ }
+#endif
+ printf("\n");
vga_common_attach(self, pa->pa_iot, pa->pa_memt,
- WSDISPLAY_TYPE_PCIVGA);
+ WSDISPLAY_TYPE_PCIVGA);
+}
+
+paddr_t
+vga_pci_mmap(void *v, off_t off, int prot)
+{
+#ifdef PCIAGP
+ struct vga_config* vs = (struct vga_config*) v;
+ struct vga_pci_softc* sc = (struct vga_pci_softc *)vs->vc_softc;
+
+ if (sc->sc_apaddr) {
+
+ if (off > AGP_GET_APERTURE(sc))
+ return (-1);
+
+#ifdef __i386__
+ return i386_btop(sc->sc_apaddr + off);
+#endif
+ }
+#endif
+ return -1;
}
int
@@ -144,5 +293,593 @@ vga_pci_ioctl(v, cmd, addr, flag, p)
int flag;
struct proc *p;
{
- return (ENOTTY);
+ int error = 0;
+#ifdef PCIAGP
+ struct vga_config *vc = v;
+ struct vga_pci_softc *sc = (struct vga_pci_softc *)vc->vc_softc;
+ struct agp_memory *mem;
+ agp_info *info;
+ agp_setup *setup;
+ agp_allocate *alloc;
+ agp_bind *bind;
+ agp_unbind *unbind;
+ vsize_t size;
+
+ switch (cmd) {
+ case AGPIOC_INFO:
+ case AGPIOC_ACQUIRE:
+ case AGPIOC_RELEASE:
+ case AGPIOC_SETUP:
+ case AGPIOC_ALLOCATE:
+ case AGPIOC_DEALLOCATE:
+ case AGPIOC_BIND:
+ case AGPIOC_UNBIND:
+ if (!sc->sc_chipc)
+ return (ENXIO);
+ }
+
+ if (cmd != AGPIOC_INFO && !(flag & FWRITE))
+ return (EPERM);
+#endif
+
+ switch (cmd) {
+#ifdef PCIAGP
+ case AGPIOC_INFO:
+ info = (agp_info *)addr;
+ bzero(info, sizeof *info);
+ info->bridge_id = sc->sc_id;
+ if (sc->sc_capoff != 0)
+ info->agp_mode = pci_conf_read(sc->sc_pc, sc->sc_pcitag,
+ AGP_STATUS + sc->sc_capoff);
+ else
+ info->agp_mode = 0; /* i810 doesn't have real AGP */
+ info->aper_base = sc->sc_apaddr;
+ info->aper_size = AGP_GET_APERTURE(sc) >> 20;
+ info->pg_total =
+ info->pg_system = sc->sc_maxmem >> AGP_PAGE_SHIFT;
+ info->pg_used = sc->sc_allocated >> AGP_PAGE_SHIFT;
+ break;
+
+ case AGPIOC_ACQUIRE:
+ if (sc->sc_state != AGP_ACQUIRE_FREE)
+ error = EBUSY;
+ else
+ sc->sc_state = AGP_ACQUIRE_USER;
+ break;
+
+ case AGPIOC_RELEASE:
+ if (sc->sc_state == AGP_ACQUIRE_FREE)
+ break;
+
+ if (sc->sc_state != AGP_ACQUIRE_USER) {
+ error = EBUSY;
+ break;
+ }
+
+ /*
+ * Clear out the aperture and free any
+ * outstanding memory blocks.
+ */
+ TAILQ_FOREACH(mem, &sc->sc_memory, am_link) {
+ if (mem->am_is_bound) {
+ printf("agp_release_helper: mem %d is bound\n",
+ mem->am_id);
+ AGP_UNBIND_MEMORY(sc, mem);
+ }
+ }
+ sc->sc_state = AGP_ACQUIRE_FREE;
+ break;
+
+ case AGPIOC_SETUP:
+ setup = (agp_setup *)addr;
+ error = AGP_ENABLE(sc, setup->agp_mode);
+ break;
+
+ case AGPIOC_ALLOCATE:
+ alloc = (agp_allocate *)addr;
+ size = alloc->pg_count << AGP_PAGE_SHIFT;
+ if (sc->sc_allocated + size > sc->sc_maxmem)
+ error = EINVAL;
+ else {
+ mem = AGP_ALLOC_MEMORY(sc, alloc->type, size);
+ if (mem) {
+ alloc->key = mem->am_id;
+ alloc->physical = mem->am_physical;
+ } else
+ error = ENOMEM;
+ }
+ break;
+
+ case AGPIOC_DEALLOCATE:
+ mem = agp_find_memory(sc, *(int *)addr);
+ if (mem)
+ AGP_FREE_MEMORY(sc, mem);
+ else
+ error = ENOENT;
+ break;
+
+ case AGPIOC_BIND:
+ bind = (agp_bind *)addr;
+ mem = agp_find_memory(sc, bind->key);
+ if (!mem)
+ error = ENOENT;
+ else
+ error = AGP_BIND_MEMORY(sc, mem,
+ bind->pg_start << AGP_PAGE_SHIFT);
+ break;
+
+ case AGPIOC_UNBIND:
+ unbind = (agp_unbind *)addr;
+ mem = agp_find_memory(sc, unbind->key);
+ if (!mem)
+ error = ENOENT;
+ else
+ error = AGP_UNBIND_MEMORY(sc, mem);
+ break;
+#endif /* PCIAGP */
+
+ default:
+ error = ENOTTY;
+ }
+
+ return (error);
}
+
+#ifdef PCIAGP
+struct agp_memory *
+agp_find_memory(struct vga_pci_softc *sc, int id)
+{
+ struct agp_memory *mem;
+
+ AGP_DPF("searching for memory block %d\n", id);
+ TAILQ_FOREACH(mem, &sc->sc_memory, am_link) {
+ AGP_DPF("considering memory block %d\n", mem->am_id);
+ if (mem->am_id == id)
+ return (mem);
+ }
+ return 0;
+}
+
+const struct agp_product *
+agp_lookup(struct pci_attach_args *pa)
+{
+ const struct agp_product *ap;
+
+ if (!agp_pchb_pa_set)
+ return (NULL);
+ agp_pchb_pa_set = 0;
+
+ /* First find the vendor. */
+ for (ap = agp_products; ap->ap_attach != NULL; ap++)
+ if (ap->ap_vendor == PCI_VENDOR(pa->pa_id))
+ break;
+
+ if (ap->ap_attach == NULL)
+ return (NULL);
+
+ /* Now find the product within the vendor's domain. */
+ for (; ap->ap_attach != NULL; ap++) {
+ /* Ran out of this vendor's section of the table. */
+ if (ap->ap_vendor != PCI_VENDOR(pa->pa_id))
+ return (NULL);
+
+ if (ap->ap_product == PCI_PRODUCT(pa->pa_id))
+ break; /* Exact match. */
+ if (ap->ap_product == (u_int32_t) -1)
+ break; /* Wildcard match. */
+ }
+
+ if (ap->ap_attach == NULL)
+ ap = NULL;
+
+ return (ap);
+}
+
+void
+pciagp_set_pchb(struct pci_attach_args *pa)
+{
+ if (!agp_pchb_pa_set) {
+ memcpy(&agp_pchb_pa, pa, sizeof *pa);
+ agp_pchb_pa_set++;
+ }
+}
+
+int
+agp_map_aperture(struct vga_pci_softc *sc)
+{
+ /*
+ * Find and the aperture. Don't map it (yet), this would
+ * eat KVA.
+ */
+ if (pci_mapreg_info(sc->sc_pc, sc->sc_pcitag, AGP_APBASE,
+ PCI_MAPREG_TYPE_MEM, &sc->sc_apaddr, &sc->sc_apsize,
+ &sc->sc_apflags) != 0)
+ return ENXIO;
+
+ return 0;
+}
+
+struct agp_gatt *
+agp_alloc_gatt(struct vga_pci_softc *sc)
+{
+ u_int32_t apsize = AGP_GET_APERTURE(sc);
+ u_int32_t entries = apsize >> AGP_PAGE_SHIFT;
+ struct agp_gatt *gatt;
+ int nseg;
+
+ gatt = malloc(sizeof(*gatt), M_DEVBUF, M_NOWAIT);
+ if (!gatt)
+ return (NULL);
+ bzero(gatt, sizeof(*gatt));
+ gatt->ag_entries = entries;
+
+ if (agp_alloc_dmamem(sc->sc_dmat, entries * sizeof(u_int32_t),
+ 0, &gatt->ag_dmamap, (caddr_t *)&gatt->ag_virtual,
+ &gatt->ag_physical, &gatt->ag_dmaseg, 1, &nseg) != 0)
+ return NULL;
+
+ gatt->ag_size = entries * sizeof(u_int32_t);
+ memset(gatt->ag_virtual, 0, gatt->ag_size);
+ agp_flush_cache();
+
+ return gatt;
+}
+
+void
+agp_free_gatt(struct vga_pci_softc *sc, struct agp_gatt *gatt)
+{
+ agp_free_dmamem(sc->sc_dmat, gatt->ag_size, gatt->ag_dmamap,
+ (caddr_t)gatt->ag_virtual, &gatt->ag_dmaseg, 1);
+ free(gatt, M_DEVBUF);
+}
+
+int
+agp_generic_detach(struct vga_pci_softc *sc)
+{
+ lockmgr(&sc->sc_lock, LK_DRAIN, NULL, curproc);
+ agp_flush_cache();
+ return 0;
+}
+
+int
+agp_generic_enable(struct vga_pci_softc *sc, u_int32_t mode)
+{
+ pcireg_t tstatus, mstatus;
+ pcireg_t command;
+ int rq, sba, fw, rate, capoff;
+
+ if (pci_get_capability(sc->sc_pc, sc->sc_pcitag, PCI_CAP_AGP,
+ &capoff, NULL) == 0) {
+ printf("agp_generic_enable: not an AGP capable device\n");
+ return -1;
+ }
+
+ tstatus = pci_conf_read(sc->sc_pc, sc->sc_pcitag,
+ sc->sc_capoff + AGP_STATUS);
+ mstatus = pci_conf_read(sc->sc_pc, sc->sc_pcitag,
+ capoff + AGP_STATUS);
+
+ /* Set RQ to the min of mode, tstatus and mstatus */
+ rq = AGP_MODE_GET_RQ(mode);
+ if (AGP_MODE_GET_RQ(tstatus) < rq)
+ rq = AGP_MODE_GET_RQ(tstatus);
+ if (AGP_MODE_GET_RQ(mstatus) < rq)
+ rq = AGP_MODE_GET_RQ(mstatus);
+
+ /* Set SBA if all three can deal with SBA */
+ sba = (AGP_MODE_GET_SBA(tstatus)
+ & AGP_MODE_GET_SBA(mstatus)
+ & AGP_MODE_GET_SBA(mode));
+
+ /* Similar for FW */
+ fw = (AGP_MODE_GET_FW(tstatus)
+ & AGP_MODE_GET_FW(mstatus)
+ & AGP_MODE_GET_FW(mode));
+
+ /* Figure out the max rate */
+ rate = (AGP_MODE_GET_RATE(tstatus)
+ & AGP_MODE_GET_RATE(mstatus)
+ & AGP_MODE_GET_RATE(mode));
+ if (rate & AGP_MODE_RATE_4x)
+ rate = AGP_MODE_RATE_4x;
+ else if (rate & AGP_MODE_RATE_2x)
+ rate = AGP_MODE_RATE_2x;
+ else
+ rate = AGP_MODE_RATE_1x;
+
+ /* Construct the new mode word and tell the hardware */
+ command = AGP_MODE_SET_RQ(0, rq);
+ 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_AGP(command, 1);
+ pci_conf_write(sc->sc_pc, sc->sc_pcitag,
+ sc->sc_capoff + AGP_COMMAND, command);
+ pci_conf_write(sc->sc_pc, sc->sc_pcitag, capoff + AGP_COMMAND, command);
+ return 0;
+}
+
+struct agp_memory *
+agp_generic_alloc_memory(struct vga_pci_softc *sc, int type, vsize_t size)
+{
+ struct agp_memory *mem;
+
+ if (type != 0) {
+ printf("agp_generic_alloc_memory: unsupported type %d\n", type);
+ return 0;
+ }
+
+ mem = malloc(sizeof *mem, M_DEVBUF, M_WAITOK);
+ if (mem == NULL)
+ return NULL;
+
+ if (bus_dmamap_create(sc->sc_dmat, size, size / PAGE_SIZE + 1,
+ size, 0, BUS_DMA_NOWAIT, &mem->am_dmamap) != 0) {
+ free(mem, M_DEVBUF);
+ return NULL;
+ }
+
+ mem->am_id = sc->sc_nextid++;
+ mem->am_size = size;
+ mem->am_type = 0;
+ mem->am_physical = 0;
+ mem->am_offset = 0;
+ mem->am_is_bound = 0;
+ TAILQ_INSERT_TAIL(&sc->sc_memory, mem, am_link);
+ sc->sc_allocated += size;
+
+ return mem;
+}
+
+int
+agp_generic_free_memory(struct vga_pci_softc *sc, struct agp_memory *mem)
+{
+ if (mem->am_is_bound)
+ return EBUSY;
+
+ sc->sc_allocated -= mem->am_size;
+ TAILQ_REMOVE(&sc->sc_memory, mem, am_link);
+ bus_dmamap_destroy(sc->sc_dmat, mem->am_dmamap);
+ free(mem, M_DEVBUF);
+ return 0;
+}
+
+int
+agp_generic_bind_memory(struct vga_pci_softc *sc, struct agp_memory *mem,
+ off_t offset)
+{
+ bus_dma_segment_t *segs, *seg;
+ bus_size_t done, j;
+ bus_addr_t pa;
+ off_t i, k;
+ int contigpages, nseg, error;
+
+ lockmgr(&sc->sc_lock, LK_EXCLUSIVE, NULL, curproc);
+
+ if (mem->am_is_bound) {
+ printf("AGP: memory already bound\n");
+ lockmgr(&sc->sc_lock, LK_RELEASE, NULL, curproc);
+ return EINVAL;
+ }
+
+ if (offset < 0
+ || (offset & (AGP_PAGE_SIZE - 1)) != 0
+ || offset + mem->am_size > AGP_GET_APERTURE(sc)) {
+ printf("AGP: binding memory at bad offset %#lx\n",
+ (unsigned long) offset);
+ lockmgr(&sc->sc_lock, LK_RELEASE, NULL, curproc);
+ return EINVAL;
+ }
+
+ /*
+ * XXXfvdl
+ * The memory here needs to be directly accessable from the
+ * AGP video card, so it should be allocated using bus_dma.
+ * However, it need not be contiguous, since individual pages
+ * are translated using the GATT.
+ *
+ * Using a large chunk of contiguous memory may get in the way
+ * of other subsystems that may need one, so we try to be friendly
+ * and ask for allocation in chunks of a minimum of 8 pages
+ * of contiguous memory on average, falling back to 4, 2 and 1
+ * if really needed. Larger chunks are preferred, since allocating
+ * a bus_dma_segment per page would be overkill.
+ */
+
+ for (contigpages = 32; contigpages > 0; contigpages >>= 1) {
+ nseg = (mem->am_size / (contigpages * PAGE_SIZE)) + 1;
+printf("nsegs=%d\n", nseg);
+ segs = malloc(nseg * sizeof *segs, M_DEVBUF, M_WAITOK);
+ if (segs == NULL)
+{ printf("malloc(%d) failed\n", nseg * sizeof *segs);
+ return ENOMEM;
+}
+ if ((error = bus_dmamem_alloc(sc->sc_dmat, mem->am_size, PAGE_SIZE, 0,
+ segs, nseg, &mem->am_nseg, BUS_DMA_WAITOK)) != 0) {
+ free(segs, M_DEVBUF);
+ AGP_DPF("bus_dmamem_alloc failed %d\n", error);
+ continue;
+ }
+ if ((error = bus_dmamem_map(sc->sc_dmat, segs, mem->am_nseg,
+ mem->am_size, &mem->am_virtual, BUS_DMA_WAITOK)) != 0) {
+ bus_dmamem_free(sc->sc_dmat, segs, mem->am_nseg);
+ free(segs, M_DEVBUF);
+ AGP_DPF("bus_dmamem_map failed %d\n", error);
+ continue;
+ }
+ if ((error = bus_dmamap_load(sc->sc_dmat, mem->am_dmamap,
+ mem->am_virtual, mem->am_size, NULL,
+ BUS_DMA_WAITOK)) != 0) {
+ bus_dmamem_unmap(sc->sc_dmat, mem->am_virtual,
+ mem->am_size);
+ bus_dmamem_free(sc->sc_dmat, segs, mem->am_nseg);
+ free(segs, M_DEVBUF);
+ AGP_DPF("bus_dmamap_load failed %d\n", error);
+ continue;
+ }
+ mem->am_dmaseg = segs;
+ break;
+ }
+
+ if (contigpages == 0) {
+ lockmgr(&sc->sc_lock, LK_RELEASE, NULL, curproc);
+ return ENOMEM;
+ }
+
+ /*
+ * Bind the individual pages and flush the chipset's
+ * TLB.
+ */
+ done = 0;
+ for (i = 0; i < mem->am_dmamap->dm_nsegs; i++) {
+ seg = &mem->am_dmamap->dm_segs[i];
+ /*
+ * Install entries in the GATT, making sure that if
+ * AGP_PAGE_SIZE < PAGE_SIZE and mem->am_size is not
+ * aligned to PAGE_SIZE, we don't modify too many GATT
+ * entries.
+ */
+ for (j = 0; j < seg->ds_len && (done + j) < mem->am_size;
+ j += AGP_PAGE_SIZE) {
+ pa = seg->ds_addr + j;
+ AGP_DPF("binding offset %#lx to pa %#lx\n",
+ (unsigned long)(offset + done + j),
+ (unsigned long)pa);
+ error = AGP_BIND_PAGE(sc, offset + done + j, pa);
+ if (error) {
+ /*
+ * Bail out. Reverse all the mappings
+ * and unwire the pages.
+ */
+ for (k = 0; k < done + j; k += AGP_PAGE_SIZE)
+ AGP_UNBIND_PAGE(sc, offset + k);
+
+ bus_dmamap_unload(sc->sc_dmat, mem->am_dmamap);
+ bus_dmamem_unmap(sc->sc_dmat, mem->am_virtual,
+ mem->am_size);
+ bus_dmamem_free(sc->sc_dmat, mem->am_dmaseg,
+ mem->am_nseg);
+ free(mem->am_dmaseg, M_DEVBUF);
+ lockmgr(&sc->sc_lock, LK_RELEASE, NULL, curproc);
+ return error;
+ }
+ }
+ done += seg->ds_len;
+ }
+
+ /*
+ * Flush the cpu cache since we are providing a new mapping
+ * for these pages.
+ */
+ agp_flush_cache();
+
+ /*
+ * Make sure the chipset gets the new mappings.
+ */
+ AGP_FLUSH_TLB(sc);
+
+ mem->am_offset = offset;
+ mem->am_is_bound = 1;
+
+ lockmgr(&sc->sc_lock, LK_RELEASE, NULL, curproc);
+
+ return 0;
+}
+
+int
+agp_generic_unbind_memory(struct vga_pci_softc *sc, struct agp_memory *mem)
+{
+ int i;
+
+ lockmgr(&sc->sc_lock, LK_EXCLUSIVE, NULL, curproc);
+
+ if (!mem->am_is_bound) {
+ printf("AGP: memory is not bound\n");
+ lockmgr(&sc->sc_lock, LK_RELEASE, NULL, curproc);
+ return EINVAL;
+ }
+
+
+ /*
+ * Unbind the individual pages and flush the chipset's
+ * TLB. Unwire the pages so they can be swapped.
+ */
+ for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE)
+ AGP_UNBIND_PAGE(sc, mem->am_offset + i);
+
+ agp_flush_cache();
+ AGP_FLUSH_TLB(sc);
+
+ bus_dmamap_unload(sc->sc_dmat, mem->am_dmamap);
+ bus_dmamem_unmap(sc->sc_dmat, mem->am_virtual, mem->am_size);
+ bus_dmamem_free(sc->sc_dmat, mem->am_dmaseg, mem->am_nseg);
+
+ free(mem->am_dmaseg, M_DEVBUF);
+
+ mem->am_offset = 0;
+ mem->am_is_bound = 0;
+
+ lockmgr(&sc->sc_lock, LK_RELEASE, NULL, curproc);
+
+ return 0;
+}
+
+int
+agp_alloc_dmamem(bus_dma_tag_t tag, size_t size, int flags,
+ bus_dmamap_t *mapp, caddr_t *vaddr, bus_addr_t *baddr,
+ bus_dma_segment_t *seg, int nseg, int *rseg)
+
+{
+ int error, level = 0;
+
+ if ((error = bus_dmamem_alloc(tag, size, PAGE_SIZE, 0,
+ seg, nseg, rseg, BUS_DMA_NOWAIT)) != 0)
+ goto out;
+ level++;
+
+ if ((error = bus_dmamem_map(tag, seg, *rseg, size, vaddr,
+ BUS_DMA_NOWAIT | flags)) != 0)
+ goto out;
+ level++;
+
+ if ((error = bus_dmamap_create(tag, size, *rseg, size, 0,
+ BUS_DMA_NOWAIT, mapp)) != 0)
+ goto out;
+ level++;
+
+ if ((error = bus_dmamap_load(tag, *mapp, *vaddr, size, NULL,
+ BUS_DMA_NOWAIT)) != 0)
+ goto out;
+
+ *baddr = (*mapp)->dm_segs[0].ds_addr;
+
+ return 0;
+out:
+ switch (level) {
+ case 3:
+ bus_dmamap_destroy(tag, *mapp);
+ /* FALLTHROUGH */
+ case 2:
+ bus_dmamem_unmap(tag, *vaddr, size);
+ /* FALLTHROUGH */
+ case 1:
+ bus_dmamem_free(tag, seg, *rseg);
+ break;
+ default:
+ break;
+ }
+
+ return error;
+}
+
+void
+agp_free_dmamem(bus_dma_tag_t tag, size_t size, bus_dmamap_t map,
+ caddr_t vaddr, bus_dma_segment_t *seg, int nseg)
+{
+
+ bus_dmamap_unload(tag, map);
+ bus_dmamap_destroy(tag, map);
+ bus_dmamem_unmap(tag, vaddr, size);
+ bus_dmamem_free(tag, seg, nseg);
+}
+#endif
diff --git a/sys/dev/pci/vga_pcivar.h b/sys/dev/pci/vga_pcivar.h
index 58b934d5169..4a297cd86d3 100644
--- a/sys/dev/pci/vga_pcivar.h
+++ b/sys/dev/pci/vga_pcivar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: vga_pcivar.h,v 1.4 2002/03/14 01:27:00 millert Exp $ */
+/* $OpenBSD: vga_pcivar.h,v 1.5 2002/07/12 20:17:03 mickey Exp $ */
/* $NetBSD: vga_pcivar.h,v 1.1 1998/03/22 15:16:19 drochner Exp $ */
/*
@@ -28,11 +28,81 @@
* rights to redistribute these changes.
*/
+#ifndef _PCI_VGA_PCIVAR_H_
+#define _PCI_VGA_PCIVAR_H_
+
#define DEVICE_IS_VGA_PCI(class, id) \
(((PCI_CLASS(class) == PCI_CLASS_DISPLAY && \
PCI_SUBCLASS(class) == PCI_SUBCLASS_DISPLAY_VGA) || \
(PCI_CLASS(class) == PCI_CLASS_PREHISTORIC && \
PCI_SUBCLASS(class) == PCI_SUBCLASS_PREHISTORIC_VGA)) ? 1 : 0)
+enum agp_acquire_state {
+ AGP_ACQUIRE_FREE,
+ AGP_ACQUIRE_USER,
+ AGP_ACQUIRE_KERNEL
+};
+
+/*
+ * Data structure to describe an AGP memory allocation.
+ */
+TAILQ_HEAD(agp_memory_list, agp_memory);
+struct agp_memory {
+ TAILQ_ENTRY(agp_memory) am_link; /* wiring for the tailq */
+ int am_id; /* unique id for block */
+ vsize_t am_size; /* number of bytes allocated */
+ int am_type; /* chipset specific type */
+ off_t am_offset; /* page offset if bound */
+ int am_is_bound; /* non-zero if bound */
+ bus_addr_t am_physical;
+ caddr_t am_virtual;
+ bus_dmamap_t am_dmamap;
+ int am_nseg;
+ bus_dma_segment_t *am_dmaseg;
+};
+
+struct vga_pci_softc {
+ struct device sc_dev;
+
+#if 0
+ struct vga_config *sc_vc; /* VGA configuration */
+#endif
+
+ /* agp stuff */
+ bus_space_tag_t sc_bt, sc_memt;
+ bus_space_handle_t sc_bh;
+ bus_addr_t sc_apaddr;
+ bus_size_t sc_apsize;
+ bus_dma_tag_t sc_dmat;
+ struct lock sc_lock; /* lock for access to GATT */
+ pcitag_t sc_pcitag; /* PCI tag, in case we need it. */
+ pcireg_t sc_id;
+ pci_chipset_tag_t sc_pc;
+
+ struct agp_methods *sc_methods;
+ void *sc_chipc; /* chipset-dependent state */
+
+ int sc_opened;
+ int sc_capoff;
+ int sc_apflags;
+ int sc_nextid; /* next memory block id */
+
+ u_int32_t sc_maxmem; /* allocation upper bound */
+ u_int32_t sc_allocated; /* amount allocated */
+ enum agp_acquire_state sc_state;
+ struct agp_memory_list sc_memory; /* list of allocated memory */
+};
+
+struct agp_product {
+ int ap_vendor;
+ int ap_product;
+ int (*ap_attach)(struct vga_pci_softc *,
+ struct pci_attach_args *, struct pci_attach_args *);
+};
+/* MD-defined */
+extern const struct agp_product agp_products[];
+
int vga_pci_cnattach(bus_space_tag_t, bus_space_tag_t,
pci_chipset_tag_t, int, int, int);
+
+#endif /* _PCI_VGA_PCIVAR_H_ */