Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/pci Implement Intel AGP chipset flush.



details:   https://anonhg.NetBSD.org/src/rev/c563017151a7
branches:  trunk
changeset: 796193:c563017151a7
user:      riastradh <riastradh%NetBSD.org@localhost>
date:      Fri May 23 22:58:56 2014 +0000

description:
Implement Intel AGP chipset flush.

While here, fix the use of the I915 PCI MSAC register: it lies on the
bridge device (bus 0 dev 0 func 0), not the graphics device (bus 0
dev 2 func 0).  I'm not sure we ever need to consult this register,
really -- the PCI BARs should be sized.  But I'll leave a rototill of
this mess for another day.

diffstat:

 sys/dev/pci/agp_i810.c    |  149 +++++++++++++++++++++++++++++++++++++++++++++-
 sys/dev/pci/agp_i810var.h |    7 +-
 sys/dev/pci/agpreg.h      |   19 ++++-
 3 files changed, 168 insertions(+), 7 deletions(-)

diffs (286 lines):

diff -r 767f18e0cc2e -r c563017151a7 sys/dev/pci/agp_i810.c
--- a/sys/dev/pci/agp_i810.c    Fri May 23 22:04:09 2014 +0000
+++ b/sys/dev/pci/agp_i810.c    Fri May 23 22:58:56 2014 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: agp_i810.c,v 1.74 2014/03/18 18:20:41 riastradh Exp $  */
+/*     $NetBSD: agp_i810.c,v 1.75 2014/05/23 22:58: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.74 2014/03/18 18:20:41 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: agp_i810.c,v 1.75 2014/05/23 22:58:56 riastradh Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -39,6 +39,7 @@
 #include <sys/proc.h>
 #include <sys/device.h>
 #include <sys/conf.h>
+#include <sys/xcall.h>
 
 #include <dev/pci/pcivar.h>
 #include <dev/pci/pcireg.h>
@@ -86,6 +87,7 @@
 static bool agp_i810_resume(device_t, const pmf_qual_t *);
 static int agp_i810_init(struct agp_softc *);
 
+static int agp_i810_setup_chipset_flush_page(struct agp_softc *);
 static int agp_i810_init(struct agp_softc *);
 
 static struct agp_methods agp_i810_methods = {
@@ -184,6 +186,40 @@
        (void)READ4(base_off + wroff);
 }
 
+static void
+agp_flush_cache_xc(void *a __unused, void *b __unused)
+{
+
+       agp_flush_cache();
+}
+
+void
+agp_i810_chipset_flush(struct agp_i810_softc *isc)
+{
+       unsigned int timo = 20000; /* * 50 us = 1 s */
+
+       switch (isc->chiptype) {
+       case CHIP_I810:
+               break;
+       case CHIP_I830:
+       case CHIP_I855:
+               xc_wait(xc_broadcast(0, &agp_flush_cache_xc, NULL, NULL));
+               WRITE4(AGP_I830_HIC, READ4(AGP_I830_HIC) | __BIT(31));
+               while (ISSET(READ4(AGP_I830_HIC), __BIT(31))) {
+                       if (timo-- == 0)
+                               break;
+                       DELAY(50);
+               }
+               break;
+       case CHIP_I915:
+       case CHIP_I965:
+       case CHIP_G33:
+       case CHIP_G4X:
+               bus_space_write_4(isc->flush_bst, isc->flush_bsh, 0, 1);
+               break;
+       }
+}
+
 /* XXXthorpej -- duplicated code (see arch/x86/pci/pchb.c) */
 static int
 agp_i810_vgamatch(const struct pci_attach_args *pa)
@@ -441,9 +477,88 @@
        agp_i810_vga_regbase = mmadr;
        agp_i810_vga_bsh = isc->bsh;
 
