diff --git a/sys/arch/i386/pci/pchb.c b/sys/arch/i386/pci/pchb.c index a3e90e1f3aec..a66dc49706fc 100644 --- a/sys/arch/i386/pci/pchb.c +++ b/sys/arch/i386/pci/pchb.c @@ -1,4 +1,4 @@ -/* $NetBSD: pchb.c,v 1.26 2001/09/12 08:25:17 fvdl Exp $ */ +/* $NetBSD: pchb.c,v 1.27 2001/09/15 00:25:01 thorpej Exp $ */ /*- * Copyright (c) 1996, 1998, 2000 The NetBSD Foundation, Inc. @@ -48,12 +48,12 @@ #include +#include #include #include #include "rnd.h" -#include "agp.h" #define PCISET_BRIDGETYPE_MASK 0x3 #define PCISET_TYPE_COMPAT 0x1 @@ -78,6 +78,8 @@ int pchbmatch __P((struct device *, struct cfdata *, void *)); void pchbattach __P((struct device *, struct device *, void *)); +int pchb_i810_vgamatch(struct pci_attach_args *); + int pchb_print __P((void *, const char *)); int agp_print __P((void *, const char *)); @@ -107,16 +109,15 @@ pchbattach(struct device *parent, struct device *self, void *aux) struct pci_attach_args *pa = aux; char devinfo[256]; struct pcibus_attach_args pba; -#if NAGP > 0 - struct agp_phcb_attach_args apa; -#endif + struct agpbus_attach_args apa; pcireg_t bcreg; u_char bdnum, pbnum; pcitag_t tag; - int doattach, attachflags; + int doattach, attachflags, has_agp; printf("\n"); doattach = 0; + has_agp = 0; attachflags = pa->pa_flags; /* @@ -251,6 +252,48 @@ pchbattach(struct device *parent, struct device *self, void *aux) break; } break; + + case PCI_PRODUCT_INTEL_82810_MCH: + case PCI_PRODUCT_INTEL_82810_DC100_MCH: + case PCI_PRODUCT_INTEL_82810E_MCH: + case PCI_PRODUCT_INTEL_82815_FULL_HUB: + { + struct pci_attach_args vga_pa; + pcireg_t ramreg; + + /* + * XXXfvdl + * This relies on the "memory hub" and the VGA controller + * being on the same bus, which is kind of gross. Fortunately, + * we know this is always the case on the i810. + */ + if (pci_find_device(&vga_pa, pchb_i810_vgamatch) != 0) { + ramreg = pci_conf_read(pa->pa_pc, pa->pa_tag, + AGP_I810_SMRAM); + if (ramreg & 0xff) + has_agp = 1; + } + break; + } + } + +#if NRND > 0 + /* + * Attach a random number generator, if there is one. + */ + pchb_attach_rnd(sc, pa); +#endif + + /* + * If we haven't detected AGP yet (via a product ID), + * then check for AGP capability on the device. + */ + if (has_agp || + pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_AGP, + NULL, NULL) != 0) { + apa.apa_busname = "agp"; + apa.apa_pci_args = *pa; + config_found(self, &apa, agp_print); } if (doattach) { @@ -263,23 +306,25 @@ pchbattach(struct device *parent, struct device *self, void *aux) pba.pba_pc = pa->pa_pc; config_found(self, &pba, pchb_print); } +} -#if NAGP > 0 - /* - * XXX re-use of pci attach args for pchb, but it's probably - * the best thing to do. - */ - apa.apa_busname = "agp"; - apa.apa_pci_args = *pa; - config_found(self, &apa, agp_print); -#endif +int +pchb_i810_vgamatch(struct pci_attach_args *pa) +{ -#if NRND > 0 - /* - * Attach a random number generator, if there is one. - */ - pchb_attach_rnd(sc, pa); -#endif + if (PCI_CLASS(pa->pa_class) != PCI_CLASS_DISPLAY || + PCI_SUBCLASS(pa->pa_class) != PCI_SUBCLASS_DISPLAY_VGA) + return (0); + + switch (PCI_PRODUCT(pa->pa_id)) { + case PCI_PRODUCT_INTEL_82810_GC: + case PCI_PRODUCT_INTEL_82810_DC100_GC: + case PCI_PRODUCT_INTEL_82810E_GC: + case PCI_PRODUCT_INTEL_82815_FULL_GRAPH: + return (1); + } + + return (0); } int @@ -296,7 +341,7 @@ pchb_print(void *aux, const char *pnp) int agp_print(void *aux, const char *pnp) { - struct agp_phcb_attach_args *apa = aux; + struct agpbus_attach_args *apa = aux; if (pnp) printf("%s at %s", apa->apa_busname, pnp); return (UNCONF); diff --git a/sys/dev/pci/agp.c b/sys/dev/pci/agp.c index d25985899655..4aa397b2655c 100644 --- a/sys/dev/pci/agp.c +++ b/sys/dev/pci/agp.c @@ -1,4 +1,4 @@ -/* $NetBSD: agp.c,v 1.4 2001/09/14 12:09:14 drochner Exp $ */ +/* $NetBSD: agp.c,v 1.5 2001/09/15 00:24:59 thorpej Exp $ */ /*- * Copyright (c) 2000 Doug Rabson @@ -106,30 +106,93 @@ static int agp_bind_user(struct agp_softc *, agp_bind *); static int agp_unbind_user(struct agp_softc *, agp_unbind *); static int agpdev_match(struct pci_attach_args *); +const struct agp_product { + uint32_t ap_vendor; + uint32_t ap_product; + int (*ap_match)(const struct pci_attach_args *); + int (*ap_attach)(struct device *, struct device *, void *); +} agp_products[] = { + { PCI_VENDOR_ALI, -1, + NULL, agp_ali_attach }, + + { PCI_VENDOR_AMD, -1, + agp_amd_match, agp_amd_attach }, + + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82810_MCH, + NULL, agp_i810_attach }, + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82810_DC100_MCH, + NULL, agp_i810_attach }, + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82810E_MCH, + NULL, agp_i810_attach }, + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82815_FULL_HUB, + NULL, agp_i810_attach }, + + { PCI_VENDOR_INTEL, -1, + NULL, agp_intel_attach }, + + { PCI_VENDOR_SIS, -1, + NULL, agp_sis_attach }, + + { PCI_VENDOR_VIATECH, -1, + NULL, agp_via_attach }, + + { 0, 0, + NULL, NULL }, +}; + +static const struct agp_product * +agp_lookup(const struct pci_attach_args *pa) +{ + const struct agp_product *ap; + + /* First find the vendor. */ + for (ap = agp_products; ap->ap_attach != NULL; ap++) { + if (PCI_VENDOR(pa->pa_id) == ap->ap_vendor) + break; + } + + if (ap->ap_attach == NULL) + return (NULL); + + /* Now find the product within the vendor's domain. */ + for (; ap->ap_attach != NULL; ap++) { + if (PCI_VENDOR(pa->pa_id) != ap->ap_vendor) { + /* Ran out of this vendor's section of the table. */ + return (NULL); + } + if (ap->ap_product == PCI_PRODUCT(pa->pa_id)) { + /* Exact match. */ + break; + } + if (ap->ap_product == (uint32_t) -1) { + /* Wildcard match. */ + break; + } + } + + if (ap->ap_attach == NULL) + return (NULL); + + /* Now let the product-specific driver filter the match. */ + if (ap->ap_match != NULL && (*ap->ap_match)(pa) == 0) + return (NULL); + + return (ap); +} + int agpmatch(struct device *parent, struct cfdata *match, void *aux) { - struct agp_phcb_attach_args *apa = aux; + struct agpbus_attach_args *apa = aux; struct pci_attach_args *pa = &apa->apa_pci_args; - switch (PCI_VENDOR(pa->pa_id)) { - case PCI_VENDOR_ALI: - return agp_ali_match(parent, match, pa); - case PCI_VENDOR_AMD: - return agp_amd_match(parent, match, pa); - case PCI_VENDOR_INTEL: - if (agp_i810_bridgematch(pa)) - return agp_i810_match(parent, match, pa); - return agp_intel_match(parent, match, pa); - case PCI_VENDOR_SIS: - return agp_sis_match(parent, match, pa); - case PCI_VENDOR_VIATECH: - return agp_via_match(parent, match, pa); - default: - return 0; - } + if (strcmp(apa->apa_busname, "agp") != 0) + return (0); - return (0); + if (agp_lookup(pa) == NULL) + return (0); + + return (1); } static int agp_max[][2] = { @@ -148,11 +211,17 @@ static int agp_max[][2] = { void agpattach(struct device *parent, struct device *self, void *aux) { - struct agp_phcb_attach_args *apa = aux; + struct agpbus_attach_args *apa = aux; struct pci_attach_args *pa = &apa->apa_pci_args; struct agp_softc *sc = (void *)self; + const struct agp_product *ap; int memsize, i, ret; + ap = agp_lookup(pa); + if (ap == NULL) { + printf("\n"); + panic("agpattach: impossible"); + } sc->as_dmat = pa->pa_dmat; sc->as_pc = pa->pa_pc; @@ -180,28 +249,7 @@ agpattach(struct device *parent, struct device *self, void *aux) TAILQ_INIT(&sc->as_memory); - switch (PCI_VENDOR(pa->pa_id)) { - case PCI_VENDOR_ALI: - ret = agp_ali_attach(parent, self, pa); - break; - case PCI_VENDOR_AMD: - ret = agp_amd_attach(parent, self, pa); - break; - case PCI_VENDOR_INTEL: - if (agp_i810_bridgematch(pa)) - ret = agp_i810_attach(parent, self, pa); - else - ret = agp_intel_attach(parent, self, pa); - break; - case PCI_VENDOR_SIS: - ret = agp_sis_attach(parent, self, pa); - break; - case PCI_VENDOR_VIATECH: - ret = agp_via_attach(parent, self, pa); - break; - default: - panic("agpattach: bad chipset detection"); - } + ret = (*ap->ap_attach)(parent, self, pa); if (ret == 0) printf(": aperture at 0x%lx, size 0x%lx\n", (unsigned long)sc->as_apaddr, diff --git a/sys/dev/pci/agp_ali.c b/sys/dev/pci/agp_ali.c index 2b6f87724338..195889ac203b 100644 --- a/sys/dev/pci/agp_ali.c +++ b/sys/dev/pci/agp_ali.c @@ -1,4 +1,4 @@ -/* $NetBSD: agp_ali.c,v 1.1 2001/09/10 10:01:01 fvdl Exp $ */ +/* $NetBSD: agp_ali.c,v 1.2 2001/09/15 00:25:00 thorpej Exp $ */ /*- * Copyright (c) 2000 Doug Rabson @@ -73,18 +73,6 @@ struct agp_methods agp_ali_methods = { agp_generic_unbind_memory, }; -int -agp_ali_match(struct device *parent, struct cfdata *match, void *aux) -{ - struct pci_attach_args *pa = aux; - - if (pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_AGP, NULL, NULL) - == 0) - return 0; - - return 1; -} - int agp_ali_attach(struct device *parent, struct device *self, void *aux) { diff --git a/sys/dev/pci/agp_amd.c b/sys/dev/pci/agp_amd.c index ce5ecec6d401..90013725b8cc 100644 --- a/sys/dev/pci/agp_amd.c +++ b/sys/dev/pci/agp_amd.c @@ -1,4 +1,4 @@ -/* $NetBSD: agp_amd.c,v 1.1 2001/09/10 10:01:01 fvdl Exp $ */ +/* $NetBSD: agp_amd.c,v 1.2 2001/09/15 00:25:00 thorpej Exp $ */ /*- * Copyright (c) 2000 Doug Rabson @@ -149,13 +149,8 @@ agp_amd_free_gatt(struct agp_softc *sc, struct agp_amd_gatt *gatt) #endif int -agp_amd_match(struct device *parent, struct cfdata *match, void *aux) +agp_amd_match(const struct pci_attach_args *pa) { - struct pci_attach_args *pa = aux; - - if (pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_AGP, NULL, NULL) - == 0) - return 0; switch (PCI_PRODUCT(pa->pa_id)) { case PCI_PRODUCT_AMD_SC751_SC: diff --git a/sys/dev/pci/agp_i810.c b/sys/dev/pci/agp_i810.c index 15b6d7c05e9b..7cdb0aaae653 100644 --- a/sys/dev/pci/agp_i810.c +++ b/sys/dev/pci/agp_i810.c @@ -1,4 +1,4 @@ -/* $NetBSD: agp_i810.c,v 1.5 2001/09/14 12:05:03 drochner Exp $ */ +/* $NetBSD: agp_i810.c,v 1.6 2001/09/15 00:25:00 thorpej Exp $ */ /*- * Copyright (c) 2000 Doug Rabson @@ -87,65 +87,24 @@ struct agp_methods agp_i810_methods = { agp_i810_unbind_memory, }; +/* XXXthorpej -- duplicated code (see arch/i386/pci/pchb.c) */ static int agp_i810_vgamatch(struct pci_attach_args *pa) { + if (PCI_CLASS(pa->pa_class) != PCI_CLASS_DISPLAY || PCI_SUBCLASS(pa->pa_class) != PCI_SUBCLASS_DISPLAY_VGA) - return 0; + return (0); + switch (PCI_PRODUCT(pa->pa_id)) { case PCI_PRODUCT_INTEL_82810_GC: case PCI_PRODUCT_INTEL_82810_DC100_GC: case PCI_PRODUCT_INTEL_82810E_GC: case PCI_PRODUCT_INTEL_82815_FULL_GRAPH: - return 1; - }; - - return 0; -} - -/* - * Find bridge device. - */ -int -agp_i810_bridgematch(struct pci_attach_args *pa) -{ - switch (PCI_PRODUCT(pa->pa_id)) { - case PCI_PRODUCT_INTEL_82810_MCH: - case PCI_PRODUCT_INTEL_82810_DC100_MCH: - case PCI_PRODUCT_INTEL_82810E_MCH: - case PCI_PRODUCT_INTEL_82815_FULL_HUB: - return 1; + return (1); } - return 0; -} - -int -agp_i810_match(struct device *parent, struct cfdata *match, void *aux) -{ - struct pci_attach_args vga_pa, *pa = aux; - pcireg_t ramreg; - - if (agp_i810_bridgematch(pa) == 0) - return 0; - /* - * XXXXfvdl - * this relies on the 'memory hub' and the VGA controller - * being on the same bus, which is bad. Fortunately, we - * know this to be the case with the i810. - * - * Could just have the attach fail later, leave as_chipc NULL - * and fail any open() call. - */ - if (pci_find_device(&vga_pa, agp_i810_vgamatch) == 0) - return 0; - - ramreg = pci_conf_read(pa->pa_pc, pa->pa_tag, AGP_I810_SMRAM); - if ((ramreg & 0xff) == 0) - return 0; - - return 1; + return (0); } int diff --git a/sys/dev/pci/agp_intel.c b/sys/dev/pci/agp_intel.c index b49f236d54e0..321056c7fda9 100644 --- a/sys/dev/pci/agp_intel.c +++ b/sys/dev/pci/agp_intel.c @@ -1,4 +1,4 @@ -/* $NetBSD: agp_intel.c,v 1.2 2001/09/11 06:30:38 fvdl Exp $ */ +/* $NetBSD: agp_intel.c,v 1.3 2001/09/15 00:25:00 thorpej Exp $ */ /*- * Copyright (c) 2000 Doug Rabson @@ -71,19 +71,6 @@ struct agp_methods agp_intel_methods = { agp_generic_unbind_memory, }; - -int -agp_intel_match(struct device *parent, struct cfdata *match, void *aux) -{ - struct pci_attach_args *pa = aux; - - if (pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_AGP, NULL, NULL) - == 0) - return 0; - - return 1; -} - int agp_intel_attach(struct device *parent, struct device *self, void *aux) { diff --git a/sys/dev/pci/agp_sis.c b/sys/dev/pci/agp_sis.c index a5a2033357f5..fa1e7d4a33c7 100644 --- a/sys/dev/pci/agp_sis.c +++ b/sys/dev/pci/agp_sis.c @@ -1,4 +1,4 @@ -/* $NetBSD: agp_sis.c,v 1.1 2001/09/10 10:01:02 fvdl Exp $ */ +/* $NetBSD: agp_sis.c,v 1.2 2001/09/15 00:25:00 thorpej Exp $ */ /*- * Copyright (c) 2000 Doug Rabson @@ -71,19 +71,6 @@ struct agp_methods agp_sis_methods = { agp_generic_unbind_memory, }; - -int -agp_sis_match(struct device *parent, struct cfdata *match, void *aux) -{ - struct pci_attach_args *pa = aux; - - if (pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_AGP, NULL, NULL) - == 0) - return 0; - - return 1; -} - int agp_sis_attach(struct device *parent, struct device *self, void *aux) { diff --git a/sys/dev/pci/agp_via.c b/sys/dev/pci/agp_via.c index 1cf8187f3bdb..84d051c12939 100644 --- a/sys/dev/pci/agp_via.c +++ b/sys/dev/pci/agp_via.c @@ -1,4 +1,4 @@ -/* $NetBSD: agp_via.c,v 1.1 2001/09/10 10:01:02 fvdl Exp $ */ +/* $NetBSD: agp_via.c,v 1.2 2001/09/15 00:25:00 thorpej Exp $ */ /*- * Copyright (c) 2000 Doug Rabson @@ -71,18 +71,6 @@ struct agp_via_softc { struct agp_gatt *gatt; }; -int -agp_via_match(struct device *parent, struct cfdata *match, void *aux) -{ - struct pci_attach_args *pa = aux; - - if (pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_AGP, NULL, NULL) - == 0) - return 0; - - return 1; -} - int agp_via_attach(struct device *parent, struct device *self, void *aux) { diff --git a/sys/dev/pci/agpvar.h b/sys/dev/pci/agpvar.h index 0fa970a12ade..538afc2bf781 100644 --- a/sys/dev/pci/agpvar.h +++ b/sys/dev/pci/agpvar.h @@ -1,4 +1,4 @@ -/* $NetBSD: agpvar.h,v 1.2 2001/09/11 06:51:47 fvdl Exp $ */ +/* $NetBSD: agpvar.h,v 1.3 2001/09/15 00:25:00 thorpej Exp $ */ /*- * Copyright (c) 2000 Doug Rabson @@ -33,8 +33,8 @@ #include -struct agp_phcb_attach_args { - char *apa_busname; /* XXX layout compat with pcibus_attach_args */ +struct agpbus_attach_args { + char *apa_busname; struct pci_attach_args apa_pci_args; }; @@ -182,13 +182,7 @@ int agp_generic_bind_memory(struct agp_softc *sc, struct agp_memory *mem, int agp_generic_unbind_memory(struct agp_softc *sc, struct agp_memory *mem); /* The vendor has already been matched when these functions are called */ -int agp_ali_match(struct device *, struct cfdata *, void *); -int agp_amd_match(struct device *, struct cfdata *, void *); -int agp_i810_match(struct device *, struct cfdata *, void *); -int agp_i810_bridgematch(struct pci_attach_args *); -int agp_intel_match(struct device *, struct cfdata *, void *); -int agp_sis_match(struct device *, struct cfdata *, void *); -int agp_via_match(struct device *, struct cfdata *, void *); +int agp_amd_match(const struct pci_attach_args *); int agp_ali_attach(struct device *parent, struct device *self, void *aux); int agp_amd_attach(struct device *parent, struct device *self, void *aux);