aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Anholt <anholt@freebsd.org>2005-02-05 08:00:14 +0000
committerEric Anholt <anholt@freebsd.org>2005-02-05 08:00:14 +0000
commit080a547d4d42d42e08a525aca9a62b5ece7616d5 (patch)
tree6996ba882ce26098fb69ba336969d88aa47dc39c
parent270ca5f3cee387c10a06a4d58e50c5d0e1cea837 (diff)
- Implement drm_initmap, and extend it with the resource number to help
FreeBSD. Add drm_get_resource_{start|len} so linux-specific stuff doesn't need to be in shared code. - Fix mach64 build by using __DECONST to work around passing a const pointer to useracc, which is unfortunately not marked const. - Get rid of a lot of maplist code by not having dev->maplist be a pointer, and by sticking the link entries directly in drm_local_map_t rather than having a separate structure for the linked list. - Factor out map uninit and removal into its own routine, rather than duplicating in both drm_takedown() and drm_rmmap(). - Hook up more driver functions, and correct FreeBSD-specific bits of radeon_cp.c, making radeon work. - Baby steps towards using bus_space as we should.
-rw-r--r--bsd-core/drmP.h56
-rw-r--r--bsd-core/drm_bufs.c254
-rw-r--r--bsd-core/drm_context.c4
-rw-r--r--bsd-core/drm_drv.c75
-rw-r--r--bsd-core/drm_fops.c11
-rw-r--r--bsd-core/drm_ioctl.c6
-rw-r--r--bsd-core/drm_memory.c10
-rw-r--r--bsd-core/drm_sysctl.c7
-rw-r--r--bsd-core/drm_vm.c8
-rw-r--r--bsd-core/radeon_drv.c4
-rw-r--r--linux-core/drmP.h7
-rw-r--r--linux-core/drm_bufs.c14
-rw-r--r--shared-core/radeon_cp.c26
-rw-r--r--shared-core/savage_bci.c34
14 files changed, 332 insertions, 184 deletions
diff --git a/bsd-core/drmP.h b/bsd-core/drmP.h
index 43e22039..b32a4422 100644
--- a/bsd-core/drmP.h
+++ b/bsd-core/drmP.h
@@ -292,24 +292,24 @@ typedef u_int8_t u8;
*(volatile u_int32_t *)(((unsigned long)(map)->handle) + (offset)) = val
#define DRM_VERIFYAREA_READ( uaddr, size ) \
- (!useracc((caddr_t)uaddr, size, VM_PROT_READ))
+ (!useracc(__DECONST(caddr_t, uaddr), size, VM_PROT_READ))
#else /* __FreeBSD__ */
typedef vaddr_t vm_offset_t;
#define DRM_READ8(map, offset) \
- bus_space_read_1( (map)->iot, (map)->ioh, (offset))
+ bus_space_read_1( (map)->bst, (map)->bsh, (offset))
#define DRM_READ16(map, offset) \
- bus_space_read_2( (map)->iot, (map)->ioh, (offset))
+ bus_space_read_2( (map)->bst, (map)->bsh, (offset))
#define DRM_READ32(map, offset) \
- bus_space_read_4( (map)->iot, (map)->ioh, (offset))
+ bus_space_read_4( (map)->bst, (map)->bsh, (offset))
#define DRM_WRITE8(map, offset, val) \
- bus_space_write_1((map)->iot, (map)->ioh, (offset), (val))
+ bus_space_write_1((map)->bst, (map)->bsh, (offset), (val))
#define DRM_WRITE16(map, offset, val) \
- bus_space_write_2((map)->iot, (map)->ioh, (offset), (val))
+ bus_space_write_2((map)->bst, (map)->bsh, (offset), (val))
#define DRM_WRITE32(map, offset, val) \
- bus_space_write_4((map)->iot, (map)->ioh, (offset), (val))
+ bus_space_write_4((map)->bst, (map)->bsh, (offset), (val))
#define DRM_VERIFYAREA_READ( uaddr, size ) \
(!uvm_useracc((caddr_t)uaddr, size, VM_PROT_READ))
@@ -373,10 +373,9 @@ do { \
#define DRM_GETSAREA() \
do { \
- drm_map_list_entry_t *listentry; \
+ drm_local_map_t *map; \
DRM_SPINLOCK_ASSERT(&dev->dev_lock); \
- TAILQ_FOREACH(listentry, dev->maplist, link) { \
- drm_local_map_t *map = listentry->map; \
+ TAILQ_FOREACH(map, &dev->maplist, link) { \
if (map->type == _DRM_SHM && \
map->flags & _DRM_CONTAINS_LOCK) { \
dev_priv->sarea = map; \
@@ -560,6 +559,8 @@ typedef struct drm_sg_mem {
dma_addr_t *busaddr;
} drm_sg_mem_t;
+typedef TAILQ_HEAD(drm_map_list, drm_local_map) drm_map_list_t;
+
typedef struct drm_local_map {
unsigned long offset; /* Physical address (0 for SAREA)*/
unsigned long size; /* Physical size (bytes) */
@@ -569,16 +570,14 @@ typedef struct drm_local_map {
/* Kernel-space: kernel-virtual address */
int mtrr; /* Boolean: MTRR used */
/* Private data */
- bus_space_tag_t iot;
- bus_space_handle_t ioh;
+ int rid; /* PCI resource ID for bus_space */
+ int kernel_owned; /* Boolean: 1 = initmapped, 0 = addmapped */
+ struct resource *bsr;
+ bus_space_tag_t bst;
+ bus_space_handle_t bsh;
+ TAILQ_ENTRY(drm_local_map) link;
} drm_local_map_t;
-typedef TAILQ_HEAD(drm_map_list, drm_map_list_entry) drm_map_list_t;
-typedef struct drm_map_list_entry {
- TAILQ_ENTRY(drm_map_list_entry) link;
- drm_local_map_t *map;
-} drm_map_list_entry_t;
-
TAILQ_HEAD(drm_vbl_sig_list, drm_vbl_sig);
typedef struct drm_vbl_sig {
TAILQ_ENTRY(drm_vbl_sig) link;
@@ -603,7 +602,8 @@ struct drm_device {
int (*postcleanup)(struct drm_device *);
int (*presetup)(struct drm_device *);
int (*postsetup)(struct drm_device *);
- void (*open_helper)(struct drm_device *, drm_file_t *);
+ int (*open_helper)(struct drm_device *, drm_file_t *);
+ void (*free_filp_priv)(struct drm_device *, drm_file_t *);
void (*release)(struct drm_device *, void *filp);
int (*dma_ioctl)(DRM_IOCTL_ARGS);
void (*dma_ready)(struct drm_device *);
@@ -676,7 +676,7 @@ struct drm_device {
drm_magic_head_t magiclist[DRM_HASH_SIZE];
/* Linked list of mappable regions. Protected by dev_lock */
- drm_map_list_t *maplist;
+ drm_map_list_t maplist;
drm_local_map_t **context_sareas;
int max_context;
@@ -793,6 +793,11 @@ int drm_lock_free(drm_device_t *dev,
unsigned int context);
/* Buffer management support (drm_bufs.c) */
+unsigned long drm_get_resource_start(drm_device_t *dev, unsigned int resource);
+unsigned long drm_get_resource_len(drm_device_t *dev, unsigned int resource);
+int drm_initmap(drm_device_t *dev, unsigned long start, unsigned long len,
+ unsigned int resource, int type, int flags);
+void drm_remove_map(drm_device_t *dev, drm_local_map_t *map);
int drm_order(unsigned long size);
/* DMA support (drm_dma.c) */
@@ -919,11 +924,12 @@ static __inline__ void drm_core_ioremapfree(struct drm_local_map *map, struct dr
static __inline__ struct drm_local_map *drm_core_findmap(struct drm_device *dev, unsigned long offset)
{
- drm_map_list_entry_t *listentry;
- TAILQ_FOREACH(listentry, dev->maplist, link) {
- if ( listentry->map->offset == offset ) {
- return listentry->map;
- }
+ drm_local_map_t *map;
+
+ DRM_SPINLOCK_ASSERT(&dev->dev_lock);
+ TAILQ_FOREACH(map, &dev->maplist, link) {
+ if (map->offset == offset)
+ return map;
}
return NULL;
}
diff --git a/bsd-core/drm_bufs.c b/bsd-core/drm_bufs.c
index 26007a4d..0fefb8f5 100644
--- a/bsd-core/drm_bufs.c
+++ b/bsd-core/drm_bufs.c
@@ -48,19 +48,151 @@ int drm_order(unsigned long size)
return order;
}
+unsigned long drm_get_resource_start(drm_device_t *dev, unsigned int resource)
+{
+ struct resource *bsr;
+ unsigned long offset;
+
+ resource = resource * 4 + 0x10;
+
+ bsr = bus_alloc_resource_any(dev->device, SYS_RES_MEMORY, &resource,
+ RF_ACTIVE | RF_SHAREABLE);
+ if (bsr == NULL) {
+ DRM_ERROR("Couldn't find resource 0x%x\n", resource);
+ return 0;
+ }
+
+ offset = rman_get_start(bsr);
+
+ bus_release_resource(dev->device, SYS_RES_MEMORY, resource, bsr);
+
+ return offset;
+}
+
+unsigned long drm_get_resource_len(drm_device_t *dev, unsigned int resource)
+{
+ struct resource *bsr;
+ unsigned long len;
+
+ resource = resource * 4 + 0x10;
+
+ bsr = bus_alloc_resource_any(dev->device, SYS_RES_MEMORY, &resource,
+ RF_ACTIVE | RF_SHAREABLE);
+ if (bsr == NULL) {
+ DRM_ERROR("Couldn't find resource 0x%x\n", resource);
+ return ENOMEM;
+ }
+
+ len = rman_get_size(bsr);
+
+ bus_release_resource(dev->device, SYS_RES_MEMORY, resource, bsr);
+
+ return len;
+}
+
+int drm_initmap(drm_device_t *dev, unsigned long start, unsigned long len,
+ unsigned int resource, int type, int flags)
+{
+ drm_local_map_t *map;
+ struct resource *bsr;
+
+ if (type != _DRM_REGISTERS && type != _DRM_FRAME_BUFFER)
+ return EINVAL;
+ if (len == 0)
+ return EINVAL;
+
+ map = malloc(sizeof(*map), M_DRM, M_ZERO | M_NOWAIT);
+ if (map == NULL)
+ return ENOMEM;
+
+ map->rid = resource * 4 + 0x10;
+ bsr = bus_alloc_resource_any(dev->device, SYS_RES_MEMORY, &map->rid,
+ RF_ACTIVE | RF_SHAREABLE);
+ if (bsr == NULL) {
+ DRM_ERROR("Couldn't allocate %s resource\n",
+ ((type == _DRM_REGISTERS) ? "mmio" : "framebuffer"));
+ free(map, M_DRM);
+ return ENOMEM;
+ }
+
+ map->kernel_owned = 1;
+ map->type = type;
+ map->flags = flags;
+ map->bsr = bsr;
+ map->bst = rman_get_bustag(bsr);
+ map->bsh = rman_get_bushandle(bsr);
+ map->offset = start;
+ map->size = len;
+
+ if (type == _DRM_REGISTERS)
+ map->handle = rman_get_virtual(bsr);
+
+ DRM_DEBUG("initmap %d,0x%x@0x%lx/0x%lx\n", map->type, map->flags,
+ map->offset, map->size);
+
+ if (map->flags & _DRM_WRITE_COMBINING) {
+ int err;
+
+ err = drm_mtrr_add(map->offset, map->size, DRM_MTRR_WC);
+ if (err == 0)
+ map->mtrr = 1;
+ }
+
+ DRM_LOCK();
+ TAILQ_INSERT_TAIL(&dev->maplist, map, link);
+ DRM_UNLOCK();
+
+ return 0;
+}
+
int drm_addmap(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_map_t request;
drm_local_map_t *map;
- drm_map_list_entry_t *list;
+ dma_addr_t bus_addr;
if (!(dev->flags & (FREAD|FWRITE)))
return DRM_ERR(EACCES); /* Require read/write */
DRM_COPY_FROM_USER_IOCTL( request, (drm_map_t *)data, sizeof(drm_map_t) );
- map = malloc(sizeof(*map), M_DRM, M_NOWAIT);
+ /* Only allow shared memory to be removable since we only keep enough
+ * book keeping information about shared memory to allow for removal
+ * when processes fork.
+ */
+ if ((request.flags & _DRM_REMOVABLE) && request.type != _DRM_SHM)
+ return EINVAL;
+ if ((request.offset & PAGE_MASK) || (request.size & PAGE_MASK))
+ return EINVAL;
+ if (request.offset + request.size < request.offset)
+ return EINVAL;
+
+ DRM_ERROR("offset = 0x%08lx, size = 0x%08lx, type = %d\n",
+ request.offset, request.size, request.type);
+
+ /* Check if this is just another version of a kernel-allocated map, and
+ * just hand that back if so.
+ */
+ if (request.type == _DRM_REGISTERS || request.type == _DRM_FRAME_BUFFER)
+ {
+ DRM_LOCK();
+ TAILQ_FOREACH(map, &dev->maplist, link) {
+ if (map->kernel_owned && map->type == request.type &&
+ map->offset == request.offset) {
+ /* XXX: this size setting is questionable. */
+ map->size = request.size;
+ DRM_DEBUG("Found kernel map %d\n", request.type);
+ goto done;
+ }
+ }
+ DRM_UNLOCK();
+ }
+
+ /* Allocate a new map structure, fill it in, and do any type-specific
+ * initialization necessary.
+ */
+ map = malloc(sizeof(*map), M_DRM, M_ZERO | M_NOWAIT);
if ( !map )
return DRM_ERR(ENOMEM);
@@ -68,31 +200,10 @@ int drm_addmap(DRM_IOCTL_ARGS)
map->size = request.size;
map->type = request.type;
map->flags = request.flags;
- map->mtrr = 0;
- map->handle = 0;
-
- /* Only allow shared memory to be removable since we only keep enough
- * book keeping information about shared memory to allow for removal
- * when processes fork.
- */
- if ( (map->flags & _DRM_REMOVABLE) && map->type != _DRM_SHM ) {
- free(map, M_DRM);
- return DRM_ERR(EINVAL);
- }
- DRM_DEBUG( "offset = 0x%08lx, size = 0x%08lx, type = %d\n",
- map->offset, map->size, map->type );
- if ( (map->offset & PAGE_MASK) || (map->size & PAGE_MASK) ) {
- free(map, M_DRM);
- return DRM_ERR(EINVAL);
- }
- if (map->offset + map->size < map->offset) {
- free(map, M_DRM);
- return DRM_ERR(EINVAL);
- }
switch ( map->type ) {
case _DRM_REGISTERS:
- drm_core_ioremap(map, dev);
+ drm_ioremap(dev, map);
if (!(map->flags & _DRM_WRITE_COMBINING))
break;
/* FALLTHROUGH */
@@ -133,29 +244,34 @@ int drm_addmap(DRM_IOCTL_ARGS)
}
map->offset = map->offset + dev->sg->handle;
break;
-
+ case _DRM_CONSISTENT:
+ map->handle = drm_pci_alloc(dev, map->size, map->size,
+ 0xfffffffful, &bus_addr);
+ if (map->handle == NULL) {
+ free(map, M_DRM);
+ return ENOMEM;
+ }
+ map->offset = (unsigned long)bus_addr;
+ break;
default:
free(map, M_DRM);
return DRM_ERR(EINVAL);
}
- list = malloc(sizeof(*list), M_DRM, M_NOWAIT | M_ZERO);
- if (list == NULL) {
- free(map, M_DRM);
- return DRM_ERR(EINVAL);
- }
- list->map = map;
-
DRM_LOCK();
- TAILQ_INSERT_TAIL(dev->maplist, list, link);
- DRM_UNLOCK();
+ TAILQ_INSERT_TAIL(&dev->maplist, map, link);
+done:
+ /* Jumped to, with lock held, when a kernel map is found. */
request.offset = map->offset;
request.size = map->size;
request.type = map->type;
request.flags = map->flags;
request.mtrr = map->mtrr;
request.handle = map->handle;
+ DRM_UNLOCK();
+
+ DRM_DEBUG("Added map %d 0x%lx/0x%lx\n", request.type, request.offset, request.size);
if ( request.type != _DRM_SHM ) {
request.handle = (void *)request.offset;
@@ -166,6 +282,44 @@ int drm_addmap(DRM_IOCTL_ARGS)
return 0;
}
+void drm_remove_map(drm_device_t *dev, drm_local_map_t *map)
+{
+ DRM_SPINLOCK_ASSERT(&dev->dev_lock);
+
+ TAILQ_REMOVE(&dev->maplist, map, link);
+
+ switch (map->type) {
+ case _DRM_REGISTERS:
+ if (map->bsr == NULL)
+ drm_ioremapfree(map);
+ /* FALLTHROUGH */
+ case _DRM_FRAME_BUFFER:
+ if (map->mtrr) {
+ int __unused retcode;
+
+ retcode = drm_mtrr_del(map->offset, map->size,
+ DRM_MTRR_WC);
+ DRM_DEBUG("mtrr_del = %d\n", retcode);
+ }
+ break;
+ case _DRM_SHM:
+ free(map->handle, M_DRM);
+ break;
+ case _DRM_AGP:
+ case _DRM_SCATTER_GATHER:
+ break;
+ case _DRM_CONSISTENT:
+ drm_pci_free(dev, map->size, map->handle, map->offset);
+ break;
+ }
+
+ if (map->bsr != NULL) {
+ bus_release_resource(dev->device, SYS_RES_MEMORY, map->rid,
+ map->bsr);
+ }
+
+ free(map, M_DRM);
+}
/* Remove a map private from list and deallocate resources if the mapping
* isn't in use.
@@ -174,50 +328,28 @@ int drm_addmap(DRM_IOCTL_ARGS)
int drm_rmmap(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
- drm_map_list_entry_t *list;
drm_local_map_t *map;
drm_map_t request;
DRM_COPY_FROM_USER_IOCTL( request, (drm_map_t *)data, sizeof(request) );
DRM_LOCK();
- TAILQ_FOREACH(list, dev->maplist, link) {
- map = list->map;
+ TAILQ_FOREACH(map, &dev->maplist, link) {
if (map->handle == request.handle &&
map->flags & _DRM_REMOVABLE)
break;
}
/* No match found. */
- if (list == NULL) {
+ if (map == NULL) {
DRM_UNLOCK();
return DRM_ERR(EINVAL);
}
- TAILQ_REMOVE(dev->maplist, list, link);
- DRM_UNLOCK();
- free(list, M_DRM);
+ drm_remove_map(dev, map);
+
+ DRM_UNLOCK();
- switch (map->type) {
- case _DRM_REGISTERS:
- case _DRM_FRAME_BUFFER:
- if (map->mtrr) {
- int __unused retcode;
-
- retcode = drm_mtrr_del(map->offset, map->size,
- DRM_MTRR_WC);
- DRM_DEBUG("mtrr_del = %d\n", retcode);
- }
- drm_ioremapfree(map);
- break;
- case _DRM_SHM:
- free(map->handle, M_DRM);
- break;
- case _DRM_AGP:
- case _DRM_SCATTER_GATHER:
- break;
- }
- free(map, M_DRM);
return 0;
}
diff --git a/bsd-core/drm_context.c b/bsd-core/drm_context.c
index 714edccc..368bdfb4 100644
--- a/bsd-core/drm_context.c
+++ b/bsd-core/drm_context.c
@@ -165,14 +165,12 @@ int drm_setsareactx( DRM_IOCTL_ARGS )
DRM_DEVICE;
drm_ctx_priv_map_t request;
drm_local_map_t *map = NULL;
- drm_map_list_entry_t *list;
DRM_COPY_FROM_USER_IOCTL( request, (drm_ctx_priv_map_t *)data,
sizeof(request) );
DRM_LOCK();
- TAILQ_FOREACH(list, dev->maplist, link) {
- map=list->map;
+ TAILQ_FOREACH(map, &dev->maplist, link) {
if (map->handle == request.handle) {
if (dev->max_context < 0)
goto bad;
diff --git a/bsd-core/drm_drv.c b/bsd-core/drm_drv.c
index fb9313af..102045c7 100644
--- a/bsd-core/drm_drv.c
+++ b/bsd-core/drm_drv.c
@@ -377,8 +377,7 @@ static int drm_setup(drm_device_t *dev)
static int drm_takedown(drm_device_t *dev)
{
drm_magic_entry_t *pt, *next;
- drm_local_map_t *map;
- drm_map_list_entry_t *list;
+ drm_local_map_t *map, *mapsave;
int i;
DRM_SPINLOCK_ASSERT(&dev->dev_lock);
@@ -432,38 +431,11 @@ static int drm_takedown(drm_device_t *dev)
dev->sg = NULL;
}
- if (dev->maplist != NULL) {
- while ((list=TAILQ_FIRST(dev->maplist))) {
- map = list->map;
- switch ( map->type ) {
- case _DRM_REGISTERS:
- drm_ioremapfree(map);
- /* FALLTHROUGH */
- case _DRM_FRAME_BUFFER:
- if (map->mtrr) {
- int __unused retcode;
-
- retcode = drm_mtrr_del(map->offset,
- map->size, DRM_MTRR_WC);
- DRM_DEBUG("mtrr_del = %d", retcode);
- }
- break;
- case _DRM_SHM:
- free(map->handle, M_DRM);
- break;
-
- case _DRM_AGP:
- case _DRM_SCATTER_GATHER:
- /* Do nothing here, because this is all
- * handled in the AGP/GART/SG functions.
- */
- break;
- }
- TAILQ_REMOVE(dev->maplist, list, link);
- free(list, M_DRM);
- free(map, M_DRM);
- }
- }
+ /* Clean up maps that weren't set up by the driver. */
+ TAILQ_FOREACH_SAFE(map, &dev->maplist, link, mapsave) {
+ if (!map->kernel_owned)
+ drm_remove_map(dev, map);
+ }
drm_dma_takedown(dev);
if ( dev->lock.hw_lock ) {
@@ -495,9 +467,6 @@ static int drm_init(device_t nbdev)
else
dev->device = nbdev;
- if (dev->preinit != NULL)
- dev->preinit(dev, 0);
-
dev->devnode = make_dev(&drm_cdevsw,
unit,
DRM_DEV_UID,
@@ -510,9 +479,6 @@ static int drm_init(device_t nbdev)
#elif defined(__NetBSD__) || defined(__OpenBSD__)
dev = nbdev;
unit = minor(dev->device.dv_unit);
-
- if (dev->preinit != NULL)
- dev->preinit(dev, 0);
#endif
dev->irq = pci_get_irq(dev->device);
@@ -522,12 +488,7 @@ static int drm_init(device_t nbdev)
dev->pci_slot = pci_get_slot(dev->device);
dev->pci_func = pci_get_function(dev->device);
- dev->maplist = malloc(sizeof(*dev->maplist), M_DRM, M_WAITOK);
- if (dev->maplist == NULL) {
- retcode = ENOMEM;
- goto error;
- }
- TAILQ_INIT(dev->maplist);
+ TAILQ_INIT(&dev->maplist);
drm_mem_init();
#ifdef __FreeBSD__
@@ -535,10 +496,18 @@ static int drm_init(device_t nbdev)
#endif
TAILQ_INIT(&dev->files);
+ if (dev->preinit != NULL) {
+ retcode = dev->preinit(dev, 0);
+ if (retcode != 0)
+ goto error;
+ }
+
if (dev->use_agp) {
- dev->agp = drm_agp_init();
+ if (drm_device_is_agp(dev))
+ dev->agp = drm_agp_init();
if (dev->require_agp && dev->agp == NULL) {
- DRM_ERROR("Cannot initialize the agpgart module.\n");
+ DRM_ERROR("Card isn't AGP, or couldn't initialize "
+ "AGP.\n");
retcode = DRM_ERR(ENOMEM);
goto error;
}
@@ -581,7 +550,6 @@ error:
mtx_destroy(&dev->dev_lock);
#endif
#endif
- free(dev->maplist, M_DRM);
return retcode;
}
@@ -591,6 +559,7 @@ error:
*/
static void drm_cleanup(drm_device_t *dev)
{
+ drm_local_map_t *map;
DRM_DEBUG( "\n" );
@@ -613,6 +582,11 @@ static void drm_cleanup(drm_device_t *dev)
drm_takedown(dev);
DRM_UNLOCK();
+ /* Clean up any maps left over that had been allocated by the driver. */
+ while ((map = TAILQ_FIRST(&dev->maplist)) != NULL) {
+ drm_remove_map(dev, map);
+ }
+
if ( dev->agp ) {
drm_agp_uninit();
free(dev->agp, M_DRM);
@@ -626,7 +600,6 @@ static void drm_cleanup(drm_device_t *dev)
#if defined(__FreeBSD__) && __FreeBSD_version >= 500000
mtx_destroy(&dev->dev_lock);
#endif
- free(dev->maplist, M_DRM);
}
@@ -778,6 +751,8 @@ int drm_close(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p)
#endif /* __NetBSD__ || __OpenBSD__ */
if (--priv->refs == 0) {
+ if (dev->free_filp_priv != NULL)
+ dev->free_filp_priv(dev, priv);
TAILQ_REMOVE(&dev->files, priv, link);
free(priv, M_DRM);
}
diff --git a/bsd-core/drm_fops.c b/bsd-core/drm_fops.c
index eeb4847a..44c2b8de 100644
--- a/bsd-core/drm_fops.c
+++ b/bsd-core/drm_fops.c
@@ -58,6 +58,7 @@ int drm_open_helper(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p,
{
int m = minor(kdev);
drm_file_t *priv;
+ int retcode;
if (flags & O_EXCL)
return EBUSY; /* No exclusive opens */
@@ -88,8 +89,14 @@ int drm_open_helper(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p,
priv->ioctl_count = 0;
priv->authenticated = !DRM_SUSER(p);
- if (dev->open_helper)
- dev->open_helper(dev, priv);
+ if (dev->open_helper) {
+ retcode = dev->open_helper(dev, priv);
+ if (retcode != 0) {
+ free(priv, M_DRM);
+ DRM_UNLOCK();
+ return retcode;
+ }
+ }
TAILQ_INSERT_TAIL(&dev->files, priv, link);
}
diff --git a/bsd-core/drm_ioctl.c b/bsd-core/drm_ioctl.c
index d40a7c90..62f42210 100644
--- a/bsd-core/drm_ioctl.c
+++ b/bsd-core/drm_ioctl.c
@@ -147,7 +147,6 @@ int drm_getmap(DRM_IOCTL_ARGS)
DRM_DEVICE;
drm_map_t map;
drm_local_map_t *mapinlist;
- drm_map_list_entry_t *list;
int idx;
int i = 0;
@@ -161,8 +160,7 @@ int drm_getmap(DRM_IOCTL_ARGS)
return DRM_ERR(EINVAL);
}
- TAILQ_FOREACH(list, dev->maplist, link) {
- mapinlist = list->map;
+ TAILQ_FOREACH(mapinlist, &dev->maplist, link) {
if (i==idx) {
map.offset = mapinlist->offset;
map.size = mapinlist->size;
@@ -177,7 +175,7 @@ int drm_getmap(DRM_IOCTL_ARGS)
DRM_UNLOCK();
- if (!list)
+ if (mapinlist == NULL)
return EINVAL;
DRM_COPY_TO_USER_IOCTL( (drm_map_t *)data, map, sizeof(map) );
diff --git a/bsd-core/drm_memory.c b/bsd-core/drm_memory.c
index 8a49d40e..497cd83f 100644
--- a/bsd-core/drm_memory.c
+++ b/bsd-core/drm_memory.c
@@ -79,11 +79,11 @@ void *drm_ioremap(drm_device_t *dev, drm_local_map_t *map)
#ifdef __FreeBSD__
return pmap_mapdev(map->offset, map->size);
#elif defined(__NetBSD__) || defined(__OpenBSD__)
- map->iot = dev->pa.pa_memt;
- if (bus_space_map(map->iot, map->offset, map->size,
- BUS_SPACE_MAP_LINEAR, &map->ioh))
+ map->bst = dev->pa.pa_memt;
+ if (bus_space_map(map->bst, map->offset, map->size,
+ BUS_SPACE_MAP_LINEAR, &map->bsh))
return NULL;
- return bus_space_vaddr(map->iot, map->ioh);
+ return bus_space_vaddr(map->bst, map->bsh);
#endif
}
@@ -92,7 +92,7 @@ void drm_ioremapfree(drm_local_map_t *map)
#ifdef __FreeBSD__
pmap_unmapdev((vm_offset_t) map->handle, map->size);
#elif defined(__NetBSD__) || defined(__OpenBSD__)
- bus_space_unmap(map->iot, map->ioh, map->size);
+ bus_space_unmap(map->bst, map->bsh, map->size);
#endif
}
diff --git a/bsd-core/drm_sysctl.c b/bsd-core/drm_sysctl.c
index 220559d9..e4e336b4 100644
--- a/bsd-core/drm_sysctl.c
+++ b/bsd-core/drm_sysctl.c
@@ -150,7 +150,6 @@ static int drm_vm_info DRM_SYSCTL_HANDLER_ARGS
{
drm_device_t *dev = arg1;
drm_local_map_t *map, *tempmaps;
- drm_map_list_entry_t *listentry;
const char *types[] = { "FB", "REG", "SHM", "AGP", "SG" };
const char *type, *yesno;
int i, mapcount;
@@ -163,7 +162,7 @@ static int drm_vm_info DRM_SYSCTL_HANDLER_ARGS
DRM_LOCK();
mapcount = 0;
- TAILQ_FOREACH(listentry, dev->maplist, link)
+ TAILQ_FOREACH(map, &dev->maplist, link)
mapcount++;
tempmaps = malloc(sizeof(drm_local_map_t) * mapcount, M_DRM, M_NOWAIT);
@@ -173,8 +172,8 @@ static int drm_vm_info DRM_SYSCTL_HANDLER_ARGS
}
i = 0;
- TAILQ_FOREACH(listentry, dev->maplist, link)
- tempmaps[i++] = *listentry->map;
+ TAILQ_FOREACH(map, &dev->maplist, link)
+ tempmaps[i++] = *map;
DRM_UNLOCK();
diff --git a/bsd-core/drm_vm.c b/bsd-core/drm_vm.c
index 1b5d4d3f..2b5f0ef4 100644
--- a/bsd-core/drm_vm.c
+++ b/bsd-core/drm_vm.c
@@ -35,8 +35,7 @@ paddr_t drm_mmap(dev_t kdev, off_t offset, int prot)
#endif
{
DRM_DEVICE;
- drm_local_map_t *map = NULL;
- drm_map_list_entry_t *listentry = NULL;
+ drm_local_map_t *map;
drm_file_t *priv;
drm_map_type_t type;
@@ -81,13 +80,12 @@ paddr_t drm_mmap(dev_t kdev, off_t offset, int prot)
for performance, even if the list was a
bit longer. */
DRM_LOCK();
- TAILQ_FOREACH(listentry, dev->maplist, link) {
- map = listentry->map;
+ TAILQ_FOREACH(map, &dev->maplist, link) {
if (offset >= map->offset && offset < map->offset + map->size)
break;
}
- if (!listentry) {
+ if (map == NULL) {
DRM_UNLOCK();
DRM_DEBUG("can't find map\n");
return -1;
diff --git a/bsd-core/radeon_drv.c b/bsd-core/radeon_drv.c
index 57ab3b9d..bac6205d 100644
--- a/bsd-core/radeon_drv.c
+++ b/bsd-core/radeon_drv.c
@@ -45,8 +45,12 @@ extern int radeon_max_ioctl;
static void radeon_configure(drm_device_t *dev)
{
dev->dev_priv_size = sizeof(drm_radeon_buf_priv_t);
+ dev->preinit = radeon_preinit;
+ dev->postcleanup = radeon_postcleanup;
dev->prerelease = radeon_driver_prerelease;
dev->pretakedown = radeon_driver_pretakedown;
+ dev->open_helper = radeon_driver_open_helper;
+ dev->free_filp_priv = radeon_driver_free_filp_priv;
dev->vblank_wait = radeon_driver_vblank_wait;
dev->irq_preinstall = radeon_driver_irq_preinstall;
dev->irq_postinstall = radeon_driver_irq_postinstall;
diff --git a/linux-core/drmP.h b/linux-core/drmP.h
index bbc7a237..e5789c65 100644
--- a/linux-core/drmP.h
+++ b/linux-core/drmP.h
@@ -851,7 +851,8 @@ extern int drm_addmap(struct inode *inode, struct file *filp,
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);
+ unsigned int size, unsigned int resource, 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,
@@ -863,6 +864,10 @@ extern int drm_freebufs(struct inode *inode, struct file *filp,
extern int drm_mapbufs(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern int drm_order(unsigned long size);
+extern unsigned long drm_get_resource_start(drm_device_t *dev,
+ unsigned int resource);
+extern unsigned long drm_get_resource_len(drm_device_t *dev,
+ unsigned int resource);
/* DMA support (drm_dma.h) */
extern int drm_dma_setup(drm_device_t * dev);
diff --git a/linux-core/drm_bufs.c b/linux-core/drm_bufs.c
index 97574a37..6339ac21 100644
--- a/linux-core/drm_bufs.c
+++ b/linux-core/drm_bufs.c
@@ -36,13 +36,25 @@
#include <linux/vmalloc.h>
#include "drmP.h"
+unsigned long drm_get_resource_start(drm_device_t *dev, unsigned int resource)
+{
+ return pci_resource_start(dev->pdev, resource);
+}
+EXPORT_SYMBOL(drm_get_resource_start);
+
+unsigned long drm_get_resource_len(drm_device_t *dev, unsigned int resource)
+{
+ return pci_resource_len(dev->pdev, resource);
+}
+EXPORT_SYMBOL(drm_get_resource_len);
+
/**
* 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)
+ unsigned int resource, int type, int flags)
{
drm_map_t *map;
drm_map_list_t *list;
diff --git a/shared-core/radeon_cp.c b/shared-core/radeon_cp.c
index 9eaa2d76..4606a332 100644
--- a/shared-core/radeon_cp.c
+++ b/shared-core/radeon_cp.c
@@ -2006,7 +2006,9 @@ int radeon_cp_buffers(DRM_IOCTL_ARGS)
/* Always create a map record for MMIO and FB memory, done from DRIVER_POSTINIT */
int radeon_preinit(struct drm_device *dev, unsigned long flags)
{
+#if defined(__linux__)
u32 save, temp;
+#endif
drm_radeon_private_t *dev_priv;
int ret = 0;
@@ -2030,19 +2032,18 @@ int radeon_preinit(struct drm_device *dev, unsigned long flags)
break;
}
-#ifdef __linux__
- /* registers */
- if ((ret = drm_initmap(dev, pci_resource_start(dev->pdev, 2),
- pci_resource_len(dev->pdev, 2), _DRM_REGISTERS,
- 0)))
+ ret = drm_initmap(dev, drm_get_resource_start(dev, 2),
+ drm_get_resource_len(dev, 2), 2, _DRM_REGISTERS, 0);
+ if (ret != 0)
return ret;
- /* framebuffer */
- if ((ret = drm_initmap(dev, pci_resource_start(dev->pdev, 0),
- pci_resource_len(dev->pdev, 0),
- _DRM_FRAME_BUFFER, _DRM_WRITE_COMBINING)))
+ ret = drm_initmap(dev, drm_get_resource_start(dev, 0),
+ drm_get_resource_len(dev, 0), 0, _DRM_FRAME_BUFFER,
+ _DRM_WRITE_COMBINING);
+ if (ret != 0)
return ret;
+#if defined(__linux__)
/* There are signatures in BIOS and PCI-SSID for a PCI card, but they are not very reliable.
Following detection method works for all cards tested so far.
Note, checking AGP_ENABLE bit after drmAgpEnable call can also give the correct result.
@@ -2057,9 +2058,14 @@ int radeon_preinit(struct drm_device *dev, unsigned long flags)
if (temp & RADEON_AGP_ENABLE)
dev_priv->flags |= CHIP_IS_AGP;
#else
+ /* The above method of detecting AGP is known to not work correctly,
+ * according to Mike Harris. The solution is to walk the capabilities
+ * list, which should be done in drm_device_is_agp().
+ */
if (drm_device_is_agp(dev))
- dev_priv->flags & CHIP_IS_AGP;
+ dev_priv->flags |= CHIP_IS_AGP;
#endif
+
DRM_DEBUG("%s card detected\n",
((dev_priv->flags & CHIP_IS_AGP) ? "AGP" : "PCI"));
diff --git a/shared-core/savage_bci.c b/shared-core/savage_bci.c
index 4656a902..36fb8737 100644
--- a/shared-core/savage_bci.c
+++ b/shared-core/savage_bci.c
@@ -296,6 +296,7 @@ int savage_preinit(drm_device_t *dev, unsigned long chipset)
{
drm_savage_private_t *dev_priv;
unsigned long mmio_base, fb_base, fb_size, aperture_base;
+ unsigned int fb_rsrc, aper_rsrc;
int ret = 0;
dev_priv = drm_alloc(sizeof(drm_savage_private_t), DRM_MEM_DRIVER);
@@ -310,12 +311,14 @@ int savage_preinit(drm_device_t *dev, unsigned long chipset)
dev_priv->mtrr[1].handle = -1;
dev_priv->mtrr[2].handle = -1;
if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
- fb_base = pci_resource_start(dev->pdev, 0);
+ fb_rsrc = 0;
+ fb_base = drm_get_resource_start(dev, 0);
fb_size = SAVAGE_FB_SIZE_S3;
mmio_base = fb_base + SAVAGE_FB_SIZE_S3;
+ aper_rsrc = 0;
aperture_base = fb_base + SAVAGE_APERTURE_OFFSET;
/* this should always be true */
- if (pci_resource_len(dev->pdev, 0) == 0x08000000) {
+ if (drm_get_resource_len(dev, 0) == 0x08000000) {
/* Don't make MMIO write-cobining! We need 3
* MTRRs. */
dev_priv->mtrr[0].base = fb_base;
@@ -335,15 +338,17 @@ int savage_preinit(drm_device_t *dev, unsigned long chipset)
MTRR_TYPE_WRCOMB, 1);
} else {
DRM_ERROR("strange pci_resource_len %08lx\n",
- pci_resource_len(dev->pdev, 0));
+ drm_get_resource_len(dev, 0));
}
} else if (chipset != S3_SUPERSAVAGE && chipset != S3_SAVAGE2000) {
- mmio_base = pci_resource_start(dev->pdev, 0);
- fb_base = pci_resource_start(dev->pdev, 1);
+ mmio_base = drm_get_resource_start(dev, 0);
+ fb_rsrc = 1;
+ fb_base = drm_get_resource_start(dev, 1);
fb_size = SAVAGE_FB_SIZE_S4;
+ aper_rsrc = 1;
aperture_base = fb_base + SAVAGE_APERTURE_OFFSET;
/* this should always be true */
- if (pci_resource_len(dev->pdev, 1) == 0x08000000) {
+ if (drm_get_resource_len(dev, 1) == 0x08000000) {
/* Can use one MTRR to cover both fb and
* aperture. */
dev_priv->mtrr[0].base = fb_base;
@@ -353,29 +358,32 @@ int savage_preinit(drm_device_t *dev, unsigned long chipset)
MTRR_TYPE_WRCOMB, 1);
} else {
DRM_ERROR("strange pci_resource_len %08lx\n",
- pci_resource_len(dev->pdev, 1));
+ drm_get_resource_len(dev, 1));
}
} else {
- mmio_base = pci_resource_start(dev->pdev, 0);
- fb_base = pci_resource_start(dev->pdev, 1);
- fb_size = pci_resource_len(dev->pdev, 1);
- aperture_base = pci_resource_start(dev->pdev, 2);
+ mmio_base = drm_get_resource_start(dev, 0);
+ fb_rsrc = 1;
+ fb_base = drm_get_resource_start(dev, 1);
+ fb_size = drm_get_resource_len(dev, 1);
+ aper_rsrc = 2;
+ aperture_base = drm_get_resource_start(dev, 2);
/* Automatic MTRR setup will do the right thing. */
}
- if ((ret = drm_initmap(dev, mmio_base, SAVAGE_MMIO_SIZE,
+ if ((ret = drm_initmap(dev, mmio_base, SAVAGE_MMIO_SIZE, 0,
_DRM_REGISTERS, 0)))
return ret;
if (!(dev_priv->mmio = drm_core_findmap (dev, mmio_base)))
return DRM_ERR(ENOMEM);
- if ((ret = drm_initmap(dev, fb_base, fb_size,
+ if ((ret = drm_initmap(dev, fb_base, fb_size, fb_rsrc,
_DRM_FRAME_BUFFER, _DRM_WRITE_COMBINING)))
return ret;
if (!(dev_priv->fb = drm_core_findmap (dev, fb_base)))
return DRM_ERR(ENOMEM);
if ((ret = drm_initmap(dev, aperture_base, SAVAGE_APERTURE_SIZE,
+ aper_rsrc,
_DRM_FRAME_BUFFER, _DRM_WRITE_COMBINING)))
return ret;
if (!(dev_priv->aperture = drm_core_findmap (dev, aperture_base)))