summaryrefslogtreecommitdiff
path: root/sys/dev/pci/agp.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/pci/agp.c')
-rw-r--r--sys/dev/pci/agp.c606
1 files changed, 411 insertions, 195 deletions
diff --git a/sys/dev/pci/agp.c b/sys/dev/pci/agp.c
index 52faa49e477..6c500c11bd2 100644
--- a/sys/dev/pci/agp.c
+++ b/sys/dev/pci/agp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: agp.c,v 1.7 2007/09/17 01:33:33 krw Exp $ */
+/* $OpenBSD: agp.c,v 1.8 2007/11/25 17:11:12 oga Exp $ */
/*-
* Copyright (c) 2000 Doug Rabson
* All rights reserved.
@@ -36,6 +36,7 @@
#include <uvm/uvm.h>
#include <dev/pci/pcivar.h>
+#include <dev/pci/pcidevs.h>
#include <dev/ic/mc6845reg.h>
#include <dev/ic/pcdisplayvar.h>
@@ -45,17 +46,88 @@
#include <dev/pci/agpvar.h>
#include <dev/pci/agpreg.h>
-struct agp_memory *agp_find_memory(struct vga_pci_softc *sc, int id);
+#include "agp_ali.h"
+#include "agp_amd.h"
+#include "agp_amd64.h"
+#include "agp_apple.h"
+#include "agp_i810.h"
+#include "agp_intel.h"
+#include "agp_sis.h"
+#include "agp_via.h"
+
+struct agp_memory *agp_find_memory(struct agp_softc *sc, int id);
const struct agp_product *agp_lookup(struct pci_attach_args *pa);
+/* userland ioctl functions */
+static int agp_info_user(void *, agp_info *);
+static int agp_setup_user(void *, agp_setup *);
+static int agp_allocate_user(void *, agp_allocate *);
+static int agp_deallocate_user(void *, int);
+static int agp_bind_user(void *, agp_bind *);
+static int agp_unbind_user(void *, agp_unbind *);
+static int agp_acquire_helper(void *dev, enum agp_acquire_state state);
+static int agp_release_helper(void *dev, enum agp_acquire_state state);
+
+const struct agp_product agp_products[] = {
+#if NAGP_ALI > 0
+ { PCI_VENDOR_ALI, -1, agp_ali_attach },
+#endif
+#if NAGP_AMD > 0
+ { PCI_VENDOR_AMD, -1, agp_amd_attach },
+#endif
+#if NAGP_I810 > 0
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82810_MCH, agp_i810_attach },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82810_DC100_MCH, agp_i810_attach },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82810E_MCH, agp_i810_attach },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82815_FULL_HUB, agp_i810_attach },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82840_HB, agp_i810_attach },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82830MP_IO_1, agp_i810_attach },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82845G, agp_i810_attach },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82852GM_HPB, agp_i810_attach },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82865_IO_1, agp_i810_attach },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82915G_HB, agp_i810_attach },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82915GM_HB, agp_i810_attach },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82945GP_MCH, agp_i810_attach },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82945GM_MCH, agp_i810_attach },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82Q963_HB, agp_i810_attach },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82965_MCH, agp_i810_attach },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82915G_IV, agp_i810_attach },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82915GM_IGD, agp_i810_attach },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82945G_IGD_1, agp_i810_attach },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82945GM_IGD, agp_i810_attach },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82965_IGD_1, agp_i810_attach },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82965GM_IGD_1, agp_i810_attach },
+#endif
+#if NAGP_INTEL > 0
+ { PCI_VENDOR_INTEL, -1, agp_intel_attach },
+#endif
+#if NAGP_SIS > 0
+ { PCI_VENDOR_SIS, -1, agp_sis_attach },
+#endif
+#if NAGP_VIA > 0
+ { PCI_VENDOR_VIATECH, -1, agp_via_attach },
+#endif
+ { 0, 0, NULL }
+};
-struct pci_attach_args agp_pchb_pa;
-int agp_pchb_pa_set = 0;
+
+static int
+agp_probe(struct device *parent, void *match, void *aux)
+{
+ struct agpbus_attach_args *aaa = aux;
+ struct pci_attach_args *pa = &aaa->apa_pci_args;
+
+ if (agp_lookup(pa) == NULL)
+ return (0);
+
+ return (1);
+}
void
agp_attach(struct device *parent, struct device *self, void *aux)
{
- struct pci_attach_args *pa = aux;
- struct vga_pci_softc *sc = (struct vga_pci_softc *)self;
+ struct agpbus_attach_args *aaa = aux;
+ struct pci_attach_args *pa = &aaa->apa_pci_args;
+ struct agp_softc *sc = (struct agp_softc *)self;
const struct agp_product *ap;
u_int memsize;
int i, ret;
@@ -104,7 +176,7 @@ agp_attach(struct device *parent, struct device *self, void *aux)
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);
+ ret = (*ap->ap_attach)(sc, pa);
if (ret == 0)
printf(": aperture at 0x%lx, size 0x%lx",
(u_long)sc->sc_apaddr,
@@ -116,183 +188,123 @@ agp_attach(struct device *parent, struct device *self, void *aux)
}
}
+struct cfattach agp_ca = {
+ sizeof (struct agp_softc), agp_probe, agp_attach,
+ NULL, NULL
+};
+
+struct cfdriver agp_cd = {
+ NULL, "agp", DV_DULL
+};
+
paddr_t
-agp_mmap(void *v, off_t off, int prot)
+agpmmap(void *v, off_t off, int prot)
{
- struct vga_config* vs = (struct vga_config*) v;
- struct vga_pci_softc* sc = (struct vga_pci_softc *)vs->vc_softc;
+ struct agp_softc* sc = (struct agp_softc *)v;
if (sc->sc_apaddr) {
if (off > AGP_GET_APERTURE(sc))
return (-1);
+ /*
+ * XXX this should use bus_space_mmap() but it's not
+ * availiable on all archs.
+ */
return atop(sc->sc_apaddr + off);
}
- return -1;
+ return (-1);
}
+int agpopen(dev_t dev , int oflags, int devtype, struct proc * p)
+{
+ struct agp_softc *sc = (struct agp_softc *)device_lookup(&agp_cd, AGPUNIT(dev));
+
+ if (sc == NULL)
+ return (ENXIO);
+
+ if (sc->sc_chipc == NULL)
+ return (ENXIO);
+
+ if (!sc->sc_opened)
+ sc->sc_opened = 1;
+ else
+ return (EBUSY);
+
+ return (0);
+}
+
+
int
-agp_ioctl(void *v, u_long cmd, caddr_t addr, int flag, struct proc *pb)
+agpioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *pb)
{
- 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;
- int error = 0;
+ struct agp_softc *sc = (struct agp_softc *)device_lookup(&agp_cd, AGPUNIT(dev));
+
+ if (sc ==NULL)
+ return (ENODEV);
if (sc->sc_methods == NULL || sc->sc_chipc == NULL)
return (ENXIO);
+
+ if (cmd != AGPIOC_INFO && !(flag & FWRITE))
+ return (EPERM);
- switch (cmd) {
- case AGPIOC_INFO:
- if (!sc->sc_chipc)
- return (ENXIO);
- case AGPIOC_ACQUIRE:
- case AGPIOC_RELEASE:
- case AGPIOC_SETUP:
- case AGPIOC_ALLOCATE:
- case AGPIOC_DEALLOCATE:
- case AGPIOC_BIND:
- case AGPIOC_UNBIND:
- if (cmd != AGPIOC_INFO && !(flag & FWRITE))
- return (EPERM);
- break;
- }
switch(cmd) {
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;
+ return (agp_info_user(sc, (agp_info *)addr));
case AGPIOC_ACQUIRE:
- if (sc->sc_state != AGP_ACQUIRE_FREE)
- error = EBUSY;
- else
- sc->sc_state = AGP_ACQUIRE_USER;
- break;
+ return (agp_acquire_helper(sc, AGP_ACQUIRE_USER));
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;
+ return (agp_release_helper(sc, AGP_ACQUIRE_USER));
case AGPIOC_SETUP:
- setup = (agp_setup *)addr;
- error = AGP_ENABLE(sc, setup->agp_mode);
- break;
+ return (agp_setup_user(sc, (agp_setup *)addr));
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;
+ return (agp_allocate_user(sc, (agp_allocate *)addr));
case AGPIOC_DEALLOCATE:
- mem = agp_find_memory(sc, *(int *)addr);
- if (mem)
- AGP_FREE_MEMORY(sc, mem);
- else
- error = ENOENT;
- break;
+ return (agp_deallocate_user(sc, *(int *)addr));
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;
+ return (agp_bind_user(sc, (agp_bind *)addr));
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;
+ return (agp_unbind_user(sc, (agp_unbind *)addr));
+
default:
- error = ENOTTY;
+ return (ENOTTY);
}
- return (error);
}
-#ifdef notyet
-void
-agp_close(void *v)
+int
+agpclose(dev_t dev, int flags, int devtype, struct proc *p)
{
- struct vga_config *vc = v;
- struct vga_pci_softc *sc = (struct vga_pci_softc *)vc->vc_softc;
+ struct agp_softc *sc =
+ (struct agp_softc *)device_lookup(&agp_cd, AGPUNIT(dev));
struct agp_memory *mem;
/*
- * Clear out the aperture and free any
- * outstanding memory blocks.
- */
- TAILQ_FOREACH(mem, &sc->sc_memory, am_link) {
- if (mem->am_is_bound) {
- AGP_UNBIND_MEMORY(sc, mem);
+ * Clear the GATT and force release on last close
+ */
+ if (sc->sc_state == AGP_ACQUIRE_USER) {
+ while ((mem = TAILQ_FIRST(&sc->sc_memory)) != 0) {
+ if (mem->am_is_bound)
+ AGP_UNBIND_MEMORY(sc, mem);
+ AGP_FREE_MEMORY(sc, mem);
}
+ agp_release_helper(sc, AGP_ACQUIRE_USER);
}
+ sc->sc_opened = 0;
- while (!TAILQ_EMPTY(&sc->sc_memory)) {
- mem = TAILQ_FIRST(&sc->sc_memory);
- AGP_FREE_MEMORY(sc, mem);
- }
-
- sc->sc_state = AGP_ACQUIRE_FREE;
+ return (0);
}
-#endif
struct agp_memory *
-agp_find_memory(struct vga_pci_softc *sc, int id)
+agp_find_memory(struct agp_softc *sc, int id)
{
struct agp_memory *mem;
@@ -302,7 +314,7 @@ agp_find_memory(struct vga_pci_softc *sc, int id)
if (mem->am_id == id)
return (mem);
}
- return 0;
+ return (0);
}
const struct agp_product *
@@ -310,10 +322,6 @@ 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))
@@ -340,39 +348,30 @@ agp_lookup(struct pci_attach_args *pa)
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, u_int32_t bar, u_int32_t memtype)
+agp_map_aperture(struct pci_attach_args *pa, struct agp_softc *sc, u_int32_t bar, u_int32_t memtype)
{
/*
* Find and the aperture. Don't map it (yet), this would
* eat KVA.
*/
- if (pci_mapreg_info(sc->sc_pc, sc->sc_pcitag, bar,
+ if (pci_mapreg_info(pa->pa_pc, pa->pa_tag, bar,
memtype, &sc->sc_apaddr, &sc->sc_apsize,
&sc->sc_apflags) != 0)
- return ENXIO;
+ return (ENXIO);
- return 0;
+ return (0);
}
struct agp_gatt *
-agp_alloc_gatt(struct vga_pci_softc *sc)
+agp_alloc_gatt(struct agp_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 | M_ZERO);
+ gatt = malloc(sizeof(*gatt), M_AGP, M_NOWAIT | M_ZERO);
if (!gatt)
return (NULL);
gatt->ag_entries = entries;
@@ -380,33 +379,33 @@ agp_alloc_gatt(struct vga_pci_softc *sc)
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;
+ return (NULL);
gatt->ag_size = entries * sizeof(u_int32_t);
memset(gatt->ag_virtual, 0, gatt->ag_size);
agp_flush_cache();
- return gatt;
+ return (gatt);
}
void
-agp_free_gatt(struct vga_pci_softc *sc, struct agp_gatt *gatt)
+agp_free_gatt(struct agp_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);
+ free(gatt, M_AGP);
}
int
-agp_generic_detach(struct vga_pci_softc *sc)
+agp_generic_detach(struct agp_softc *sc)
{
lockmgr(&sc->sc_lock, LK_DRAIN, NULL);
agp_flush_cache();
- return 0;
+ return (0);
}
int
-agp_generic_enable(struct vga_pci_softc *sc, u_int32_t mode)
+agp_generic_enable(struct agp_softc *sc, u_int32_t mode)
{
pcireg_t tstatus, mstatus;
pcireg_t command;
@@ -415,7 +414,7 @@ agp_generic_enable(struct vga_pci_softc *sc, u_int32_t mode)
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;
+ return (-1);
}
tstatus = pci_conf_read(sc->sc_pc, sc->sc_pcitag,
@@ -460,27 +459,27 @@ agp_generic_enable(struct vga_pci_softc *sc, u_int32_t mode)
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;
+ return (0);
}
struct agp_memory *
-agp_generic_alloc_memory(struct vga_pci_softc *sc, int type, vsize_t size)
+agp_generic_alloc_memory(struct agp_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;
+ return (0);
}
- mem = malloc(sizeof *mem, M_DEVBUF, M_WAITOK | M_ZERO);
+ mem = malloc(sizeof *mem, M_AGP, M_WAITOK | M_ZERO);
if (mem == NULL)
- return 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;
+ free(mem, M_AGP);
+ return (NULL);
}
mem->am_id = sc->sc_nextid++;
@@ -488,24 +487,24 @@ agp_generic_alloc_memory(struct vga_pci_softc *sc, int type, vsize_t size)
TAILQ_INSERT_TAIL(&sc->sc_memory, mem, am_link);
sc->sc_allocated += size;
- return mem;
+ return (mem);
}
int
-agp_generic_free_memory(struct vga_pci_softc *sc, struct agp_memory *mem)
+agp_generic_free_memory(struct agp_softc *sc, struct agp_memory *mem)
{
if (mem->am_is_bound)
- return EBUSY;
+ 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;
+ free(mem, M_AGP);
+ return (0);
}
int
-agp_generic_bind_memory(struct vga_pci_softc *sc, struct agp_memory *mem,
+agp_generic_bind_memory(struct agp_softc *sc, struct agp_memory *mem,
off_t offset)
{
bus_dma_segment_t *segs, *seg;
@@ -519,7 +518,7 @@ agp_generic_bind_memory(struct vga_pci_softc *sc, struct agp_memory *mem,
if (mem->am_is_bound) {
printf("AGP: memory already bound\n");
lockmgr(&sc->sc_lock, LK_RELEASE, NULL);
- return EINVAL;
+ return (EINVAL);
}
if (offset < 0
@@ -528,7 +527,7 @@ agp_generic_bind_memory(struct vga_pci_softc *sc, struct agp_memory *mem,
printf("AGP: binding memory at bad offset %#lx\n",
(unsigned long) offset);
lockmgr(&sc->sc_lock, LK_RELEASE, NULL);
- return EINVAL;
+ return (EINVAL);
}
/*
@@ -539,27 +538,27 @@ agp_generic_bind_memory(struct vga_pci_softc *sc, struct agp_memory *mem,
*/
nseg = (mem->am_size + PAGE_SIZE - 1) / PAGE_SIZE;
- segs = malloc(nseg * sizeof *segs, M_DEVBUF, M_WAITOK);
+ segs = malloc(nseg * sizeof *segs, M_AGP, M_WAITOK);
if (segs == NULL) {
lockmgr(&sc->sc_lock, LK_RELEASE, NULL);
AGP_DPF("malloc segs (%u) failed\n",
nseg * sizeof *segs);
- return ENOMEM;
+ 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);
+ free(segs, M_AGP);
lockmgr(&sc->sc_lock, LK_RELEASE, NULL);
AGP_DPF("bus_dmamem_alloc failed %d\n", error);
- return error;
+ return (error);
}
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);
+ free(segs, M_AGP);
lockmgr(&sc->sc_lock, LK_RELEASE, NULL);
AGP_DPF("bus_dmamem_map failed %d\n", error);
- return error;
+ return (error);
}
if ((error = bus_dmamap_load(sc->sc_dmat, mem->am_dmamap,
mem->am_virtual, mem->am_size, NULL,
@@ -567,10 +566,10 @@ agp_generic_bind_memory(struct vga_pci_softc *sc, struct agp_memory *mem,
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);
+ free(segs, M_AGP);
lockmgr(&sc->sc_lock, LK_RELEASE, NULL);
AGP_DPF("bus_dmamap_load failed %d\n", error);
- return error;
+ return (error);
}
mem->am_dmaseg = segs;
@@ -607,10 +606,10 @@ agp_generic_bind_memory(struct vga_pci_softc *sc, struct agp_memory *mem,
mem->am_size);
bus_dmamem_free(sc->sc_dmat, mem->am_dmaseg,
mem->am_nseg);
- free(mem->am_dmaseg, M_DEVBUF);
+ free(mem->am_dmaseg, M_AGP);
lockmgr(&sc->sc_lock, LK_RELEASE, NULL);
AGP_DPF("AGP_BIND_PAGE failed %d\n", error);
- return error;
+ return (error);
}
}
done += seg->ds_len;
@@ -632,11 +631,11 @@ agp_generic_bind_memory(struct vga_pci_softc *sc, struct agp_memory *mem,
lockmgr(&sc->sc_lock, LK_RELEASE, NULL);
- return 0;
+ return (0);
}
int
-agp_generic_unbind_memory(struct vga_pci_softc *sc, struct agp_memory *mem)
+agp_generic_unbind_memory(struct agp_softc *sc, struct agp_memory *mem)
{
int i;
@@ -645,7 +644,7 @@ agp_generic_unbind_memory(struct vga_pci_softc *sc, struct agp_memory *mem)
if (!mem->am_is_bound) {
printf("AGP: memory is not bound\n");
lockmgr(&sc->sc_lock, LK_RELEASE, NULL);
- return EINVAL;
+ return (EINVAL);
}
@@ -663,14 +662,14 @@ agp_generic_unbind_memory(struct vga_pci_softc *sc, struct agp_memory *mem)
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);
+ free(mem->am_dmaseg, M_AGP);
mem->am_offset = 0;
mem->am_is_bound = 0;
lockmgr(&sc->sc_lock, LK_RELEASE, NULL);
- return 0;
+ return (0);
}
int
@@ -702,7 +701,7 @@ agp_alloc_dmamem(bus_dma_tag_t tag, size_t size, int flags,
*baddr = (*mapp)->dm_segs[0].ds_addr;
- return 0;
+ return (0);
out:
switch (level) {
case 3:
@@ -718,7 +717,7 @@ out:
break;
}
- return error;
+ return (error);
}
void
@@ -731,3 +730,220 @@ agp_free_dmamem(bus_dma_tag_t tag, size_t size, bus_dmamap_t map,
bus_dmamem_unmap(tag, vaddr, size);
bus_dmamem_free(tag, seg, nseg);
}
+
+/* Helper functions used in both user and kernel APIs */
+
+static int
+agp_acquire_helper(void *dev, enum agp_acquire_state state)
+{
+ struct agp_softc *sc = (struct agp_softc *)dev;
+
+ if (sc->sc_state != AGP_ACQUIRE_FREE)
+ return (EBUSY);
+ sc->sc_state = state;
+
+ return (0);
+}
+
+static int
+agp_release_helper(void *dev, enum agp_acquire_state state)
+{
+ struct agp_softc *sc = (struct agp_softc *)dev;
+ struct agp_memory* mem;
+
+ if (sc->sc_state == AGP_ACQUIRE_FREE)
+ return (0);
+
+ if (sc->sc_state != state)
+ return (EBUSY);
+
+ /*
+ * 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;
+ return (0);
+}
+
+/* Implementation of the userland ioctl API */
+
+static int
+agp_info_user(void *dev, agp_info *info)
+{
+ struct agp_softc *sc = (struct agp_softc *) dev;
+
+ if (!sc->sc_chipc)
+ return (ENXIO);
+
+ 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;
+
+ return (0);
+}
+
+static int
+agp_setup_user(void *dev, agp_setup *setup)
+{
+ struct agp_softc *sc = (struct agp_softc *) dev;
+ return (AGP_ENABLE(sc, setup->agp_mode));
+}
+
+static int
+agp_allocate_user(void *dev, agp_allocate *alloc)
+{
+ struct agp_softc *sc = (struct agp_softc *) dev;
+ struct agp_memory* mem;
+ size_t size = alloc->pg_count << AGP_PAGE_SHIFT;
+
+ if (sc->sc_allocated + size > sc->sc_maxmem)
+ return (EINVAL);
+
+ mem = AGP_ALLOC_MEMORY(sc, alloc->type, size);
+ if (mem) {
+ alloc->key = mem->am_id;
+ alloc->physical = mem->am_physical;
+ return (0);
+ } else
+ return (ENOMEM);
+}
+
+static int
+agp_deallocate_user(void *dev, int id)
+{
+ struct agp_softc *sc = (struct agp_softc *) dev;
+ struct agp_memory *mem = agp_find_memory(sc, id);
+ if (mem) {
+ AGP_FREE_MEMORY(sc, mem);
+ return (0);
+ } else
+ return (ENOENT);
+}
+
+static int
+agp_bind_user(void *dev, agp_bind *bind)
+{
+ struct agp_softc *sc = (struct agp_softc *) dev;
+ struct agp_memory *mem = agp_find_memory(sc, bind->key);
+
+ if (!mem)
+ return (ENOENT);
+
+ return (AGP_BIND_MEMORY(sc, mem, bind->pg_start << AGP_PAGE_SHIFT));
+}
+
+
+static int
+agp_unbind_user(void *dev, agp_unbind *unbind)
+{
+ struct agp_softc *sc = (struct agp_softc *) dev;
+ struct agp_memory *mem = agp_find_memory(sc, unbind->key);
+
+ if (!mem)
+ return (ENOENT);
+
+ return (AGP_UNBIND_MEMORY(sc, mem));
+}
+
+/* Implementation of the kernel api */
+
+void *
+agp_find_device(int unit)
+{
+ return (device_lookup(&agp_cd, unit));
+}
+
+enum agp_acquire_state
+agp_state(void *dev)
+{
+ struct agp_softc *sc = (struct agp_softc *) dev;
+ return (sc->sc_state);
+}
+
+void
+agp_get_info(void *dev, struct agp_info *info)
+{
+ struct agp_softc *sc = (struct agp_softc *)dev;
+
+ info->ai_mode = pci_conf_read(sc->sc_pc, sc->sc_pcitag,
+ sc->sc_capoff + AGP_STATUS);
+ info->ai_aperture_base = sc->sc_apaddr;
+ info->ai_aperture_size = sc->sc_apsize;
+ info->ai_memory_allowed = sc->sc_maxmem;
+ info->ai_memory_used = sc->sc_allocated;
+}
+
+int
+agp_acquire(void *dev)
+{
+ struct agp_softc *sc = (struct agp_softc *)dev;
+ return (agp_acquire_helper(sc, AGP_ACQUIRE_KERNEL));
+}
+
+int
+agp_release(void *dev)
+{
+ struct agp_softc *sc = (struct agp_softc *)dev;
+ return (agp_release_helper(sc, AGP_ACQUIRE_KERNEL));
+}
+
+int
+agp_enable(void *dev, u_int32_t mode)
+{
+ struct agp_softc *sc = (struct agp_softc *) dev;
+ return (AGP_ENABLE(sc, mode));
+}
+
+void *agp_alloc_memory(void *dev, int type, vsize_t bytes)
+{
+ struct agp_softc *sc = (struct agp_softc *)dev;
+ return ((void *) AGP_ALLOC_MEMORY(sc, type, bytes));
+}
+
+void agp_free_memory(void *dev, void *handle)
+{
+ struct agp_softc *sc = (struct agp_softc *) dev;
+ struct agp_memory *mem = (struct agp_memory *) handle;
+ AGP_FREE_MEMORY(sc, mem);
+}
+
+int agp_bind_memory(void *dev, void *handle, off_t offset)
+{
+ struct agp_softc *sc = (struct agp_softc *) dev;
+ struct agp_memory *mem = (struct agp_memory *) handle;
+ return (AGP_BIND_MEMORY(sc, mem, offset));
+}
+
+int agp_unbind_memory(void *dev, void *handle)
+{
+ struct agp_softc *sc = (struct agp_softc *) dev;
+ struct agp_memory *mem = (struct agp_memory *) handle;
+ return (AGP_UNBIND_MEMORY(sc, mem));
+}
+
+void agp_memory_info(void *dev, void *handle, struct
+ agp_memory_info *mi)
+{
+ struct agp_memory *mem = (struct agp_memory *) handle;
+
+ mi->ami_size = mem->am_size;
+ mi->ami_physical = mem->am_physical;
+ mi->ami_offset = mem->am_offset;
+ mi->ami_is_bound = mem->am_is_bound;
+}