summaryrefslogtreecommitdiff
path: root/sys/dev/pci/agp_sis.c
diff options
context:
space:
mode:
authorOwain Ainsworth <oga@cvs.openbsd.org>2008-11-09 15:11:20 +0000
committerOwain Ainsworth <oga@cvs.openbsd.org>2008-11-09 15:11:20 +0000
commitc82365de6d1669d3aa8f37a7f91c598524aba316 (patch)
treeb47841f2a3a7541cc4236df1638f5f4433c8f81e /sys/dev/pci/agp_sis.c
parent19e72e3b9f3138440f80b79260f2adaee85eae40 (diff)
Rework that way that agp attaches.
previously, we had a static list of pcidevs and which agp driver would be interanlly attached. Instead, split the agp drivers so they work like audio(4), where we attach a driver, which sets up some callbacks and initial state, then attaches the interface (agp(4)). Since this allows us to attach different drivers in different places, and give them /proper/ probe functions move most of the drivers back to attaching at pchb, where they should, and intagp (formerly agp_i810) stays attaching at vga, since it's part of the intel integrated graphics chips. Diff shrinks the kernel slightly, gets rid of the annoying "no integrated graphics" warning, and allows more cleanup later. Tested by many. fix for alpha build (the only other vga_pci.c consumer) suggested by miod.
Diffstat (limited to 'sys/dev/pci/agp_sis.c')
-rw-r--r--sys/dev/pci/agp_sis.c135
1 files changed, 75 insertions, 60 deletions
diff --git a/sys/dev/pci/agp_sis.c b/sys/dev/pci/agp_sis.c
index 9a3b8a59329..0bc46a241b7 100644
--- a/sys/dev/pci/agp_sis.c
+++ b/sys/dev/pci/agp_sis.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: agp_sis.c,v 1.7 2007/12/07 17:35:22 oga Exp $ */
+/* $OpenBSD: agp_sis.c,v 1.8 2008/11/09 15:11:19 oga Exp $ */
/* $NetBSD: agp_sis.c,v 1.2 2001/09/15 00:25:00 thorpej Exp $ */
/*-
@@ -29,7 +29,6 @@
* $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>
@@ -42,6 +41,7 @@
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
+#include <dev/pci/pcidevs.h>
#include <dev/pci/vga_pcivar.h>
#include <dev/pci/agpvar.h>
#include <dev/pci/agpreg.h>
@@ -49,80 +49,92 @@
#include <machine/bus.h>
struct agp_sis_softc {
- u_int32_t initial_aperture; /* aperture size at startup */
- struct agp_gatt *gatt;
+ struct device dev;
+ struct agp_softc *agpdev;
+ struct agp_gatt *gatt;
+ pci_chipset_tag_t ssc_pc;
+ pcitag_t ssc_tag;
+ bus_size_t initial_aperture;
+};
+
+void agp_sis_attach(struct device *, struct device *, void *);
+int agp_sis_probe(struct device *, void *, void *);
+bus_size_t agp_sis_get_aperture(void *);
+int agp_sis_set_aperture(void *, bus_size_t);
+int agp_sis_bind_page(void *, off_t, bus_addr_t);
+int agp_sis_unbind_page(void *, off_t);
+void agp_sis_flush_tlb(void *);
+
+struct cfattach sisagp_ca = {
+ sizeof(struct agp_sis_softc), agp_sis_probe, agp_sis_attach
};
-u_int32_t agp_sis_get_aperture(struct agp_softc *);
-int agp_sis_set_aperture(struct agp_softc *, u_int32_t);
-int agp_sis_bind_page(struct agp_softc *, off_t, bus_addr_t);
-int agp_sis_unbind_page(struct agp_softc *, off_t);
-void agp_sis_flush_tlb(struct agp_softc *);
+struct cfdriver sisagp_cd = {
+ NULL, "intelagp", DV_DULL
+};
-struct agp_methods agp_sis_methods = {
+const 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 agp_softc *sc, struct pci_attach_args *pa)
+agp_sis_probe(struct device *parent, void *match, void *aux)
{
- struct agp_sis_softc *ssc;
- struct agp_gatt *gatt;
- pcireg_t reg;
+ struct agp_attach_args *aa = aux;
+ struct pci_attach_args *pa = aa->aa_pa;
- ssc = malloc(sizeof *ssc, M_AGP, 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;
+ /* Must be a pchb */
+ if (agpbus_probe(aa) == 1 && PCI_VENDOR(pa->pa_id) == PCI_VENDOR_SIS)
+ return (1);
+ return (0);
+}
- if (agp_map_aperture(pa, sc, AGP_APBASE, PCI_MAPREG_TYPE_MEM) != 0) {
- printf("can't map aperture\n");
- free(ssc, M_AGP);
- return (ENXIO);
- }
- ssc->initial_aperture = AGP_GET_APERTURE(sc);
+void
+agp_sis_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct agp_sis_softc *ssc = (struct agp_sis_softc *)self;
+ struct agp_attach_args *aa = aux;
+ struct pci_attach_args *pa = aa->aa_pa;
+ struct agp_gatt *gatt;
+ pcireg_t reg;
+
+ ssc->ssc_pc = pa->pa_pc;
+ ssc->ssc_tag = pa->pa_tag;
+ ssc->initial_aperture = agp_sis_get_aperture(ssc);
for (;;) {
- gatt = agp_alloc_gatt(sc);
- if (gatt)
+ bus_size_t size = agp_sis_get_aperture(ssc);
+ gatt = agp_alloc_gatt(pa->pa_dmat, size);
+ if (gatt != NULL)
break;
/*
- * Probably contigmalloc failure. Try reducing the
+ * Probably failed to alloc congigious memory. 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);
+ if (agp_sis_set_aperture(ssc, size / 2)) {
+ printf("can't set aperture size\n");
+ return;
}
}
ssc->gatt = gatt;
/* Install the gatt. */
- pci_conf_write(sc->sc_pc, sc->sc_pcitag, AGP_SIS_ATTBASE,
+ pci_conf_write(ssc->ssc_pc, ssc->ssc_tag, 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 = pci_conf_read(ssc->ssc_pc, ssc->ssc_tag, AGP_SIS_WINCTRL);
reg |= (0x05 << 24) | 3;
- pci_conf_write(sc->sc_pc, sc->sc_pcitag, AGP_SIS_WINCTRL, reg);
+ pci_conf_write(ssc->ssc_pc, ssc->ssc_tag, AGP_SIS_WINCTRL, reg);
- return (0);
+ ssc->agpdev = (struct agp_softc *)agp_attach_bus(pa, &agp_sis_methods,
+ AGP_APBASE, PCI_MAPREG_TYPE_MEM, &ssc->dev);
+ return;
}
#if 0
@@ -150,22 +162,24 @@ agp_sis_detach(struct agp_softc *sc)
}
#endif
-u_int32_t
-agp_sis_get_aperture(struct agp_softc *sc)
+bus_size_t
+agp_sis_get_aperture(void *sc)
{
- int gws;
+ struct agp_sis_softc *ssc = sc;
+ int gws;
/*
* The aperture size is equal to 4M<<gws.
*/
- gws = (pci_conf_read(sc->sc_pc, sc->sc_pcitag,
+ gws = (pci_conf_read(ssc->ssc_pc, ssc->ssc_tag,
AGP_SIS_WINCTRL)&0x70) >> 4;
return ((4 * 1024 * 1024) << gws);
}
int
-agp_sis_set_aperture(struct agp_softc *sc, u_int32_t aperture)
+agp_sis_set_aperture(void *sc, bus_size_t aperture)
{
+ struct agp_sis_softc *ssc = sc;
int gws;
pcireg_t reg;
@@ -180,18 +194,18 @@ agp_sis_set_aperture(struct agp_softc *sc, u_int32_t aperture)
gws = ffs(aperture / 4*1024*1024) - 1;
- reg = pci_conf_read(sc->sc_pc, sc->sc_pcitag, AGP_SIS_WINCTRL);
+ reg = pci_conf_read(ssc->ssc_pc, ssc->ssc_tag, AGP_SIS_WINCTRL);
reg &= ~0x00000070;
reg |= gws << 4;
- pci_conf_write(sc->sc_pc, sc->sc_pcitag, AGP_SIS_WINCTRL, reg);
+ pci_conf_write(ssc->ssc_pc, ssc->ssc_tag, AGP_SIS_WINCTRL, reg);
return (0);
}
int
-agp_sis_bind_page(struct agp_softc *sc, off_t offset, bus_addr_t physical)
+agp_sis_bind_page(void *sc, off_t offset, bus_addr_t physical)
{
- struct agp_sis_softc *ssc = sc->sc_chipc;
+ struct agp_sis_softc *ssc = sc;
if (offset < 0 || offset >= (ssc->gatt->ag_entries << AGP_PAGE_SHIFT))
return (EINVAL);
@@ -201,9 +215,9 @@ agp_sis_bind_page(struct agp_softc *sc, off_t offset, bus_addr_t physical)
}
int
-agp_sis_unbind_page(struct agp_softc *sc, off_t offset)
+agp_sis_unbind_page(void *sc, off_t offset)
{
- struct agp_sis_softc *ssc = sc->sc_chipc;
+ struct agp_sis_softc *ssc = sc;
if (offset < 0 || offset >= (ssc->gatt->ag_entries << AGP_PAGE_SHIFT))
return (EINVAL);
@@ -213,12 +227,13 @@ agp_sis_unbind_page(struct agp_softc *sc, off_t offset)
}
void
-agp_sis_flush_tlb(struct agp_softc *sc)
+agp_sis_flush_tlb(void *sc)
{
- pcireg_t reg;
+ struct agp_sis_softc *ssc = sc;
+ pcireg_t reg;
- reg = pci_conf_read(sc->sc_pc, sc->sc_pcitag, AGP_SIS_TLBFLUSH);
+ reg = pci_conf_read(ssc->ssc_pc, ssc->ssc_tag, AGP_SIS_TLBFLUSH);
reg &= 0xffffff00;
reg |= 0x02;
- pci_conf_write(sc->sc_pc, sc->sc_pcitag, AGP_SIS_TLBFLUSH, reg);
+ pci_conf_write(ssc->ssc_pc, ssc->ssc_tag, AGP_SIS_TLBFLUSH, reg);
}