#define DRIVER_DMA_QUEUE 0x200
#define DRIVER_FB_DMA 0x400
#define DRIVER_IRQ_VBL2 0x800
+#define DRIVER_GEM 0x1000
/***********************************************************************/
/** \name Begin the DRM... */
*/
#define LOCK_TEST_WITH_RETURN( dev, file_priv ) \
do { \
- if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || \
- dev->lock.file_priv != file_priv ) { \
+ if (!_DRM_LOCK_IS_HELD(file_priv->master->lock.hw_lock->lock) || \
+ file_priv->master->lock.file_priv != file_priv) { \
DRM_ERROR( "%s called without lock held, held %d owner %p %p\n",\
- __func__, _DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ),\
- dev->lock.file_priv, file_priv ); \
+ __func__, _DRM_LOCK_IS_HELD(file_priv->master->lock.hw_lock->lock),\
+ file_priv->master->lock.file_priv, file_priv); \
return -EINVAL; \
} \
} while (0)
/** File private data */
struct drm_file {
int authenticated;
- int master;
pid_t pid;
uid_t uid;
drm_magic_t magic;
unsigned long ioctl_count;
struct list_head lhead;
struct drm_minor *minor;
- int remove_auth_on_close;
unsigned long lock_count;
+
+ /** Mapping of mm object handles to object pointers. */
+ struct idr object_idr;
+ /** Lock for synchronization of access to object_idr. */
+ spinlock_t table_lock;
+
struct file *filp;
void *driver_priv;
+
+ int is_master; /* this file private is a master for a minor */
+ struct drm_master *master; /* master this node is currently associated with
+ N.B. not always minor->master */
};
/** Wait queue */
struct drm_hash_item hash;
struct drm_map *map; /**< mapping */
uint64_t user_token;
+ struct drm_master *master;
+ struct drm_mm_node *file_offset_node; /**< fake offset */
};
typedef struct drm_map drm_local_map_t;
};
/**
+ * GEM specific mm private for tracking GEM objects
+ */
+struct drm_gem_mm {
+ struct drm_mm offset_manager; /**< Offset mgmt for buffer objects */
+ struct drm_open_hash offset_hash; /**< User token hash table for maps */
+};
+
+/**
+ * This structure defines the drm_mm memory object, which will be used by the
+ * DRM for its buffer objects.
+ */
+struct drm_gem_object {
+ /** Reference count of this object */
+ struct kref refcount;
+
+ /** Handle count of this object. Each handle also holds a reference */
+ struct kref handlecount;
+
+ /** Related drm device */
+ struct drm_device *dev;
+
+ /** File representing the shmem storage */
+ struct file *filp;
+
+ /* Mapping info for this object */
+ struct drm_map_list map_list;
+
+ /**
+ * Size of the object, in bytes. Immutable over the object's
+ * lifetime.
+ */
+ size_t size;
+
+ /**
+ * Global name for this object, starts at 1. 0 means unnamed.
+ * Access is covered by the object_name_lock in the related drm_device
+ */
+ int name;
+
+ /**
+ * Memory domains. These monitor which caches contain read/write data
+ * related to the object. When transitioning from one set of domains
+ * to another, the driver is called to ensure that caches are suitably
+ * flushed and invalidated
+ */
+ uint32_t read_domains;
+ uint32_t write_domain;
+
+ /**
+ * While validating an exec operation, the
+ * new read/write domain values are computed here.
+ * They will be transferred to the above values
+ * at the point that any cache flushing occurs
+ */
+ uint32_t pending_read_domains;
+ uint32_t pending_write_domain;
+
+ void *driver_private;
+};
+
+/* per-master structure */
+struct drm_master {
+
+ struct kref refcount; /* refcount for this master */
+
+ struct list_head head; /**< each minor contains a list of masters */
+ struct drm_minor *minor; /**< link back to minor we are a master for */
+
+ char *unique; /**< Unique identifier: e.g., busid */
+ int unique_len; /**< Length of unique field */
+ int unique_size; /**< amount allocated */
+
+ int blocked; /**< Blocked due to VC switch? */
+
+ /** \name Authentication */
+ /*@{ */
+ struct drm_open_hash magiclist;
+ struct list_head magicfree;
+ /*@} */
+
+ struct drm_lock_data lock; /**< Information on hardware lock */
+
+ void *driver_priv; /**< Private structure for driver to use */
+};
+
+/**
* DRM driver structure. This structure represent the common code for
* a family of cards. There will one drm_device for each card present
* in this family
void (*set_version) (struct drm_device *dev,
struct drm_set_version *sv);
+ /* Master routines */
+ int (*master_create)(struct drm_device *dev, struct drm_master *master);
+ void (*master_destroy)(struct drm_device *dev, struct drm_master *master);
+
+ int (*proc_init)(struct drm_minor *minor);
+ void (*proc_cleanup)(struct drm_minor *minor);
+
+ /**
+ * Driver-specific constructor for drm_gem_objects, to set up
+ * obj->driver_private.
+ *
+ * Returns 0 on success.
+ */
+ int (*gem_init_object) (struct drm_gem_object *obj);
+ void (*gem_free_object) (struct drm_gem_object *obj);
+
+ /* Driver private ops for this object */
+ struct vm_operations_struct *gem_vm_ops;
+
int major;
int minor;
int patchlevel;
int num_ioctls;
struct file_operations fops;
struct pci_driver pci_driver;
+ /* List of devices hanging off this driver */
+ struct list_head device_list;
};
#define DRM_MINOR_UNASSIGNED 0
struct device kdev; /**< Linux device */
struct drm_device *dev;
struct proc_dir_entry *dev_root; /**< proc directory entry */
+ struct drm_master *master; /* currently active master for this node */
+ struct list_head master_list;
};
/**
* may contain multiple heads.
*/
struct drm_device {
- char *unique; /**< Unique identifier: e.g., busid */
- int unique_len; /**< Length of unique field */
+ struct list_head driver_item; /**< list of devices per driver */
char *devname; /**< For /proc/interrupts */
int if_version; /**< Highest interface version set */
- int blocked; /**< Blocked due to VC switch? */
-
/** \name Locks */
/*@{ */
spinlock_t count_lock; /**< For inuse, drm_device::open_count, drm_device::buf_use */
atomic_t counts[15];
/*@} */
- /** \name Authentication */
- /*@{ */
struct list_head filelist;
- struct drm_open_hash magiclist; /**< magic hash table */
- struct list_head magicfree;
- /*@} */
/** \name Memory management */
/*@{ */
struct idr ctx_idr;
struct list_head vmalist; /**< List of vmas (for debugging) */
- struct drm_lock_data lock; /**< Information on hardware lock */
/*@} */
/** \name DMA queues (contexts) */
/** \name Context support */
/*@{ */
- int irq; /**< Interrupt used by board */
int irq_enabled; /**< True if irq handler is enabled */
__volatile__ long context_flag; /**< Context swapping flag */
__volatile__ long interrupt_flag; /**< Interruption handler flag */
struct timer_list vblank_disable_timer;
u32 max_vblank_count; /**< size of vblank counter register */
- spinlock_t tasklet_lock; /**< For drm_locked_tasklet */
- void (*locked_tasklet_func)(struct drm_device *dev);
/*@} */
cycles_t ctx_start;
struct drm_sg_mem *sg; /**< Scatter gather memory */
int num_crtcs; /**< Number of CRTCs on this device */
void *dev_private; /**< device private data */
+ void *mm_private;
+ struct address_space *dev_mapping;
struct drm_sigdata sigdata; /**< For block_all_signals */
sigset_t sigmask;
spinlock_t drw_lock;
struct idr drw_idr;
/*@} */
+
+ /** \name GEM information */
+ /*@{ */
+ spinlock_t object_name_lock;
+ struct idr object_name_idr;
+ atomic_t object_count;
+ atomic_t object_memory;
+ atomic_t pin_count;
+ atomic_t pin_memory;
+ atomic_t gtt_count;
+ atomic_t gtt_memory;
+ uint32_t gtt_total;
+ uint32_t invalidate_domains; /* domains pending invalidation */
+ uint32_t flush_domains; /* domains pending flush */
+ /*@} */
+
};
+static inline int drm_dev_to_irq(struct drm_device *dev)
+{
+ return dev->pdev->irq;
+}
+
static __inline__ int drm_core_check_feature(struct drm_device *dev,
int feature)
{
/* Mapping support (drm_vm.h) */
extern int drm_mmap(struct file *filp, struct vm_area_struct *vma);
+extern int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma);
+extern void drm_vm_open_locked(struct vm_area_struct *vma);
extern unsigned long drm_core_get_map_ofs(struct drm_map * map);
extern unsigned long drm_core_get_reg_ofs(struct drm_device *dev);
extern unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait);
extern DRM_AGP_MEM *drm_alloc_agp(struct drm_device *dev, int pages, u32 type);
extern int drm_free_agp(DRM_AGP_MEM * handle, int pages);
extern int drm_bind_agp(DRM_AGP_MEM * handle, unsigned int start);
+extern DRM_AGP_MEM *drm_agp_bind_pages(struct drm_device *dev,
+ struct page **pages,
+ unsigned long num_pages,
+ uint32_t gtt_offset,
+ uint32_t type);
extern int drm_unbind_agp(DRM_AGP_MEM * handle);
/* Misc. IOCTL support (drm_ioctl.h) */
extern int drm_authmagic(struct drm_device *dev, void *data,
struct drm_file *file_priv);
+/* Cache management (drm_cache.c) */
+void drm_clflush_pages(struct page *pages[], unsigned long num_pages);
+
/* Locking IOCTL support (drm_lock.h) */
extern int drm_lock(struct drm_device *dev, void *data,
struct drm_file *file_priv);
extern int drm_control(struct drm_device *dev, void *data,
struct drm_file *file_priv);
extern irqreturn_t drm_irq_handler(DRM_IRQ_ARGS);
+extern int drm_irq_install(struct drm_device *dev);
extern int drm_irq_uninstall(struct drm_device *dev);
extern void drm_driver_irq_preinstall(struct drm_device *dev);
extern void drm_driver_irq_postinstall(struct drm_device *dev);
extern int drm_wait_vblank(struct drm_device *dev, void *data,
struct drm_file *filp);
extern int drm_vblank_wait(struct drm_device *dev, unsigned int *vbl_seq);
-extern void drm_locked_tasklet(struct drm_device *dev,
- void(*func)(struct drm_device *));
extern u32 drm_vblank_count(struct drm_device *dev, int crtc);
extern void drm_handle_vblank(struct drm_device *dev, int crtc);
extern int drm_vblank_get(struct drm_device *dev, int crtc);
extern void drm_vblank_put(struct drm_device *dev, int crtc);
+extern void drm_vblank_cleanup(struct drm_device *dev);
/* Modesetting support */
extern int drm_modeset_ctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
-extern void drm_locked_tasklet(struct drm_device *dev, void(*func)(struct drm_device*));
/* AGP/GART support (drm_agpsupport.h) */
extern struct drm_agp_head *drm_agp_init(struct drm_device *dev);
extern int drm_agp_free_memory(DRM_AGP_MEM * handle);
extern int drm_agp_bind_memory(DRM_AGP_MEM * handle, off_t start);
extern int drm_agp_unbind_memory(DRM_AGP_MEM * handle);
+extern void drm_agp_chipset_flush(struct drm_device *dev);
/* Stub support (drm_stub.h) */
+extern int drm_setmaster_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern int drm_dropmaster_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+struct drm_master *drm_master_create(struct drm_minor *minor);
+extern struct drm_master *drm_master_get(struct drm_master *master);
+extern void drm_master_put(struct drm_master **master);
extern int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
struct drm_driver *driver);
extern int drm_put_dev(struct drm_device *dev);
extern int drm_mm_remove_space_from_tail(struct drm_mm *mm, unsigned long size);
extern int drm_mm_add_space_to_tail(struct drm_mm *mm, unsigned long size);
+/* Graphics Execution Manager library functions (drm_gem.c) */
+int drm_gem_init(struct drm_device *dev);
+void drm_gem_destroy(struct drm_device *dev);
+void drm_gem_object_free(struct kref *kref);
+struct drm_gem_object *drm_gem_object_alloc(struct drm_device *dev,
+ size_t size);
+void drm_gem_object_handle_free(struct kref *kref);
+int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma);
+
+static inline void
+drm_gem_object_reference(struct drm_gem_object *obj)
+{
+ kref_get(&obj->refcount);
+}
+
+static inline void
+drm_gem_object_unreference(struct drm_gem_object *obj)
+{
+ if (obj == NULL)
+ return;
+
+ kref_put(&obj->refcount, drm_gem_object_free);
+}
+
+int drm_gem_handle_create(struct drm_file *file_priv,
+ struct drm_gem_object *obj,
+ int *handlep);
+
+static inline void
+drm_gem_object_handle_reference(struct drm_gem_object *obj)
+{
+ drm_gem_object_reference(obj);
+ kref_get(&obj->handlecount);
+}
+
+static inline void
+drm_gem_object_handle_unreference(struct drm_gem_object *obj)
+{
+ if (obj == NULL)
+ return;
+
+ /*
+ * Must bump handle count first as this may be the last
+ * ref, in which case the object would disappear before we
+ * checked for a name
+ */
+ kref_put(&obj->handlecount, drm_gem_object_handle_free);
+ drm_gem_object_unreference(obj);
+}
+
+struct drm_gem_object *drm_gem_object_lookup(struct drm_device *dev,
+ struct drm_file *filp,
+ int handle);
+int drm_gem_close_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+int drm_gem_flink_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+int drm_gem_open_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+void drm_gem_open(struct drm_device *dev, struct drm_file *file_private);
+void drm_gem_release(struct drm_device *dev, struct drm_file *file_private);
+
extern void drm_core_ioremap(struct drm_map *map, struct drm_device *dev);
extern void drm_core_ioremap_wc(struct drm_map *map, struct drm_device *dev);
extern void drm_core_ioremapfree(struct drm_map *map, struct drm_device *dev);