From a686be5bc8c5d8a260513b680f322e3b790aadf7 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Sat, 21 May 2005 02:27:51 +0000 Subject: [PATCH] Change the MGA initialization and cleanup a bit. The dev_private structure is now allocated (and partially filled in) by the new mga_driver_preinit function. This allows the driver to detect the type of card (i.e., G200 class vs. G400 class) on its own. The chipset value passed to mga_dma_init is now ignored. This same technique is used by the radeon DRM. As a result of this, mga_driver_pretakedown was converted to mga_driver_postcleanup. This routine gets called in some other places than might be expected, and it sets the dev_private pointer to NULL. That little gem took over an hour to track down. :( --- bsd-core/mga_drv.c | 3 ++- linux-core/mga_drv.c | 3 ++- shared-core/drm_pciids.txt | 6 ++--- shared-core/mga_dma.c | 52 +++++++++++++++----------------------- shared-core/mga_drv.h | 3 ++- 5 files changed, 29 insertions(+), 38 deletions(-) diff --git a/bsd-core/mga_drv.c b/bsd-core/mga_drv.c index 1dd4c81b..e088ceca 100644 --- a/bsd-core/mga_drv.c +++ b/bsd-core/mga_drv.c @@ -52,7 +52,8 @@ static void mga_configure(drm_device_t *dev) { dev->dev_priv_size = sizeof(drm_mga_buf_priv_t); /* XXX dev->prerelease = mga_driver_prerelease; */ - dev->pretakedown = mga_driver_pretakedown; + dev->preinit = mga_driver_preinit; + dev->postcleanup = mga_driver_postcleanup; dev->vblank_wait = mga_driver_vblank_wait; dev->irq_preinstall = mga_driver_irq_preinstall; dev->irq_postinstall = mga_driver_irq_postinstall; diff --git a/linux-core/mga_drv.c b/linux-core/mga_drv.c index e0f1ab31..c04de5a3 100644 --- a/linux-core/mga_drv.c +++ b/linux-core/mga_drv.c @@ -81,7 +81,8 @@ static struct drm_driver driver = { DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL, - .pretakedown = mga_driver_pretakedown, + .preinit = mga_driver_preinit, + .postcleanup = mga_driver_postcleanup, .dma_quiescent = mga_driver_dma_quiescent, .device_is_agp = mga_driver_device_is_agp, .vblank_wait = mga_driver_vblank_wait, diff --git a/shared-core/drm_pciids.txt b/shared-core/drm_pciids.txt index d9b42e01..82cbdd46 100644 --- a/shared-core/drm_pciids.txt +++ b/shared-core/drm_pciids.txt @@ -110,9 +110,9 @@ 0x1002 0x5452 0 "ATI Rage 128 Pro Ultra TR (AGP)" [mga] -0x102b 0x0521 0 "Matrox G200 (AGP)" -0x102b 0x0525 0 "Matrox G400/G450 (AGP)" -0x102b 0x2527 0 "Matrox G550 (AGP)" +0x102b 0x0521 MGA_CARD_TYPE_G200 "Matrox G200 (AGP)" +0x102b 0x0525 MGA_CARD_TYPE_G400 "Matrox G400/G450 (AGP)" +0x102b 0x2527 MGA_CARD_TYPE_G400 "Matrox G550 (AGP)" [mach64] 0x1002 0x4749 0 "3D Rage Pro" diff --git a/shared-core/mga_dma.c b/shared-core/mga_dma.c index be96161e..2adb30ac 100644 --- a/shared-core/mga_dma.c +++ b/shared-core/mga_dma.c @@ -388,21 +388,31 @@ int mga_freelist_put(drm_device_t * dev, drm_buf_t * buf) * DMA initialization, cleanup */ +int mga_driver_preinit(drm_device_t *dev, unsigned long flags) +{ + drm_mga_private_t * dev_priv; + + dev_priv = drm_alloc(sizeof(drm_mga_private_t), DRM_MEM_DRIVER); + if (!dev_priv) + return DRM_ERR(ENOMEM); + + dev->dev_private = (void *)dev_priv; + memset(dev_priv, 0, sizeof(drm_mga_private_t)); + + dev_priv->usec_timeout = MGA_DEFAULT_USEC_TIMEOUT; + dev_priv->chipset = flags; + + return 0; +} + static int mga_do_init_dma(drm_device_t * dev, drm_mga_init_t * init) { drm_mga_private_t *dev_priv; int ret; DRM_DEBUG("\n"); - dev_priv = drm_alloc(sizeof(drm_mga_private_t), DRM_MEM_DRIVER); - if (!dev_priv) - return DRM_ERR(ENOMEM); - memset(dev_priv, 0, sizeof(drm_mga_private_t)); - - dev_priv->chipset = init->chipset; - - dev_priv->usec_timeout = MGA_DEFAULT_USEC_TIMEOUT; + dev_priv = dev->dev_private; if (init->sgram) { dev_priv->clear_cmd = MGA_DWGCTL_CLEAR | MGA_ATYPE_BLK; @@ -430,8 +440,6 @@ static int mga_do_init_dma(drm_device_t * dev, drm_mga_init_t * init) if (!dev_priv->sarea) { DRM_ERROR("failed to find sarea!\n"); - /* Assign dev_private so we can do cleanup. */ - dev->dev_private = (void *)dev_priv; mga_do_cleanup_dma(dev); return DRM_ERR(EINVAL); } @@ -439,40 +447,30 @@ static int mga_do_init_dma(drm_device_t * dev, drm_mga_init_t * init) dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset); if (!dev_priv->mmio) { DRM_ERROR("failed to find mmio region!\n"); - /* Assign dev_private so we can do cleanup. */ - dev->dev_private = (void *)dev_priv; mga_do_cleanup_dma(dev); return DRM_ERR(EINVAL); } dev_priv->status = drm_core_findmap(dev, init->status_offset); if (!dev_priv->status) { DRM_ERROR("failed to find status page!\n"); - /* Assign dev_private so we can do cleanup. */ - dev->dev_private = (void *)dev_priv; mga_do_cleanup_dma(dev); return DRM_ERR(EINVAL); } dev_priv->warp = drm_core_findmap(dev, init->warp_offset); if (!dev_priv->warp) { DRM_ERROR("failed to find warp microcode region!\n"); - /* Assign dev_private so we can do cleanup. */ - dev->dev_private = (void *)dev_priv; mga_do_cleanup_dma(dev); return DRM_ERR(EINVAL); } dev_priv->primary = drm_core_findmap(dev, init->primary_offset); if (!dev_priv->primary) { DRM_ERROR("failed to find primary dma region!\n"); - /* Assign dev_private so we can do cleanup. */ - dev->dev_private = (void *)dev_priv; mga_do_cleanup_dma(dev); return DRM_ERR(EINVAL); } dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset); if (!dev->agp_buffer_map) { DRM_ERROR("failed to find dma buffer region!\n"); - /* Assign dev_private so we can do cleanup. */ - dev->dev_private = (void *)dev_priv; mga_do_cleanup_dma(dev); return DRM_ERR(EINVAL); } @@ -488,8 +486,6 @@ static int mga_do_init_dma(drm_device_t * dev, drm_mga_init_t * init) if (!dev_priv->warp->handle || !dev_priv->primary->handle || !dev->agp_buffer_map->handle) { DRM_ERROR("failed to ioremap agp regions!\n"); - /* Assign dev_private so we can do cleanup. */ - dev->dev_private = (void *)dev_priv; mga_do_cleanup_dma(dev); return DRM_ERR(ENOMEM); } @@ -497,8 +493,6 @@ static int mga_do_init_dma(drm_device_t * dev, drm_mga_init_t * init) ret = mga_warp_install_microcode(dev_priv); if (ret < 0) { DRM_ERROR("failed to install WARP ucode!\n"); - /* Assign dev_private so we can do cleanup. */ - dev->dev_private = (void *)dev_priv; mga_do_cleanup_dma(dev); return ret; } @@ -506,8 +500,6 @@ static int mga_do_init_dma(drm_device_t * dev, drm_mga_init_t * init) ret = mga_warp_init(dev_priv); if (ret < 0) { DRM_ERROR("failed to init WARP engine!\n"); - /* Assign dev_private so we can do cleanup. */ - dev->dev_private = (void *)dev_priv; mga_do_cleanup_dma(dev); return ret; } @@ -547,14 +539,10 @@ static int mga_do_init_dma(drm_device_t * dev, drm_mga_init_t * init) if (mga_freelist_init(dev, dev_priv) < 0) { DRM_ERROR("could not initialize freelist\n"); - /* Assign dev_private so we can do cleanup. */ - dev->dev_private = (void *)dev_priv; mga_do_cleanup_dma(dev); return DRM_ERR(ENOMEM); } - /* Make dev_private visable to others. */ - dev->dev_private = (void *)dev_priv; return 0; } @@ -733,9 +721,9 @@ int mga_dma_buffers(DRM_IOCTL_ARGS) return ret; } -void mga_driver_pretakedown(drm_device_t * dev) +int mga_driver_postcleanup(drm_device_t * dev) { - mga_do_cleanup_dma(dev); + return mga_do_cleanup_dma(dev); } int mga_driver_dma_quiescent(drm_device_t * dev) diff --git a/shared-core/mga_drv.h b/shared-core/mga_drv.h index f1c3cf3e..54373cc7 100644 --- a/shared-core/mga_drv.h +++ b/shared-core/mga_drv.h @@ -113,11 +113,12 @@ typedef struct drm_mga_private { } drm_mga_private_t; /* mga_dma.c */ +extern int mga_driver_preinit(drm_device_t * dev, unsigned long flags); extern int mga_dma_init(DRM_IOCTL_ARGS); extern int mga_dma_flush(DRM_IOCTL_ARGS); extern int mga_dma_reset(DRM_IOCTL_ARGS); extern int mga_dma_buffers(DRM_IOCTL_ARGS); -extern void mga_driver_pretakedown(drm_device_t * dev); +extern int mga_driver_postcleanup(drm_device_t * dev); extern int mga_driver_dma_quiescent(drm_device_t * dev); extern int mga_do_wait_for_idle(drm_mga_private_t * dev_priv);