diff options
-rw-r--r-- | linux-core/drmP.h | 1 | ||||
-rw-r--r-- | linux-core/mga_drv.c | 116 | ||||
-rw-r--r-- | linux/drmP.h | 1 | ||||
-rw-r--r-- | linux/mga_dma.c | 21 | ||||
-rw-r--r-- | linux/mga_dma.h | 2 | ||||
-rw-r--r-- | linux/mga_drv.c | 116 |
6 files changed, 251 insertions, 6 deletions
diff --git a/linux-core/drmP.h b/linux-core/drmP.h index 8f50d90b..f1759f85 100644 --- a/linux-core/drmP.h +++ b/linux-core/drmP.h @@ -421,6 +421,7 @@ typedef struct drm_agp_head { int enabled; int acquired; unsigned long base; + int agp_mtrr; } drm_agp_head_t; typedef struct { diff --git a/linux-core/mga_drv.c b/linux-core/mga_drv.c index 43b3e17e..e85cba45 100644 --- a/linux-core/mga_drv.c +++ b/linux-core/mga_drv.c @@ -353,6 +353,95 @@ static int mga_takedown(drm_device_t *dev) /* mga_init is called via init_module at module load time, or via * linux/init/main.c (this is not currently supported). */ +typedef union { + void (*free_memory)(agp_memory *); + agp_memory *(*allocate_memory)(size_t, u32); + int (*bind_memory)(agp_memory *, off_t); + int (*unbind_memory)(agp_memory *); + void (*enable)(u32); + int (*acquire)(void); + void (*release)(void); + void (*copy_info)(agp_kern_info *); + unsigned long address; +} drm_agp_func_u; + +typedef struct drm_agp_fill { + const char *name; + drm_agp_func_u *f; +} drm_agp_fill_t; + +static drm_agp_fill_t drm_agp_fill[] = { + { __MODULE_STRING(agp_free_memory), + (drm_agp_func_u *)&drm_agp.free_memory }, + { __MODULE_STRING(agp_allocate_memory), + (drm_agp_func_u *)&drm_agp.allocate_memory }, + { __MODULE_STRING(agp_bind_memory), + (drm_agp_func_u *)&drm_agp.bind_memory }, + { __MODULE_STRING(agp_unbind_memory), + (drm_agp_func_u *)&drm_agp.unbind_memory }, + { __MODULE_STRING(agp_enable), + (drm_agp_func_u *)&drm_agp.enable }, + { __MODULE_STRING(agp_backend_acquire), + (drm_agp_func_u *)&drm_agp.acquire }, + { __MODULE_STRING(agp_backend_release), + (drm_agp_func_u *)&drm_agp.release }, + { __MODULE_STRING(agp_copy_info), + (drm_agp_func_u *)&drm_agp.copy_info }, + { NULL, NULL } +}; + +drm_agp_head_t *mga_agp_init(void) +{ + drm_agp_fill_t *fill; + drm_agp_head_t *head = NULL; + int agp_available = 1; + + for (fill = &drm_agp_fill[0]; fill->name; fill++) { + char *n = (char *)fill->name; + *fill->f = (drm_agp_func_u)get_module_symbol(NULL, n); + printk("%s resolves to 0x%08lx\n", n, (*fill->f).address); + if (!(*fill->f).address) agp_available = 0; + } + + printk("agp_available = %d\n", agp_available); + + if(agp_available == 0) { + printk("agp is not available\n"); + return NULL; + } + + if (agp_available) { + if (!(head = drm_alloc(sizeof(*head), DRM_MEM_AGPLISTS))) + return NULL; + memset((void *)head, 0, sizeof(*head)); + (*drm_agp.copy_info)(&head->agp_info); + head->memory = NULL; + switch (head->agp_info.chipset) { + case INTEL_GENERIC: head->chipset = "Intel"; break; + case INTEL_LX: head->chipset = "Intel 440LX"; break; + case INTEL_BX: head->chipset = "Intel 440BX"; break; + case INTEL_GX: head->chipset = "Intel 440GX"; break; + case INTEL_I810: head->chipset = "Intel i810"; break; + case VIA_GENERIC: head->chipset = "VIA"; break; + case VIA_VP3: head->chipset = "VIA VP3"; break; + case VIA_MVP3: head->chipset = "VIA MVP3"; break; + case VIA_APOLLO_PRO: head->chipset = "VIA Apollo Pro"; break; + case SIS_GENERIC: head->chipset = "SiS"; break; + case AMD_GENERIC: head->chipset = "AMD"; break; + case AMD_IRONGATE: head->chipset = "AMD Irongate"; break; + case ALI_GENERIC: head->chipset = "ALi"; break; + case ALI_M1541: head->chipset = "ALi M1541"; break; + default: + } + DRM_INFO("AGP %d.%d on %s @ 0x%08lx %dMB\n", + head->agp_info.version.major, + head->agp_info.version.minor, + head->chipset, + head->agp_info.aper_base, + head->agp_info.aper_size); + } + return head; +} int mga_init(void) { @@ -381,7 +470,22 @@ int mga_init(void) DRM_DEBUG("doing proc init\n"); drm_proc_init(dev); DRM_DEBUG("doing agp init\n"); - dev->agp = drm_agp_init(); + dev->agp = mga_agp_init(); + if(dev->agp == NULL) { + printk("The mga drm module requires the agpgart module" + " to function correctly\nPlease load the agpgart" + " module before you load the mga module\n"); + drm_proc_cleanup(); + misc_deregister(&mga_misc); + mga_takedown(dev); + return -ENOMEM; + } +#ifdef CONFIG_MTRR + dev->agp->agp_mtrr = mtrr_add(dev->agp->agp_info.aper_base, + dev->agp->agp_info.aper_size, + MTRR_TYPE_WRCOMB, + 1); +#endif DRM_DEBUG("doing ctxbitmap init\n"); if((retcode = drm_ctxbitmap_init(dev))) { DRM_ERROR("Cannot allocate memory for context bitmap.\n"); @@ -418,6 +522,16 @@ void mga_cleanup(void) } drm_ctxbitmap_cleanup(dev); mga_dma_cleanup(dev); +#ifdef CONFIG_MTRR + if(dev->agp && dev->agp->agp_mtrr) { + int retval; + retval = mtrr_del(dev->agp->agp_mtrr, + dev->agp->agp_info.aper_base, + dev->agp->agp_info.aper_size); + DRM_DEBUG("mtrr_del = %d\n", retval); + } +#endif + mga_takedown(dev); if (dev->agp) { drm_free(dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS); diff --git a/linux/drmP.h b/linux/drmP.h index 8f50d90b..f1759f85 100644 --- a/linux/drmP.h +++ b/linux/drmP.h @@ -421,6 +421,7 @@ typedef struct drm_agp_head { int enabled; int acquired; unsigned long base; + int agp_mtrr; } drm_agp_head_t; typedef struct { diff --git a/linux/mga_dma.c b/linux/mga_dma.c index c4ebbdde..1d9d5bb1 100644 --- a/linux/mga_dma.c +++ b/linux/mga_dma.c @@ -93,6 +93,15 @@ static void mga_delay(void) return; } +static void mga_flush_write_combine(void) +{ + int xchangeDummy; + __asm__ volatile( " push %%eax ; xchg %%eax, %0 ; pop %%eax" : : "m" (xchangeDummy)); + __asm__ volatile(" push %%eax ; push %%ebx ; push %%ecx ; push %%edx ;" + " movl $0,%%eax ; cpuid ; pop %%edx ; pop %%ecx ; pop %%ebx ;" + " pop %%eax" : /* no outputs */ : /* no inputs */ ); +} + int mga_dma_cleanup(drm_device_t *dev) { if(dev->dev_private) { @@ -347,6 +356,7 @@ static int mga_dma_initialize(drm_device_t *dev, drm_mga_init_t *init) { status[1] = 0; + mga_flush_write_combine(); MGA_WRITE(MGAREG_PRIMADDRESS, phys_head | TT_GENERAL); MGA_WRITE(MGAREG_PRIMEND, ((phys_head + num_dwords * 4) | @@ -444,6 +454,7 @@ static void __mga_iload_small(drm_device_t *dev, drm_buf_t *buf) } PRIMADVANCE(dev_priv); + mga_flush_write_combine(); MGA_WRITE(MGAREG_PRIMADDRESS, dev_priv->prim_phys_head | TT_GENERAL); MGA_WRITE(MGAREG_PRIMEND, (phys_head + num_dwords * 4) | use_agp); } @@ -523,6 +534,7 @@ static void __mga_iload_xy(drm_device_t *dev, drm_buf_t *buf ) sarea_priv->dirty &= ~(MGA_DMA_FLUSH); } + mga_flush_write_combine(); MGA_WRITE(MGAREG_PRIMADDRESS, dev_priv->prim_phys_head | TT_GENERAL); MGA_WRITE(MGAREG_PRIMEND, (phys_head + num_dwords * 4) | use_agp); } @@ -616,7 +628,7 @@ static void mga_dma_dispatch_tex_blit(drm_device_t *dev, drm_buf_t *buf ) sarea_priv->dirty &= ~(MGA_DMA_FLUSH); } - + mga_flush_write_combine(); MGA_WRITE(MGAREG_PRIMADDRESS, dev_priv->prim_phys_head | TT_GENERAL); MGA_WRITE(MGAREG_PRIMEND, (phys_head + num_dwords * 4) | use_agp); @@ -682,7 +694,7 @@ static void mga_dma_dispatch_vertex(drm_device_t *dev, drm_buf_t *buf) } PRIMADVANCE( dev_priv ); - + mga_flush_write_combine(); MGA_WRITE(MGAREG_PRIMADDRESS, dev_priv->prim_phys_head | TT_GENERAL); MGA_WRITE(MGAREG_PRIMEND, (phys_head + num_dwords * 4) | use_agp); } @@ -720,6 +732,7 @@ static void mga_dma_dispatch_general(drm_device_t *dev, drm_buf_t *buf) sarea_priv->dirty &= ~(MGA_DMA_FLUSH); } + mga_flush_write_combine(); MGA_WRITE(MGAREG_PRIMADDRESS, dev_priv->prim_phys_head | TT_GENERAL); MGA_WRITE(MGAREG_PRIMEND, (phys_head + num_dwords * 4) | use_agp); } @@ -859,6 +872,7 @@ static void mga_dma_dispatch_clear( drm_device_t *dev, drm_buf_t *buf ) sarea_priv->dirty &= ~(MGA_DMA_FLUSH); } + mga_flush_write_combine(); MGA_WRITE(MGAREG_PRIMADDRESS, dev_priv->prim_phys_head | TT_GENERAL); MGA_WRITE(MGAREG_PRIMEND, (phys_head + num_dwords * 4) | use_agp); } @@ -916,6 +930,7 @@ static void mga_dma_dispatch_swap( drm_device_t *dev, drm_buf_t *buf ) sarea_priv->dirty &= ~(MGA_DMA_FLUSH); } + mga_flush_write_combine(); MGA_WRITE(MGAREG_PRIMADDRESS, dev_priv->prim_phys_head | TT_GENERAL); MGA_WRITE(MGAREG_PRIMEND, (phys_head + num_dwords * 4) | use_agp); } @@ -951,6 +966,7 @@ static void mga_dma_dispatch_bad( drm_device_t *dev, drm_buf_t *buf ) sarea_priv->dirty &= ~(MGA_DMA_FLUSH); } + mga_flush_write_combine(); MGA_WRITE(MGAREG_PRIMADDRESS, dev_priv->prim_phys_head | TT_GENERAL); MGA_WRITE(MGAREG_PRIMEND, (phys_head + num_dwords * 4) | use_agp); } @@ -1480,7 +1496,6 @@ int mga_lock(struct inode *inode, struct file *filp, unsigned int cmd, } } -out_lock: DRM_DEBUG("%d %s\n", lock.context, ret ? "interrupted" : "has lock"); return ret; } diff --git a/linux/mga_dma.h b/linux/mga_dma.h index d3823d47..e91f608b 100644 --- a/linux/mga_dma.h +++ b/linux/mga_dma.h @@ -52,7 +52,7 @@ typedef struct { -#define MGA_VERBOSE 1 +#define MGA_VERBOSE 0 diff --git a/linux/mga_drv.c b/linux/mga_drv.c index 43b3e17e..e85cba45 100644 --- a/linux/mga_drv.c +++ b/linux/mga_drv.c @@ -353,6 +353,95 @@ static int mga_takedown(drm_device_t *dev) /* mga_init is called via init_module at module load time, or via * linux/init/main.c (this is not currently supported). */ +typedef union { + void (*free_memory)(agp_memory *); + agp_memory *(*allocate_memory)(size_t, u32); + int (*bind_memory)(agp_memory *, off_t); + int (*unbind_memory)(agp_memory *); + void (*enable)(u32); + int (*acquire)(void); + void (*release)(void); + void (*copy_info)(agp_kern_info *); + unsigned long address; +} drm_agp_func_u; + +typedef struct drm_agp_fill { + const char *name; + drm_agp_func_u *f; +} drm_agp_fill_t; + +static drm_agp_fill_t drm_agp_fill[] = { + { __MODULE_STRING(agp_free_memory), + (drm_agp_func_u *)&drm_agp.free_memory }, + { __MODULE_STRING(agp_allocate_memory), + (drm_agp_func_u *)&drm_agp.allocate_memory }, + { __MODULE_STRING(agp_bind_memory), + (drm_agp_func_u *)&drm_agp.bind_memory }, + { __MODULE_STRING(agp_unbind_memory), + (drm_agp_func_u *)&drm_agp.unbind_memory }, + { __MODULE_STRING(agp_enable), + (drm_agp_func_u *)&drm_agp.enable }, + { __MODULE_STRING(agp_backend_acquire), + (drm_agp_func_u *)&drm_agp.acquire }, + { __MODULE_STRING(agp_backend_release), + (drm_agp_func_u *)&drm_agp.release }, + { __MODULE_STRING(agp_copy_info), + (drm_agp_func_u *)&drm_agp.copy_info }, + { NULL, NULL } +}; + +drm_agp_head_t *mga_agp_init(void) +{ + drm_agp_fill_t *fill; + drm_agp_head_t *head = NULL; + int agp_available = 1; + + for (fill = &drm_agp_fill[0]; fill->name; fill++) { + char *n = (char *)fill->name; + *fill->f = (drm_agp_func_u)get_module_symbol(NULL, n); + printk("%s resolves to 0x%08lx\n", n, (*fill->f).address); + if (!(*fill->f).address) agp_available = 0; + } + + printk("agp_available = %d\n", agp_available); + + if(agp_available == 0) { + printk("agp is not available\n"); + return NULL; + } + + if (agp_available) { + if (!(head = drm_alloc(sizeof(*head), DRM_MEM_AGPLISTS))) + return NULL; + memset((void *)head, 0, sizeof(*head)); + (*drm_agp.copy_info)(&head->agp_info); + head->memory = NULL; + switch (head->agp_info.chipset) { + case INTEL_GENERIC: head->chipset = "Intel"; break; + case INTEL_LX: head->chipset = "Intel 440LX"; break; + case INTEL_BX: head->chipset = "Intel 440BX"; break; + case INTEL_GX: head->chipset = "Intel 440GX"; break; + case INTEL_I810: head->chipset = "Intel i810"; break; + case VIA_GENERIC: head->chipset = "VIA"; break; + case VIA_VP3: head->chipset = "VIA VP3"; break; + case VIA_MVP3: head->chipset = "VIA MVP3"; break; + case VIA_APOLLO_PRO: head->chipset = "VIA Apollo Pro"; break; + case SIS_GENERIC: head->chipset = "SiS"; break; + case AMD_GENERIC: head->chipset = "AMD"; break; + case AMD_IRONGATE: head->chipset = "AMD Irongate"; break; + case ALI_GENERIC: head->chipset = "ALi"; break; + case ALI_M1541: head->chipset = "ALi M1541"; break; + default: + } + DRM_INFO("AGP %d.%d on %s @ 0x%08lx %dMB\n", + head->agp_info.version.major, + head->agp_info.version.minor, + head->chipset, + head->agp_info.aper_base, + head->agp_info.aper_size); + } + return head; +} int mga_init(void) { @@ -381,7 +470,22 @@ int mga_init(void) DRM_DEBUG("doing proc init\n"); drm_proc_init(dev); DRM_DEBUG("doing agp init\n"); - dev->agp = drm_agp_init(); + dev->agp = mga_agp_init(); + if(dev->agp == NULL) { + printk("The mga drm module requires the agpgart module" + " to function correctly\nPlease load the agpgart" + " module before you load the mga module\n"); + drm_proc_cleanup(); + misc_deregister(&mga_misc); + mga_takedown(dev); + return -ENOMEM; + } +#ifdef CONFIG_MTRR + dev->agp->agp_mtrr = mtrr_add(dev->agp->agp_info.aper_base, + dev->agp->agp_info.aper_size, + MTRR_TYPE_WRCOMB, + 1); +#endif DRM_DEBUG("doing ctxbitmap init\n"); if((retcode = drm_ctxbitmap_init(dev))) { DRM_ERROR("Cannot allocate memory for context bitmap.\n"); @@ -418,6 +522,16 @@ void mga_cleanup(void) } drm_ctxbitmap_cleanup(dev); mga_dma_cleanup(dev); +#ifdef CONFIG_MTRR + if(dev->agp && dev->agp->agp_mtrr) { + int retval; + retval = mtrr_del(dev->agp->agp_mtrr, + dev->agp->agp_info.aper_base, + dev->agp->agp_info.aper_size); + DRM_DEBUG("mtrr_del = %d\n", retval); + } +#endif + mga_takedown(dev); if (dev->agp) { drm_free(dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS); |