+       /* 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,
+                           "failed to set up chipset flush page: %d\n",
+                           error);
+                       agp_generic_detach(sc);
+                       return error;
+               }
+               break;
+       }
+
        return agp_i810_init(sc);
 }
 
+static int
+agp_i810_setup_chipset_flush_page(struct agp_softc *sc)
+{
+       struct agp_i810_softc *const isc = sc->as_chipc;
+       pcireg_t reg, lo, hi;
+       bus_addr_t addr, minaddr, maxaddr;
+       int error;
+
+       /* We always use memory-mapped I/O.  */
+       isc->flush_bst = isc->vga_pa.pa_memt;
+
+       /* No page allocated yet.  */
+       isc->flush_addr = 0;
+
+       /* Read the PCI config register: 4-byte on gen3, 8-byte on gen>=4.  */
+       if (isc->chiptype == CHIP_I915) {
+               reg = pci_conf_read(sc->as_pc, sc->as_tag, AGP_I915_IFPADDR);
+               addr = reg;
+               minaddr = PAGE_SIZE;    /* XXX PCIBIOS_MIN_MEM?  */
+               maxaddr = UINT32_MAX;
+       } else {
+               hi = pci_conf_read(sc->as_pc, sc->as_tag, AGP_I965_IFPADDR+4);
+               lo = pci_conf_read(sc->as_pc, sc->as_tag, AGP_I965_IFPADDR);
+               addr = ((bus_addr_t)hi << 32) | lo;
+               minaddr = PAGE_SIZE;    /* XXX PCIBIOS_MIN_MEM?  */
+               maxaddr = UINT64_MAX;
+       }
+
+       /* Allocate or map a pre-allocated a page for it.  */
+       if (ISSET(addr, 1)) {
+               /* BIOS allocated it for us.  Use that.  */
+               error = bus_space_map(isc->flush_bst, addr & ~1, PAGE_SIZE, 0,
+                   &isc->flush_bsh);
+               if (error)
+                       return error;
+       } else {
+               /* None allocated.  Allocate one.  */
+               error = bus_space_alloc(isc->flush_bst, minaddr, maxaddr,
+                   PAGE_SIZE, PAGE_SIZE, 0, 0,
+                   &isc->flush_addr, &isc->flush_bsh);
+               if (error)
+                       return error;
+               KASSERT(isc->flush_addr != 0);
+               /* Write it into the PCI config register.  */
+               addr = isc->flush_addr | 1;
+               if (isc->chiptype == CHIP_I915) {
+                       pci_conf_write(sc->as_pc, sc->as_tag, AGP_I915_IFPADDR,
+                           addr);
+               } else {
+                       pci_conf_write(sc->as_pc, sc->as_tag,
+                           AGP_I965_IFPADDR + 4,
+                           __SHIFTOUT(addr, __BITS(63, 32)));
+                       pci_conf_write(sc->as_pc, sc->as_tag,
+                           AGP_I965_IFPADDR,
+                           __SHIFTOUT(addr, __BITS(31, 0)));
+               }
+       }
+
+       /* Success!  */
+       return 0;
+}
+
 /*
  * XXX horrible hack to allow drm code to use our mapping
  * of VGA chip registers
@@ -713,6 +828,33 @@
        if (error)
                return error;
 
+       switch (isc->chiptype) {
+       case CHIP_I915:
+       case CHIP_I965:
+       case CHIP_G33:
+       case CHIP_G4X:
+               if (isc->flush_addr) {
+                       /* If we allocated a page, clear it.  */
+                       if (isc->chiptype == CHIP_I915) {
+                               pci_conf_write(sc->as_pc, sc->as_tag,
+                                   AGP_I915_IFPADDR, 0);
+                       } else {
+                               pci_conf_write(sc->as_pc, sc->as_tag,
+                                   AGP_I915_IFPADDR, 0);
+                               pci_conf_write(sc->as_pc, sc->as_tag,
+                                   AGP_I915_IFPADDR + 4, 0);
+                       }
+                       isc->flush_addr = 0;
+                       bus_space_free(isc->flush_bst, isc->flush_bsh,
+                           PAGE_SIZE);
+               } else {
+                       /* Otherwise, just unmap the pre-allocated page.  */
+                       bus_space_unmap(isc->flush_bst, isc->flush_bsh,
+                           PAGE_SIZE);
+               }
+               break;
+       }
+
        /* Clear the GATT base. */
        if (sc->chiptype == CHIP_I810) {
                WRITE4(AGP_I810_PGTBL_CTL, 0);
@@ -770,7 +912,8 @@
        case CHIP_I915:
        case CHIP_G33:
        case CHIP_G4X:
-               reg = pci_conf_read(sc->as_pc, sc->as_tag, AGP_I915_MSAC);
+               reg = pci_conf_read(isc->vga_pa.pa_pc, isc->vga_pa.pa_tag,
+                   AGP_I915_MSAC);
                msac = (u_int16_t)(reg >> 16);
                if (msac & AGP_I915_MSAC_APER_128M)
                        size = 128 * 1024 * 1024;
diff -r 767f18e0cc2e -r c563017151a7 sys/dev/pci/agp_i810var.h
--- a/sys/dev/pci/agp_i810var.h Fri May 23 22:04:09 2014 +0000
+++ b/sys/dev/pci/agp_i810var.h Fri May 23 22:58:56 2014 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: agp_i810var.h,v 1.2 2014/03/18 18:20:41 riastradh Exp $        */
+/*     $NetBSD: agp_i810var.h,v 1.3 2014/05/23 22:58:56 riastradh Exp $        */
 
 /*-
  * Copyright (c) 2000 Doug Rabson
@@ -48,9 +48,14 @@
        struct pci_attach_args vga_pa;
 
        u_int32_t pgtblctl;
+
+       bus_space_tag_t flush_bst;      /* flush page bus_space tag */
+       bus_space_handle_t flush_bsh;   /* flush page bus_space handle */
+       bus_addr_t flush_addr;          /* flush page bus address */
 };
 
 extern struct agp_softc        *agp_i810_sc;
 
 int    agp_i810_write_gtt_entry(struct agp_i810_softc *, off_t, bus_addr_t);
 void   agp_i810_post_gtt_entry(struct agp_i810_softc *, off_t);
