mirror of
https://gitlab.freedesktop.org/mesa/drm.git
synced 2025-12-20 11:40:20 +01:00
- 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:
parent
270ca5f3ce
commit
080a547d4d
14 changed files with 335 additions and 187 deletions
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,40 +282,17 @@ int drm_addmap(DRM_IOCTL_ARGS)
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Remove a map private from list and deallocate resources if the mapping
|
||||
* isn't in use.
|
||||
*/
|
||||
|
||||
int drm_rmmap(DRM_IOCTL_ARGS)
|
||||
void drm_remove_map(drm_device_t *dev, drm_local_map_t *map)
|
||||
{
|
||||
DRM_DEVICE;
|
||||
drm_map_list_entry_t *list;
|
||||
drm_local_map_t *map;
|
||||
drm_map_t request;
|
||||
DRM_SPINLOCK_ASSERT(&dev->dev_lock);
|
||||
|
||||
DRM_COPY_FROM_USER_IOCTL( request, (drm_map_t *)data, sizeof(request) );
|
||||
|
||||
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);
|
||||
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;
|
||||
|
|
@ -208,7 +301,6 @@ int drm_rmmap(DRM_IOCTL_ARGS)
|
|||
DRM_MTRR_WC);
|
||||
DRM_DEBUG("mtrr_del = %d\n", retcode);
|
||||
}
|
||||
drm_ioremapfree(map);
|
||||
break;
|
||||
case _DRM_SHM:
|
||||
free(map->handle, M_DRM);
|
||||
|
|
@ -216,8 +308,48 @@ int drm_rmmap(DRM_IOCTL_ARGS)
|
|||
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.
|
||||
*/
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) );
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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"));
|
||||
|
||||
|
|
|
|||
|
|
@ -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)))
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue