- 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.
This commit is contained in:
Eric Anholt 2005-02-05 08:00:14 +00:00
parent 270ca5f3ce
commit 080a547d4d
14 changed files with 335 additions and 187 deletions

View file

@ -292,24 +292,24 @@ typedef u_int8_t u8;
*(volatile u_int32_t *)(((unsigned long)(map)->handle) + (offset)) = val *(volatile u_int32_t *)(((unsigned long)(map)->handle) + (offset)) = val
#define DRM_VERIFYAREA_READ( uaddr, size ) \ #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__ */ #else /* __FreeBSD__ */
typedef vaddr_t vm_offset_t; typedef vaddr_t vm_offset_t;
#define DRM_READ8(map, offset) \ #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) \ #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) \ #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) \ #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) \ #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) \ #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 ) \ #define DRM_VERIFYAREA_READ( uaddr, size ) \
(!uvm_useracc((caddr_t)uaddr, size, VM_PROT_READ)) (!uvm_useracc((caddr_t)uaddr, size, VM_PROT_READ))
@ -373,10 +373,9 @@ do { \
#define DRM_GETSAREA() \ #define DRM_GETSAREA() \
do { \ do { \
drm_map_list_entry_t *listentry; \ drm_local_map_t *map; \
DRM_SPINLOCK_ASSERT(&dev->dev_lock); \ DRM_SPINLOCK_ASSERT(&dev->dev_lock); \
TAILQ_FOREACH(listentry, dev->maplist, link) { \ TAILQ_FOREACH(map, &dev->maplist, link) { \
drm_local_map_t *map = listentry->map; \
if (map->type == _DRM_SHM && \ if (map->type == _DRM_SHM && \
map->flags & _DRM_CONTAINS_LOCK) { \ map->flags & _DRM_CONTAINS_LOCK) { \
dev_priv->sarea = map; \ dev_priv->sarea = map; \
@ -560,6 +559,8 @@ typedef struct drm_sg_mem {
dma_addr_t *busaddr; dma_addr_t *busaddr;
} drm_sg_mem_t; } drm_sg_mem_t;
typedef TAILQ_HEAD(drm_map_list, drm_local_map) drm_map_list_t;
typedef struct drm_local_map { typedef struct drm_local_map {
unsigned long offset; /* Physical address (0 for SAREA)*/ unsigned long offset; /* Physical address (0 for SAREA)*/
unsigned long size; /* Physical size (bytes) */ unsigned long size; /* Physical size (bytes) */
@ -569,16 +570,14 @@ typedef struct drm_local_map {
/* Kernel-space: kernel-virtual address */ /* Kernel-space: kernel-virtual address */
int mtrr; /* Boolean: MTRR used */ int mtrr; /* Boolean: MTRR used */
/* Private data */ /* Private data */
bus_space_tag_t iot; int rid; /* PCI resource ID for bus_space */
bus_space_handle_t ioh; 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; } 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); TAILQ_HEAD(drm_vbl_sig_list, drm_vbl_sig);
typedef struct drm_vbl_sig { typedef struct drm_vbl_sig {
TAILQ_ENTRY(drm_vbl_sig) link; TAILQ_ENTRY(drm_vbl_sig) link;
@ -603,7 +602,8 @@ struct drm_device {
int (*postcleanup)(struct drm_device *); int (*postcleanup)(struct drm_device *);
int (*presetup)(struct drm_device *); int (*presetup)(struct drm_device *);
int (*postsetup)(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); void (*release)(struct drm_device *, void *filp);
int (*dma_ioctl)(DRM_IOCTL_ARGS); int (*dma_ioctl)(DRM_IOCTL_ARGS);
void (*dma_ready)(struct drm_device *); void (*dma_ready)(struct drm_device *);
@ -676,7 +676,7 @@ struct drm_device {
drm_magic_head_t magiclist[DRM_HASH_SIZE]; drm_magic_head_t magiclist[DRM_HASH_SIZE];
/* Linked list of mappable regions. Protected by dev_lock */ /* 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; drm_local_map_t **context_sareas;
int max_context; int max_context;
@ -793,6 +793,11 @@ int drm_lock_free(drm_device_t *dev,
unsigned int context); unsigned int context);
/* Buffer management support (drm_bufs.c) */ /* 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); int drm_order(unsigned long size);
/* DMA support (drm_dma.c) */ /* 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) static __inline__ struct drm_local_map *drm_core_findmap(struct drm_device *dev, unsigned long offset)
{ {
drm_map_list_entry_t *listentry; drm_local_map_t *map;
TAILQ_FOREACH(listentry, dev->maplist, link) {
if ( listentry->map->offset == offset ) { DRM_SPINLOCK_ASSERT(&dev->dev_lock);
return listentry->map; TAILQ_FOREACH(map, &dev->maplist, link) {
} if (map->offset == offset)
return map;
} }
return NULL; return NULL;
} }

View file

@ -48,19 +48,151 @@ int drm_order(unsigned long size)
return order; 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) int drm_addmap(DRM_IOCTL_ARGS)
{ {
DRM_DEVICE; DRM_DEVICE;
drm_map_t request; drm_map_t request;
drm_local_map_t *map; drm_local_map_t *map;
drm_map_list_entry_t *list; dma_addr_t bus_addr;
if (!(dev->flags & (FREAD|FWRITE))) if (!(dev->flags & (FREAD|FWRITE)))
return DRM_ERR(EACCES); /* Require read/write */ return DRM_ERR(EACCES); /* Require read/write */
DRM_COPY_FROM_USER_IOCTL( request, (drm_map_t *)data, sizeof(drm_map_t) ); 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 ) if ( !map )
return DRM_ERR(ENOMEM); return DRM_ERR(ENOMEM);
@ -68,31 +200,10 @@ int drm_addmap(DRM_IOCTL_ARGS)
map->size = request.size; map->size = request.size;
map->type = request.type; map->type = request.type;
map->flags = request.flags; 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 ) { switch ( map->type ) {
case _DRM_REGISTERS: case _DRM_REGISTERS:
drm_core_ioremap(map, dev); drm_ioremap(dev, map);
if (!(map->flags & _DRM_WRITE_COMBINING)) if (!(map->flags & _DRM_WRITE_COMBINING))
break; break;
/* FALLTHROUGH */ /* FALLTHROUGH */
@ -133,29 +244,34 @@ int drm_addmap(DRM_IOCTL_ARGS)
} }
map->offset = map->offset + dev->sg->handle; map->offset = map->offset + dev->sg->handle;
break; 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: default:
free(map, M_DRM); free(map, M_DRM);
return DRM_ERR(EINVAL); 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(); DRM_LOCK();
TAILQ_INSERT_TAIL(dev->maplist, list, link); TAILQ_INSERT_TAIL(&dev->maplist, map, link);
DRM_UNLOCK();
done:
/* Jumped to, with lock held, when a kernel map is found. */
request.offset = map->offset; request.offset = map->offset;
request.size = map->size; request.size = map->size;
request.type = map->type; request.type = map->type;
request.flags = map->flags; request.flags = map->flags;
request.mtrr = map->mtrr; request.mtrr = map->mtrr;
request.handle = map->handle; 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 ) { if ( request.type != _DRM_SHM ) {
request.handle = (void *)request.offset; request.handle = (void *)request.offset;
@ -166,40 +282,17 @@ int drm_addmap(DRM_IOCTL_ARGS)
return 0; return 0;
} }
void drm_remove_map(drm_device_t *dev, drm_local_map_t *map)
/* Remove a map private from list and deallocate resources if the mapping
* isn't in use.
*/
int drm_rmmap(DRM_IOCTL_ARGS)
{ {
DRM_DEVICE; DRM_SPINLOCK_ASSERT(&dev->dev_lock);
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) ); TAILQ_REMOVE(&dev->maplist, map, link);
DRM_LOCK();
TAILQ_FOREACH(list, dev->maplist, link) {
map = list->map;
if (map->handle == request.handle &&
map->flags & _DRM_REMOVABLE)
break;
}
/* No match found. */
if (list == NULL) {
DRM_UNLOCK();
return DRM_ERR(EINVAL);
}
TAILQ_REMOVE(dev->maplist, list, link);
DRM_UNLOCK();
free(list, M_DRM);
switch (map->type) { switch (map->type) {
case _DRM_REGISTERS: case _DRM_REGISTERS:
if (map->bsr == NULL)
drm_ioremapfree(map);
/* FALLTHROUGH */
case _DRM_FRAME_BUFFER: case _DRM_FRAME_BUFFER:
if (map->mtrr) { if (map->mtrr) {
int __unused retcode; int __unused retcode;
@ -208,7 +301,6 @@ int drm_rmmap(DRM_IOCTL_ARGS)
DRM_MTRR_WC); DRM_MTRR_WC);
DRM_DEBUG("mtrr_del = %d\n", retcode); DRM_DEBUG("mtrr_del = %d\n", retcode);
} }
drm_ioremapfree(map);
break; break;
case _DRM_SHM: case _DRM_SHM:
free(map->handle, M_DRM); free(map->handle, M_DRM);
@ -216,8 +308,48 @@ int drm_rmmap(DRM_IOCTL_ARGS)
case _DRM_AGP: case _DRM_AGP:
case _DRM_SCATTER_GATHER: case _DRM_SCATTER_GATHER:
break; 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); free(map, M_DRM);
}
/* Remove a map private from list and deallocate resources if the mapping
* isn't in use.
*/
int drm_rmmap(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
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(map, &dev->maplist, link) {
if (map->handle == request.handle &&
map->flags & _DRM_REMOVABLE)
break;
}
/* No match found. */
if (map == NULL) {
DRM_UNLOCK();
return DRM_ERR(EINVAL);
}
drm_remove_map(dev, map);
DRM_UNLOCK();
return 0; return 0;
} }

View file

@ -165,14 +165,12 @@ int drm_setsareactx( DRM_IOCTL_ARGS )
DRM_DEVICE; DRM_DEVICE;
drm_ctx_priv_map_t request; drm_ctx_priv_map_t request;
drm_local_map_t *map = NULL; drm_local_map_t *map = NULL;
drm_map_list_entry_t *list;
DRM_COPY_FROM_USER_IOCTL( request, (drm_ctx_priv_map_t *)data, DRM_COPY_FROM_USER_IOCTL( request, (drm_ctx_priv_map_t *)data,
sizeof(request) ); sizeof(request) );
DRM_LOCK(); DRM_LOCK();
TAILQ_FOREACH(list, dev->maplist, link) { TAILQ_FOREACH(map, &dev->maplist, link) {
map=list->map;
if (map->handle == request.handle) { if (map->handle == request.handle) {
if (dev->max_context < 0) if (dev->max_context < 0)
goto bad; goto bad;

View file

@ -377,8 +377,7 @@ static int drm_setup(drm_device_t *dev)
static int drm_takedown(drm_device_t *dev) static int drm_takedown(drm_device_t *dev)
{ {
drm_magic_entry_t *pt, *next; drm_magic_entry_t *pt, *next;
drm_local_map_t *map; drm_local_map_t *map, *mapsave;
drm_map_list_entry_t *list;
int i; int i;
DRM_SPINLOCK_ASSERT(&dev->dev_lock); DRM_SPINLOCK_ASSERT(&dev->dev_lock);
@ -432,38 +431,11 @@ static int drm_takedown(drm_device_t *dev)
dev->sg = NULL; dev->sg = NULL;
} }
if (dev->maplist != NULL) { /* Clean up maps that weren't set up by the driver. */
while ((list=TAILQ_FIRST(dev->maplist))) { TAILQ_FOREACH_SAFE(map, &dev->maplist, link, mapsave) {
map = list->map; if (!map->kernel_owned)
switch ( map->type ) { drm_remove_map(dev, map);
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);
}
}
drm_dma_takedown(dev); drm_dma_takedown(dev);
if ( dev->lock.hw_lock ) { if ( dev->lock.hw_lock ) {
@ -495,9 +467,6 @@ static int drm_init(device_t nbdev)
else else
dev->device = nbdev; dev->device = nbdev;
if (dev->preinit != NULL)
dev->preinit(dev, 0);
dev->devnode = make_dev(&drm_cdevsw, dev->devnode = make_dev(&drm_cdevsw,
unit, unit,
DRM_DEV_UID, DRM_DEV_UID,
@ -510,9 +479,6 @@ static int drm_init(device_t nbdev)
#elif defined(__NetBSD__) || defined(__OpenBSD__) #elif defined(__NetBSD__) || defined(__OpenBSD__)
dev = nbdev; dev = nbdev;
unit = minor(dev->device.dv_unit); unit = minor(dev->device.dv_unit);
if (dev->preinit != NULL)
dev->preinit(dev, 0);
#endif #endif
dev->irq = pci_get_irq(dev->device); 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_slot = pci_get_slot(dev->device);
dev->pci_func = pci_get_function(dev->device); dev->pci_func = pci_get_function(dev->device);
dev->maplist = malloc(sizeof(*dev->maplist), M_DRM, M_WAITOK); TAILQ_INIT(&dev->maplist);
if (dev->maplist == NULL) {
retcode = ENOMEM;
goto error;
}
TAILQ_INIT(dev->maplist);
drm_mem_init(); drm_mem_init();
#ifdef __FreeBSD__ #ifdef __FreeBSD__
@ -535,10 +496,18 @@ static int drm_init(device_t nbdev)
#endif #endif
TAILQ_INIT(&dev->files); TAILQ_INIT(&dev->files);
if (dev->preinit != NULL) {
retcode = dev->preinit(dev, 0);
if (retcode != 0)
goto error;
}
if (dev->use_agp) { 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) { 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); retcode = DRM_ERR(ENOMEM);
goto error; goto error;
} }
@ -581,7 +550,6 @@ error:
mtx_destroy(&dev->dev_lock); mtx_destroy(&dev->dev_lock);
#endif #endif
#endif #endif
free(dev->maplist, M_DRM);
return retcode; return retcode;
} }
@ -591,6 +559,7 @@ error:
*/ */
static void drm_cleanup(drm_device_t *dev) static void drm_cleanup(drm_device_t *dev)
{ {
drm_local_map_t *map;
DRM_DEBUG( "\n" ); DRM_DEBUG( "\n" );
@ -613,6 +582,11 @@ static void drm_cleanup(drm_device_t *dev)
drm_takedown(dev); drm_takedown(dev);
DRM_UNLOCK(); 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 ) { if ( dev->agp ) {
drm_agp_uninit(); drm_agp_uninit();
free(dev->agp, M_DRM); free(dev->agp, M_DRM);
@ -626,7 +600,6 @@ static void drm_cleanup(drm_device_t *dev)
#if defined(__FreeBSD__) && __FreeBSD_version >= 500000 #if defined(__FreeBSD__) && __FreeBSD_version >= 500000
mtx_destroy(&dev->dev_lock); mtx_destroy(&dev->dev_lock);
#endif #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__ */ #endif /* __NetBSD__ || __OpenBSD__ */
if (--priv->refs == 0) { if (--priv->refs == 0) {
if (dev->free_filp_priv != NULL)
dev->free_filp_priv(dev, priv);
TAILQ_REMOVE(&dev->files, priv, link); TAILQ_REMOVE(&dev->files, priv, link);
free(priv, M_DRM); free(priv, M_DRM);
} }

View file

@ -58,6 +58,7 @@ int drm_open_helper(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p,
{ {
int m = minor(kdev); int m = minor(kdev);
drm_file_t *priv; drm_file_t *priv;
int retcode;
if (flags & O_EXCL) if (flags & O_EXCL)
return EBUSY; /* No exclusive opens */ 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->ioctl_count = 0;
priv->authenticated = !DRM_SUSER(p); priv->authenticated = !DRM_SUSER(p);
if (dev->open_helper) if (dev->open_helper) {
dev->open_helper(dev, priv); retcode = dev->open_helper(dev, priv);
if (retcode != 0) {
free(priv, M_DRM);
DRM_UNLOCK();
return retcode;
}
}
TAILQ_INSERT_TAIL(&dev->files, priv, link); TAILQ_INSERT_TAIL(&dev->files, priv, link);
} }

View file

@ -147,7 +147,6 @@ int drm_getmap(DRM_IOCTL_ARGS)
DRM_DEVICE; DRM_DEVICE;
drm_map_t map; drm_map_t map;
drm_local_map_t *mapinlist; drm_local_map_t *mapinlist;
drm_map_list_entry_t *list;
int idx; int idx;
int i = 0; int i = 0;
@ -161,8 +160,7 @@ int drm_getmap(DRM_IOCTL_ARGS)
return DRM_ERR(EINVAL); return DRM_ERR(EINVAL);
} }
TAILQ_FOREACH(list, dev->maplist, link) { TAILQ_FOREACH(mapinlist, &dev->maplist, link) {
mapinlist = list->map;
if (i==idx) { if (i==idx) {
map.offset = mapinlist->offset; map.offset = mapinlist->offset;
map.size = mapinlist->size; map.size = mapinlist->size;
@ -177,7 +175,7 @@ int drm_getmap(DRM_IOCTL_ARGS)
DRM_UNLOCK(); DRM_UNLOCK();
if (!list) if (mapinlist == NULL)
return EINVAL; return EINVAL;
DRM_COPY_TO_USER_IOCTL( (drm_map_t *)data, map, sizeof(map) ); DRM_COPY_TO_USER_IOCTL( (drm_map_t *)data, map, sizeof(map) );

View file

@ -79,11 +79,11 @@ void *drm_ioremap(drm_device_t *dev, drm_local_map_t *map)
#ifdef __FreeBSD__ #ifdef __FreeBSD__
return pmap_mapdev(map->offset, map->size); return pmap_mapdev(map->offset, map->size);
#elif defined(__NetBSD__) || defined(__OpenBSD__) #elif defined(__NetBSD__) || defined(__OpenBSD__)
map->iot = dev->pa.pa_memt; map->bst = dev->pa.pa_memt;
if (bus_space_map(map->iot, map->offset, map->size, if (bus_space_map(map->bst, map->offset, map->size,
BUS_SPACE_MAP_LINEAR, &map->ioh)) BUS_SPACE_MAP_LINEAR, &map->bsh))
return NULL; return NULL;
return bus_space_vaddr(map->iot, map->ioh); return bus_space_vaddr(map->bst, map->bsh);
#endif #endif
} }
@ -92,7 +92,7 @@ void drm_ioremapfree(drm_local_map_t *map)
#ifdef __FreeBSD__ #ifdef __FreeBSD__
pmap_unmapdev((vm_offset_t) map->handle, map->size); pmap_unmapdev((vm_offset_t) map->handle, map->size);
#elif defined(__NetBSD__) || defined(__OpenBSD__) #elif defined(__NetBSD__) || defined(__OpenBSD__)
bus_space_unmap(map->iot, map->ioh, map->size); bus_space_unmap(map->bst, map->bsh, map->size);
#endif #endif
} }

View file

@ -150,7 +150,6 @@ static int drm_vm_info DRM_SYSCTL_HANDLER_ARGS
{ {
drm_device_t *dev = arg1; drm_device_t *dev = arg1;
drm_local_map_t *map, *tempmaps; drm_local_map_t *map, *tempmaps;
drm_map_list_entry_t *listentry;
const char *types[] = { "FB", "REG", "SHM", "AGP", "SG" }; const char *types[] = { "FB", "REG", "SHM", "AGP", "SG" };
const char *type, *yesno; const char *type, *yesno;
int i, mapcount; int i, mapcount;
@ -163,7 +162,7 @@ static int drm_vm_info DRM_SYSCTL_HANDLER_ARGS
DRM_LOCK(); DRM_LOCK();
mapcount = 0; mapcount = 0;
TAILQ_FOREACH(listentry, dev->maplist, link) TAILQ_FOREACH(map, &dev->maplist, link)
mapcount++; mapcount++;
tempmaps = malloc(sizeof(drm_local_map_t) * mapcount, M_DRM, M_NOWAIT); 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; i = 0;
TAILQ_FOREACH(listentry, dev->maplist, link) TAILQ_FOREACH(map, &dev->maplist, link)
tempmaps[i++] = *listentry->map; tempmaps[i++] = *map;
DRM_UNLOCK(); DRM_UNLOCK();

View file

@ -35,8 +35,7 @@ paddr_t drm_mmap(dev_t kdev, off_t offset, int prot)
#endif #endif
{ {
DRM_DEVICE; DRM_DEVICE;
drm_local_map_t *map = NULL; drm_local_map_t *map;
drm_map_list_entry_t *listentry = NULL;
drm_file_t *priv; drm_file_t *priv;
drm_map_type_t type; 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 for performance, even if the list was a
bit longer. */ bit longer. */
DRM_LOCK(); DRM_LOCK();
TAILQ_FOREACH(listentry, dev->maplist, link) { TAILQ_FOREACH(map, &dev->maplist, link) {
map = listentry->map;
if (offset >= map->offset && offset < map->offset + map->size) if (offset >= map->offset && offset < map->offset + map->size)
break; break;
} }
if (!listentry) { if (map == NULL) {
DRM_UNLOCK(); DRM_UNLOCK();
DRM_DEBUG("can't find map\n"); DRM_DEBUG("can't find map\n");
return -1; return -1;

View file

@ -45,8 +45,12 @@ extern int radeon_max_ioctl;
static void radeon_configure(drm_device_t *dev) static void radeon_configure(drm_device_t *dev)
{ {
dev->dev_priv_size = sizeof(drm_radeon_buf_priv_t); dev->dev_priv_size = sizeof(drm_radeon_buf_priv_t);
dev->preinit = radeon_preinit;
dev->postcleanup = radeon_postcleanup;
dev->prerelease = radeon_driver_prerelease; dev->prerelease = radeon_driver_prerelease;
dev->pretakedown = radeon_driver_pretakedown; 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->vblank_wait = radeon_driver_vblank_wait;
dev->irq_preinstall = radeon_driver_irq_preinstall; dev->irq_preinstall = radeon_driver_irq_preinstall;
dev->irq_postinstall = radeon_driver_irq_postinstall; dev->irq_postinstall = radeon_driver_irq_postinstall;

View file

@ -851,7 +851,8 @@ extern int drm_addmap(struct inode *inode, struct file *filp,
extern int drm_rmmap(struct inode *inode, struct file *filp, extern int drm_rmmap(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg); unsigned int cmd, unsigned long arg);
extern int drm_initmap(drm_device_t * dev, unsigned int offset, 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, extern int drm_addbufs(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg); unsigned int cmd, unsigned long arg);
extern int drm_infobufs(struct inode *inode, struct file *filp, 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, extern int drm_mapbufs(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg); unsigned int cmd, unsigned long arg);
extern int drm_order(unsigned long size); 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) */ /* DMA support (drm_dma.h) */
extern int drm_dma_setup(drm_device_t * dev); extern int drm_dma_setup(drm_device_t * dev);

View file

@ -36,13 +36,25 @@
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include "drmP.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 * 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 * type. Adds the map to the map list drm_device::maplist. Adds MTRR's where
* applicable and if supported by the kernel. * applicable and if supported by the kernel.
*/ */
int drm_initmap(drm_device_t * dev, unsigned int offset, unsigned int size, 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_t *map;
drm_map_list_t *list; drm_map_list_t *list;

View file

@ -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 */ /* Always create a map record for MMIO and FB memory, done from DRIVER_POSTINIT */
int radeon_preinit(struct drm_device *dev, unsigned long flags) int radeon_preinit(struct drm_device *dev, unsigned long flags)
{ {
#if defined(__linux__)
u32 save, temp; u32 save, temp;
#endif
drm_radeon_private_t *dev_priv; drm_radeon_private_t *dev_priv;
int ret = 0; int ret = 0;
@ -2030,19 +2032,18 @@ int radeon_preinit(struct drm_device *dev, unsigned long flags)
break; break;
} }
#ifdef __linux__ ret = drm_initmap(dev, drm_get_resource_start(dev, 2),
/* registers */ drm_get_resource_len(dev, 2), 2, _DRM_REGISTERS, 0);
if ((ret = drm_initmap(dev, pci_resource_start(dev->pdev, 2), if (ret != 0)
pci_resource_len(dev->pdev, 2), _DRM_REGISTERS,
0)))
return ret; return ret;
/* framebuffer */ ret = drm_initmap(dev, drm_get_resource_start(dev, 0),
if ((ret = drm_initmap(dev, pci_resource_start(dev->pdev, 0), drm_get_resource_len(dev, 0), 0, _DRM_FRAME_BUFFER,
pci_resource_len(dev->pdev, 0), _DRM_WRITE_COMBINING);
_DRM_FRAME_BUFFER, _DRM_WRITE_COMBINING))) if (ret != 0)
return ret; return ret;
#if defined(__linux__)
/* There are signatures in BIOS and PCI-SSID for a PCI card, but they are not very reliable. /* 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. Following detection method works for all cards tested so far.
Note, checking AGP_ENABLE bit after drmAgpEnable call can also give the correct result. 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) if (temp & RADEON_AGP_ENABLE)
dev_priv->flags |= CHIP_IS_AGP; dev_priv->flags |= CHIP_IS_AGP;
#else #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)) if (drm_device_is_agp(dev))
dev_priv->flags & CHIP_IS_AGP; dev_priv->flags |= CHIP_IS_AGP;
#endif #endif
DRM_DEBUG("%s card detected\n", DRM_DEBUG("%s card detected\n",
((dev_priv->flags & CHIP_IS_AGP) ? "AGP" : "PCI")); ((dev_priv->flags & CHIP_IS_AGP) ? "AGP" : "PCI"));

View file

@ -296,6 +296,7 @@ int savage_preinit(drm_device_t *dev, unsigned long chipset)
{ {
drm_savage_private_t *dev_priv; drm_savage_private_t *dev_priv;
unsigned long mmio_base, fb_base, fb_size, aperture_base; unsigned long mmio_base, fb_base, fb_size, aperture_base;
unsigned int fb_rsrc, aper_rsrc;
int ret = 0; int ret = 0;
dev_priv = drm_alloc(sizeof(drm_savage_private_t), DRM_MEM_DRIVER); 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[1].handle = -1;
dev_priv->mtrr[2].handle = -1; dev_priv->mtrr[2].handle = -1;
if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) { 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; fb_size = SAVAGE_FB_SIZE_S3;
mmio_base = fb_base + SAVAGE_FB_SIZE_S3; mmio_base = fb_base + SAVAGE_FB_SIZE_S3;
aper_rsrc = 0;
aperture_base = fb_base + SAVAGE_APERTURE_OFFSET; aperture_base = fb_base + SAVAGE_APERTURE_OFFSET;
/* this should always be true */ /* 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 /* Don't make MMIO write-cobining! We need 3
* MTRRs. */ * MTRRs. */
dev_priv->mtrr[0].base = fb_base; 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); MTRR_TYPE_WRCOMB, 1);
} else { } else {
DRM_ERROR("strange pci_resource_len %08lx\n", 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) { } else if (chipset != S3_SUPERSAVAGE && chipset != S3_SAVAGE2000) {
mmio_base = pci_resource_start(dev->pdev, 0); mmio_base = drm_get_resource_start(dev, 0);
fb_base = pci_resource_start(dev->pdev, 1); fb_rsrc = 1;
fb_base = drm_get_resource_start(dev, 1);
fb_size = SAVAGE_FB_SIZE_S4; fb_size = SAVAGE_FB_SIZE_S4;
aper_rsrc = 1;
aperture_base = fb_base + SAVAGE_APERTURE_OFFSET; aperture_base = fb_base + SAVAGE_APERTURE_OFFSET;
/* this should always be true */ /* 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 /* Can use one MTRR to cover both fb and
* aperture. */ * aperture. */
dev_priv->mtrr[0].base = fb_base; 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); MTRR_TYPE_WRCOMB, 1);
} else { } else {
DRM_ERROR("strange pci_resource_len %08lx\n", DRM_ERROR("strange pci_resource_len %08lx\n",
pci_resource_len(dev->pdev, 1)); drm_get_resource_len(dev, 1));
} }
} else { } else {
mmio_base = pci_resource_start(dev->pdev, 0); mmio_base = drm_get_resource_start(dev, 0);
fb_base = pci_resource_start(dev->pdev, 1); fb_rsrc = 1;
fb_size = pci_resource_len(dev->pdev, 1); fb_base = drm_get_resource_start(dev, 1);
aperture_base = pci_resource_start(dev->pdev, 2); 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. */ /* 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))) _DRM_REGISTERS, 0)))
return ret; return ret;
if (!(dev_priv->mmio = drm_core_findmap (dev, mmio_base))) if (!(dev_priv->mmio = drm_core_findmap (dev, mmio_base)))
return DRM_ERR(ENOMEM); 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))) _DRM_FRAME_BUFFER, _DRM_WRITE_COMBINING)))
return ret; return ret;
if (!(dev_priv->fb = drm_core_findmap (dev, fb_base))) if (!(dev_priv->fb = drm_core_findmap (dev, fb_base)))
return DRM_ERR(ENOMEM); return DRM_ERR(ENOMEM);
if ((ret = drm_initmap(dev, aperture_base, SAVAGE_APERTURE_SIZE, if ((ret = drm_initmap(dev, aperture_base, SAVAGE_APERTURE_SIZE,
aper_rsrc,
_DRM_FRAME_BUFFER, _DRM_WRITE_COMBINING))) _DRM_FRAME_BUFFER, _DRM_WRITE_COMBINING)))
return ret; return ret;
if (!(dev_priv->aperture = drm_core_findmap (dev, aperture_base))) if (!(dev_priv->aperture = drm_core_findmap (dev, aperture_base)))