+void   agp_i810_chipset_flush(struct agp_i810_softc *);
diff -r 767f18e0cc2e -r c563017151a7 sys/dev/pci/agpreg.h
--- a/sys/dev/pci/agpreg.h      Fri May 23 22:04:09 2014 +0000
+++ b/sys/dev/pci/agpreg.h      Fri May 23 22:58:56 2014 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: agpreg.h,v 1.20 2008/11/29 23:48:12 christos Exp $     */
+/*     $NetBSD: agpreg.h,v 1.21 2014/05/23 22:58:56 riastradh Exp $    */
 
 /*-
  * Copyright (c) 2000 Doug Rabson
@@ -206,6 +206,10 @@
 #define AGP_I830_GCC1_GMASIZE_64       0x01
 #define AGP_I830_GCC1_GMASIZE_128      0x00
 
+/*
+ * Memory mapped register offsets for i830 chipset.
+ */
+#define        AGP_I830_HIC                    0x70
 
 /*
  * Config registers for 852GM/855GM/865G device 0
@@ -228,6 +232,12 @@
 #define AGP_I915_MMADR                 0x10
 #define AGP_I915_GMADR                 0x18
 #define AGP_I915_GTTADR                        0x1c
+#define AGP_I915_MSAC                  0x60 /* upper word */
+#define AGP_I915_MSAC_APER_128M                0x02
+
+/*
+ * Config registers for 915G/915GM device 0
+ */
 #define AGP_I915_GCC1                  0x52
 #define AGP_I915_GCC1_GMS              0x70
 #define AGP_I915_GCC1_GMS_STOLEN_0M    0x00
@@ -237,8 +247,7 @@
 #define AGP_I915_GCC1_GMS_STOLEN_32M   0x50
 #define AGP_I915_GCC1_GMS_STOLEN_48M   0x60
 #define AGP_I915_GCC1_GMS_STOLEN_64M   0x70
-#define AGP_I915_MSAC                  0x60 /* upper word */
-#define AGP_I915_MSAC_APER_128M                0x02
+#define AGP_I915_IFPADDR               0x60
 
 /*
  * Config registers for 965G/965Q
@@ -252,6 +261,10 @@
 #define AGP_I965_PGTBL_SIZE_2MB                (4 << 1)
 #define AGP_I965_PGTBL_SIZE_1_5MB      (5 << 1)
 
+/*
+ * Config registers for 965G/965Q device 0
+ */
+#define AGP_I965_IFPADDR               0x70
 
 /*
  * Config registers for G33



Home | Main Index | Thread Index | Old Index