Here's a new version that should be compatible with all of the cases: 1) multiple maps 2) old X doing AddMap 3) fixed X doing GetMap - X needs to switch to this after all the drivers get fixed 4) drivers that have implemented permanent maps 4) drivers that have not implemented permanent maps
I have a fix for my editor now that strips trailing blanks so I'm generating a few extra diffs but this will get rid of the trailing blanks in CVS after a few check ins. The reason for this change is to prevent X from moving the address of the framebuffer in PCI space. That is an illegal thing for X to do on Linux without also making the appropriate kernel calls. After all of the DRM drivers implement permanent mapping, X will get an error if it tried to move the framebuffer address.
===== linux/drm_bufs.h 1.8 vs edited ===== --- 1.8/linux/drm_bufs.h Sun Sep 5 21:22:06 2004 +++ edited/linux/drm_bufs.h Tue Sep 7 11:31:45 2004 @@ -1,7 +1,7 @@ /** - * \file drm_bufs.h + * \file drm_bufs.h * Generic buffer template - * + * * \author Rickard E. (Rik) Faith <[EMAIL PROTECTED]> * \author Gareth Hughes <[EMAIL PROTECTED]> */ @@ -39,7 +39,7 @@ /** * Compute size order. Returns the exponent of the smaller power of two which * is greater or equal to given number. - * + * * \param size size. * \return order. * @@ -59,6 +59,7 @@ return order; } +static int permanent_maps = 0; /** * 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 @@ -80,7 +81,7 @@ 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; @@ -98,7 +99,7 @@ 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 @@ -116,7 +117,8 @@ down(&dev->struct_sem); list_add(&list->head, &dev->maplist->head); up(&dev->struct_sem); - + + permanent_maps = 1; DRM_DEBUG("finished\n"); return 0; @@ -175,19 +177,24 @@ switch ( map->type ) { case _DRM_REGISTERS: 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 permanent maps are implemented, maps must match */ + if (permanent_maps) { + 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 && + _entry->map->offset == map->offset && + _entry->map->size == map->size ) { + 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; + } } + /* addmap didn't match an existing permanent maps, that's an error */ + return -EINVAL; } #if !defined(__sparc__) && !defined(__alpha__) && !defined(__ia64__) if ( map->offset + map->size < map->offset || @@ -309,7 +316,7 @@ sizeof(request))) { return -EFAULT; } - + down(&dev->struct_sem); list = &dev->maplist->head; list_for_each(list, &dev->maplist->head) { @@ -328,7 +335,7 @@ 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); @@ -412,7 +419,7 @@ * \param cmd command. * \param arg pointer to a drm_buf_desc_t request. * \return zero on success or a negative number on failure. - * + * * After some sanity checks creates a drm_buf structure for each buffer and * reallocates the buffer list of the same size order to accommodate the new * buffers. @@ -837,7 +844,7 @@ drm_buf_t **temp_buflist; if (!drm_core_check_feature(dev, DRIVER_SG)) return -EINVAL; - + if ( !dma ) return -EINVAL; if ( copy_from_user( &request, argp, sizeof(request) ) ) @@ -1000,7 +1007,7 @@ drm_buf_desc_t request; drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; - + if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA)) return -EINVAL; @@ -1160,14 +1167,14 @@ } /** - * Unreserve the buffers in list, previously reserved using drmDMA. + * Unreserve the buffers in list, previously reserved using drmDMA. * * \param inode device inode. * \param filp file pointer. * \param cmd command. * \param arg pointer to a drm_buf_free structure. * \return zero on success or a negative number on failure. - * + * * Calls free_buffer() for each used buffer. * This function is primarily used for debugging. */