Module Name: src Committed By: riastradh Date: Tue Jun 10 14:00:56 UTC 2014
Modified Files: src/sys/dev/pci: agp_i810.c agp_i810var.h Log Message: Another round of weed-whacking for agp_i810. - Make struct agp_i810_softc::gatt specific to i810 chipsets; use other members of struct agp_i810_softc for non-i810 chipsets. - agp_i810_init detects and sets isc->gtt_size. - Map GTT based on the GTT size detected by agp_i810_init. - Sprinkle some comments particularly about questionable calculations. To generate a diff of this commit: cvs rdiff -u -r1.84 -r1.85 src/sys/dev/pci/agp_i810.c cvs rdiff -u -r1.4 -r1.5 src/sys/dev/pci/agp_i810var.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/pci/agp_i810.c diff -u src/sys/dev/pci/agp_i810.c:1.84 src/sys/dev/pci/agp_i810.c:1.85 --- src/sys/dev/pci/agp_i810.c:1.84 Wed May 28 16:07:58 2014 +++ src/sys/dev/pci/agp_i810.c Tue Jun 10 14:00:56 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: agp_i810.c,v 1.84 2014/05/28 16:07:58 riastradh Exp $ */ +/* $NetBSD: agp_i810.c,v 1.85 2014/06/10 14:00:56 riastradh Exp $ */ /*- * Copyright (c) 2000 Doug Rabson @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: agp_i810.c,v 1.84 2014/05/28 16:07:58 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: agp_i810.c,v 1.85 2014/06/10 14:00:56 riastradh Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -272,7 +272,6 @@ agp_i810_attach(device_t parent, device_ { struct agp_softc *sc = device_private(self); struct agp_i810_softc *isc; - struct agp_gatt *gatt; int apbase, mmadr_bar, gtt_bar; int mmadr_type, mmadr_flags; bus_addr_t mmadr, gtt_off; @@ -448,18 +447,54 @@ agp_i810_attach(device_t parent, device_ goto fail1; } + /* Set up a chipset flush page if necessary. */ + switch (isc->chiptype) { + case CHIP_I915: + case CHIP_I965: + case CHIP_G33: + case CHIP_G4X: + error = agp_i810_setup_chipset_flush_page(sc); + if (error) { + aprint_error_dev(self, + "can't set up chipset flush page: %d\n", error); + goto fail2; + } + break; + } + + /* + * XXX horrible hack to allow drm code to use our mapping + * of VGA chip registers + */ + agp_i810_vga_regbase = mmadr; + agp_i810_vga_bsh = isc->bsh; + + /* Initialize the chipset. */ + error = agp_i810_init(sc); + if (error) + goto fail3; + /* Map the GTT, from either part of the MMIO region or its own BAR. */ if (gtt_bar == 0) { isc->gtt_bst = isc->bst; - isc->gtt_size = (mmadr_size - gtt_off); + if (isc->gtt_size < (mmadr_size - gtt_off)) { + aprint_error_dev(self, "GTTMMADR too small for GTT" + ": %"PRIxMAX" < (%"PRIxMAX" - %"PRIxMAX")\n", + (uintmax_t)isc->gtt_size, + (uintmax_t)mmadr_size, + (uintmax_t)gtt_off); + error = ENXIO; + goto fail4; + } error = bus_space_map(isc->gtt_bst, (mmadr + gtt_off), isc->gtt_size, mmadr_flags, &isc->gtt_bsh); if (error) { aprint_error_dev(self, "can't map GTT: %d\n", error); error = ENXIO; - goto fail2; + goto fail4; } } else { + bus_size_t gtt_bar_size; /* * All chipsets with a separate BAR for the GTT, namely * the i915 and G33 families, have 32-bit GTT BARs. @@ -468,68 +503,41 @@ agp_i810_attach(device_t parent, device_ */ if (pci_mapreg_map(&isc->vga_pa, gtt_bar, PCI_MAPREG_TYPE_MEM, 0, - &isc->gtt_bst, &isc->gtt_bsh, NULL, &isc->gtt_size)) { + &isc->gtt_bst, &isc->gtt_bsh, NULL, >t_bar_size)) { aprint_error_dev(self, "can't map GTT\n"); error = ENXIO; - goto fail2; + goto fail4; } - } - - /* Set up a chipset flush page if necessary. */ - switch (isc->chiptype) { - case CHIP_I915: - case CHIP_I965: - case CHIP_G33: - case CHIP_G4X: - error = agp_i810_setup_chipset_flush_page(sc); - if (error) { + if (gtt_bar_size != isc->gtt_size) { aprint_error_dev(self, - "can't set up chipset flush page: %d\n", error); - goto fail3; + "BAR size %"PRIxMAX + " mismatches detected GTT size %"PRIxMAX + "; trusting BAR\n", + (uintmax_t)gtt_bar_size, + (uintmax_t)isc->gtt_size); + isc->gtt_size = gtt_bar_size; } - break; } - /* Set up the generic AGP GATT record. */ - isc->initial_aperture = AGP_GET_APERTURE(sc); - gatt = malloc(sizeof(struct agp_gatt), M_AGP, M_NOWAIT); - if (!gatt) { - error = ENOMEM; - goto fail4; - } - isc->gatt = gatt; - gatt->ag_entries = AGP_GET_APERTURE(sc) >> AGP_PAGE_SHIFT; - /* Power management. (XXX Nothing to save on suspend? Fishy...) */ if (!pmf_device_register(self, NULL, agp_i810_resume)) aprint_error_dev(self, "can't establish power handler\n"); - /* - * XXX horrible hack to allow drm code to use our mapping - * of VGA chip registers - */ - agp_i810_vga_regbase = mmadr; - agp_i810_vga_bsh = isc->bsh; - - /* Initialize the chipset. */ - error = agp_i810_init(sc); - if (error) - goto fail5; - /* Match the generic AGP code's autoconf output format. */ aprint_normal("%s", device_xname(self)); /* Success! */ return 0; +fail5: __unused + pmf_device_deregister(self); + bus_space_unmap(isc->gtt_bst, isc->gtt_bsh, isc->gtt_size); + isc->gtt_size = 0; +fail4: #if notyet -fail6: __unused agp_i810_fini(sc); #endif -fail5: pmf_device_deregister(self); - free(gatt, M_AGP); - isc->gatt = NULL; -fail4: switch (isc->chiptype) { +fail3: switch (isc->chiptype) { case CHIP_I915: case CHIP_I965: case CHIP_G33: @@ -537,8 +545,6 @@ fail4: switch (isc->chiptype) { agp_i810_teardown_chipset_flush_page(sc); break; } -fail3: bus_space_unmap(isc->gtt_bst, isc->gtt_bsh, isc->gtt_size); - isc->gtt_size = 0; fail2: bus_space_unmap(isc->bst, isc->bsh, isc->size); isc->size = 0; fail1: free(isc, M_AGP); @@ -667,13 +673,12 @@ static int agp_i810_init(struct agp_softc *sc) { struct agp_i810_softc *isc; - struct agp_gatt *gatt; int error; isc = sc->as_chipc; - gatt = isc->gatt; if (isc->chiptype == CHIP_I810) { + struct agp_gatt *gatt; void *virtual; int dummyseg; @@ -684,28 +689,42 @@ agp_i810_init(struct agp_softc *sc) isc->dcache_size = 0; /* According to the specs the gatt on the i810 must be 64k */ - error = agp_alloc_dmamem(sc->as_dmat, 64 * 1024, + isc->gtt_size = 64 * 1024; + gatt = malloc(sizeof(*gatt), M_AGP, M_NOWAIT); + if (gatt == NULL) { + aprint_error_dev(sc->as_dev, + "can't malloc GATT record\n"); + error = ENOMEM; + goto fail0; + } + gatt->ag_entries = isc->gtt_size / sizeof(uint32_t); + error = agp_alloc_dmamem(sc->as_dmat, isc->gtt_size, 0, &gatt->ag_dmamap, &virtual, &gatt->ag_physical, &gatt->ag_dmaseg, 1, &dummyseg); if (error) { aprint_error_dev(sc->as_dev, "can't allocate memory for GTT: %d\n", error); + free(gatt, M_AGP); goto fail0; } gatt->ag_virtual = (uint32_t *)virtual; - gatt->ag_size = gatt->ag_entries * sizeof(u_int32_t); + gatt->ag_size = gatt->ag_entries * sizeof(uint32_t); memset(gatt->ag_virtual, 0, gatt->ag_size); - agp_flush_cache(); + /* Install the GATT. */ - WRITE4(AGP_I810_PGTBL_CTL, gatt->ag_physical | 1); + isc->pgtblctl = gatt->ag_physical | 1; + WRITE4(AGP_I810_PGTBL_CTL, isc->pgtblctl); + isc->gatt = gatt; } else if (isc->chiptype == CHIP_I830) { /* The i830 automatically initializes the 128k gatt on boot. */ + /* XXX [citation needed] */ pcireg_t reg; - u_int32_t pgtblctl; u_int16_t gcc1; + isc->gtt_size = 128 * 1024; + reg = pci_conf_read(sc->as_pc, sc->as_tag, AGP_I830_GCC0); gcc1 = (u_int16_t)(reg >> 16); switch (gcc1 & AGP_I830_GCC1_GMS) { @@ -733,22 +752,20 @@ agp_i810_init(struct agp_softc *sc) } /* GATT address is already in there, make sure it's enabled */ - pgtblctl = READ4(AGP_I810_PGTBL_CTL); - pgtblctl |= 1; - WRITE4(AGP_I810_PGTBL_CTL, pgtblctl); - - gatt->ag_physical = pgtblctl & ~1; + isc->pgtblctl = READ4(AGP_I810_PGTBL_CTL); + isc->pgtblctl |= 1; + WRITE4(AGP_I810_PGTBL_CTL, isc->pgtblctl); } else if (isc->chiptype == CHIP_I855 || isc->chiptype == CHIP_I915 || isc->chiptype == CHIP_I965 || isc->chiptype == CHIP_G33 || isc->chiptype == CHIP_G4X) { pcireg_t reg; - u_int32_t pgtblctl, gtt_size, stolen; + u_int32_t gtt_size, stolen; /* XXX kilobytes */ u_int16_t gcc1; reg = pci_conf_read(sc->as_pc, sc->as_tag, AGP_I855_GCC1); gcc1 = (u_int16_t)(reg >> 16); - pgtblctl = READ4(AGP_I810_PGTBL_CTL); + isc->pgtblctl = READ4(AGP_I810_PGTBL_CTL); /* Stolen memory is set up at the beginning of the aperture by * the BIOS, consisting of the GATT followed by 4kb for the @@ -762,7 +779,7 @@ agp_i810_init(struct agp_softc *sc) gtt_size = 256; break; case CHIP_I965: - switch (pgtblctl & AGP_I810_PGTBL_SIZE_MASK) { + switch (isc->pgtblctl & AGP_I810_PGTBL_SIZE_MASK) { case AGP_I810_PGTBL_SIZE_128KB: case AGP_I810_PGTBL_SIZE_512KB: gtt_size = 512; @@ -805,6 +822,10 @@ agp_i810_init(struct agp_softc *sc) panic("impossible chiptype %d", isc->chiptype); } + /* + * XXX If I'm reading the datasheets right, this stolen + * memory detection logic is totally wrong. + */ switch (gcc1 & AGP_I855_GCC1_GMS) { case AGP_I855_GCC1_GMS_STOLEN_1M: stolen = 1024; @@ -878,9 +899,13 @@ agp_i810_init(struct agp_softc *sc) break; } + isc->gtt_size = gtt_size * 1024; + /* BIOS space */ + /* XXX [citation needed] */ gtt_size += 4; + /* XXX [citation needed] for this subtraction */ isc->stolen = (stolen - gtt_size) * 1024 / 4096; if (isc->stolen > 0) { @@ -890,10 +915,8 @@ agp_i810_init(struct agp_softc *sc) } /* GATT address is already in there, make sure it's enabled */ - pgtblctl |= 1; - WRITE4(AGP_I810_PGTBL_CTL, pgtblctl); - - gatt->ag_physical = pgtblctl & ~1; + isc->pgtblctl |= 1; + WRITE4(AGP_I810_PGTBL_CTL, isc->pgtblctl); } /* @@ -947,14 +970,11 @@ agp_i810_detach(struct agp_softc *sc) WRITE4(AGP_I810_PGTBL_CTL, pgtblctl); } - /* Put the aperture back the way it started. */ - AGP_SET_APERTURE(sc, isc->initial_aperture); - if (sc->chiptype == CHIP_I810) { agp_free_dmamem(sc->as_dmat, gatt->ag_size, gatt->ag_dmamap, (void *)gatt->ag_virtual, &gatt->ag_dmaseg, 1); + free(isc->gatt, M_AGP); } - free(sc->gatt, M_AGP); return 0; } @@ -1087,11 +1107,11 @@ agp_i810_bind_page(struct agp_softc *sc, { struct agp_i810_softc *isc = sc->as_chipc; - if (offset < 0 || offset >= (isc->gatt->ag_entries << AGP_PAGE_SHIFT)) { + if (offset < 0 || offset >= ((isc->gtt_size/4) << AGP_PAGE_SHIFT)) { #ifdef AGP_DEBUG printf("%s: failed: offset 0x%08x, shift %d, entries %d\n", device_xname(sc->as_dev), (int)offset, AGP_PAGE_SHIFT, - isc->gatt->ag_entries); + isc->gtt_size/4); #endif return EINVAL; } @@ -1114,7 +1134,7 @@ agp_i810_unbind_page(struct agp_softc *s { struct agp_i810_softc *isc = sc->as_chipc; - if (offset < 0 || offset >= (isc->gatt->ag_entries << AGP_PAGE_SHIFT)) + if (offset < 0 || offset >= ((isc->gtt_size/4) << AGP_PAGE_SHIFT)) return EINVAL; if (isc->chiptype != CHIP_I810 ) { @@ -1253,11 +1273,11 @@ agp_i810_bind_memory(struct agp_softc *s * 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)) { + if (regval != isc->pgtblctl) { 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); + isc->pgtblctl); } if (mem->am_type == 2) { @@ -1317,10 +1337,9 @@ agp_i810_resume(device_t dv, const pmf_q struct agp_i810_softc *isc = sc->as_chipc; /* - * XXX Nothing uses isc->pgtblctl! Save on suspend, restore on - * resume? + * XXX Nothing uses this! Save on suspend, restore on resume? */ - isc->pgtblctl = READ4(AGP_I810_PGTBL_CTL); + isc->pgtblctl_resume_hack = READ4(AGP_I810_PGTBL_CTL); agp_flush_cache(); return true; Index: src/sys/dev/pci/agp_i810var.h diff -u src/sys/dev/pci/agp_i810var.h:1.4 src/sys/dev/pci/agp_i810var.h:1.5 --- src/sys/dev/pci/agp_i810var.h:1.4 Tue May 27 03:17:33 2014 +++ src/sys/dev/pci/agp_i810var.h Tue Jun 10 14:00:56 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: agp_i810var.h,v 1.4 2014/05/27 03:17:33 riastradh Exp $ */ +/* $NetBSD: agp_i810var.h,v 1.5 2014/06/10 14:00:56 riastradh Exp $ */ /*- * Copyright (c) 2000 Doug Rabson @@ -37,8 +37,9 @@ struct agp_i810_softc { struct pci_attach_args vga_pa; /* integrated graphics device args */ int chiptype; /* chipset family: i810, i830, &c. */ + uint32_t stolen; /* pages of stolen graphics memory */ - /* Memory-mapped I/O for device registers. */ + /* Memory-mapped I/O for integrated graphics device registers. */ bus_space_tag_t bst; bus_space_handle_t bsh; bus_size_t size; @@ -53,12 +54,15 @@ struct agp_i810_softc { bus_space_handle_t flush_bsh; bus_addr_t flush_addr; - uint32_t initial_aperture; /* aperture size at startup */ - struct agp_gatt *gatt; /* AGP graphics addr. trans. tbl. */ + /* i810-only fields. */ + struct agp_gatt *gatt; /* i810-only OS-allocated GTT */ uint32_t dcache_size; /* i810-only on-chip memory size */ - uint32_t stolen; /* num. GTT entries for stolen mem. */ - uint32_t pgtblctl; /* saved PGTBL_CTL? XXX unused */ + /* XXX Kludge to work around broken X servers. */ + pcireg_t pgtblctl; + + /* XXX Vestige of unfinished powerhook? */ + uint32_t pgtblctl_resume_hack; }; extern struct agp_softc *agp_i810_sc;