diff options
Diffstat (limited to 'linux')
-rw-r--r-- | linux/Makefile | 7 | ||||
-rw-r--r-- | linux/Makefile.kernel | 2 | ||||
-rw-r--r-- | linux/drmP.h | 2 | ||||
-rw-r--r-- | linux/drm_bufs.h | 107 | ||||
-rw-r--r-- | linux/drm_drv.h | 71 |
5 files changed, 147 insertions, 42 deletions
diff --git a/linux/Makefile b/linux/Makefile index 9836f58c..f677f63d 100644 --- a/linux/Makefile +++ b/linux/Makefile @@ -97,9 +97,10 @@ SISSHARED= sis.h sis_drv.h sis_drm.h sis_ds.c sis_ds.h sis_mm.c SAVAGEHEADERS= savage.h savage_drv.h savage_drm.h $(DRMHEADERS) \ $(DRMTEMPLATES) VIAHEADERS = via_drm.h via_drv.h via.h via_mm.h via_ds.h \ - $(DRMHEADERS) $(DRMTEMPLATES) -VIASHARED = via_drm.h via_drv.h via.h via_mm.h via_ds.h via_drv.c \ - via_ds.c via_irq.c via_map.c via_mm.c + via_3d_reg.h $(DRMHEADERS) $(DRMTEMPLATES) +VIASHARED = via_drm.h via_drv.h via.h via_mm.h via_ds.h \ + via_3d_reg.h via_drv.c via_ds.c via_irq.c via_map.c \ + via_mm.c via_dma.c MACH64HEADERS = mach64.h mach64_drv.h mach64_drm.h $(DRMHEADERS) \ $(DRMTEMPLATES) MACH64SHARED = mach64.h mach64_drv.h mach64_drm.h mach64_dma.c \ diff --git a/linux/Makefile.kernel b/linux/Makefile.kernel index 30b00f62..857c236a 100644 --- a/linux/Makefile.kernel +++ b/linux/Makefile.kernel @@ -18,7 +18,7 @@ radeon-objs := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o radeon_irq.o sis-objs := sis_drv.o sis_ds.o sis_mm.o ffb-objs := ffb_drv.o ffb_context.o savage-objs := savage_drv.o savage_dma.o -via-objs := via_irq.o via_drv.o via_ds.o via_map.o via_mm.o +via-objs := via_irq.o via_drv.o via_ds.o via_map.o via_mm.o via_dma.o mach64-objs := mach64_drv.o mach64_dma.o mach64_irq.o mach64_state.o # Kernel version checks diff --git a/linux/drmP.h b/linux/drmP.h index a7a0e32b..e84685de 100644 --- a/linux/drmP.h +++ b/linux/drmP.h @@ -833,6 +833,8 @@ extern int DRM(addmap)( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ); extern int DRM(rmmap)( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ); +extern int DRM(initmap)( drm_device_t *dev, unsigned int offset, + unsigned int size, int type, int flags ); extern int DRM(addbufs)( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ); extern int DRM(infobufs)( struct inode *inode, struct file *filp, diff --git a/linux/drm_bufs.h b/linux/drm_bufs.h index e882efc7..38fcb777 100644 --- a/linux/drm_bufs.h +++ b/linux/drm_bufs.h @@ -60,6 +60,71 @@ int DRM(order)( unsigned long size ) return order; } + /** + * Adjusts the memory offset to its absolute value according to the mapping + * type. Adds the map to the map list drm_device::maplist. Adds MTRR's where + * applicable and if supported by the kernel. + */ +int DRM(initmap)( drm_device_t *dev, unsigned int offset, unsigned int size, int type, int flags ) +{ + drm_map_t *map; + drm_map_list_t *list; + + DRM_DEBUG("\n"); + + if ( (offset & (~PAGE_MASK)) || (size & (~PAGE_MASK)) ) + return -EINVAL; +#if !defined(__sparc__) && !defined(__alpha__) + if ( offset + size < offset || offset < virt_to_phys(high_memory) ) + return -EINVAL; +#endif + if ( !(list = DRM(alloc)( sizeof(*list), DRM_MEM_MAPS ))) + return -ENOMEM; + memset(list, 0, sizeof(*list)); + + if ( !(map = DRM(alloc)( sizeof(*map), DRM_MEM_MAPS ))) { + DRM(free)(list, sizeof(*list), DRM_MEM_MAPS); + return -ENOMEM; + } + + *map = (drm_map_t){ + .offset = offset, + .size = size, + .type = type, + .flags = flags, + .mtrr = -1, + .handle = 0, + }; + list->map = map; + + DRM_DEBUG( "initmap offset = 0x%08lx, size = 0x%08lx, type = %d\n", + map->offset, map->size, map->type ); + +#ifdef __alpha__ + map->offset += dev->hose->mem_space->start; +#endif +#if __OS_HAS_MTRR + if ( dev->driver_features & DRIVER_USE_MTRR) { + if ( map->type == _DRM_FRAME_BUFFER || + (map->flags & _DRM_WRITE_COMBINING) ) { + map->mtrr = mtrr_add( map->offset, map->size, + MTRR_TYPE_WRCOMB, 1 ); + } + } +#endif + if (map->type == _DRM_REGISTERS) + map->handle = DRM(ioremap)( map->offset, map->size, dev ); + + down(&dev->struct_sem); + list_add(&list->head, &dev->maplist->head); + up(&dev->struct_sem); + + DRM_DEBUG("finished\n"); + + return 0; +} + + /** * Ioctl to specify a range of memory that is available for mapping by a non-root process. * @@ -112,7 +177,21 @@ int DRM(addmap)( struct inode *inode, struct file *filp, switch ( map->type ) { case _DRM_REGISTERS: - case _DRM_FRAME_BUFFER: + case _DRM_FRAME_BUFFER: { + /* after all the drivers switch to permanent mapping this should just return an error */ + struct list_head *_list; + + /* if map already exists, return the existing one instead of creating a new one */ + list_for_each( _list, &dev->maplist->head ) { + drm_map_list_t *_entry = list_entry( _list, drm_map_list_t, head ); + if ( _entry->map && _entry->map->type == map->type ) { + DRM(free)( map, sizeof(*map), DRM_MEM_MAPS ); + map = _entry->map; + DRM_DEBUG( "Found existing: offset = 0x%08lx, size = 0x%08lx, type = %d\n", + map->offset, map->size, map->type ); + goto found_it; + } + } #if !defined(__sparc__) && !defined(__alpha__) && !defined(__ia64__) if ( map->offset + map->size < map->offset || map->offset < virt_to_phys(high_memory) ) { @@ -136,7 +215,7 @@ int DRM(addmap)( struct inode *inode, struct file *filp, map->handle = DRM(ioremap)( map->offset, map->size, dev ); break; - + } case _DRM_SHM: map->handle = vmalloc_32(map->size); DRM_DEBUG( "%lu %d %p\n", @@ -192,7 +271,7 @@ int DRM(addmap)( struct inode *inode, struct file *filp, down(&dev->struct_sem); list_add(&list->head, &dev->maplist->head); up(&dev->struct_sem); - +found_it: if ( copy_to_user( argp, map, sizeof(*map) ) ) return -EFAULT; if ( map->type != _DRM_SHM ) { @@ -237,7 +316,7 @@ int DRM(rmmap)(struct inode *inode, struct file *filp, sizeof(request))) { return -EFAULT; } - + down(&dev->struct_sem); list = &dev->maplist->head; list_for_each(list, &dev->maplist->head) { @@ -256,6 +335,12 @@ int DRM(rmmap)(struct inode *inode, struct file *filp, return -EINVAL; } map = r_list->map; + + /* Register and framebuffer maps are permanent */ + if ((map->type == _DRM_REGISTERS) || (map->type == _DRM_FRAME_BUFFER)) { + up(&dev->struct_sem); + return 0; + } list_del(list); DRM(free)(list, sizeof(*list), DRM_MEM_MAPS); @@ -267,19 +352,7 @@ int DRM(rmmap)(struct inode *inode, struct file *filp, switch (map->type) { case _DRM_REGISTERS: case _DRM_FRAME_BUFFER: -#if __OS_HAS_MTRR - if (dev->driver_features & DRIVER_USE_MTRR) { - if (map->mtrr >= 0) { - int retcode; - retcode = mtrr_del(map->mtrr, - map->offset, - map->size); - DRM_DEBUG("mtrr_del = %d\n", retcode); - } - } -#endif - DRM(ioremapfree)(map->handle, map->size, dev); - break; + break; /* Can't get here, make compiler happy */ case _DRM_SHM: vfree(map->handle); break; diff --git a/linux/drm_drv.h b/linux/drm_drv.h index 8b07a298..9588781b 100644 --- a/linux/drm_drv.h +++ b/linux/drm_drv.h @@ -246,12 +246,6 @@ static int DRM(setup)( drm_device_t *dev ) dev->magiclist[i].tail = NULL; } - dev->maplist = DRM(alloc)(sizeof(*dev->maplist), - DRM_MEM_MAPS); - if(dev->maplist == NULL) return -ENOMEM; - memset(dev->maplist, 0, sizeof(*dev->maplist)); - INIT_LIST_HEAD(&dev->maplist->head); - dev->ctxlist = DRM(alloc)(sizeof(*dev->ctxlist), DRM_MEM_CTXLIST); if(dev->ctxlist == NULL) return -ENOMEM; @@ -390,19 +384,8 @@ static int DRM(takedown)( drm_device_t *dev ) switch ( map->type ) { case _DRM_REGISTERS: case _DRM_FRAME_BUFFER: -#if __OS_HAS_MTRR - if (dev->driver_features & DRIVER_USE_MTRR) { - if ( map->mtrr >= 0 ) { - int retcode; - retcode = mtrr_del( map->mtrr, - map->offset, - map->size ); - DRM_DEBUG( "mtrr_del=%d\n", retcode ); - } - } -#endif - DRM(ioremapfree)( map->handle, map->size, dev ); - break; + continue; + case _DRM_SHM: vfree(map->handle); break; @@ -425,8 +408,6 @@ static int DRM(takedown)( drm_device_t *dev ) list_del( list ); DRM(free)(r_list, sizeof(*r_list), DRM_MEM_MAPS); } - DRM(free)(dev->maplist, sizeof(*dev->maplist), DRM_MEM_MAPS); - dev->maplist = NULL; } @@ -511,6 +492,11 @@ static int drm_probe(struct pci_dev *pdev, const struct pci_device_id *ent) dev->pci_func = PCI_FUNC(pdev->devfn); dev->irq = pdev->irq; + dev->maplist = DRM(alloc)(sizeof(*dev->maplist), DRM_MEM_MAPS); + if(dev->maplist == NULL) return -ENOMEM; + memset(dev->maplist, 0, sizeof(*dev->maplist)); + INIT_LIST_HEAD(&dev->maplist->head); + /* dev_priv_size can be changed by a driver in driver_register_fns */ dev->dev_priv_size = sizeof(u32); @@ -658,6 +644,10 @@ static int __init drm_init( void ) */ static void __exit drm_cleanup( drm_device_t *dev ) { + drm_map_t *map; + drm_map_list_t *r_list; + struct list_head *list, *list_next; + DRM_DEBUG( "\n" ); if (!dev) { DRM_ERROR("cleanup called no dev\n"); @@ -666,6 +656,44 @@ static void __exit drm_cleanup( drm_device_t *dev ) DRM(takedown)(dev); + if( dev->maplist ) { + list_for_each_safe( list, list_next, &dev->maplist->head ) { + r_list = (drm_map_list_t *)list; + + if ( ( map = r_list->map ) ) { + switch ( map->type ) { + case _DRM_REGISTERS: + DRM(ioremapfree)( map->handle, map->size, dev ); + break; + + case _DRM_FRAME_BUFFER: +#if __OS_HAS_MTRR + if ( dev->driver_features & DRIVER_USE_MTRR) { + if ( map->mtrr >= 0 ) { + int retcode; + retcode = mtrr_del( map->mtrr, + map->offset, + map->size ); + DRM_DEBUG( "mtrr_del=%d\n", retcode ); + } + } +#endif + break; + + case _DRM_SHM: + case _DRM_AGP: + case _DRM_SCATTER_GATHER: + DRM_DEBUG("Extra maplist item\n"); + break; + } + DRM(free)(map, sizeof(*map), DRM_MEM_MAPS); + } + list_del( list ); + DRM(free)(r_list, sizeof(*r_list), DRM_MEM_MAPS); + } + DRM(free)(dev->maplist, sizeof(*dev->maplist), DRM_MEM_MAPS); + dev->maplist = NULL; + } if (DRM(fb_loaded)==0) pci_disable_device(dev->pdev); @@ -916,6 +944,7 @@ int DRM(release)( struct inode *inode, struct file *filp ) list_del( &pos->head ); DRM(free)( pos, sizeof(*pos), DRM_MEM_CTXLIST ); + --dev->ctx_count; } } } |