summaryrefslogtreecommitdiff
path: root/linux
diff options
context:
space:
mode:
Diffstat (limited to 'linux')
-rw-r--r--linux/Makefile7
-rw-r--r--linux/Makefile.kernel2
-rw-r--r--linux/drmP.h2
-rw-r--r--linux/drm_bufs.h107
-rw-r--r--linux/drm_drv.h71
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;
}
}
}