Setup MTRRs for frame buffer and aperture manually on Savage3D and
authorFelix Kuehling <fxkuehl@gmx.de>
Sat, 15 Jan 2005 16:55:01 +0000 (16:55 +0000)
committerFelix Kuehling <fxkuehl@gmx.de>
Sat, 15 Jan 2005 16:55:01 +0000 (16:55 +0000)
    Savage4-based cards. Automatic setup in drm_initmap doesn't work due to
    the weird alignment and size of the aperture.

linux-core/savage_drv.c
shared-core/savage_bci.c
shared-core/savage_drv.h

index fff5b68..ff15fb1 100644 (file)
@@ -76,6 +76,7 @@ static struct drm_driver driver = {
        .dev_priv_size = sizeof(drm_savage_buf_priv_t),
        .preinit = savage_preinit,
        .postinit = postinit,
+       .postcleanup = savage_postcleanup,
        .reclaim_buffers = savage_reclaim_buffers,
        .get_map_ofs = drm_core_get_map_ofs,
        .get_reg_ofs = drm_core_get_reg_ofs,
index 0f91cf7..4656a90 100644 (file)
@@ -283,10 +283,19 @@ void savage_freelist_put(drm_device_t *dev, drm_buf_t *buf)
        entry->next = next;
 }
 
+/*
+ * Initalize permanent mappings. On Savage4 and SavageIX the alignment
+ * and size of the aperture is not suitable for automatic MTRR setup
+ * in drm_initmap. Therefore we do it manually before the maps are
+ * initialized. We also need to take care of deleting the MTRRs in
+ * postcleanup.
+ *
+ * FIXME: this is linux-specific
+ */
 int savage_preinit(drm_device_t *dev, unsigned long chipset)
 {
        drm_savage_private_t *dev_priv;
-       unsigned int mmio_base, fb_base, fb_size, aperture_base;
+       unsigned long mmio_base, fb_base, fb_size, aperture_base;
        int ret = 0;
 
        dev_priv = drm_alloc(sizeof(drm_savage_private_t), DRM_MEM_DRIVER);
@@ -297,21 +306,61 @@ int savage_preinit(drm_device_t *dev, unsigned long chipset)
        dev->dev_private = (void *)dev_priv;
        dev_priv->chipset = (enum savage_family)chipset;
 
+       dev_priv->mtrr[0].handle = -1;
+       dev_priv->mtrr[1].handle = -1;
+       dev_priv->mtrr[2].handle = -1;
        if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
                fb_base = pci_resource_start(dev->pdev, 0);
                fb_size = SAVAGE_FB_SIZE_S3;
                mmio_base = fb_base + SAVAGE_FB_SIZE_S3;
                aperture_base = fb_base + SAVAGE_APERTURE_OFFSET;
+               /* this should always be true */
+               if (pci_resource_len(dev->pdev, 0) == 0x08000000) {
+                       /* Don't make MMIO write-cobining! We need 3
+                        * MTRRs. */
+                       dev_priv->mtrr[0].base = fb_base;
+                       dev_priv->mtrr[0].size = 0x01000000;
+                       dev_priv->mtrr[0].handle = mtrr_add(
+                               dev_priv->mtrr[0].base, dev_priv->mtrr[0].size,
+                               MTRR_TYPE_WRCOMB, 1);
+                       dev_priv->mtrr[1].base = fb_base+0x02000000;
+                       dev_priv->mtrr[1].size = 0x02000000;
+                       dev_priv->mtrr[1].handle = mtrr_add(
+                               dev_priv->mtrr[1].base, dev_priv->mtrr[1].size,
+                               MTRR_TYPE_WRCOMB, 1);
+                       dev_priv->mtrr[2].base = fb_base+0x04000000;
+                       dev_priv->mtrr[2].size = 0x04000000;
+                       dev_priv->mtrr[2].handle = mtrr_add(
+                               dev_priv->mtrr[2].base, dev_priv->mtrr[2].size,
+                               MTRR_TYPE_WRCOMB, 1);
+               } else {
+                       DRM_ERROR("strange pci_resource_len %08lx\n",
+                                 pci_resource_len(dev->pdev, 0));
+               }
        } else if (chipset != S3_SUPERSAVAGE && chipset != S3_SAVAGE2000) {
                mmio_base = pci_resource_start(dev->pdev, 0);
                fb_base = pci_resource_start(dev->pdev, 1);
                fb_size = SAVAGE_FB_SIZE_S4;
                aperture_base = fb_base + SAVAGE_APERTURE_OFFSET;
+               /* this should always be true */
+               if (pci_resource_len(dev->pdev, 1) == 0x08000000) {
+                       /* Can use one MTRR to cover both fb and
+                        * aperture. */
+                       dev_priv->mtrr[0].base = fb_base;
+                       dev_priv->mtrr[0].size = 0x08000000;
+                       dev_priv->mtrr[0].handle = mtrr_add(
+                               dev_priv->mtrr[0].base, dev_priv->mtrr[0].size,
+                               MTRR_TYPE_WRCOMB, 1);
+               } else {
+                       DRM_ERROR("strange pci_resource_len %08lx\n",
+                                 pci_resource_len(dev->pdev, 1));
+               }
        } else {
                mmio_base = pci_resource_start(dev->pdev, 0);
                fb_base = pci_resource_start(dev->pdev, 1);
                fb_size = pci_resource_len(dev->pdev, 1);
                aperture_base = pci_resource_start(dev->pdev, 2);
+               /* Automatic MTRR setup will do the right thing. */
        }
 
        if ((ret = drm_initmap(dev, mmio_base, SAVAGE_MMIO_SIZE,
@@ -335,6 +384,25 @@ int savage_preinit(drm_device_t *dev, unsigned long chipset)
        return ret;
 }
 
+/*
+ * Delete MTRRs and free device-private data.
+ */
+int savage_postcleanup(drm_device_t *dev)
+{
+       drm_savage_private_t *dev_priv = dev->dev_private;
+       int i;
+
+       for (i = 0; i < 3; ++i)
+               if (dev_priv->mtrr[i].handle >= 0)
+                       mtrr_del(dev_priv->mtrr[i].handle,
+                                dev_priv->mtrr[i].base,
+                                dev_priv->mtrr[i].size);
+
+       drm_free(dev_priv, sizeof(drm_savage_private_t), DRM_MEM_DRIVER);
+
+       return 0;
+}
+
 static int savage_do_init_bci(drm_device_t *dev, drm_savage_init_t *init)
 {
        drm_savage_private_t *dev_priv = dev->dev_private;
index a3671db..16211a5 100644 (file)
@@ -140,6 +140,11 @@ typedef struct drm_savage_private {
        drm_local_map_t *agp_textures;
        drm_local_map_t *cmd_dma;
 
+       struct {
+               int handle;
+               unsigned long base, size;
+       } mtrr[3];
+
        /* BCI and status-related stuff */
        volatile uint32_t *status_ptr, *bci_ptr;
        uint32_t status_used_mask;
@@ -177,6 +182,7 @@ extern uint16_t savage_bci_emit_event(drm_savage_private_t *dev_priv,
                                      unsigned int flags);
 extern void savage_freelist_put(drm_device_t *dev, drm_buf_t *buf);
 extern int savage_preinit(drm_device_t *dev, unsigned long chipset);
+extern int savage_postcleanup(drm_device_t *dev);
 extern int savage_do_cleanup_bci(drm_device_t *dev);
 extern void savage_reclaim_buffers(drm_device_t *dev, DRMFILE filp);