···90#define DRM_MAX_ORDER 22 /**< Up to 2^22 bytes = 4MB */91#define DRM_RAM_PERCENT 10 /**< How much system ram can we lock? */9293-#define _DRM_LOCK_HELD 0x80000000 /**< Hardware lock is held */94-#define _DRM_LOCK_CONT 0x40000000 /**< Hardware lock is contended */95#define _DRM_LOCK_IS_HELD(lock) ((lock) & _DRM_LOCK_HELD)96#define _DRM_LOCK_IS_CONT(lock) ((lock) & _DRM_LOCK_CONT)97#define _DRM_LOCKING_CONTEXT(lock) ((lock) & ~(_DRM_LOCK_HELD|_DRM_LOCK_CONT))
···90#define DRM_MAX_ORDER 22 /**< Up to 2^22 bytes = 4MB */91#define DRM_RAM_PERCENT 10 /**< How much system ram can we lock? */9293+#define _DRM_LOCK_HELD 0x80000000U /**< Hardware lock is held */94+#define _DRM_LOCK_CONT 0x40000000U /**< Hardware lock is contended */95#define _DRM_LOCK_IS_HELD(lock) ((lock) & _DRM_LOCK_HELD)96#define _DRM_LOCK_IS_CONT(lock) ((lock) & _DRM_LOCK_CONT)97#define _DRM_LOCKING_CONTEXT(lock) ((lock) & ~(_DRM_LOCK_HELD|_DRM_LOCK_CONT))
+72-50
drivers/char/drm/drmP.h
···144/** \name Backward compatibility section */145/*@{*/146147-#ifndef MODULE_LICENSE148-#define MODULE_LICENSE(x)149-#endif150-151-#ifndef preempt_disable152-#define preempt_disable()153-#define preempt_enable()154-#endif155-156-#ifndef pte_offset_map157-#define pte_offset_map pte_offset158-#define pte_unmap(pte)159-#endif160-161#define DRM_RPR_ARG(vma) vma,162163#define VM_OFFSET(vma) ((vma)->vm_pgoff << PAGE_SHIFT)···272typedef int drm_ioctl_compat_t(struct file *filp, unsigned int cmd,273 unsigned long arg);2740000275typedef struct drm_ioctl_desc {276 drm_ioctl_t *func;277- int auth_needed;278- int root_only;279} drm_ioctl_desc_t;280281typedef struct drm_devstate {···373/** File private data */374typedef struct drm_file {375 int authenticated;0376 int minor;377 pid_t pid;378 uid_t uid;···522typedef struct ati_pcigart_info {523 int gart_table_location;524 int is_pcie;525- unsigned long addr;526 dma_addr_t bus_addr;0527} drm_ati_pcigart_info;528529/**···535struct drm_device;536537struct drm_driver {538- int (*preinit) (struct drm_device *, unsigned long flags);539- void (*prerelease) (struct drm_device *, struct file * filp);540- void (*pretakedown) (struct drm_device *);541- int (*postcleanup) (struct drm_device *);542- int (*presetup) (struct drm_device *);543- int (*postsetup) (struct drm_device *);0544 int (*dma_ioctl) (DRM_IOCTL_ARGS);545- int (*open_helper) (struct drm_device *, drm_file_t *);546- void (*free_filp_priv) (struct drm_device *, drm_file_t *);547- void (*release) (struct drm_device *, struct file * filp);548 void (*dma_ready) (struct drm_device *);549 int (*dma_quiescent) (struct drm_device *);550 int (*context_ctor) (struct drm_device * dev, int context);···550 int (*kernel_context_switch) (struct drm_device * dev, int old,551 int new);552 void (*kernel_context_switch_unlock) (struct drm_device * dev,553- drm_lock_t * lock);554 int (*vblank_wait) (struct drm_device * dev, unsigned int *sequence);0555556 /**557 * Called by \c drm_device_is_agp. Typically used to determine if a···569570 /* these have to be filled in */571572- int (*postinit) (struct drm_device *, unsigned long flags);573- irqreturn_t(*irq_handler) (DRM_IRQ_ARGS);574 void (*irq_preinstall) (struct drm_device * dev);575 void (*irq_postinstall) (struct drm_device * dev);576 void (*irq_uninstall) (struct drm_device * dev);577 void (*reclaim_buffers) (struct drm_device * dev, struct file * filp);00578 unsigned long (*get_map_ofs) (drm_map_t * map);579 unsigned long (*get_reg_ofs) (struct drm_device * dev);580 void (*set_version) (struct drm_device * dev, drm_set_version_t * sv);581- int (*version) (drm_version_t * version);0000000582 u32 driver_features;583 int dev_priv_size;584 drm_ioctl_desc_t *ioctls;···750{751 return drm_core_check_feature(dev, DRIVER_USE_MTRR);752}000000000000000753#else754#define drm_core_has_MTRR(dev) (0)00000000000000755#endif756757/******************************************************************/758/** \name Internal function definitions */759/*@{*/760-761- /* Misc. support (drm_init.h) */762-extern int drm_flags;763-extern void drm_parse_options(char *s);764-extern int drm_cpu_valid(void);765766 /* Driver support (drm_drv.h) */767extern int drm_init(struct drm_driver *driver);···794 unsigned int cmd, unsigned long arg);795extern long drm_compat_ioctl(struct file *filp,796 unsigned int cmd, unsigned long arg);797-extern int drm_takedown(drm_device_t * dev);798799 /* Device support (drm_fops.h) */800extern int drm_open(struct inode *inode, struct file *filp);801extern int drm_stub_open(struct inode *inode, struct file *filp);802-extern int drm_flush(struct file *filp);803extern int drm_fasync(int fd, struct file *filp, int on);804extern int drm_release(struct inode *inode, struct file *filp);805···840 unsigned int cmd, unsigned long arg);841extern int drm_setversion(struct inode *inode, struct file *filp,842 unsigned int cmd, unsigned long arg);00843844 /* Context IOCTL support (drm_context.h) */845extern int drm_resctx(struct inode *inode, struct file *filp,···880extern int drm_authmagic(struct inode *inode, struct file *filp,881 unsigned int cmd, unsigned long arg);882883- /* Placeholder for ioctls past */884-extern int drm_noop(struct inode *inode, struct file *filp,885- unsigned int cmd, unsigned long arg);886-887 /* Locking IOCTL support (drm_lock.h) */888extern int drm_lock(struct inode *inode, struct file *filp,889 unsigned int cmd, unsigned long arg);···892 /* Buffer management support (drm_bufs.h) */893extern int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request);894extern int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request);0895extern int drm_addmap(drm_device_t * dev, unsigned int offset,896 unsigned int size, drm_map_type_t type,897 drm_map_flags_t flags, drm_local_map_t ** map_ptr);···928 /* IRQ support (drm_irq.h) */929extern int drm_control(struct inode *inode, struct file *filp,930 unsigned int cmd, unsigned long arg);931-extern int drm_irq_uninstall(drm_device_t * dev);932extern irqreturn_t drm_irq_handler(DRM_IRQ_ARGS);0933extern void drm_driver_irq_preinstall(drm_device_t * dev);934extern void drm_driver_irq_postinstall(drm_device_t * dev);935extern void drm_driver_irq_uninstall(drm_device_t * dev);···953extern int drm_agp_info(drm_device_t * dev, drm_agp_info_t * info);954extern int drm_agp_info_ioctl(struct inode *inode, struct file *filp,955 unsigned int cmd, unsigned long arg);956-extern int drm_agp_alloc(struct inode *inode, struct file *filp,0957 unsigned int cmd, unsigned long arg);958-extern int drm_agp_free(struct inode *inode, struct file *filp,0959 unsigned int cmd, unsigned long arg);960-extern int drm_agp_unbind(struct inode *inode, struct file *filp,0961 unsigned int cmd, unsigned long arg);962-extern int drm_agp_bind(struct inode *inode, struct file *filp,0963 unsigned int cmd, unsigned long arg);964extern DRM_AGP_MEM *drm_agp_allocate_memory(struct agp_bridge_data *bridge,965 size_t pages, u32 type);···1015 char *name);1016extern void drm_sysfs_destroy(struct drm_sysfs_class *cs);1017extern struct class_device *drm_sysfs_device_add(struct drm_sysfs_class *cs,1018- dev_t dev,1019- struct device *device,1020- const char *fmt, ...);1021-extern void drm_sysfs_device_remove(dev_t dev);10221023/* Inline replacements for DRM_IOREMAP macros */1024static __inline__ void drm_core_ioremap(struct drm_map *map,
···144/** \name Backward compatibility section */145/*@{*/14600000000000000147#define DRM_RPR_ARG(vma) vma,148149#define VM_OFFSET(vma) ((vma)->vm_pgoff << PAGE_SHIFT)···286typedef int drm_ioctl_compat_t(struct file *filp, unsigned int cmd,287 unsigned long arg);288289+#define DRM_AUTH 0x1290+#define DRM_MASTER 0x2291+#define DRM_ROOT_ONLY 0x4292+293typedef struct drm_ioctl_desc {294 drm_ioctl_t *func;295+ int flags;0296} drm_ioctl_desc_t;297298typedef struct drm_devstate {···384/** File private data */385typedef struct drm_file {386 int authenticated;387+ int master;388 int minor;389 pid_t pid;390 uid_t uid;···532typedef struct ati_pcigart_info {533 int gart_table_location;534 int is_pcie;535+ void *addr;536 dma_addr_t bus_addr;537+ drm_local_map_t mapping;538} drm_ati_pcigart_info;539540/**···544struct drm_device;545546struct drm_driver {547+ int (*load) (struct drm_device *, unsigned long flags);548+ int (*firstopen) (struct drm_device *);549+ int (*open) (struct drm_device *, drm_file_t *);550+ void (*preclose) (struct drm_device *, struct file * filp);551+ void (*postclose) (struct drm_device *, drm_file_t *);552+ void (*lastclose) (struct drm_device *);553+ int (*unload) (struct drm_device *);554 int (*dma_ioctl) (DRM_IOCTL_ARGS);000555 void (*dma_ready) (struct drm_device *);556 int (*dma_quiescent) (struct drm_device *);557 int (*context_ctor) (struct drm_device * dev, int context);···561 int (*kernel_context_switch) (struct drm_device * dev, int old,562 int new);563 void (*kernel_context_switch_unlock) (struct drm_device * dev,564+ drm_lock_t *lock);565 int (*vblank_wait) (struct drm_device * dev, unsigned int *sequence);566+ int (*dri_library_name) (struct drm_device *dev, char *buf);567568 /**569 * Called by \c drm_device_is_agp. Typically used to determine if a···579580 /* these have to be filled in */581582+ irqreturn_t(*irq_handler) (DRM_IRQ_ARGS);0583 void (*irq_preinstall) (struct drm_device * dev);584 void (*irq_postinstall) (struct drm_device * dev);585 void (*irq_uninstall) (struct drm_device * dev);586 void (*reclaim_buffers) (struct drm_device * dev, struct file * filp);587+ void (*reclaim_buffers_locked) (struct drm_device *dev,588+ struct file *filp);589 unsigned long (*get_map_ofs) (drm_map_t * map);590 unsigned long (*get_reg_ofs) (struct drm_device * dev);591 void (*set_version) (struct drm_device * dev, drm_set_version_t * sv);592+593+ int major;594+ int minor;595+ int patchlevel;596+ char *name;597+ char *desc;598+ char *date;599+600 u32 driver_features;601 int dev_priv_size;602 drm_ioctl_desc_t *ioctls;···752{753 return drm_core_check_feature(dev, DRIVER_USE_MTRR);754}755+756+#define DRM_MTRR_WC MTRR_TYPE_WRCOMB757+758+static inline int drm_mtrr_add(unsigned long offset, unsigned long size,759+ unsigned int flags)760+{761+ return mtrr_add(offset, size, flags, 1);762+}763+764+static inline int drm_mtrr_del(int handle, unsigned long offset,765+ unsigned long size, unsigned int flags)766+{767+ return mtrr_del(handle, offset, size);768+}769+770#else771#define drm_core_has_MTRR(dev) (0)772+773+#define DRM_MTRR_WC 0774+775+static inline int drm_mtrr_add(unsigned long offset, unsigned long size,776+ unsigned int flags)777+{778+ return 0;779+}780+781+static inline int drm_mtrr_del(int handle, unsigned long offset,782+ unsigned long size, unsigned int flags)783+{784+ return 0;785+}786#endif787788/******************************************************************/789/** \name Internal function definitions */790/*@{*/00000791792 /* Driver support (drm_drv.h) */793extern int drm_init(struct drm_driver *driver);···772 unsigned int cmd, unsigned long arg);773extern long drm_compat_ioctl(struct file *filp,774 unsigned int cmd, unsigned long arg);775+extern int drm_lastclose(drm_device_t *dev);776777 /* Device support (drm_fops.h) */778extern int drm_open(struct inode *inode, struct file *filp);779extern int drm_stub_open(struct inode *inode, struct file *filp);0780extern int drm_fasync(int fd, struct file *filp, int on);781extern int drm_release(struct inode *inode, struct file *filp);782···819 unsigned int cmd, unsigned long arg);820extern int drm_setversion(struct inode *inode, struct file *filp,821 unsigned int cmd, unsigned long arg);822+extern int drm_noop(struct inode *inode, struct file *filp,823+ unsigned int cmd, unsigned long arg);824825 /* Context IOCTL support (drm_context.h) */826extern int drm_resctx(struct inode *inode, struct file *filp,···857extern int drm_authmagic(struct inode *inode, struct file *filp,858 unsigned int cmd, unsigned long arg);8590000860 /* Locking IOCTL support (drm_lock.h) */861extern int drm_lock(struct inode *inode, struct file *filp,862 unsigned int cmd, unsigned long arg);···873 /* Buffer management support (drm_bufs.h) */874extern int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request);875extern int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request);876+extern int drm_addbufs_fb(drm_device_t *dev, drm_buf_desc_t *request);877extern int drm_addmap(drm_device_t * dev, unsigned int offset,878 unsigned int size, drm_map_type_t type,879 drm_map_flags_t flags, drm_local_map_t ** map_ptr);···908 /* IRQ support (drm_irq.h) */909extern int drm_control(struct inode *inode, struct file *filp,910 unsigned int cmd, unsigned long arg);0911extern irqreturn_t drm_irq_handler(DRM_IRQ_ARGS);912+extern int drm_irq_uninstall(drm_device_t * dev);913extern void drm_driver_irq_preinstall(drm_device_t * dev);914extern void drm_driver_irq_postinstall(drm_device_t * dev);915extern void drm_driver_irq_uninstall(drm_device_t * dev);···933extern int drm_agp_info(drm_device_t * dev, drm_agp_info_t * info);934extern int drm_agp_info_ioctl(struct inode *inode, struct file *filp,935 unsigned int cmd, unsigned long arg);936+extern int drm_agp_alloc(drm_device_t *dev, drm_agp_buffer_t *request);937+extern int drm_agp_alloc_ioctl(struct inode *inode, struct file *filp,938 unsigned int cmd, unsigned long arg);939+extern int drm_agp_free(drm_device_t *dev, drm_agp_buffer_t *request);940+extern int drm_agp_free_ioctl(struct inode *inode, struct file *filp,941 unsigned int cmd, unsigned long arg);942+extern int drm_agp_unbind(drm_device_t *dev, drm_agp_binding_t *request);943+extern int drm_agp_unbind_ioctl(struct inode *inode, struct file *filp,944 unsigned int cmd, unsigned long arg);945+extern int drm_agp_bind(drm_device_t *dev, drm_agp_binding_t *request);946+extern int drm_agp_bind_ioctl(struct inode *inode, struct file *filp,947 unsigned int cmd, unsigned long arg);948extern DRM_AGP_MEM *drm_agp_allocate_memory(struct agp_bridge_data *bridge,949 size_t pages, u32 type);···991 char *name);992extern void drm_sysfs_destroy(struct drm_sysfs_class *cs);993extern struct class_device *drm_sysfs_device_add(struct drm_sysfs_class *cs,994+ drm_head_t *head);995+extern void drm_sysfs_device_remove(struct class_device *class_dev);00996997/* Inline replacements for DRM_IOREMAP macros */998static __inline__ void drm_core_ioremap(struct drm_map *map,
+87-46
drivers/char/drm/drm_agpsupport.c
···1/**2- * \file drm_agpsupport.h3 * DRM support for AGP/GART backend4 *5 * \author Rickard E. (Rik) Faith <faith@valinux.com>···91/**92 * Acquire the AGP device.93 *94- * \param dev DRM device that is to acquire AGP95 * \return zero on success or a negative number on failure.96 *97 * Verifies the AGP device hasn't been acquired before and calls···134/**135 * Release the AGP device.136 *137- * \param dev DRM device that is to release AGP138 * \return zero on success or a negative number on failure.139 *140 * Verifies the AGP device has been acquired and calls \c agp_backend_release.···147 dev->agp->acquired = 0;148 return 0;149}150-151EXPORT_SYMBOL(drm_agp_release);152153int drm_agp_release_ioctl(struct inode *inode, struct file *filp,···207 * Verifies the AGP device is present and has been acquired, allocates the208 * memory via alloc_agp() and creates a drm_agp_mem entry for it.209 */210-int drm_agp_alloc(struct inode *inode, struct file *filp,211- unsigned int cmd, unsigned long arg)212{213- drm_file_t *priv = filp->private_data;214- drm_device_t *dev = priv->head->dev;215- drm_agp_buffer_t request;216 drm_agp_mem_t *entry;217 DRM_AGP_MEM *memory;218 unsigned long pages;219 u32 type;220- drm_agp_buffer_t __user *argp = (void __user *)arg;221222 if (!dev->agp || !dev->agp->acquired)223 return -EINVAL;224- if (copy_from_user(&request, argp, sizeof(request)))225- return -EFAULT;226 if (!(entry = drm_alloc(sizeof(*entry), DRM_MEM_AGPLISTS)))227 return -ENOMEM;228229 memset(entry, 0, sizeof(*entry));230231- pages = (request.size + PAGE_SIZE - 1) / PAGE_SIZE;232- type = (u32) request.type;233-234 if (!(memory = drm_alloc_agp(dev, pages, type))) {235 drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);236 return -ENOMEM;···238 dev->agp->memory->prev = entry;239 dev->agp->memory = entry;240241- request.handle = entry->handle;242- request.physical = memory->physical;00000000000000000000243244 if (copy_to_user(argp, &request, sizeof(request))) {00245 dev->agp->memory = entry->next;246 dev->agp->memory->prev = NULL;247- drm_free_agp(memory, pages);248 drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);249 return -EFAULT;250 }0251 return 0;252}253···307 * Verifies the AGP device is present and acquired, looks-up the AGP memory308 * entry and passes it to the unbind_agp() function.309 */310-int drm_agp_unbind(struct inode *inode, struct file *filp,311- unsigned int cmd, unsigned long arg)312{313- drm_file_t *priv = filp->private_data;314- drm_device_t *dev = priv->head->dev;315- drm_agp_binding_t request;316 drm_agp_mem_t *entry;317 int ret;318319 if (!dev->agp || !dev->agp->acquired)320 return -EINVAL;321- if (copy_from_user322- (&request, (drm_agp_binding_t __user *) arg, sizeof(request)))323- return -EFAULT;324- if (!(entry = drm_agp_lookup_entry(dev, request.handle)))325 return -EINVAL;326 if (!entry->bound)327 return -EINVAL;···322 if (ret == 0)323 entry->bound = 0;324 return ret;000000000000000325}326327/**···352 * is currently bound into the GATT. Looks-up the AGP memory entry and passes353 * it to bind_agp() function.354 */355-int drm_agp_bind(struct inode *inode, struct file *filp,356- unsigned int cmd, unsigned long arg)357{358- drm_file_t *priv = filp->private_data;359- drm_device_t *dev = priv->head->dev;360- drm_agp_binding_t request;361 drm_agp_mem_t *entry;362 int retcode;363 int page;364365 if (!dev->agp || !dev->agp->acquired)366 return -EINVAL;367- if (copy_from_user368- (&request, (drm_agp_binding_t __user *) arg, sizeof(request)))369- return -EFAULT;370- if (!(entry = drm_agp_lookup_entry(dev, request.handle)))371 return -EINVAL;372 if (entry->bound)373 return -EINVAL;374- page = (request.offset + PAGE_SIZE - 1) / PAGE_SIZE;375 if ((retcode = drm_bind_agp(entry->memory, page)))376 return retcode;377 entry->bound = dev->agp->base + (page << PAGE_SHIFT);378 DRM_DEBUG("base = 0x%lx entry->bound = 0x%lx\n",379 dev->agp->base, entry->bound);380 return 0;000000000000000381}382383/**···402 * unbind_agp(). Frees it via free_agp() as well as the entry itself403 * and unlinks from the doubly linked list it's inserted in.404 */405-int drm_agp_free(struct inode *inode, struct file *filp,406- unsigned int cmd, unsigned long arg)407{408- drm_file_t *priv = filp->private_data;409- drm_device_t *dev = priv->head->dev;410- drm_agp_buffer_t request;411 drm_agp_mem_t *entry;412413 if (!dev->agp || !dev->agp->acquired)414 return -EINVAL;415- if (copy_from_user416- (&request, (drm_agp_buffer_t __user *) arg, sizeof(request)))417- return -EFAULT;418- if (!(entry = drm_agp_lookup_entry(dev, request.handle)))419 return -EINVAL;420 if (entry->bound)421 drm_unbind_agp(entry->memory);···425 drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);426 return 0;427}000000000000000428429/**430 * Initialize the AGP resources.431 *432 * \return pointer to a drm_agp_head structure.433 *000434 */435drm_agp_head_t *drm_agp_init(drm_device_t * dev)436{
···1/**2+ * \file drm_agpsupport.c3 * DRM support for AGP/GART backend4 *5 * \author Rickard E. (Rik) Faith <faith@valinux.com>···91/**92 * Acquire the AGP device.93 *94+ * \param dev DRM device that is to acquire AGP.95 * \return zero on success or a negative number on failure.96 *97 * Verifies the AGP device hasn't been acquired before and calls···134/**135 * Release the AGP device.136 *137+ * \param dev DRM device that is to release AGP.138 * \return zero on success or a negative number on failure.139 *140 * Verifies the AGP device has been acquired and calls \c agp_backend_release.···147 dev->agp->acquired = 0;148 return 0;149}0150EXPORT_SYMBOL(drm_agp_release);151152int drm_agp_release_ioctl(struct inode *inode, struct file *filp,···208 * Verifies the AGP device is present and has been acquired, allocates the209 * memory via alloc_agp() and creates a drm_agp_mem entry for it.210 */211+int drm_agp_alloc(drm_device_t *dev, drm_agp_buffer_t *request)0212{000213 drm_agp_mem_t *entry;214 DRM_AGP_MEM *memory;215 unsigned long pages;216 u32 type;0217218 if (!dev->agp || !dev->agp->acquired)219 return -EINVAL;00220 if (!(entry = drm_alloc(sizeof(*entry), DRM_MEM_AGPLISTS)))221 return -ENOMEM;222223 memset(entry, 0, sizeof(*entry));224225+ pages = (request->size + PAGE_SIZE - 1) / PAGE_SIZE;226+ type = (u32) request->type;0227 if (!(memory = drm_alloc_agp(dev, pages, type))) {228 drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);229 return -ENOMEM;···247 dev->agp->memory->prev = entry;248 dev->agp->memory = entry;249250+ request->handle = entry->handle;251+ request->physical = memory->physical;252+253+ return 0;254+}255+EXPORT_SYMBOL(drm_agp_alloc);256+257+int drm_agp_alloc_ioctl(struct inode *inode, struct file *filp,258+ unsigned int cmd, unsigned long arg)259+{260+ drm_file_t *priv = filp->private_data;261+ drm_device_t *dev = priv->head->dev;262+ drm_agp_buffer_t request;263+ drm_agp_buffer_t __user *argp = (void __user *)arg;264+ int err;265+266+ if (copy_from_user(&request, argp, sizeof(request)))267+ return -EFAULT;268+269+ err = drm_agp_alloc(dev, &request);270+ if (err)271+ return err;272273 if (copy_to_user(argp, &request, sizeof(request))) {274+ drm_agp_mem_t *entry = dev->agp->memory;275+276 dev->agp->memory = entry->next;277 dev->agp->memory->prev = NULL;278+ drm_free_agp(entry->memory, entry->pages);279 drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);280 return -EFAULT;281 }282+283 return 0;284}285···293 * Verifies the AGP device is present and acquired, looks-up the AGP memory294 * entry and passes it to the unbind_agp() function.295 */296+int drm_agp_unbind(drm_device_t *dev, drm_agp_binding_t *request)0297{000298 drm_agp_mem_t *entry;299 int ret;300301 if (!dev->agp || !dev->agp->acquired)302 return -EINVAL;303+ if (!(entry = drm_agp_lookup_entry(dev, request->handle)))000304 return -EINVAL;305 if (!entry->bound)306 return -EINVAL;···315 if (ret == 0)316 entry->bound = 0;317 return ret;318+}319+EXPORT_SYMBOL(drm_agp_unbind);320+321+int drm_agp_unbind_ioctl(struct inode *inode, struct file *filp,322+ unsigned int cmd, unsigned long arg)323+{324+ drm_file_t *priv = filp->private_data;325+ drm_device_t *dev = priv->head->dev;326+ drm_agp_binding_t request;327+328+ if (copy_from_user329+ (&request, (drm_agp_binding_t __user *) arg, sizeof(request)))330+ return -EFAULT;331+332+ return drm_agp_unbind(dev, &request);333}334335/**···330 * is currently bound into the GATT. Looks-up the AGP memory entry and passes331 * it to bind_agp() function.332 */333+int drm_agp_bind(drm_device_t *dev, drm_agp_binding_t *request)0334{000335 drm_agp_mem_t *entry;336 int retcode;337 int page;338339 if (!dev->agp || !dev->agp->acquired)340 return -EINVAL;341+ if (!(entry = drm_agp_lookup_entry(dev, request->handle)))000342 return -EINVAL;343 if (entry->bound)344 return -EINVAL;345+ page = (request->offset + PAGE_SIZE - 1) / PAGE_SIZE;346 if ((retcode = drm_bind_agp(entry->memory, page)))347 return retcode;348 entry->bound = dev->agp->base + (page << PAGE_SHIFT);349 DRM_DEBUG("base = 0x%lx entry->bound = 0x%lx\n",350 dev->agp->base, entry->bound);351 return 0;352+}353+EXPORT_SYMBOL(drm_agp_bind);354+355+int drm_agp_bind_ioctl(struct inode *inode, struct file *filp,356+ unsigned int cmd, unsigned long arg)357+{358+ drm_file_t *priv = filp->private_data;359+ drm_device_t *dev = priv->head->dev;360+ drm_agp_binding_t request;361+362+ if (copy_from_user363+ (&request, (drm_agp_binding_t __user *) arg, sizeof(request)))364+ return -EFAULT;365+366+ return drm_agp_bind(dev, &request);367}368369/**···372 * unbind_agp(). Frees it via free_agp() as well as the entry itself373 * and unlinks from the doubly linked list it's inserted in.374 */375+int drm_agp_free(drm_device_t *dev, drm_agp_buffer_t *request)0376{000377 drm_agp_mem_t *entry;378379 if (!dev->agp || !dev->agp->acquired)380 return -EINVAL;381+ if (!(entry = drm_agp_lookup_entry(dev, request->handle)))000382 return -EINVAL;383 if (entry->bound)384 drm_unbind_agp(entry->memory);···402 drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);403 return 0;404}405+EXPORT_SYMBOL(drm_agp_free);406+407+int drm_agp_free_ioctl(struct inode *inode, struct file *filp,408+ unsigned int cmd, unsigned long arg)409+{410+ drm_file_t *priv = filp->private_data;411+ drm_device_t *dev = priv->head->dev;412+ drm_agp_buffer_t request;413+414+ if (copy_from_user415+ (&request, (drm_agp_buffer_t __user *) arg, sizeof(request)))416+ return -EFAULT;417+418+ return drm_agp_free(dev, &request);419+}420421/**422 * Initialize the AGP resources.423 *424 * \return pointer to a drm_agp_head structure.425 *426+ * Gets the drm_agp_t structure which is made available by the agpgart module427+ * via the inter_module_* functions. Creates and initializes a drm_agp_head428+ * structure.429 */430drm_agp_head_t *drm_agp_init(drm_device_t * dev)431{
+33-16
drivers/char/drm/drm_bufs.c
···36#include <linux/vmalloc.h>37#include "drmP.h"3839-unsigned long drm_get_resource_start(drm_device_t * dev, unsigned int resource)40{41 return pci_resource_start(dev->pdev, resource);42}43-44EXPORT_SYMBOL(drm_get_resource_start);4546-unsigned long drm_get_resource_len(drm_device_t * dev, unsigned int resource)47{48 return pci_resource_len(dev->pdev, resource);49}5051EXPORT_SYMBOL(drm_get_resource_len);5253-static drm_map_list_t *drm_find_matching_map(drm_device_t * dev,54- drm_local_map_t * map)55{56 struct list_head *list;57···7374#ifdef _LP6475static __inline__ unsigned int HandleID(unsigned long lhandle,76- drm_device_t * dev)77{78 static unsigned int map32_handle = START_RANGE;79 unsigned int hash;···154 case _DRM_REGISTERS:155 case _DRM_FRAME_BUFFER:156#if !defined(__sparc__) && !defined(__alpha__) && !defined(__ia64__) && !defined(__powerpc64__) && !defined(__x86_64__)157- if (map->offset + map->size < map->offset ||158 map->offset < virt_to_phys(high_memory)) {159 drm_free(map, sizeof(*map), DRM_MEM_MAPS);160 return -EINVAL;···300 return -EFAULT;301 }302000303 err = drm_addmap_core(dev, map.offset, map.size, map.type, map.flags,304 &maplist);305···334 *335 * \sa drm_addmap336 */337-int drm_rmmap_locked(drm_device_t * dev, drm_local_map_t * map)338{339 struct list_head *list;340 drm_map_list_t *r_list = NULL;···386387 return 0;388}389-390EXPORT_SYMBOL(drm_rmmap_locked);391392-int drm_rmmap(drm_device_t * dev, drm_local_map_t * map)393{394 int ret;395···398399 return ret;400}401-402EXPORT_SYMBOL(drm_rmmap);403404/* The rmmap ioctl appears to be unnecessary. All mappings are torn down on···548 DRM_DEBUG("count: %d\n", count);549 DRM_DEBUG("order: %d\n", order);550 DRM_DEBUG("size: %d\n", size);551- DRM_DEBUG("agp_offset: %lu\n", agp_offset);552 DRM_DEBUG("alignment: %d\n", alignment);553 DRM_DEBUG("page_order: %d\n", page_order);554 DRM_DEBUG("total: %d\n", total);···649 }650651 dma->buf_count += entry->buf_count;00652 dma->byte_count += byte_count;653654 DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count);···666 atomic_dec(&dev->buf_alloc);667 return 0;668}669-670EXPORT_SYMBOL(drm_addbufs_agp);671#endif /* __OS_HAS_AGP */672···690691 if (!drm_core_check_feature(dev, DRIVER_PCI_DMA))692 return -EINVAL;0693 if (!dma)694 return -EINVAL;000695696 count = request->count;697 order = drm_order(request->size);···887 return 0;888889}890-891EXPORT_SYMBOL(drm_addbufs_pci);892893static int drm_addbufs_sg(drm_device_t * dev, drm_buf_desc_t * request)···911912 if (!dma)913 return -EINVAL;000914915 count = request->count;916 order = drm_order(request->size);···1033 }10341035 dma->buf_count += entry->buf_count;001036 dma->byte_count += byte_count;10371038 DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count);···1051 return 0;1052}10531054-static int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request)1055{1056 drm_device_dma_t *dma = dev->dma;1057 drm_buf_entry_t *entry;···10731074 if (!dma)1075 return -EINVAL;00010761077 count = request->count;1078 order = drm_order(request->size);···1193 }11941195 dma->buf_count += entry->buf_count;001196 dma->byte_count += byte_count;11971198 DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count);···1210 atomic_dec(&dev->buf_alloc);1211 return 0;1212}0012131214/**1215 * Add buffers for DMA transfers (ioctl).···15931594 return order;1595}1596-1597EXPORT_SYMBOL(drm_order);00
···36#include <linux/vmalloc.h>37#include "drmP.h"3839+unsigned long drm_get_resource_start(drm_device_t *dev, unsigned int resource)40{41 return pci_resource_start(dev->pdev, resource);42}043EXPORT_SYMBOL(drm_get_resource_start);4445+unsigned long drm_get_resource_len(drm_device_t *dev, unsigned int resource)46{47 return pci_resource_len(dev->pdev, resource);48}4950EXPORT_SYMBOL(drm_get_resource_len);5152+static drm_map_list_t *drm_find_matching_map(drm_device_t *dev,53+ drm_local_map_t *map)54{55 struct list_head *list;56···7475#ifdef _LP6476static __inline__ unsigned int HandleID(unsigned long lhandle,77+ drm_device_t *dev)78{79 static unsigned int map32_handle = START_RANGE;80 unsigned int hash;···155 case _DRM_REGISTERS:156 case _DRM_FRAME_BUFFER:157#if !defined(__sparc__) && !defined(__alpha__) && !defined(__ia64__) && !defined(__powerpc64__) && !defined(__x86_64__)158+ if (map->offset + (map->size-1) < map->offset ||159 map->offset < virt_to_phys(high_memory)) {160 drm_free(map, sizeof(*map), DRM_MEM_MAPS);161 return -EINVAL;···301 return -EFAULT;302 }303304+ if (!(capable(CAP_SYS_ADMIN) || map.type == _DRM_AGP))305+ return -EPERM;306+307 err = drm_addmap_core(dev, map.offset, map.size, map.type, map.flags,308 &maplist);309···332 *333 * \sa drm_addmap334 */335+int drm_rmmap_locked(drm_device_t *dev, drm_local_map_t *map)336{337 struct list_head *list;338 drm_map_list_t *r_list = NULL;···384385 return 0;386}0387EXPORT_SYMBOL(drm_rmmap_locked);388389+int drm_rmmap(drm_device_t *dev, drm_local_map_t *map)390{391 int ret;392···397398 return ret;399}0400EXPORT_SYMBOL(drm_rmmap);401402/* The rmmap ioctl appears to be unnecessary. All mappings are torn down on···548 DRM_DEBUG("count: %d\n", count);549 DRM_DEBUG("order: %d\n", order);550 DRM_DEBUG("size: %d\n", size);551+ DRM_DEBUG("agp_offset: %lx\n", agp_offset);552 DRM_DEBUG("alignment: %d\n", alignment);553 DRM_DEBUG("page_order: %d\n", page_order);554 DRM_DEBUG("total: %d\n", total);···649 }650651 dma->buf_count += entry->buf_count;652+ dma->seg_count += entry->seg_count;653+ dma->page_count += byte_count >> PAGE_SHIFT;654 dma->byte_count += byte_count;655656 DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count);···664 atomic_dec(&dev->buf_alloc);665 return 0;666}0667EXPORT_SYMBOL(drm_addbufs_agp);668#endif /* __OS_HAS_AGP */669···689690 if (!drm_core_check_feature(dev, DRIVER_PCI_DMA))691 return -EINVAL;692+693 if (!dma)694 return -EINVAL;695+696+ if (!capable(CAP_SYS_ADMIN))697+ return -EPERM;698699 count = request->count;700 order = drm_order(request->size);···882 return 0;883884}0885EXPORT_SYMBOL(drm_addbufs_pci);886887static int drm_addbufs_sg(drm_device_t * dev, drm_buf_desc_t * request)···907908 if (!dma)909 return -EINVAL;910+911+ if (!capable(CAP_SYS_ADMIN))912+ return -EPERM;913914 count = request->count;915 order = drm_order(request->size);···1026 }10271028 dma->buf_count += entry->buf_count;1029+ dma->seg_count += entry->seg_count;1030+ dma->page_count += byte_count >> PAGE_SHIFT;1031 dma->byte_count += byte_count;10321033 DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count);···1042 return 0;1043}10441045+int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request)1046{1047 drm_device_dma_t *dma = dev->dma;1048 drm_buf_entry_t *entry;···10641065 if (!dma)1066 return -EINVAL;1067+1068+ if (!capable(CAP_SYS_ADMIN))1069+ return -EPERM;10701071 count = request->count;1072 order = drm_order(request->size);···1181 }11821183 dma->buf_count += entry->buf_count;1184+ dma->seg_count += entry->seg_count;1185+ dma->page_count += byte_count >> PAGE_SHIFT;1186 dma->byte_count += byte_count;11871188 DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count);···1196 atomic_dec(&dev->buf_alloc);1197 return 0;1198}1199+EXPORT_SYMBOL(drm_addbufs_fb);1200+12011202/**1203 * Add buffers for DMA transfers (ioctl).···15771578 return order;1579}01580EXPORT_SYMBOL(drm_order);1581+1582+
+1-1
drivers/char/drm/drm_context.c
···433 if (ctx.handle != DRM_KERNEL_CONTEXT) {434 if (dev->driver->context_ctor)435 if (!dev->driver->context_ctor(dev, ctx.handle)) {436- DRM_DEBUG( "Running out of ctxs or memory.\n");437 return -ENOMEM;438 }439 }
···433 if (ctx.handle != DRM_KERNEL_CONTEXT) {434 if (dev->driver->context_ctor)435 if (!dev->driver->context_ctor(dev, ctx.handle)) {436+ DRM_DEBUG("Running out of ctxs or memory.\n");437 return -ENOMEM;438 }439 }
···35 */3637#include "drmP.h"038#include <linux/poll.h>3940static int drm_open_helper(struct inode *inode, struct file *filp,···4344static int drm_setup(drm_device_t * dev)45{046 int i;47 int ret;4849- if (dev->driver->presetup) {50- ret = dev->driver->presetup(dev);51 if (ret != 0)52 return ret;53 }000005455 atomic_set(&dev->ioctl_count, 0);56 atomic_set(&dev->vma_count, 0);···116 * drm_select_queue fails between the time the interrupt is117 * initialized and the time the queues are initialized.118 */119- if (dev->driver->postsetup)120- dev->driver->postsetup(dev);121122 return 0;123}···159160 return retcode;161}162-163EXPORT_SYMBOL(drm_open);000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000164165/**166 * Release file.···330 * If the hardware lock is held then free it, and take it again for the kernel331 * context since it's necessary to reclaim buffers. Unlink the file private332 * data from its list and free it. Decreases the open count and if it reaches333- * zero calls takedown().334 */335int drm_release(struct inode *inode, struct file *filp)336{···343344 DRM_DEBUG("open_count = %d\n", dev->open_count);345346- if (dev->driver->prerelease)347- dev->driver->prerelease(dev, filp);348349 /* ========================================================350 * Begin inline drm_release···360 DRM_DEBUG("File %p released, freeing lock for context %d\n",361 filp, _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));362363- if (dev->driver->release)364- dev->driver->release(dev, filp);365366 drm_lock_free(dev, &dev->lock.hw_lock->lock,367 _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));···370 hardware at this point, possibly371 processed via a callback to the X372 server. */373- } else if (dev->driver->release && priv->lock_count374 && dev->lock.hw_lock) {375 /* The lock is required to reclaim buffers */376 DECLARE_WAITQUEUE(entry, current);···400 __set_current_state(TASK_RUNNING);401 remove_wait_queue(&dev->lock.lock_queue, &entry);402 if (!retcode) {403- if (dev->driver->release)404- dev->driver->release(dev, filp);405 drm_lock_free(dev, &dev->lock.hw_lock->lock,406 DRM_KERNEL_CONTEXT);407 }408 }409410- if (drm_core_check_feature(dev, DRIVER_HAVE_DMA)411- && !dev->driver->release) {412 dev->driver->reclaim_buffers(dev, filp);413 }414···454 }455 up(&dev->struct_sem);456457- if (dev->driver->free_filp_priv)458- dev->driver->free_filp_priv(dev, priv);459-460 drm_free(priv, sizeof(*priv), DRM_MEM_FILES);461462 /* ========================================================···474 }475 spin_unlock(&dev->count_lock);476 unlock_kernel();477- return drm_takedown(dev);478 }479 spin_unlock(&dev->count_lock);480···482483 return retcode;484}485-486EXPORT_SYMBOL(drm_release);487-488-/**489- * Called whenever a process opens /dev/drm.490- *491- * \param inode device inode.492- * \param filp file pointer.493- * \param dev device.494- * \return zero on success or a negative number on failure.495- *496- * Creates and initializes a drm_file structure for the file private data in \p497- * filp and add it into the double linked list in \p dev.498- */499-static int drm_open_helper(struct inode *inode, struct file *filp,500- drm_device_t * dev)501-{502- int minor = iminor(inode);503- drm_file_t *priv;504- int ret;505-506- if (filp->f_flags & O_EXCL)507- return -EBUSY; /* No exclusive opens */508- if (!drm_cpu_valid())509- return -EINVAL;510-511- DRM_DEBUG("pid = %d, minor = %d\n", current->pid, minor);512-513- priv = drm_alloc(sizeof(*priv), DRM_MEM_FILES);514- if (!priv)515- return -ENOMEM;516-517- memset(priv, 0, sizeof(*priv));518- filp->private_data = priv;519- priv->uid = current->euid;520- priv->pid = current->pid;521- priv->minor = minor;522- priv->head = drm_heads[minor];523- priv->ioctl_count = 0;524- priv->authenticated = capable(CAP_SYS_ADMIN);525- priv->lock_count = 0;526-527- if (dev->driver->open_helper) {528- ret = dev->driver->open_helper(dev, priv);529- if (ret < 0)530- goto out_free;531- }532-533- down(&dev->struct_sem);534- if (!dev->file_last) {535- priv->next = NULL;536- priv->prev = NULL;537- dev->file_first = priv;538- dev->file_last = priv;539- } else {540- priv->next = NULL;541- priv->prev = dev->file_last;542- dev->file_last->next = priv;543- dev->file_last = priv;544- }545- up(&dev->struct_sem);546-547-#ifdef __alpha__548- /*549- * Default the hose550- */551- if (!dev->hose) {552- struct pci_dev *pci_dev;553- pci_dev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, NULL);554- if (pci_dev) {555- dev->hose = pci_dev->sysdata;556- pci_dev_put(pci_dev);557- }558- if (!dev->hose) {559- struct pci_bus *b = pci_bus_b(pci_root_buses.next);560- if (b)561- dev->hose = b->sysdata;562- }563- }564-#endif565-566- return 0;567- out_free:568- drm_free(priv, sizeof(*priv), DRM_MEM_FILES);569- filp->private_data = NULL;570- return ret;571-}572-573-/** No-op. */574-int drm_flush(struct file *filp)575-{576- drm_file_t *priv = filp->private_data;577- drm_device_t *dev = priv->head->dev;578-579- DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n",580- current->pid, (long)old_encode_dev(priv->head->device),581- dev->open_count);582- return 0;583-}584-585-EXPORT_SYMBOL(drm_flush);586-587-/** No-op. */588-int drm_fasync(int fd, struct file *filp, int on)589-{590- drm_file_t *priv = filp->private_data;591- drm_device_t *dev = priv->head->dev;592- int retcode;593-594- DRM_DEBUG("fd = %d, device = 0x%lx\n", fd,595- (long)old_encode_dev(priv->head->device));596- retcode = fasync_helper(fd, filp, on, &dev->buf_async);597- if (retcode < 0)598- return retcode;599- return 0;600-}601-602-EXPORT_SYMBOL(drm_fasync);603604/** No-op. */605unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait)606{607 return 0;608}609-610EXPORT_SYMBOL(drm_poll);
···35 */3637#include "drmP.h"38+#include "drm_sarea.h"39#include <linux/poll.h>4041static int drm_open_helper(struct inode *inode, struct file *filp,···4243static int drm_setup(drm_device_t * dev)44{45+ drm_local_map_t *map;46 int i;47 int ret;4849+ if (dev->driver->firstopen) {50+ ret = dev->driver->firstopen(dev);51 if (ret != 0)52 return ret;53 }54+55+ /* prebuild the SAREA */56+ i = drm_addmap(dev, 0, SAREA_MAX, _DRM_SHM, _DRM_CONTAINS_LOCK, &map);57+ if (i != 0)58+ return i;5960 atomic_set(&dev->ioctl_count, 0);61 atomic_set(&dev->vma_count, 0);···109 * drm_select_queue fails between the time the interrupt is110 * initialized and the time the queues are initialized.111 */00112113 return 0;114}···154155 return retcode;156}0157EXPORT_SYMBOL(drm_open);158+159+/**160+ * File \c open operation.161+ *162+ * \param inode device inode.163+ * \param filp file pointer.164+ *165+ * Puts the dev->fops corresponding to the device minor number into166+ * \p filp, call the \c open method, and restore the file operations.167+ */168+int drm_stub_open(struct inode *inode, struct file *filp)169+{170+ drm_device_t *dev = NULL;171+ int minor = iminor(inode);172+ int err = -ENODEV;173+ struct file_operations *old_fops;174+175+ DRM_DEBUG("\n");176+177+ if (!((minor >= 0) && (minor < drm_cards_limit)))178+ return -ENODEV;179+180+ if (!drm_heads[minor])181+ return -ENODEV;182+183+ if (!(dev = drm_heads[minor]->dev))184+ return -ENODEV;185+186+ old_fops = filp->f_op;187+ filp->f_op = fops_get(&dev->driver->fops);188+ if (filp->f_op->open && (err = filp->f_op->open(inode, filp))) {189+ fops_put(filp->f_op);190+ filp->f_op = fops_get(old_fops);191+ }192+ fops_put(old_fops);193+194+ return err;195+}196+197+/**198+ * Check whether DRI will run on this CPU.199+ *200+ * \return non-zero if the DRI will run on this CPU, or zero otherwise.201+ */202+static int drm_cpu_valid(void)203+{204+#if defined(__i386__)205+ if (boot_cpu_data.x86 == 3)206+ return 0; /* No cmpxchg on a 386 */207+#endif208+#if defined(__sparc__) && !defined(__sparc_v9__)209+ return 0; /* No cmpxchg before v9 sparc. */210+#endif211+ return 1;212+}213+214+/**215+ * Called whenever a process opens /dev/drm.216+ *217+ * \param inode device inode.218+ * \param filp file pointer.219+ * \param dev device.220+ * \return zero on success or a negative number on failure.221+ *222+ * Creates and initializes a drm_file structure for the file private data in \p223+ * filp and add it into the double linked list in \p dev.224+ */225+static int drm_open_helper(struct inode *inode, struct file *filp,226+ drm_device_t * dev)227+{228+ int minor = iminor(inode);229+ drm_file_t *priv;230+ int ret;231+232+ if (filp->f_flags & O_EXCL)233+ return -EBUSY; /* No exclusive opens */234+ if (!drm_cpu_valid())235+ return -EINVAL;236+237+ DRM_DEBUG("pid = %d, minor = %d\n", current->pid, minor);238+239+ priv = drm_alloc(sizeof(*priv), DRM_MEM_FILES);240+ if (!priv)241+ return -ENOMEM;242+243+ memset(priv, 0, sizeof(*priv));244+ filp->private_data = priv;245+ priv->uid = current->euid;246+ priv->pid = current->pid;247+ priv->minor = minor;248+ priv->head = drm_heads[minor];249+ priv->ioctl_count = 0;250+ /* for compatibility root is always authenticated */251+ priv->authenticated = capable(CAP_SYS_ADMIN);252+ priv->lock_count = 0;253+254+ if (dev->driver->open) {255+ ret = dev->driver->open(dev, priv);256+ if (ret < 0)257+ goto out_free;258+ }259+260+ down(&dev->struct_sem);261+ if (!dev->file_last) {262+ priv->next = NULL;263+ priv->prev = NULL;264+ dev->file_first = priv;265+ dev->file_last = priv;266+ /* first opener automatically becomes master */267+ priv->master = 1;268+ } else {269+ priv->next = NULL;270+ priv->prev = dev->file_last;271+ dev->file_last->next = priv;272+ dev->file_last = priv;273+ }274+ up(&dev->struct_sem);275+276+#ifdef __alpha__277+ /*278+ * Default the hose279+ */280+ if (!dev->hose) {281+ struct pci_dev *pci_dev;282+ pci_dev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, NULL);283+ if (pci_dev) {284+ dev->hose = pci_dev->sysdata;285+ pci_dev_put(pci_dev);286+ }287+ if (!dev->hose) {288+ struct pci_bus *b = pci_bus_b(pci_root_buses.next);289+ if (b)290+ dev->hose = b->sysdata;291+ }292+ }293+#endif294+295+ return 0;296+ out_free:297+ drm_free(priv, sizeof(*priv), DRM_MEM_FILES);298+ filp->private_data = NULL;299+ return ret;300+}301+302+/** No-op. */303+int drm_fasync(int fd, struct file *filp, int on)304+{305+ drm_file_t *priv = filp->private_data;306+ drm_device_t *dev = priv->head->dev;307+ int retcode;308+309+ DRM_DEBUG("fd = %d, device = 0x%lx\n", fd,310+ (long)old_encode_dev(priv->head->device));311+ retcode = fasync_helper(fd, filp, on, &dev->buf_async);312+ if (retcode < 0)313+ return retcode;314+ return 0;315+}316+EXPORT_SYMBOL(drm_fasync);317318/**319 * Release file.···167 * If the hardware lock is held then free it, and take it again for the kernel168 * context since it's necessary to reclaim buffers. Unlink the file private169 * data from its list and free it. Decreases the open count and if it reaches170+ * zero calls drm_lastclose().171 */172int drm_release(struct inode *inode, struct file *filp)173{···180181 DRM_DEBUG("open_count = %d\n", dev->open_count);182183+ if (dev->driver->preclose)184+ dev->driver->preclose(dev, filp);185186 /* ========================================================187 * Begin inline drm_release···197 DRM_DEBUG("File %p released, freeing lock for context %d\n",198 filp, _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));199200+ if (dev->driver->reclaim_buffers_locked)201+ dev->driver->reclaim_buffers_locked(dev, filp);202203 drm_lock_free(dev, &dev->lock.hw_lock->lock,204 _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));···207 hardware at this point, possibly208 processed via a callback to the X209 server. */210+ } else if (dev->driver->reclaim_buffers_locked && priv->lock_count211 && dev->lock.hw_lock) {212 /* The lock is required to reclaim buffers */213 DECLARE_WAITQUEUE(entry, current);···237 __set_current_state(TASK_RUNNING);238 remove_wait_queue(&dev->lock.lock_queue, &entry);239 if (!retcode) {240+ dev->driver->reclaim_buffers_locked(dev, filp);0241 drm_lock_free(dev, &dev->lock.hw_lock->lock,242 DRM_KERNEL_CONTEXT);243 }244 }245246+ if (drm_core_check_feature(dev, DRIVER_HAVE_DMA) &&247+ !dev->driver->reclaim_buffers_locked) {248 dev->driver->reclaim_buffers(dev, filp);249 }250···292 }293 up(&dev->struct_sem);294295+ if (dev->driver->postclose)296+ dev->driver->postclose(dev, priv);0297 drm_free(priv, sizeof(*priv), DRM_MEM_FILES);298299 /* ========================================================···313 }314 spin_unlock(&dev->count_lock);315 unlock_kernel();316+ return drm_lastclose(dev);317 }318 spin_unlock(&dev->count_lock);319···321322 return retcode;323}0324EXPORT_SYMBOL(drm_release);00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000325326/** No-op. */327unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait)328{329 return 0;330}0331EXPORT_SYMBOL(drm_poll);
-53
drivers/char/drm/drm_init.c
···1-/**2- * \file drm_init.c3- * Setup/Cleanup for DRM4- *5- * \author Rickard E. (Rik) Faith <faith@valinux.com>6- * \author Gareth Hughes <gareth@valinux.com>7- */8-9-/*10- * Created: Mon Jan 4 08:58:31 1999 by faith@valinux.com11- *12- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.13- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.14- * All Rights Reserved.15- *16- * Permission is hereby granted, free of charge, to any person obtaining a17- * copy of this software and associated documentation files (the "Software"),18- * to deal in the Software without restriction, including without limitation19- * the rights to use, copy, modify, merge, publish, distribute, sublicense,20- * and/or sell copies of the Software, and to permit persons to whom the21- * Software is furnished to do so, subject to the following conditions:22- *23- * The above copyright notice and this permission notice (including the next24- * paragraph) shall be included in all copies or substantial portions of the25- * Software.26- *27- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR28- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,29- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL30- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR31- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,32- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR33- * OTHER DEALINGS IN THE SOFTWARE.34- */35-36-#include "drmP.h"37-38-/**39- * Check whether DRI will run on this CPU.40- *41- * \return non-zero if the DRI will run on this CPU, or zero otherwise.42- */43-int drm_cpu_valid(void)44-{45-#if defined(__i386__)46- if (boot_cpu_data.x86 == 3)47- return 0; /* No cmpxchg on a 386 */48-#endif49-#if defined(__sparc__) && !defined(__sparc_v9__)50- return 0; /* No cmpxchg before v9 sparc. */51-#endif52- return 1;53-}
···130 /* dev->driver->kernel_context_switch isn't used by any of the x86131 * drivers but is used by the Sparc driver.132 */133-134 if (dev->driver->kernel_context_switch &&135 dev->last_context != lock.context) {136 dev->driver->kernel_context_switch(dev, dev->last_context,
···130 /* dev->driver->kernel_context_switch isn't used by any of the x86131 * drivers but is used by the Sparc driver.132 */0133 if (dev->driver->kernel_context_switch &&134 dev->last_context != lock.context) {135 dev->driver->kernel_context_switch(dev, dev->last_context,
-8
drivers/char/drm/drm_memory.c
···145 return drm_agp_allocate_memory(dev->agp->bridge, pages, type);146}147148-EXPORT_SYMBOL(drm_alloc_agp);149-150/** Wrapper around agp_free_memory() */151int drm_free_agp(DRM_AGP_MEM * handle, int pages)152{153 return drm_agp_free_memory(handle) ? 0 : -EINVAL;154}155-156-EXPORT_SYMBOL(drm_free_agp);157158/** Wrapper around agp_bind_memory() */159int drm_bind_agp(DRM_AGP_MEM * handle, unsigned int start)···157 return drm_agp_bind_memory(handle, start);158}159160-EXPORT_SYMBOL(drm_bind_agp);161-162/** Wrapper around agp_unbind_memory() */163int drm_unbind_agp(DRM_AGP_MEM * handle)164{165 return drm_agp_unbind_memory(handle);166}167-168-EXPORT_SYMBOL(drm_unbind_agp);169#endif /* agp */170#endif /* debug_memory */
···145 return drm_agp_allocate_memory(dev->agp->bridge, pages, type);146}14700148/** Wrapper around agp_free_memory() */149int drm_free_agp(DRM_AGP_MEM * handle, int pages)150{151 return drm_agp_free_memory(handle) ? 0 : -EINVAL;152}00153154/** Wrapper around agp_bind_memory() */155int drm_bind_agp(DRM_AGP_MEM * handle, unsigned int start)···161 return drm_agp_bind_memory(handle, start);162}16300164/** Wrapper around agp_unbind_memory() */165int drm_unbind_agp(DRM_AGP_MEM * handle)166{167 return drm_agp_unbind_memory(handle);168}00169#endif /* agp */170#endif /* debug_memory */
+134-135
drivers/char/drm/drm_memory_debug.h
···1/**2- * \file drm_memory.h3 * Memory management wrappers for DRM.4 *5 * \author Rickard E. (Rik) Faith <faith@valinux.com>···43 unsigned long bytes_freed;44} drm_mem_stats_t;4546-static DEFINE_SPINLOCK(DRM(mem_lock));47-static unsigned long DRM(ram_available) = 0; /* In pages */48-static unsigned long DRM(ram_used) = 0;49-static drm_mem_stats_t DRM(mem_stats)[] =50{51- [DRM_MEM_DMA] = {52- "dmabufs"},[DRM_MEM_SAREA] = {53- "sareas"},[DRM_MEM_DRIVER] = {54- "driver"},[DRM_MEM_MAGIC] = {55- "magic"},[DRM_MEM_IOCTLS] = {56- "ioctltab"},[DRM_MEM_MAPS] = {57- "maplist"},[DRM_MEM_VMAS] = {58- "vmalist"},[DRM_MEM_BUFS] = {59- "buflist"},[DRM_MEM_SEGS] = {60- "seglist"},[DRM_MEM_PAGES] = {61- "pagelist"},[DRM_MEM_FILES] = {62- "files"},[DRM_MEM_QUEUES] = {63- "queues"},[DRM_MEM_CMDS] = {64- "commands"},[DRM_MEM_MAPPINGS] = {65- "mappings"},[DRM_MEM_BUFLISTS] = {66- "buflists"},[DRM_MEM_AGPLISTS] = {67- "agplist"},[DRM_MEM_SGLISTS] = {68- "sglist"},[DRM_MEM_TOTALAGP] = {69- "totalagp"},[DRM_MEM_BOUNDAGP] = {70- "boundagp"},[DRM_MEM_CTXBITMAP] = {71- "ctxbitmap"},[DRM_MEM_CTXLIST] = {72- "ctxlist"},[DRM_MEM_STUB] = {73- "stub"}, {74- NULL, 0,} /* Last entry must be null */75};7677-void DRM(mem_init) (void) {78 drm_mem_stats_t *mem;79 struct sysinfo si;8081- for (mem = DRM(mem_stats); mem->name; ++mem) {82 mem->succeed_count = 0;83 mem->free_count = 0;84 mem->fail_count = 0;···86 }8788 si_meminfo(&si);89- DRM(ram_available) = si.totalram;90- DRM(ram_used) = 0;91}9293/* drm_mem_info is called whenever a process reads /dev/drm/mem. */9495-static int DRM(_mem_info) (char *buf, char **start, off_t offset,96 int request, int *eof, void *data) {97 drm_mem_stats_t *pt;98 int len = 0;···111 " | allocs bytes\n\n");112 DRM_PROC_PRINT("%-9.9s %5d %5d %4d %10lu kB |\n",113 "system", 0, 0, 0,114- DRM(ram_available) << (PAGE_SHIFT - 10));115 DRM_PROC_PRINT("%-9.9s %5d %5d %4d %10lu kB |\n",116- "locked", 0, 0, 0, DRM(ram_used) >> 10);117 DRM_PROC_PRINT("\n");118- for (pt = DRM(mem_stats); pt->name; pt++) {119 DRM_PROC_PRINT("%-9.9s %5d %5d %4d %10lu %10lu | %6d %10ld\n",120 pt->name,121 pt->succeed_count,···134 return len - offset;135}136137-int DRM(mem_info) (char *buf, char **start, off_t offset,138 int len, int *eof, void *data) {139 int ret;140141- spin_lock(&DRM(mem_lock));142- ret = DRM(_mem_info) (buf, start, offset, len, eof, data);143- spin_unlock(&DRM(mem_lock));144 return ret;145}146147-void *DRM(alloc) (size_t size, int area) {148 void *pt;149150 if (!size) {···153 }154155 if (!(pt = kmalloc(size, GFP_KERNEL))) {156- spin_lock(&DRM(mem_lock));157- ++DRM(mem_stats)[area].fail_count;158- spin_unlock(&DRM(mem_lock));159 return NULL;160 }161- spin_lock(&DRM(mem_lock));162- ++DRM(mem_stats)[area].succeed_count;163- DRM(mem_stats)[area].bytes_allocated += size;164- spin_unlock(&DRM(mem_lock));165 return pt;166}167168-void *DRM(calloc) (size_t nmemb, size_t size, int area) {169 void *addr;170171- addr = DRM(alloc) (nmemb * size, area);172 if (addr != NULL)173 memset((void *)addr, 0, size * nmemb);174175 return addr;176}177178-void *DRM(realloc) (void *oldpt, size_t oldsize, size_t size, int area) {179 void *pt;180181- if (!(pt = DRM(alloc) (size, area)))182 return NULL;183 if (oldpt && oldsize) {184 memcpy(pt, oldpt, oldsize);185- DRM(free) (oldpt, oldsize, area);186 }187 return pt;188}189190-void DRM(free) (void *pt, size_t size, int area) {191 int alloc_count;192 int free_count;193···195 DRM_MEM_ERROR(area, "Attempt to free NULL pointer\n");196 else197 kfree(pt);198- spin_lock(&DRM(mem_lock));199- DRM(mem_stats)[area].bytes_freed += size;200- free_count = ++DRM(mem_stats)[area].free_count;201- alloc_count = DRM(mem_stats)[area].succeed_count;202- spin_unlock(&DRM(mem_lock));203 if (free_count > alloc_count) {204 DRM_MEM_ERROR(area, "Excess frees: %d frees, %d allocs\n",205 free_count, alloc_count);206 }207}208209-unsigned long DRM(alloc_pages) (int order, int area) {210 unsigned long address;211 unsigned long bytes = PAGE_SIZE << order;212 unsigned long addr;213 unsigned int sz;214215- spin_lock(&DRM(mem_lock));216- if ((DRM(ram_used) >> PAGE_SHIFT)217- > (DRM_RAM_PERCENT * DRM(ram_available)) / 100) {218- spin_unlock(&DRM(mem_lock));219 return 0;220 }221- spin_unlock(&DRM(mem_lock));222223 address = __get_free_pages(GFP_KERNEL|__GFP_COMP, order);224 if (!address) {225- spin_lock(&DRM(mem_lock));226- ++DRM(mem_stats)[area].fail_count;227- spin_unlock(&DRM(mem_lock));228 return 0;229 }230- spin_lock(&DRM(mem_lock));231- ++DRM(mem_stats)[area].succeed_count;232- DRM(mem_stats)[area].bytes_allocated += bytes;233- DRM(ram_used) += bytes;234- spin_unlock(&DRM(mem_lock));235236 /* Zero outside the lock */237 memset((void *)address, 0, bytes);···245 return address;246}247248-void DRM(free_pages) (unsigned long address, int order, int area) {249 unsigned long bytes = PAGE_SIZE << order;250 int alloc_count;251 int free_count;···263 free_pages(address, order);264 }265266- spin_lock(&DRM(mem_lock));267- free_count = ++DRM(mem_stats)[area].free_count;268- alloc_count = DRM(mem_stats)[area].succeed_count;269- DRM(mem_stats)[area].bytes_freed += bytes;270- DRM(ram_used) -= bytes;271- spin_unlock(&DRM(mem_lock));272 if (free_count > alloc_count) {273 DRM_MEM_ERROR(area,274 "Excess frees: %d frees, %d allocs\n",···276 }277}278279-void *DRM(ioremap) (unsigned long offset, unsigned long size,280 drm_device_t * dev) {281 void *pt;282···287 }288289 if (!(pt = drm_ioremap(offset, size, dev))) {290- spin_lock(&DRM(mem_lock));291- ++DRM(mem_stats)[DRM_MEM_MAPPINGS].fail_count;292- spin_unlock(&DRM(mem_lock));293 return NULL;294 }295- spin_lock(&DRM(mem_lock));296- ++DRM(mem_stats)[DRM_MEM_MAPPINGS].succeed_count;297- DRM(mem_stats)[DRM_MEM_MAPPINGS].bytes_allocated += size;298- spin_unlock(&DRM(mem_lock));299 return pt;300}301302-void *DRM(ioremap_nocache) (unsigned long offset, unsigned long size,303 drm_device_t * dev) {304 void *pt;305···310 }311312 if (!(pt = drm_ioremap_nocache(offset, size, dev))) {313- spin_lock(&DRM(mem_lock));314- ++DRM(mem_stats)[DRM_MEM_MAPPINGS].fail_count;315- spin_unlock(&DRM(mem_lock));316 return NULL;317 }318- spin_lock(&DRM(mem_lock));319- ++DRM(mem_stats)[DRM_MEM_MAPPINGS].succeed_count;320- DRM(mem_stats)[DRM_MEM_MAPPINGS].bytes_allocated += size;321- spin_unlock(&DRM(mem_lock));322 return pt;323}324325-void DRM(ioremapfree) (void *pt, unsigned long size, drm_device_t * dev) {326 int alloc_count;327 int free_count;328···332 else333 drm_ioremapfree(pt, size, dev);334335- spin_lock(&DRM(mem_lock));336- DRM(mem_stats)[DRM_MEM_MAPPINGS].bytes_freed += size;337- free_count = ++DRM(mem_stats)[DRM_MEM_MAPPINGS].free_count;338- alloc_count = DRM(mem_stats)[DRM_MEM_MAPPINGS].succeed_count;339- spin_unlock(&DRM(mem_lock));340 if (free_count > alloc_count) {341 DRM_MEM_ERROR(DRM_MEM_MAPPINGS,342 "Excess frees: %d frees, %d allocs\n",···346347#if __OS_HAS_AGP348349-DRM_AGP_MEM *DRM(alloc_agp) (int pages, u32 type) {350 DRM_AGP_MEM *handle;351352 if (!pages) {···354 return NULL;355 }356357- if ((handle = DRM(agp_allocate_memory) (pages, type))) {358- spin_lock(&DRM(mem_lock));359- ++DRM(mem_stats)[DRM_MEM_TOTALAGP].succeed_count;360- DRM(mem_stats)[DRM_MEM_TOTALAGP].bytes_allocated361 += pages << PAGE_SHIFT;362- spin_unlock(&DRM(mem_lock));363 return handle;364 }365- spin_lock(&DRM(mem_lock));366- ++DRM(mem_stats)[DRM_MEM_TOTALAGP].fail_count;367- spin_unlock(&DRM(mem_lock));368 return NULL;369}370371-int DRM(free_agp) (DRM_AGP_MEM * handle, int pages) {372 int alloc_count;373 int free_count;374 int retval = -EINVAL;···379 return retval;380 }381382- if (DRM(agp_free_memory) (handle)) {383- spin_lock(&DRM(mem_lock));384- free_count = ++DRM(mem_stats)[DRM_MEM_TOTALAGP].free_count;385- alloc_count = DRM(mem_stats)[DRM_MEM_TOTALAGP].succeed_count;386- DRM(mem_stats)[DRM_MEM_TOTALAGP].bytes_freed387 += pages << PAGE_SHIFT;388- spin_unlock(&DRM(mem_lock));389 if (free_count > alloc_count) {390 DRM_MEM_ERROR(DRM_MEM_TOTALAGP,391 "Excess frees: %d frees, %d allocs\n",···396 return retval;397}398399-int DRM(bind_agp) (DRM_AGP_MEM * handle, unsigned int start) {400 int retcode = -EINVAL;401402 if (!handle) {···405 return retcode;406 }407408- if (!(retcode = DRM(agp_bind_memory) (handle, start))) {409- spin_lock(&DRM(mem_lock));410- ++DRM(mem_stats)[DRM_MEM_BOUNDAGP].succeed_count;411- DRM(mem_stats)[DRM_MEM_BOUNDAGP].bytes_allocated412 += handle->page_count << PAGE_SHIFT;413- spin_unlock(&DRM(mem_lock));414 return retcode;415 }416- spin_lock(&DRM(mem_lock));417- ++DRM(mem_stats)[DRM_MEM_BOUNDAGP].fail_count;418- spin_unlock(&DRM(mem_lock));419 return retcode;420}421422-int DRM(unbind_agp) (DRM_AGP_MEM * handle) {423 int alloc_count;424 int free_count;425 int retcode = -EINVAL;···430 return retcode;431 }432433- if ((retcode = DRM(agp_unbind_memory) (handle)))434 return retcode;435- spin_lock(&DRM(mem_lock));436- free_count = ++DRM(mem_stats)[DRM_MEM_BOUNDAGP].free_count;437- alloc_count = DRM(mem_stats)[DRM_MEM_BOUNDAGP].succeed_count;438- DRM(mem_stats)[DRM_MEM_BOUNDAGP].bytes_freed439 += handle->page_count << PAGE_SHIFT;440- spin_unlock(&DRM(mem_lock));441 if (free_count > alloc_count) {442 DRM_MEM_ERROR(DRM_MEM_BOUNDAGP,443 "Excess frees: %d frees, %d allocs\n",
···1/**2+ * \file drm_memory_debug.h3 * Memory management wrappers for DRM.4 *5 * \author Rickard E. (Rik) Faith <faith@valinux.com>···43 unsigned long bytes_freed;44} drm_mem_stats_t;4546+static spinlock_t drm_mem_lock = SPIN_LOCK_UNLOCKED;47+static unsigned long drm_ram_available = 0; /* In pages */48+static unsigned long drm_ram_used = 0;49+static drm_mem_stats_t drm_mem_stats[] =50{51+ [DRM_MEM_DMA] = {"dmabufs"},52+ [DRM_MEM_SAREA] = {"sareas"},53+ [DRM_MEM_DRIVER] = {"driver"},54+ [DRM_MEM_MAGIC] = {"magic"},55+ [DRM_MEM_IOCTLS] = {"ioctltab"},56+ [DRM_MEM_MAPS] = {"maplist"},57+ [DRM_MEM_VMAS] = {"vmalist"},58+ [DRM_MEM_BUFS] = {"buflist"},59+ [DRM_MEM_SEGS] = {"seglist"},60+ [DRM_MEM_PAGES] = {"pagelist"},61+ [DRM_MEM_FILES] = {"files"},62+ [DRM_MEM_QUEUES] = {"queues"},63+ [DRM_MEM_CMDS] = {"commands"},64+ [DRM_MEM_MAPPINGS] = {"mappings"},65+ [DRM_MEM_BUFLISTS] = {"buflists"},66+ [DRM_MEM_AGPLISTS] = {"agplist"},67+ [DRM_MEM_SGLISTS] = {"sglist"},68+ [DRM_MEM_TOTALAGP] = {"totalagp"},69+ [DRM_MEM_BOUNDAGP] = {"boundagp"},70+ [DRM_MEM_CTXBITMAP] = {"ctxbitmap"},71+ [DRM_MEM_CTXLIST] = {"ctxlist"},72+ [DRM_MEM_STUB] = {"stub"},73+ {NULL, 0,} /* Last entry must be null */074};7576+void drm_mem_init (void) {77 drm_mem_stats_t *mem;78 struct sysinfo si;7980+ for (mem = drm_mem_stats; mem->name; ++mem) {81 mem->succeed_count = 0;82 mem->free_count = 0;83 mem->fail_count = 0;···87 }8889 si_meminfo(&si);90+ drm_ram_available = si.totalram;91+ drm_ram_used = 0;92}9394/* drm_mem_info is called whenever a process reads /dev/drm/mem. */9596+static int drm__mem_info (char *buf, char **start, off_t offset,97 int request, int *eof, void *data) {98 drm_mem_stats_t *pt;99 int len = 0;···112 " | allocs bytes\n\n");113 DRM_PROC_PRINT("%-9.9s %5d %5d %4d %10lu kB |\n",114 "system", 0, 0, 0,115+ drm_ram_available << (PAGE_SHIFT - 10));116 DRM_PROC_PRINT("%-9.9s %5d %5d %4d %10lu kB |\n",117+ "locked", 0, 0, 0, drm_ram_used >> 10);118 DRM_PROC_PRINT("\n");119+ for (pt = drm_mem_stats; pt->name; pt++) {120 DRM_PROC_PRINT("%-9.9s %5d %5d %4d %10lu %10lu | %6d %10ld\n",121 pt->name,122 pt->succeed_count,···135 return len - offset;136}137138+int drm_mem_info (char *buf, char **start, off_t offset,139 int len, int *eof, void *data) {140 int ret;141142+ spin_lock(&drm_mem_lock);143+ ret = drm__mem_info (buf, start, offset, len, eof, data);144+ spin_unlock(&drm_mem_lock);145 return ret;146}147148+void *drm_alloc (size_t size, int area) {149 void *pt;150151 if (!size) {···154 }155156 if (!(pt = kmalloc(size, GFP_KERNEL))) {157+ spin_lock(&drm_mem_lock);158+ ++drm_mem_stats[area].fail_count;159+ spin_unlock(&drm_mem_lock);160 return NULL;161 }162+ spin_lock(&drm_mem_lock);163+ ++drm_mem_stats[area].succeed_count;164+ drm_mem_stats[area].bytes_allocated += size;165+ spin_unlock(&drm_mem_lock);166 return pt;167}168169+void *drm_calloc (size_t nmemb, size_t size, int area) {170 void *addr;171172+ addr = drm_alloc (nmemb * size, area);173 if (addr != NULL)174 memset((void *)addr, 0, size * nmemb);175176 return addr;177}178179+void *drm_realloc (void *oldpt, size_t oldsize, size_t size, int area) {180 void *pt;181182+ if (!(pt = drm_alloc (size, area)))183 return NULL;184 if (oldpt && oldsize) {185 memcpy(pt, oldpt, oldsize);186+ drm_free (oldpt, oldsize, area);187 }188 return pt;189}190191+void drm_free (void *pt, size_t size, int area) {192 int alloc_count;193 int free_count;194···196 DRM_MEM_ERROR(area, "Attempt to free NULL pointer\n");197 else198 kfree(pt);199+ spin_lock(&drm_mem_lock);200+ drm_mem_stats[area].bytes_freed += size;201+ free_count = ++drm_mem_stats[area].free_count;202+ alloc_count = drm_mem_stats[area].succeed_count;203+ spin_unlock(&drm_mem_lock);204 if (free_count > alloc_count) {205 DRM_MEM_ERROR(area, "Excess frees: %d frees, %d allocs\n",206 free_count, alloc_count);207 }208}209210+unsigned long drm_alloc_pages (int order, int area) {211 unsigned long address;212 unsigned long bytes = PAGE_SIZE << order;213 unsigned long addr;214 unsigned int sz;215216+ spin_lock(&drm_mem_lock);217+ if ((drm_ram_used >> PAGE_SHIFT)218+ > (DRM_RAM_PERCENT * drm_ram_available) / 100) {219+ spin_unlock(&drm_mem_lock);220 return 0;221 }222+ spin_unlock(&drm_mem_lock);223224 address = __get_free_pages(GFP_KERNEL|__GFP_COMP, order);225 if (!address) {226+ spin_lock(&drm_mem_lock);227+ ++drm_mem_stats[area].fail_count;228+ spin_unlock(&drm_mem_lock);229 return 0;230 }231+ spin_lock(&drm_mem_lock);232+ ++drm_mem_stats[area].succeed_count;233+ drm_mem_stats[area].bytes_allocated += bytes;234+ drm_ram_used += bytes;235+ spin_unlock(&drm_mem_lock);236237 /* Zero outside the lock */238 memset((void *)address, 0, bytes);···246 return address;247}248249+void drm_free_pages (unsigned long address, int order, int area) {250 unsigned long bytes = PAGE_SIZE << order;251 int alloc_count;252 int free_count;···264 free_pages(address, order);265 }266267+ spin_lock(&drm_mem_lock);268+ free_count = ++drm_mem_stats[area].free_count;269+ alloc_count = drm_mem_stats[area].succeed_count;270+ drm_mem_stats[area].bytes_freed += bytes;271+ drm_ram_used -= bytes;272+ spin_unlock(&drm_mem_lock);273 if (free_count > alloc_count) {274 DRM_MEM_ERROR(area,275 "Excess frees: %d frees, %d allocs\n",···277 }278}279280+void *drm_ioremap (unsigned long offset, unsigned long size,281 drm_device_t * dev) {282 void *pt;283···288 }289290 if (!(pt = drm_ioremap(offset, size, dev))) {291+ spin_lock(&drm_mem_lock);292+ ++drm_mem_stats[DRM_MEM_MAPPINGS].fail_count;293+ spin_unlock(&drm_mem_lock);294 return NULL;295 }296+ spin_lock(&drm_mem_lock);297+ ++drm_mem_stats[DRM_MEM_MAPPINGS].succeed_count;298+ drm_mem_stats[DRM_MEM_MAPPINGS].bytes_allocated += size;299+ spin_unlock(&drm_mem_lock);300 return pt;301}302303+void *drm_ioremap_nocache (unsigned long offset, unsigned long size,304 drm_device_t * dev) {305 void *pt;306···311 }312313 if (!(pt = drm_ioremap_nocache(offset, size, dev))) {314+ spin_lock(&drm_mem_lock);315+ ++drm_mem_stats[DRM_MEM_MAPPINGS].fail_count;316+ spin_unlock(&drm_mem_lock);317 return NULL;318 }319+ spin_lock(&drm_mem_lock);320+ ++drm_mem_stats[DRM_MEM_MAPPINGS].succeed_count;321+ drm_mem_stats[DRM_MEM_MAPPINGS].bytes_allocated += size;322+ spin_unlock(&drm_mem_lock);323 return pt;324}325326+void drm_ioremapfree (void *pt, unsigned long size, drm_device_t * dev) {327 int alloc_count;328 int free_count;329···333 else334 drm_ioremapfree(pt, size, dev);335336+ spin_lock(&drm_mem_lock);337+ drm_mem_stats[DRM_MEM_MAPPINGS].bytes_freed += size;338+ free_count = ++drm_mem_stats[DRM_MEM_MAPPINGS].free_count;339+ alloc_count = drm_mem_stats[DRM_MEM_MAPPINGS].succeed_count;340+ spin_unlock(&drm_mem_lock);341 if (free_count > alloc_count) {342 DRM_MEM_ERROR(DRM_MEM_MAPPINGS,343 "Excess frees: %d frees, %d allocs\n",···347348#if __OS_HAS_AGP349350+DRM_AGP_MEM *drm_alloc_agp (drm_device_t *dev, int pages, u32 type) {351 DRM_AGP_MEM *handle;352353 if (!pages) {···355 return NULL;356 }357358+ if ((handle = drm_agp_allocate_memory (pages, type))) {359+ spin_lock(&drm_mem_lock);360+ ++drm_mem_stats[DRM_MEM_TOTALAGP].succeed_count;361+ drm_mem_stats[DRM_MEM_TOTALAGP].bytes_allocated362 += pages << PAGE_SHIFT;363+ spin_unlock(&drm_mem_lock);364 return handle;365 }366+ spin_lock(&drm_mem_lock);367+ ++drm_mem_stats[DRM_MEM_TOTALAGP].fail_count;368+ spin_unlock(&drm_mem_lock);369 return NULL;370}371372+int drm_free_agp (DRM_AGP_MEM * handle, int pages) {373 int alloc_count;374 int free_count;375 int retval = -EINVAL;···380 return retval;381 }382383+ if (drm_agp_free_memory (handle)) {384+ spin_lock(&drm_mem_lock);385+ free_count = ++drm_mem_stats[DRM_MEM_TOTALAGP].free_count;386+ alloc_count = drm_mem_stats[DRM_MEM_TOTALAGP].succeed_count;387+ drm_mem_stats[DRM_MEM_TOTALAGP].bytes_freed388 += pages << PAGE_SHIFT;389+ spin_unlock(&drm_mem_lock);390 if (free_count > alloc_count) {391 DRM_MEM_ERROR(DRM_MEM_TOTALAGP,392 "Excess frees: %d frees, %d allocs\n",···397 return retval;398}399400+int drm_bind_agp (DRM_AGP_MEM * handle, unsigned int start) {401 int retcode = -EINVAL;402403 if (!handle) {···406 return retcode;407 }408409+ if (!(retcode = drm_agp_bind_memory (handle, start))) {410+ spin_lock(&drm_mem_lock);411+ ++drm_mem_stats[DRM_MEM_BOUNDAGP].succeed_count;412+ drm_mem_stats[DRM_MEM_BOUNDAGP].bytes_allocated413 += handle->page_count << PAGE_SHIFT;414+ spin_unlock(&drm_mem_lock);415 return retcode;416 }417+ spin_lock(&drm_mem_lock);418+ ++drm_mem_stats[DRM_MEM_BOUNDAGP].fail_count;419+ spin_unlock(&drm_mem_lock);420 return retcode;421}422423+int drm_unbind_agp (DRM_AGP_MEM * handle) {424 int alloc_count;425 int free_count;426 int retcode = -EINVAL;···431 return retcode;432 }433434+ if ((retcode = drm_agp_unbind_memory (handle)))435 return retcode;436+ spin_lock(&drm_mem_lock);437+ free_count = ++drm_mem_stats[DRM_MEM_BOUNDAGP].free_count;438+ alloc_count = drm_mem_stats[DRM_MEM_BOUNDAGP].succeed_count;439+ drm_mem_stats[DRM_MEM_BOUNDAGP].bytes_freed440 += handle->page_count << PAGE_SHIFT;441+ spin_unlock(&drm_mem_lock);442 if (free_count > alloc_count) {443 DRM_MEM_ERROR(DRM_MEM_BOUNDAGP,444 "Excess frees: %d frees, %d allocs\n",
+1
drivers/char/drm/drm_os_linux.h
···13#define DRM_ERR(d) -(d)14/** Current process ID */15#define DRM_CURRENTPID current->pid016#define DRM_UDELAY(d) udelay(d)17/** Read a byte from a MMIO region */18#define DRM_READ8(map, offset) readb(((void __iomem *)(map)->handle) + (offset))
···13#define DRM_ERR(d) -(d)14/** Current process ID */15#define DRM_CURRENTPID current->pid16+#define DRM_SUSER(p) capable(CAP_SYS_ADMIN)17#define DRM_UDELAY(d) udelay(d)18/** Read a byte from a MMIO region */19#define DRM_READ8(map, offset) readb(((void __iomem *)(map)->handle) + (offset))
···9394 dev->driver = driver;9596- if (dev->driver->preinit)97- if ((retcode = dev->driver->preinit(dev, ent->driver_data)))98 goto error_out_unreg;99100 if (drm_core_has_AGP(dev)) {···124 return 0;125126 error_out_unreg:127- drm_takedown(dev);128 return retcode;129}130131-/**132- * File \c open operation.133- *134- * \param inode device inode.135- * \param filp file pointer.136- *137- * Puts the dev->fops corresponding to the device minor number into138- * \p filp, call the \c open method, and restore the file operations.139- */140-int drm_stub_open(struct inode *inode, struct file *filp)141-{142- drm_device_t *dev = NULL;143- int minor = iminor(inode);144- int err = -ENODEV;145- struct file_operations *old_fops;146-147- DRM_DEBUG("\n");148-149- if (!((minor >= 0) && (minor < drm_cards_limit)))150- return -ENODEV;151-152- if (!drm_heads[minor])153- return -ENODEV;154-155- if (!(dev = drm_heads[minor]->dev))156- return -ENODEV;157-158- old_fops = filp->f_op;159- filp->f_op = fops_get(&dev->driver->fops);160- if (filp->f_op->open && (err = filp->f_op->open(inode, filp))) {161- fops_put(filp->f_op);162- filp->f_op = fops_get(old_fops);163- }164- fops_put(old_fops);165-166- return err;167-}168169/**170 * Get a secondary minor number.···163 goto err_g1;164 }165166- head->dev_class = drm_sysfs_device_add(drm_class,167- MKDEV(DRM_MAJOR,168- minor),169- &dev->pdev->dev,170- "card%d", minor);171 if (IS_ERR(head->dev_class)) {172 printk(KERN_ERR173 "DRM: Error sysfs_device_add.\n");···217 }218 if ((ret = drm_get_head(dev, &dev->primary)))219 goto err_g1;220-221- /* postinit is a required function to display the signon banner */222- /* drivers add secondary heads here if needed */223- if ((ret = dev->driver->postinit(dev, ent->driver_data)))224- goto err_g1;225226 return 0;227···276 DRM_DEBUG("release secondary minor %d\n", minor);277278 drm_proc_cleanup(minor, drm_proc_root, head->dev_root);279- drm_sysfs_device_remove(MKDEV(DRM_MAJOR, head->minor));280281- *head = (drm_head_t) {282- .dev = NULL};283284 drm_heads[minor] = NULL;285
···9394 dev->driver = driver;9596+ if (dev->driver->load)97+ if ((retcode = dev->driver->load(dev, ent->driver_data)))98 goto error_out_unreg;99100 if (drm_core_has_AGP(dev)) {···124 return 0;125126 error_out_unreg:127+ drm_lastclose(dev);128 return retcode;129}1300000000000000000000000000000000000000131132/**133 * Get a secondary minor number.···200 goto err_g1;201 }202203+ head->dev_class = drm_sysfs_device_add(drm_class, head);0000204 if (IS_ERR(head->dev_class)) {205 printk(KERN_ERR206 "DRM: Error sysfs_device_add.\n");···258 }259 if ((ret = drm_get_head(dev, &dev->primary)))260 goto err_g1;261+262+ DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n",263+ driver->name, driver->major, driver->minor, driver->patchlevel,264+ driver->date, dev->primary.minor);0265266 return 0;267···318 DRM_DEBUG("release secondary minor %d\n", minor);319320 drm_proc_cleanup(minor, drm_proc_root, head->dev_root);321+ drm_sysfs_device_remove(head->dev_class);322323+ *head = (drm_head_t) {.dev = NULL};0324325 drm_heads[minor] = NULL;326
+28-38
drivers/char/drm/drm_sysfs.c
···15#include <linux/device.h>16#include <linux/kdev_t.h>17#include <linux/err.h>18-#include <linux/slab.h>19-#include <linux/string.h>2021#include "drm_core.h"22#include "drmP.h"···26#define to_drm_sysfs_class(d) container_of(d, struct drm_sysfs_class, class)2728struct simple_dev {29- struct list_head node;30 dev_t dev;31 struct class_device class_dev;32};33#define to_simple_dev(d) container_of(d, struct simple_dev, class_dev)34-35-static LIST_HEAD(simple_dev_list);36-static DEFINE_SPINLOCK(simple_dev_list_lock);3738static void release_simple_dev(struct class_device *class_dev)39{···118 class_unregister(&cs->class);119}120000000000000121/**122 * drm_sysfs_device_add - adds a class device to sysfs for a character driver123 * @cs: pointer to the struct drm_sysfs_class that this device should be registered to.···144 * Note: the struct drm_sysfs_class passed to this function must have previously been145 * created with a call to drm_sysfs_create().146 */147-struct class_device *drm_sysfs_device_add(struct drm_sysfs_class *cs, dev_t dev,148- struct device *device,149- const char *fmt, ...)150{151- va_list args;152 struct simple_dev *s_dev = NULL;153- int retval;154155 if ((cs == NULL) || (IS_ERR(cs))) {156 retval = -ENODEV;···162 }163 memset(s_dev, 0x00, sizeof(*s_dev));164165- s_dev->dev = dev;166- s_dev->class_dev.dev = device;167 s_dev->class_dev.class = &cs->class;168169- va_start(args, fmt);170- vsnprintf(s_dev->class_dev.class_id, BUS_ID_SIZE, fmt, args);171- va_end(args);172 retval = class_device_register(&s_dev->class_dev);173 if (retval)174 goto error;175176 class_device_create_file(&s_dev->class_dev, &cs->attr);0177178- spin_lock(&simple_dev_list_lock);179- list_add(&s_dev->node, &simple_dev_list);180- spin_unlock(&simple_dev_list_lock);181-182 return &s_dev->class_dev;183184- error:185 kfree(s_dev);186 return ERR_PTR(retval);187}···190 * This call unregisters and cleans up a class device that was created with a191 * call to drm_sysfs_device_add()192 */193-void drm_sysfs_device_remove(dev_t dev)194{195- struct simple_dev *s_dev = NULL;196- int found = 0;197198- spin_lock(&simple_dev_list_lock);199- list_for_each_entry(s_dev, &simple_dev_list, node) {200- if (s_dev->dev == dev) {201- found = 1;202- break;203- }204- }205- if (found) {206- list_del(&s_dev->node);207- spin_unlock(&simple_dev_list_lock);208- class_device_unregister(&s_dev->class_dev);209- } else {210- spin_unlock(&simple_dev_list_lock);211- }212}
···15#include <linux/device.h>16#include <linux/kdev_t.h>17#include <linux/err.h>001819#include "drm_core.h"20#include "drmP.h"···28#define to_drm_sysfs_class(d) container_of(d, struct drm_sysfs_class, class)2930struct simple_dev {031 dev_t dev;32 struct class_device class_dev;33};34#define to_simple_dev(d) container_of(d, struct simple_dev, class_dev)0003536static void release_simple_dev(struct class_device *class_dev)37{···124 class_unregister(&cs->class);125}126127+static ssize_t show_dri(struct class_device *class_device, char *buf)128+{129+ drm_device_t * dev = ((drm_head_t *)class_get_devdata(class_device))->dev;130+ if (dev->driver->dri_library_name)131+ return dev->driver->dri_library_name(dev, buf);132+ return snprintf(buf, PAGE_SIZE, "%s\n", dev->driver->pci_driver.name);133+}134+135+static struct class_device_attribute class_device_attrs[] = {136+ __ATTR(dri_library_name, S_IRUGO, show_dri, NULL),137+};138+139/**140 * drm_sysfs_device_add - adds a class device to sysfs for a character driver141 * @cs: pointer to the struct drm_sysfs_class that this device should be registered to.···138 * Note: the struct drm_sysfs_class passed to this function must have previously been139 * created with a call to drm_sysfs_create().140 */141+struct class_device *drm_sysfs_device_add(struct drm_sysfs_class *cs,142+ drm_head_t *head)0143{0144 struct simple_dev *s_dev = NULL;145+ int i, retval;146147 if ((cs == NULL) || (IS_ERR(cs))) {148 retval = -ENODEV;···158 }159 memset(s_dev, 0x00, sizeof(*s_dev));160161+ s_dev->dev = MKDEV(DRM_MAJOR, head->minor);162+ s_dev->class_dev.dev = &(head->dev->pdev)->dev;163 s_dev->class_dev.class = &cs->class;164165+ snprintf(s_dev->class_dev.class_id, BUS_ID_SIZE, "card%d", head->minor);00166 retval = class_device_register(&s_dev->class_dev);167 if (retval)168 goto error;169170 class_device_create_file(&s_dev->class_dev, &cs->attr);171+ class_set_devdata(&s_dev->class_dev, head);172173+ for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++)174+ class_device_create_file(&s_dev->class_dev, &class_device_attrs[i]);00175 return &s_dev->class_dev;176177+error:178 kfree(s_dev);179 return ERR_PTR(retval);180}···189 * This call unregisters and cleans up a class device that was created with a190 * call to drm_sysfs_device_add()191 */192+void drm_sysfs_device_remove(struct class_device *class_dev)193{194+ struct simple_dev *s_dev = to_simple_dev(class_dev);195+ int i;196197+ for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++)198+ class_device_remove_file(&s_dev->class_dev, &class_device_attrs[i]);199+ class_device_unregister(&s_dev->class_dev);00000000000200}
···1/* i915_dma.c -- DMA support for the I915 -*- linux-c -*-2 */3-/**************************************************************************4- *5 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.6 * All Rights Reserved.7 *···24 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.26 *27- **************************************************************************/2829#include "drmP.h"30#include "drm.h"···195 return 0;196}197198-static int i915_resume(drm_device_t * dev)199{200 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;201···252 retcode = i915_dma_cleanup(dev);253 break;254 case I915_RESUME_DMA:255- retcode = i915_resume(dev);256 break;257 default:258 retcode = -EINVAL;···653 case I915_PARAM_ALLOW_BATCHBUFFER:654 value = dev_priv->allow_batchbuffer ? 1 : 0;655 break;000656 default:657 DRM_ERROR("Unkown parameter %d\n", param.param);658 return DRM_ERR(EINVAL);···701 return 0;702}703704-void i915_driver_pretakedown(drm_device_t * dev)000000000000705{706 if (dev->dev_private) {707 drm_i915_private_t *dev_priv = dev->dev_private;···722 i915_dma_cleanup(dev);723}724725-void i915_driver_prerelease(drm_device_t * dev, DRMFILE filp)726{727 if (dev->dev_private) {728 drm_i915_private_t *dev_priv = dev->dev_private;···731}732733drm_ioctl_desc_t i915_ioctls[] = {734- [DRM_IOCTL_NR(DRM_I915_INIT)] = {i915_dma_init, 1, 1},735- [DRM_IOCTL_NR(DRM_I915_FLUSH)] = {i915_flush_ioctl, 1, 0},736- [DRM_IOCTL_NR(DRM_I915_FLIP)] = {i915_flip_bufs, 1, 0},737- [DRM_IOCTL_NR(DRM_I915_BATCHBUFFER)] = {i915_batchbuffer, 1, 0},738- [DRM_IOCTL_NR(DRM_I915_IRQ_EMIT)] = {i915_irq_emit, 1, 0},739- [DRM_IOCTL_NR(DRM_I915_IRQ_WAIT)] = {i915_irq_wait, 1, 0},740- [DRM_IOCTL_NR(DRM_I915_GETPARAM)] = {i915_getparam, 1, 0},741- [DRM_IOCTL_NR(DRM_I915_SETPARAM)] = {i915_setparam, 1, 1},742- [DRM_IOCTL_NR(DRM_I915_ALLOC)] = {i915_mem_alloc, 1, 0},743- [DRM_IOCTL_NR(DRM_I915_FREE)] = {i915_mem_free, 1, 0},744- [DRM_IOCTL_NR(DRM_I915_INIT_HEAP)] = {i915_mem_init_heap, 1, 1},745- [DRM_IOCTL_NR(DRM_I915_CMDBUFFER)] = {i915_cmdbuffer, 1, 0}746};747748int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
···1/* i915_dma.c -- DMA support for the I915 -*- linux-c -*-2 */3+/*04 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.5 * All Rights Reserved.6 *···25 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE26 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.27 *28+ */2930#include "drmP.h"31#include "drm.h"···196 return 0;197}198199+static int i915_dma_resume(drm_device_t * dev)200{201 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;202···253 retcode = i915_dma_cleanup(dev);254 break;255 case I915_RESUME_DMA:256+ retcode = i915_dma_resume(dev);257 break;258 default:259 retcode = -EINVAL;···654 case I915_PARAM_ALLOW_BATCHBUFFER:655 value = dev_priv->allow_batchbuffer ? 1 : 0;656 break;657+ case I915_PARAM_LAST_DISPATCH:658+ value = READ_BREADCRUMB(dev_priv);659+ break;660 default:661 DRM_ERROR("Unkown parameter %d\n", param.param);662 return DRM_ERR(EINVAL);···699 return 0;700}701702+int i915_driver_load(drm_device_t *dev, unsigned long flags)703+{704+ /* i915 has 4 more counters */705+ dev->counters += 4;706+ dev->types[6] = _DRM_STAT_IRQ;707+ dev->types[7] = _DRM_STAT_PRIMARY;708+ dev->types[8] = _DRM_STAT_SECONDARY;709+ dev->types[9] = _DRM_STAT_DMA;710+711+ return 0;712+}713+714+void i915_driver_lastclose(drm_device_t * dev)715{716 if (dev->dev_private) {717 drm_i915_private_t *dev_priv = dev->dev_private;···708 i915_dma_cleanup(dev);709}710711+void i915_driver_preclose(drm_device_t * dev, DRMFILE filp)712{713 if (dev->dev_private) {714 drm_i915_private_t *dev_priv = dev->dev_private;···717}718719drm_ioctl_desc_t i915_ioctls[] = {720+ [DRM_IOCTL_NR(DRM_I915_INIT)] = {i915_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},721+ [DRM_IOCTL_NR(DRM_I915_FLUSH)] = {i915_flush_ioctl, DRM_AUTH},722+ [DRM_IOCTL_NR(DRM_I915_FLIP)] = {i915_flip_bufs, DRM_AUTH},723+ [DRM_IOCTL_NR(DRM_I915_BATCHBUFFER)] = {i915_batchbuffer, DRM_AUTH},724+ [DRM_IOCTL_NR(DRM_I915_IRQ_EMIT)] = {i915_irq_emit, DRM_AUTH},725+ [DRM_IOCTL_NR(DRM_I915_IRQ_WAIT)] = {i915_irq_wait, DRM_AUTH},726+ [DRM_IOCTL_NR(DRM_I915_GETPARAM)] = {i915_getparam, DRM_AUTH},727+ [DRM_IOCTL_NR(DRM_I915_SETPARAM)] = {i915_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},728+ [DRM_IOCTL_NR(DRM_I915_ALLOC)] = {i915_mem_alloc, DRM_AUTH},729+ [DRM_IOCTL_NR(DRM_I915_FREE)] = {i915_mem_free, DRM_AUTH},730+ [DRM_IOCTL_NR(DRM_I915_INIT_HEAP)] = {i915_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},731+ [DRM_IOCTL_NR(DRM_I915_CMDBUFFER)] = {i915_cmdbuffer, DRM_AUTH}732};733734int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
+3-3
drivers/char/drm/i915_drm.h
···1-/**************************************************************************2- *3 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.4 * All Rights Reserved.5 *···22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.24 *25- **************************************************************************/2627#ifndef _I915_DRM_H_28#define _I915_DRM_H_···151 */152#define I915_PARAM_IRQ_ACTIVE 1153#define I915_PARAM_ALLOW_BATCHBUFFER 20154155typedef struct drm_i915_getparam {156 int param;
···1+/*02 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.3 * All Rights Reserved.4 *···23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.25 *26+ */2728#ifndef _I915_DRM_H_29#define _I915_DRM_H_···152 */153#define I915_PARAM_IRQ_ACTIVE 1154#define I915_PARAM_ALLOW_BATCHBUFFER 2155+#define I915_PARAM_LAST_DISPATCH 3156157typedef struct drm_i915_getparam {158 int param;
+23-43
drivers/char/drm/i915_drv.c
···1/* i915_drv.c -- i830,i845,i855,i865,i915 driver -*- linux-c -*-2 */3-/**************************************************************************4 *5 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.6 * All Rights Reserved.···25 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE26 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.27 *28- **************************************************************************/2930#include "drmP.h"31#include "drm.h"···3435#include "drm_pciids.h"3637-static int postinit(struct drm_device *dev, unsigned long flags)38-{39- dev->counters += 4;40- dev->types[6] = _DRM_STAT_IRQ;41- dev->types[7] = _DRM_STAT_PRIMARY;42- dev->types[8] = _DRM_STAT_SECONDARY;43- dev->types[9] = _DRM_STAT_DMA;44-45- DRM_INFO("Initialized %s %d.%d.%d %s on minor %d: %s\n",46- DRIVER_NAME,47- DRIVER_MAJOR,48- DRIVER_MINOR,49- DRIVER_PATCHLEVEL,50- DRIVER_DATE, dev->primary.minor, pci_pretty_name(dev->pdev)51- );52- return 0;53-}54-55-static int version(drm_version_t * version)56-{57- int len;58-59- version->version_major = DRIVER_MAJOR;60- version->version_minor = DRIVER_MINOR;61- version->version_patchlevel = DRIVER_PATCHLEVEL;62- DRM_COPY(version->name, DRIVER_NAME);63- DRM_COPY(version->date, DRIVER_DATE);64- DRM_COPY(version->desc, DRIVER_DESC);65- return 0;66-}67-68static struct pci_device_id pciidlist[] = {69 i915_PCI_IDS70};7172static struct drm_driver driver = {00073 .driver_features =74- DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR |75- DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED,76- .pretakedown = i915_driver_pretakedown,77- .prerelease = i915_driver_prerelease,078 .device_is_agp = i915_driver_device_is_agp,079 .irq_preinstall = i915_driver_irq_preinstall,80 .irq_postinstall = i915_driver_irq_postinstall,81 .irq_uninstall = i915_driver_irq_uninstall,···57 .reclaim_buffers = drm_core_reclaim_buffers,58 .get_map_ofs = drm_core_get_map_ofs,59 .get_reg_ofs = drm_core_get_reg_ofs,60- .postinit = postinit,61- .version = version,62 .ioctls = i915_ioctls,63 .fops = {64 .owner = THIS_MODULE,···69#ifdef CONFIG_COMPAT70 .compat_ioctl = i915_compat_ioctl,71#endif72- },073 .pci_driver = {74- .name = DRIVER_NAME,75- .id_table = pciidlist,76- }000000077};7879static int __init i915_init(void)
···1/* i915_drv.c -- i830,i845,i855,i865,i915 driver -*- linux-c -*-2 */3+/*4 *5 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.6 * All Rights Reserved.···25 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE26 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.27 *28+ */2930#include "drmP.h"31#include "drm.h"···3435#include "drm_pciids.h"36000000000000000000000000000000037static struct pci_device_id pciidlist[] = {38 i915_PCI_IDS39};4041static struct drm_driver driver = {42+ /* don't use mtrr's here, the Xserver or user space app should43+ * deal with them for intel hardware.44+ */45 .driver_features =46+ DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | /* DRIVER_USE_MTRR |*/47+ DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL,48+ .load = i915_driver_load,49+ .lastclose = i915_driver_lastclose,50+ .preclose = i915_driver_preclose,51 .device_is_agp = i915_driver_device_is_agp,52+ .vblank_wait = i915_driver_vblank_wait,53 .irq_preinstall = i915_driver_irq_preinstall,54 .irq_postinstall = i915_driver_irq_postinstall,55 .irq_uninstall = i915_driver_irq_uninstall,···83 .reclaim_buffers = drm_core_reclaim_buffers,84 .get_map_ofs = drm_core_get_map_ofs,85 .get_reg_ofs = drm_core_get_reg_ofs,0086 .ioctls = i915_ioctls,87 .fops = {88 .owner = THIS_MODULE,···97#ifdef CONFIG_COMPAT98 .compat_ioctl = i915_compat_ioctl,99#endif100+ },101+102 .pci_driver = {103+ .name = DRIVER_NAME,104+ .id_table = pciidlist,105+ },106+107+ .name = DRIVER_NAME,108+ .desc = DRIVER_DESC,109+ .date = DRIVER_DATE,110+ .major = DRIVER_MAJOR,111+ .minor = DRIVER_MINOR,112+ .patchlevel = DRIVER_PATCHLEVEL,113};114115static int __init i915_init(void)
+26-18
drivers/char/drm/i915_drv.h
···1/* i915_drv.h -- Private header for the I915 driver -*- linux-c -*-2 */3-/**************************************************************************4 *5 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.6 * All Rights Reserved.···25 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE26 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.27 *28- **************************************************************************/2930#ifndef _I915_DRV_H_31#define _I915_DRV_H_···3738#define DRIVER_NAME "i915"39#define DRIVER_DESC "Intel Graphics"40-#define DRIVER_DATE "20040405"4142/* Interface history:43 *44 * 1.1: Original.0045 */46#define DRIVER_MAJOR 147-#define DRIVER_MINOR 148#define DRIVER_PATCHLEVEL 049-50-/* We use our own dma mechanisms, not the drm template code. However,51- * the shared IRQ code is useful to us:52- */53-#define __HAVE_PM 15455typedef struct _drm_i915_ring_buffer {56 int tail_mask;···94 int tex_lru_log_granularity;95 int allow_batchbuffer;96 struct mem_block *agp_heap;097} drm_i915_private_t;9899extern drm_ioctl_desc_t i915_ioctls[];···102103 /* i915_dma.c */104extern void i915_kernel_lost_context(drm_device_t * dev);105-extern void i915_driver_pretakedown(drm_device_t * dev);106-extern void i915_driver_prerelease(drm_device_t * dev, DRMFILE filp);0107extern int i915_driver_device_is_agp(drm_device_t * dev);00108109/* i915_irq.c */110extern int i915_irq_emit(DRM_IOCTL_ARGS);111extern int i915_irq_wait(DRM_IOCTL_ARGS);1120113extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS);114extern void i915_driver_irq_preinstall(drm_device_t * dev);115extern void i915_driver_irq_postinstall(drm_device_t * dev);···127extern void i915_mem_release(drm_device_t * dev,128 DRMFILE filp, struct mem_block *heap);129130-extern long i915_compat_ioctl(struct file *filp, unsigned int cmd,131- unsigned long arg);132-133-#define I915_READ(reg) DRM_READ32(dev_priv->mmio_map, reg)134-#define I915_WRITE(reg,val) DRM_WRITE32(dev_priv->mmio_map, reg, val)135-#define I915_READ16(reg) DRM_READ16(dev_priv->mmio_map, reg)136-#define I915_WRITE16(reg,val) DRM_WRITE16(dev_priv->mmio_map, reg, val)137138#define I915_VERBOSE 0139···194#define PPCR 0x61204195#define PPCR_ON (1<<0)1960000000197#define ADPA 0x61100198#define ADPA_DPMS_MASK (~(3<<10))199#define ADPA_DPMS_ON (0<<10)···263#define ASYNC_FLIP (1<<22)264265#define CMD_OP_DESTBUFFER_INFO ((0x3<<29)|(0x1d<<24)|(0x8e<<16)|1)00266267#endif
···1/* i915_drv.h -- Private header for the I915 driver -*- linux-c -*-2 */3+/*4 *5 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.6 * All Rights Reserved.···25 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE26 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.27 *28+ */2930#ifndef _I915_DRV_H_31#define _I915_DRV_H_···3738#define DRIVER_NAME "i915"39#define DRIVER_DESC "Intel Graphics"40+#define DRIVER_DATE "20051209"4142/* Interface history:43 *44 * 1.1: Original.45+ * 1.2: Add Power Management46+ * 1.3: Add vblank support47 */48#define DRIVER_MAJOR 149+#define DRIVER_MINOR 350#define DRIVER_PATCHLEVEL 0000005152typedef struct _drm_i915_ring_buffer {53 int tail_mask;···97 int tex_lru_log_granularity;98 int allow_batchbuffer;99 struct mem_block *agp_heap;100+ unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds;101} drm_i915_private_t;102103extern drm_ioctl_desc_t i915_ioctls[];···104105 /* i915_dma.c */106extern void i915_kernel_lost_context(drm_device_t * dev);107+extern int i915_driver_load(struct drm_device *, unsigned long flags);108+extern void i915_driver_lastclose(drm_device_t * dev);109+extern void i915_driver_preclose(drm_device_t * dev, DRMFILE filp);110extern int i915_driver_device_is_agp(drm_device_t * dev);111+extern long i915_compat_ioctl(struct file *filp, unsigned int cmd,112+ unsigned long arg);113114/* i915_irq.c */115extern int i915_irq_emit(DRM_IOCTL_ARGS);116extern int i915_irq_wait(DRM_IOCTL_ARGS);117118+extern int i915_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence);119extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS);120extern void i915_driver_irq_preinstall(drm_device_t * dev);121extern void i915_driver_irq_postinstall(drm_device_t * dev);···125extern void i915_mem_release(drm_device_t * dev,126 DRMFILE filp, struct mem_block *heap);127128+#define I915_READ(reg) DRM_READ32(dev_priv->mmio_map, (reg))129+#define I915_WRITE(reg,val) DRM_WRITE32(dev_priv->mmio_map, (reg), (val))130+#define I915_READ16(reg) DRM_READ16(dev_priv->mmio_map, (reg))131+#define I915_WRITE16(reg,val) DRM_WRITE16(dev_priv->mmio_map, (reg), (val))000132133#define I915_VERBOSE 0134···195#define PPCR 0x61204196#define PPCR_ON (1<<0)197198+#define DVOB 0x61140199+#define DVOB_ON (1<<31)200+#define DVOC 0x61160201+#define DVOC_ON (1<<31)202+#define LVDS 0x61180203+#define LVDS_ON (1<<31)204+205#define ADPA 0x61100206#define ADPA_DPMS_MASK (~(3<<10))207#define ADPA_DPMS_ON (0<<10)···257#define ASYNC_FLIP (1<<22)258259#define CMD_OP_DESTBUFFER_INFO ((0x3<<29)|(0x1d<<24)|(0x8e<<16)|1)260+261+#define READ_BREADCRUMB(dev_priv) (((u32 *)(dev_priv->hw_status_page))[5])262263#endif
+39-9
drivers/char/drm/i915_irq.c
···1-/* i915_dma.c -- DMA support for the I915 -*- linux-c -*-2 */3-/**************************************************************************4- *5 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.6 * All Rights Reserved.7 *···24 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.26 *27- **************************************************************************/2829#include "drmP.h"30#include "drm.h"31#include "i915_drm.h"32#include "i915_drv.h"3334-#define USER_INT_FLAG 0x200035#define MAX_NOPID ((u32)~0)36-#define READ_BREADCRUMB(dev_priv) (((u32*)(dev_priv->hw_status_page))[5])3738irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)39{···44 u16 temp;4546 temp = I915_READ16(I915REG_INT_IDENTITY_R);47- temp &= USER_INT_FLAG;4849 DRM_DEBUG("%s flag=%08x\n", __FUNCTION__, temp);50···52 return IRQ_NONE;5354 I915_WRITE16(I915REG_INT_IDENTITY_R, temp);55- DRM_WAKEUP(&dev_priv->irq_queue);000000005657 return IRQ_HANDLED;58}···110 dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);111 return ret;112}000000000000000000000113114/* Needs the lock as it touches the ring.115 */···195{196 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;197198- I915_WRITE16(I915REG_INT_ENABLE_R, USER_INT_FLAG);199 DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);200}201
···1+/* i915_irq.c -- IRQ support for the I915 -*- linux-c -*-2 */3+/*04 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.5 * All Rights Reserved.6 *···25 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE26 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.27 *28+ */2930#include "drmP.h"31#include "drm.h"32#include "i915_drm.h"33#include "i915_drv.h"3435+#define USER_INT_FLAG (1<<1)36+#define VSYNC_PIPEB_FLAG (1<<5)37+#define VSYNC_PIPEA_FLAG (1<<7)38+39#define MAX_NOPID ((u32)~0)04041irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)42{···43 u16 temp;4445 temp = I915_READ16(I915REG_INT_IDENTITY_R);46+ temp &= (USER_INT_FLAG | VSYNC_PIPEA_FLAG);4748 DRM_DEBUG("%s flag=%08x\n", __FUNCTION__, temp);49···51 return IRQ_NONE;5253 I915_WRITE16(I915REG_INT_IDENTITY_R, temp);54+55+ if (temp & USER_INT_FLAG)56+ DRM_WAKEUP(&dev_priv->irq_queue);57+58+ if (temp & VSYNC_PIPEA_FLAG) {59+ atomic_inc(&dev->vbl_received);60+ DRM_WAKEUP(&dev->vbl_queue);61+ drm_vbl_send_signals(dev);62+ }6364 return IRQ_HANDLED;65}···101 dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);102 return ret;103}104+105+int i915_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence)106+{107+ drm_i915_private_t *dev_priv = dev->dev_private;108+ unsigned int cur_vblank;109+ int ret = 0;110+111+ if (!dev_priv) {112+ DRM_ERROR("%s called with no initialization\n", __FUNCTION__);113+ return DRM_ERR(EINVAL);114+ }115+116+ DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,117+ (((cur_vblank = atomic_read(&dev->vbl_received))118+ - *sequence) <= (1<<23)));119+120+ *sequence = cur_vblank;121+122+ return ret;123+}124+125126/* Needs the lock as it touches the ring.127 */···165{166 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;167168+ I915_WRITE16(I915REG_INT_ENABLE_R, USER_INT_FLAG | VSYNC_PIPEA_FLAG);169 DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);170}171
+2-3
drivers/char/drm/i915_mem.c
···1/* i915_mem.c -- Simple agp/fb memory manager for i915 -*- linux-c -*-2 */3-/**************************************************************************4- *5 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.6 * All Rights Reserved.7 *···24 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.26 *27- **************************************************************************/2829#include "drmP.h"30#include "drm.h"
···1/* i915_mem.c -- Simple agp/fb memory manager for i915 -*- linux-c -*-2 */3+/*04 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.5 * All Rights Reserved.6 *···25 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE26 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.27 *28+ */2930#include "drmP.h"31#include "drm.h"
+100-62
drivers/char/drm/mga_dma.c
···44#define MGA_DEFAULT_USEC_TIMEOUT 1000045#define MGA_FREELIST_DEBUG 04647-static int mga_do_cleanup_dma(drm_device_t * dev);004849/* ================================================================50 * Engine control···393 * DMA initialization, cleanup394 */395396-int mga_driver_preinit(drm_device_t * dev, unsigned long flags)397{398 drm_mga_private_t *dev_priv;399···406407 dev_priv->usec_timeout = MGA_DEFAULT_USEC_TIMEOUT;408 dev_priv->chipset = flags;00000000409410 return 0;411}···448 drm_buf_desc_t req;449 drm_agp_mode_t mode;450 drm_agp_info_t info;00451452 /* Acquire AGP. */453 err = drm_agp_acquire(dev);454 if (err) {455- DRM_ERROR("Unable to acquire AGP\n");456 return err;457 }458459 err = drm_agp_info(dev, &info);460 if (err) {461- DRM_ERROR("Unable to get AGP info\n");462 return err;463 }464···484 }485486 /* Allocate and bind AGP memory. */487- dev_priv->agp_pages = agp_size / PAGE_SIZE;488- dev_priv->agp_mem = drm_alloc_agp(dev, dev_priv->agp_pages, 0);489- if (dev_priv->agp_mem == NULL) {490- dev_priv->agp_pages = 0;0491 DRM_ERROR("Unable to allocate %uMB AGP memory\n",492 dma_bs->agp_size);493- return DRM_ERR(ENOMEM);494 }000495496- err = drm_bind_agp(dev_priv->agp_mem, 0);00497 if (err) {498- DRM_ERROR("Unable to bind AGP memory\n");499 return err;500 }501···515 err = drm_addmap(dev, offset, warp_size,516 _DRM_AGP, _DRM_READ_ONLY, &dev_priv->warp);517 if (err) {518- DRM_ERROR("Unable to map WARP microcode\n");519 return err;520 }521···523 err = drm_addmap(dev, offset, dma_bs->primary_size,524 _DRM_AGP, _DRM_READ_ONLY, &dev_priv->primary);525 if (err) {526- DRM_ERROR("Unable to map primary DMA region\n");527 return err;528 }529···531 err = drm_addmap(dev, offset, secondary_size,532 _DRM_AGP, 0, &dev->agp_buffer_map);533 if (err) {534- DRM_ERROR("Unable to map secondary DMA region\n");535 return err;536 }537···543544 err = drm_addbufs_agp(dev, &req);545 if (err) {546- DRM_ERROR("Unable to add secondary DMA buffers\n");547 return err;00000000000000548 }549550 offset += secondary_size;551 err = drm_addmap(dev, offset, agp_size - offset,552 _DRM_AGP, 0, &dev_priv->agp_textures);553 if (err) {554- DRM_ERROR("Unable to map AGP texture region\n");555 return err;556 }557···635 err = drm_addmap(dev, 0, warp_size, _DRM_CONSISTENT,636 _DRM_READ_ONLY, &dev_priv->warp);637 if (err != 0) {638- DRM_ERROR("Unable to create mapping for WARP microcode\n");0639 return err;640 }641···655 }656657 if (err != 0) {658- DRM_ERROR("Unable to allocate primary DMA region\n");659 return DRM_ERR(ENOMEM);660 }661···679 }680681 if (bin_count == 0) {682- DRM_ERROR("Unable to add secondary DMA buffers\n");683 return err;684 }685···715 err = drm_addmap(dev, dev_priv->mmio_base, dev_priv->mmio_size,716 _DRM_REGISTERS, _DRM_READ_ONLY, &dev_priv->mmio);717 if (err) {718- DRM_ERROR("Unable to map MMIO region\n");719 return err;720 }721···723 _DRM_READ_ONLY | _DRM_LOCKED | _DRM_KERNEL,724 &dev_priv->status);725 if (err) {726- DRM_ERROR("Unable to map status region\n");727 return err;728 }729···741 */742743 if (err) {744- mga_do_cleanup_dma(dev);745 }746747 /* Not only do we want to try and initialized PCI cards for PCI DMA,···764 DRM_DEVICE;765 drm_mga_dma_bootstrap_t bootstrap;766 int err;000767768 DRM_COPY_FROM_USER_IOCTL(bootstrap,769 (drm_mga_dma_bootstrap_t __user *) data,770 sizeof(bootstrap));771772 err = mga_do_dma_bootstrap(dev, &bootstrap);773- if (!err) {774- static const int modes[] = { 0, 1, 2, 2, 4, 4, 4, 4 };775- const drm_mga_private_t *const dev_priv =776- (drm_mga_private_t *) dev->dev_private;777-778- if (dev_priv->agp_textures != NULL) {779- bootstrap.texture_handle =780- dev_priv->agp_textures->offset;781- bootstrap.texture_size = dev_priv->agp_textures->size;782- } else {783- bootstrap.texture_handle = 0;784- bootstrap.texture_size = 0;785- }786-787- bootstrap.agp_mode = modes[bootstrap.agp_mode & 0x07];788- if (DRM_COPY_TO_USER((void __user *)data, &bootstrap,789- sizeof(bootstrap))) {790- err = DRM_ERR(EFAULT);791- }792- } else {793- mga_do_cleanup_dma(dev);794 }000000000000795796 return err;797}···883884 ret = mga_warp_install_microcode(dev_priv);885 if (ret < 0) {886- DRM_ERROR("failed to install WARP ucode!\n");887 return ret;888 }889890 ret = mga_warp_init(dev_priv);891 if (ret < 0) {892- DRM_ERROR("failed to init WARP engine!\n");893 return ret;894 }895···934 return 0;935}936937-static int mga_do_cleanup_dma(drm_device_t * dev)938{939 int err = 0;940 DRM_DEBUG("\n");···962963 if (dev_priv->used_new_dma_init) {964#if __OS_HAS_AGP965- if (dev_priv->agp_mem != NULL) {966- dev_priv->agp_textures = NULL;967- drm_unbind_agp(dev_priv->agp_mem);968969- drm_free_agp(dev_priv->agp_mem,970- dev_priv->agp_pages);971- dev_priv->agp_pages = 0;972- dev_priv->agp_mem = NULL;00000973 }974975 if ((dev->agp != NULL) && dev->agp->acquired) {976 err = drm_agp_release(dev);977 }978#endif979- dev_priv->used_new_dma_init = 0;980 }981982 dev_priv->warp = NULL;983 dev_priv->primary = NULL;984- dev_priv->mmio = NULL;985- dev_priv->status = NULL;986 dev_priv->sarea = NULL;987 dev_priv->sarea_priv = NULL;988 dev->agp_buffer_map = NULL;000000989990 memset(&dev_priv->prim, 0, sizeof(dev_priv->prim));991 dev_priv->warp_pipe = 0;···1005 }1006 }10071008- return err;1009}10101011int mga_dma_init(DRM_IOCTL_ARGS)···1023 case MGA_INIT_DMA:1024 err = mga_do_init_dma(dev, &init);1025 if (err) {1026- (void)mga_do_cleanup_dma(dev);1027 }1028 return err;1029 case MGA_CLEANUP_DMA:1030- return mga_do_cleanup_dma(dev);1031 }10321033 return DRM_ERR(EINVAL);···1156/**1157 * Called just before the module is unloaded.1158 */1159-int mga_driver_postcleanup(drm_device_t * dev)1160{1161 drm_free(dev->dev_private, sizeof(drm_mga_private_t), DRM_MEM_DRIVER);1162 dev->dev_private = NULL;···1167/**1168 * Called when the last opener of the device is closed.1169 */1170-void mga_driver_pretakedown(drm_device_t * dev)1171{1172- mga_do_cleanup_dma(dev);1173}11741175int mga_driver_dma_quiescent(drm_device_t * dev)
···44#define MGA_DEFAULT_USEC_TIMEOUT 1000045#define MGA_FREELIST_DEBUG 04647+#define MINIMAL_CLEANUP 048+#define FULL_CLEANUP 149+static int mga_do_cleanup_dma(drm_device_t *dev, int full_cleanup);5051/* ================================================================52 * Engine control···391 * DMA initialization, cleanup392 */393394+int mga_driver_load(drm_device_t * dev, unsigned long flags)395{396 drm_mga_private_t *dev_priv;397···404405 dev_priv->usec_timeout = MGA_DEFAULT_USEC_TIMEOUT;406 dev_priv->chipset = flags;407+408+ dev_priv->mmio_base = drm_get_resource_start(dev, 1);409+ dev_priv->mmio_size = drm_get_resource_len(dev, 1);410+411+ dev->counters += 3;412+ dev->types[6] = _DRM_STAT_IRQ;413+ dev->types[7] = _DRM_STAT_PRIMARY;414+ dev->types[8] = _DRM_STAT_SECONDARY;415416 return 0;417}···438 drm_buf_desc_t req;439 drm_agp_mode_t mode;440 drm_agp_info_t info;441+ drm_agp_buffer_t agp_req;442+ drm_agp_binding_t bind_req;443444 /* Acquire AGP. */445 err = drm_agp_acquire(dev);446 if (err) {447+ DRM_ERROR("Unable to acquire AGP: %d\n", err);448 return err;449 }450451 err = drm_agp_info(dev, &info);452 if (err) {453+ DRM_ERROR("Unable to get AGP info: %d\n", err);454 return err;455 }456···472 }473474 /* Allocate and bind AGP memory. */475+ agp_req.size = agp_size;476+ agp_req.type = 0;477+ err = drm_agp_alloc(dev, &agp_req);478+ if (err) {479+ dev_priv->agp_size = 0;480 DRM_ERROR("Unable to allocate %uMB AGP memory\n",481 dma_bs->agp_size);482+ return err;483 }484+485+ dev_priv->agp_size = agp_size;486+ dev_priv->agp_handle = agp_req.handle;487488+ bind_req.handle = agp_req.handle;489+ bind_req.offset = 0;490+ err = drm_agp_bind(dev, &bind_req);491 if (err) {492+ DRM_ERROR("Unable to bind AGP memory: %d\n", err);493 return err;494 }495···497 err = drm_addmap(dev, offset, warp_size,498 _DRM_AGP, _DRM_READ_ONLY, &dev_priv->warp);499 if (err) {500+ DRM_ERROR("Unable to map WARP microcode: %d\n", err);501 return err;502 }503···505 err = drm_addmap(dev, offset, dma_bs->primary_size,506 _DRM_AGP, _DRM_READ_ONLY, &dev_priv->primary);507 if (err) {508+ DRM_ERROR("Unable to map primary DMA region: %d\n", err);509 return err;510 }511···513 err = drm_addmap(dev, offset, secondary_size,514 _DRM_AGP, 0, &dev->agp_buffer_map);515 if (err) {516+ DRM_ERROR("Unable to map secondary DMA region: %d\n", err);517 return err;518 }519···525526 err = drm_addbufs_agp(dev, &req);527 if (err) {528+ DRM_ERROR("Unable to add secondary DMA buffers: %d\n", err);529 return err;530+ }531+532+ {533+ drm_map_list_t *_entry;534+ unsigned long agp_token = 0;535+536+ list_for_each_entry(_entry, &dev->maplist->head, head) {537+ if (_entry->map == dev->agp_buffer_map)538+ agp_token = _entry->user_token;539+ }540+ if (!agp_token)541+ return -EFAULT;542+543+ dev->agp_buffer_token = agp_token;544 }545546 offset += secondary_size;547 err = drm_addmap(dev, offset, agp_size - offset,548 _DRM_AGP, 0, &dev_priv->agp_textures);549 if (err) {550+ DRM_ERROR("Unable to map AGP texture region %d\n", err);551 return err;552 }553···603 err = drm_addmap(dev, 0, warp_size, _DRM_CONSISTENT,604 _DRM_READ_ONLY, &dev_priv->warp);605 if (err != 0) {606+ DRM_ERROR("Unable to create mapping for WARP microcode: %d\n",607+ err);608 return err;609 }610···622 }623624 if (err != 0) {625+ DRM_ERROR("Unable to allocate primary DMA region: %d\n", err);626 return DRM_ERR(ENOMEM);627 }628···646 }647648 if (bin_count == 0) {649+ DRM_ERROR("Unable to add secondary DMA buffers: %d\n", err);650 return err;651 }652···682 err = drm_addmap(dev, dev_priv->mmio_base, dev_priv->mmio_size,683 _DRM_REGISTERS, _DRM_READ_ONLY, &dev_priv->mmio);684 if (err) {685+ DRM_ERROR("Unable to map MMIO region: %d\n", err);686 return err;687 }688···690 _DRM_READ_ONLY | _DRM_LOCKED | _DRM_KERNEL,691 &dev_priv->status);692 if (err) {693+ DRM_ERROR("Unable to map status region: %d\n", err);694 return err;695 }696···708 */709710 if (err) {711+ mga_do_cleanup_dma(dev, MINIMAL_CLEANUP);712 }713714 /* Not only do we want to try and initialized PCI cards for PCI DMA,···731 DRM_DEVICE;732 drm_mga_dma_bootstrap_t bootstrap;733 int err;734+ static const int modes[] = { 0, 1, 2, 2, 4, 4, 4, 4 };735+ const drm_mga_private_t *const dev_priv =736+ (drm_mga_private_t *) dev->dev_private;737738 DRM_COPY_FROM_USER_IOCTL(bootstrap,739 (drm_mga_dma_bootstrap_t __user *) data,740 sizeof(bootstrap));741742 err = mga_do_dma_bootstrap(dev, &bootstrap);743+ if (err) {744+ mga_do_cleanup_dma(dev, FULL_CLEANUP);745+ return err;000000000000000000746 }747+748+ if (dev_priv->agp_textures != NULL) {749+ bootstrap.texture_handle = dev_priv->agp_textures->offset;750+ bootstrap.texture_size = dev_priv->agp_textures->size;751+ } else {752+ bootstrap.texture_handle = 0;753+ bootstrap.texture_size = 0;754+ }755+756+ bootstrap.agp_mode = modes[bootstrap.agp_mode & 0x07];757+ DRM_COPY_TO_USER_IOCTL((drm_mga_dma_bootstrap_t __user *)data,758+ bootstrap, sizeof(bootstrap));759760 return err;761}···853854 ret = mga_warp_install_microcode(dev_priv);855 if (ret < 0) {856+ DRM_ERROR("failed to install WARP ucode!: %d\n", ret);857 return ret;858 }859860 ret = mga_warp_init(dev_priv);861 if (ret < 0) {862+ DRM_ERROR("failed to init WARP engine!: %d\n", ret);863 return ret;864 }865···904 return 0;905}906907+static int mga_do_cleanup_dma(drm_device_t *dev, int full_cleanup)908{909 int err = 0;910 DRM_DEBUG("\n");···932933 if (dev_priv->used_new_dma_init) {934#if __OS_HAS_AGP935+ if (dev_priv->agp_handle != 0) {936+ drm_agp_binding_t unbind_req;937+ drm_agp_buffer_t free_req;938939+ unbind_req.handle = dev_priv->agp_handle;940+ drm_agp_unbind(dev, &unbind_req);941+942+ free_req.handle = dev_priv->agp_handle;943+ drm_agp_free(dev, &free_req);944+945+ dev_priv->agp_textures = NULL;946+ dev_priv->agp_size = 0;947+ dev_priv->agp_handle = 0;948 }949950 if ((dev->agp != NULL) && dev->agp->acquired) {951 err = drm_agp_release(dev);952 }953#endif0954 }955956 dev_priv->warp = NULL;957 dev_priv->primary = NULL;00958 dev_priv->sarea = NULL;959 dev_priv->sarea_priv = NULL;960 dev->agp_buffer_map = NULL;961+962+ if (full_cleanup) {963+ dev_priv->mmio = NULL;964+ dev_priv->status = NULL;965+ dev_priv->used_new_dma_init = 0;966+ }967968 memset(&dev_priv->prim, 0, sizeof(dev_priv->prim));969 dev_priv->warp_pipe = 0;···967 }968 }969970+ return 0;971}972973int mga_dma_init(DRM_IOCTL_ARGS)···985 case MGA_INIT_DMA:986 err = mga_do_init_dma(dev, &init);987 if (err) {988+ (void)mga_do_cleanup_dma(dev, FULL_CLEANUP);989 }990 return err;991 case MGA_CLEANUP_DMA:992+ return mga_do_cleanup_dma(dev, FULL_CLEANUP);993 }994995 return DRM_ERR(EINVAL);···1118/**1119 * Called just before the module is unloaded.1120 */1121+int mga_driver_unload(drm_device_t * dev)1122{1123 drm_free(dev->dev_private, sizeof(drm_mga_private_t), DRM_MEM_DRIVER);1124 dev->dev_private = NULL;···1129/**1130 * Called when the last opener of the device is closed.1131 */1132+void mga_driver_lastclose(drm_device_t * dev)1133{1134+ mga_do_cleanup_dma(dev, FULL_CLEANUP);1135}11361137int mga_driver_dma_quiescent(drm_device_t * dev)
···1-/* r128_cce.c -- ATI Rage 128 driver -*- linux-c -*-2 * Created: Wed Apr 5 19:24:19 2000 by kevin@precisioninsight.com3- *04 * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.5 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.6 * All Rights Reserved.···560 if (dev_priv->is_pci) {561#endif562 dev_priv->gart_info.gart_table_location = DRM_ATI_GART_MAIN;563- dev_priv->gart_info.addr = dev_priv->gart_info.bus_addr = 0;0564 dev_priv->gart_info.is_pcie = 0;565 if (!drm_ati_pcigart_init(dev, &dev_priv->gart_info)) {566 DRM_ERROR("failed to init PCI GART!\n");···603 drm_core_ioremapfree(dev_priv->cce_ring, dev);604 if (dev_priv->ring_rptr != NULL)605 drm_core_ioremapfree(dev_priv->ring_rptr, dev);606- if (dev->agp_buffer_map != NULL)607 drm_core_ioremapfree(dev->agp_buffer_map, dev);00608 } else609#endif610 {611 if (dev_priv->gart_info.bus_addr)612 if (!drm_ati_pcigart_cleanup(dev,613- &dev_priv->614- gart_info))615 DRM_ERROR616 ("failed to cleanup PCI GART!\n");617 }
···1+/* r128_cce.c -- ATI Rage 128 driver -*- linux-c -*- 2 * Created: Wed Apr 5 19:24:19 2000 by kevin@precisioninsight.com3+ */4+/*5 * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.6 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.7 * All Rights Reserved.···559 if (dev_priv->is_pci) {560#endif561 dev_priv->gart_info.gart_table_location = DRM_ATI_GART_MAIN;562+ dev_priv->gart_info.addr = NULL;563+ dev_priv->gart_info.bus_addr = 0;564 dev_priv->gart_info.is_pcie = 0;565 if (!drm_ati_pcigart_init(dev, &dev_priv->gart_info)) {566 DRM_ERROR("failed to init PCI GART!\n");···601 drm_core_ioremapfree(dev_priv->cce_ring, dev);602 if (dev_priv->ring_rptr != NULL)603 drm_core_ioremapfree(dev_priv->ring_rptr, dev);604+ if (dev->agp_buffer_map != NULL) {605 drm_core_ioremapfree(dev->agp_buffer_map, dev);606+ dev->agp_buffer_map = NULL;607+ }608 } else609#endif610 {611 if (dev_priv->gart_info.bus_addr)612 if (!drm_ati_pcigart_cleanup(dev,613+ &dev_priv->gart_info))0614 DRM_ERROR615 ("failed to cleanup PCI GART!\n");616 }
+2-2
drivers/char/drm/r128_drm.h
···1/* r128_drm.h -- Public header for the r128 driver -*- linux-c -*-2 * Created: Wed Apr 5 19:24:19 2000 by kevin@precisioninsight.com3- *4- * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.5 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.6 * All rights reserved.7 *
···1/* r128_drm.h -- Public header for the r128 driver -*- linux-c -*-2 * Created: Wed Apr 5 19:24:19 2000 by kevin@precisioninsight.com3+ */4+/* Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.5 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.6 * All rights reserved.7 *
···1/* r128_drv.h -- Private header for r128 driver -*- linux-c -*-2 * Created: Mon Dec 13 09:51:11 1999 by faith@precisioninsight.com3- *4- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.5 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.6 * All rights reserved.7 *···154extern void r128_driver_irq_preinstall(drm_device_t * dev);155extern void r128_driver_irq_postinstall(drm_device_t * dev);156extern void r128_driver_irq_uninstall(drm_device_t * dev);157-extern void r128_driver_pretakedown(drm_device_t * dev);158-extern void r128_driver_prerelease(drm_device_t * dev, DRMFILE filp);159160extern long r128_compat_ioctl(struct file *filp, unsigned int cmd,161 unsigned long arg);
···1/* r128_drv.h -- Private header for r128 driver -*- linux-c -*-2 * Created: Mon Dec 13 09:51:11 1999 by faith@precisioninsight.com3+ */4+/* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.5 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.6 * All rights reserved.7 *···154extern void r128_driver_irq_preinstall(drm_device_t * dev);155extern void r128_driver_irq_postinstall(drm_device_t * dev);156extern void r128_driver_irq_uninstall(drm_device_t * dev);157+extern void r128_driver_lastclose(drm_device_t * dev);158+extern void r128_driver_preclose(drm_device_t * dev, DRMFILE filp);159160extern long r128_compat_ioctl(struct file *filp, unsigned int cmd,161 unsigned long arg);
+2-2
drivers/char/drm/r128_irq.c
···1-/* r128_irq.c -- IRQ handling for radeon -*- linux-c -*-2- *3 * Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.4 *5 * The Weather Channel (TM) funded Tungsten Graphics to develop the
···1+/* r128_irq.c -- IRQ handling for radeon -*- linux-c -*- */2+/*3 * Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.4 *5 * The Weather Channel (TM) funded Tungsten Graphics to develop the
···1/* r128_state.c -- State support for r128 -*- linux-c -*-2 * Created: Thu Jan 27 02:53:43 2000 by gareth@valinux.com3+ */4+/* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.5 * All Rights Reserved.6 *7 * Permission is hereby granted, free of charge, to any person obtaining a···1674 return 0;1675}16761677+void r128_driver_preclose(drm_device_t * dev, DRMFILE filp)1678{1679 if (dev->dev_private) {1680 drm_r128_private_t *dev_priv = dev->dev_private;···1684 }1685}16861687+void r128_driver_lastclose(drm_device_t * dev)1688{1689 r128_do_cleanup_cce(dev);1690}16911692drm_ioctl_desc_t r128_ioctls[] = {1693+ [DRM_IOCTL_NR(DRM_R128_INIT)] = {r128_cce_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},1694+ [DRM_IOCTL_NR(DRM_R128_CCE_START)] = {r128_cce_start, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},1695+ [DRM_IOCTL_NR(DRM_R128_CCE_STOP)] = {r128_cce_stop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},1696+ [DRM_IOCTL_NR(DRM_R128_CCE_RESET)] = {r128_cce_reset, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},1697+ [DRM_IOCTL_NR(DRM_R128_CCE_IDLE)] = {r128_cce_idle, DRM_AUTH},1698+ [DRM_IOCTL_NR(DRM_R128_RESET)] = {r128_engine_reset, DRM_AUTH},1699+ [DRM_IOCTL_NR(DRM_R128_FULLSCREEN)] = {r128_fullscreen, DRM_AUTH},1700+ [DRM_IOCTL_NR(DRM_R128_SWAP)] = {r128_cce_swap, DRM_AUTH},1701+ [DRM_IOCTL_NR(DRM_R128_FLIP)] = {r128_cce_flip, DRM_AUTH},1702+ [DRM_IOCTL_NR(DRM_R128_CLEAR)] = {r128_cce_clear, DRM_AUTH},1703+ [DRM_IOCTL_NR(DRM_R128_VERTEX)] = {r128_cce_vertex, DRM_AUTH},1704+ [DRM_IOCTL_NR(DRM_R128_INDICES)] = {r128_cce_indices, DRM_AUTH},1705+ [DRM_IOCTL_NR(DRM_R128_BLIT)] = {r128_cce_blit, DRM_AUTH},1706+ [DRM_IOCTL_NR(DRM_R128_DEPTH)] = {r128_cce_depth, DRM_AUTH},1707+ [DRM_IOCTL_NR(DRM_R128_STIPPLE)] = {r128_cce_stipple, DRM_AUTH},1708+ [DRM_IOCTL_NR(DRM_R128_INDIRECT)] = {r128_cce_indirect, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},1709+ [DRM_IOCTL_NR(DRM_R128_GETPARAM)] = {r128_getparam, DRM_AUTH},1710};17111712int r128_max_ioctl = DRM_ARRAY_SIZE(r128_ioctls);
+20-18
drivers/char/drm/r300_cmdbuf.c
···52 * Emit up to R300_SIMULTANEOUS_CLIPRECTS cliprects from the given command53 * buffer, starting with index n.54 */55-static int r300_emit_cliprects(drm_radeon_private_t * dev_priv,56- drm_radeon_kcmd_buffer_t * cmdbuf, int n)57{58 drm_clip_rect_t box;59 int nr;···216 ADD_RANGE(R300_TX_UNK1_0, 16);217 ADD_RANGE(R300_TX_SIZE_0, 16);218 ADD_RANGE(R300_TX_FORMAT_0, 16);0219 /* Texture offset is dangerous and needs more checking */220 ADD_RANGE_MARK(R300_TX_OFFSET_0, 16, MARK_CHECK_OFFSET);221 ADD_RANGE(R300_TX_UNK4_0, 16);···243244 /* we expect offsets passed to the framebuffer to be either within video memory or245 within AGP space */246-static __inline__ int r300_check_offset(drm_radeon_private_t * dev_priv,247 u32 offset)248{249 /* we realy want to check against end of video aperture···318 *319 * Note that checks are performed on contents and addresses of the registers320 */321-static __inline__ int r300_emit_packet0(drm_radeon_private_t * dev_priv,322- drm_radeon_kcmd_buffer_t * cmdbuf,323 drm_r300_cmd_header_t header)324{325 int reg;···364 * the graphics card.365 * Called by r300_do_cp_cmdbuf.366 */367-static __inline__ int r300_emit_vpu(drm_radeon_private_t * dev_priv,368- drm_radeon_kcmd_buffer_t * cmdbuf,369 drm_r300_cmd_header_t header)370{371 int sz;···401 * Emit a clear packet from userspace.402 * Called by r300_emit_packet3.403 */404-static __inline__ int r300_emit_clear(drm_radeon_private_t * dev_priv,405- drm_radeon_kcmd_buffer_t * cmdbuf)406{407 RING_LOCALS;408···422 return 0;423}424425-static __inline__ int r300_emit_3d_load_vbpntr(drm_radeon_private_t * dev_priv,426- drm_radeon_kcmd_buffer_t * cmdbuf,427 u32 header)428{429 int count, i, k;···490 return 0;491}492493-static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t * dev_priv,494- drm_radeon_kcmd_buffer_t * cmdbuf)495{496 u32 header;497 int count;···555 * Emit a rendering packet3 from userspace.556 * Called by r300_do_cp_cmdbuf.557 */558-static __inline__ int r300_emit_packet3(drm_radeon_private_t * dev_priv,559- drm_radeon_kcmd_buffer_t * cmdbuf,560 drm_r300_cmd_header_t header)561{562 int n;···624/**625 * Emit the sequence to pacify R300.626 */627-static __inline__ void r300_pacify(drm_radeon_private_t * dev_priv)628{629 RING_LOCALS;630···658 * commands on the DMA ring buffer.659 * Called by the ioctl handler function radeon_cp_cmdbuf.660 */661-int r300_do_cp_cmdbuf(drm_device_t * dev,662 DRMFILE filp,663- drm_file_t * filp_priv, drm_radeon_kcmd_buffer_t * cmdbuf)0664{665 drm_radeon_private_t *dev_priv = dev->dev_private;666 drm_device_dma_t *dma = dev->dma;
···52 * Emit up to R300_SIMULTANEOUS_CLIPRECTS cliprects from the given command53 * buffer, starting with index n.54 */55+static int r300_emit_cliprects(drm_radeon_private_t *dev_priv,56+ drm_radeon_kcmd_buffer_t *cmdbuf, int n)57{58 drm_clip_rect_t box;59 int nr;···216 ADD_RANGE(R300_TX_UNK1_0, 16);217 ADD_RANGE(R300_TX_SIZE_0, 16);218 ADD_RANGE(R300_TX_FORMAT_0, 16);219+ ADD_RANGE(R300_TX_PITCH_0, 16);220 /* Texture offset is dangerous and needs more checking */221 ADD_RANGE_MARK(R300_TX_OFFSET_0, 16, MARK_CHECK_OFFSET);222 ADD_RANGE(R300_TX_UNK4_0, 16);···242243 /* we expect offsets passed to the framebuffer to be either within video memory or244 within AGP space */245+static __inline__ int r300_check_offset(drm_radeon_private_t *dev_priv,246 u32 offset)247{248 /* we realy want to check against end of video aperture···317 *318 * Note that checks are performed on contents and addresses of the registers319 */320+static __inline__ int r300_emit_packet0(drm_radeon_private_t *dev_priv,321+ drm_radeon_kcmd_buffer_t *cmdbuf,322 drm_r300_cmd_header_t header)323{324 int reg;···363 * the graphics card.364 * Called by r300_do_cp_cmdbuf.365 */366+static __inline__ int r300_emit_vpu(drm_radeon_private_t *dev_priv,367+ drm_radeon_kcmd_buffer_t *cmdbuf,368 drm_r300_cmd_header_t header)369{370 int sz;···400 * Emit a clear packet from userspace.401 * Called by r300_emit_packet3.402 */403+static __inline__ int r300_emit_clear(drm_radeon_private_t *dev_priv,404+ drm_radeon_kcmd_buffer_t *cmdbuf)405{406 RING_LOCALS;407···421 return 0;422}423424+static __inline__ int r300_emit_3d_load_vbpntr(drm_radeon_private_t *dev_priv,425+ drm_radeon_kcmd_buffer_t *cmdbuf,426 u32 header)427{428 int count, i, k;···489 return 0;490}491492+static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t *dev_priv,493+ drm_radeon_kcmd_buffer_t *cmdbuf)494{495 u32 header;496 int count;···554 * Emit a rendering packet3 from userspace.555 * Called by r300_do_cp_cmdbuf.556 */557+static __inline__ int r300_emit_packet3(drm_radeon_private_t *dev_priv,558+ drm_radeon_kcmd_buffer_t *cmdbuf,559 drm_r300_cmd_header_t header)560{561 int n;···623/**624 * Emit the sequence to pacify R300.625 */626+static __inline__ void r300_pacify(drm_radeon_private_t *dev_priv)627{628 RING_LOCALS;629···657 * commands on the DMA ring buffer.658 * Called by the ioctl handler function radeon_cp_cmdbuf.659 */660+int r300_do_cp_cmdbuf(drm_device_t *dev,661 DRMFILE filp,662+ drm_file_t *filp_priv,663+ drm_radeon_kcmd_buffer_t *cmdbuf)664{665 drm_radeon_private_t *dev_priv = dev->dev_private;666 drm_device_dma_t *dma = dev->dma;
···1-/* radeon_cp.c -- CP support for Radeon -*- linux-c -*-2- *3 * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.4 * Copyright 2000 VA Linux Systems, Inc., Fremont, California.5 * All Rights Reserved.···824 return RADEON_READ(RADEON_CLOCK_CNTL_DATA);825}826827-static int RADEON_READ_PCIE(drm_radeon_private_t * dev_priv, int addr)828{829 RADEON_WRITE8(RADEON_PCIE_INDEX, addr & 0xff);830 return RADEON_READ(RADEON_PCIE_DATA);···1125 | (dev_priv->fb_location >> 16));11261127#if __OS_HAS_AGP1128- if (!dev_priv->is_pci) {1129 RADEON_WRITE(RADEON_MC_AGP_LOCATION,1130 (((dev_priv->gart_vm_start - 1 +1131 dev_priv->gart_size) & 0xffff0000) |···1152 dev_priv->ring.tail = cur_read_ptr;11531154#if __OS_HAS_AGP1155- if (!dev_priv->is_pci) {1156 /* set RADEON_AGP_BASE here instead of relying on X from user space */1157 RADEON_WRITE(RADEON_AGP_BASE, (unsigned int)dev->agp->base);1158 RADEON_WRITE(RADEON_CP_RB_RPTR_ADDR,···1278/* Enable or disable PCI GART on the chip */1279static void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on)1280{1281- u32 tmp = RADEON_READ(RADEON_AIC_CNTL);12821283 if (dev_priv->flags & CHIP_IS_PCIE) {1284 radeon_set_pciegart(dev_priv, on);1285 return;1286 }0012871288 if (on) {1289 RADEON_WRITE(RADEON_AIC_CNTL,···1314static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)1315{1316 drm_radeon_private_t *dev_priv = dev->dev_private;01317 DRM_DEBUG("\n");13181319- dev_priv->is_pci = init->is_pci;000013201321- if (dev_priv->is_pci && !dev->sg) {1322 DRM_ERROR("PCI GART memory not allocated!\n");1323- dev->dev_private = (void *)dev_priv;1324 radeon_do_cleanup_cp(dev);1325 return DRM_ERR(EINVAL);1326 }···1333 if (dev_priv->usec_timeout < 1 ||1334 dev_priv->usec_timeout > RADEON_MAX_USEC_TIMEOUT) {1335 DRM_DEBUG("TIMEOUT problem!\n");1336- dev->dev_private = (void *)dev_priv;1337 radeon_do_cleanup_cp(dev);1338 return DRM_ERR(EINVAL);1339 }13401341- switch (init->func) {1342 case RADEON_INIT_R200_CP:1343 dev_priv->microcode_version = UCODE_R200;1344 break;···1358 if ((init->cp_mode != RADEON_CSQ_PRIBM_INDDIS) &&1359 (init->cp_mode != RADEON_CSQ_PRIBM_INDBM)) {1360 DRM_DEBUG("BAD cp_mode (%x)!\n", init->cp_mode);1361- dev->dev_private = (void *)dev_priv;1362 radeon_do_cleanup_cp(dev);1363 return DRM_ERR(EINVAL);1364 }···14201421 DRM_GETSAREA();14221423- dev_priv->fb_offset = init->fb_offset;1424- dev_priv->mmio_offset = init->mmio_offset;1425 dev_priv->ring_offset = init->ring_offset;1426 dev_priv->ring_rptr_offset = init->ring_rptr_offset;1427 dev_priv->buffers_offset = init->buffers_offset;···14271428 if (!dev_priv->sarea) {1429 DRM_ERROR("could not find sarea!\n");1430- dev->dev_private = (void *)dev_priv;1431 radeon_do_cleanup_cp(dev);1432 return DRM_ERR(EINVAL);1433 }14341435- dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset);1436- if (!dev_priv->mmio) {1437- DRM_ERROR("could not find mmio region!\n");1438- dev->dev_private = (void *)dev_priv;1439- radeon_do_cleanup_cp(dev);1440- return DRM_ERR(EINVAL);1441- }1442 dev_priv->cp_ring = drm_core_findmap(dev, init->ring_offset);1443 if (!dev_priv->cp_ring) {1444 DRM_ERROR("could not find cp ring region!\n");1445- dev->dev_private = (void *)dev_priv;1446 radeon_do_cleanup_cp(dev);1447 return DRM_ERR(EINVAL);1448 }1449 dev_priv->ring_rptr = drm_core_findmap(dev, init->ring_rptr_offset);1450 if (!dev_priv->ring_rptr) {1451 DRM_ERROR("could not find ring read pointer!\n");1452- dev->dev_private = (void *)dev_priv;1453 radeon_do_cleanup_cp(dev);1454 return DRM_ERR(EINVAL);1455 }···1447 dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);1448 if (!dev->agp_buffer_map) {1449 DRM_ERROR("could not find dma buffer region!\n");1450- dev->dev_private = (void *)dev_priv;1451 radeon_do_cleanup_cp(dev);1452 return DRM_ERR(EINVAL);1453 }···1456 drm_core_findmap(dev, init->gart_textures_offset);1457 if (!dev_priv->gart_textures) {1458 DRM_ERROR("could not find GART texture region!\n");1459- dev->dev_private = (void *)dev_priv;1460 radeon_do_cleanup_cp(dev);1461 return DRM_ERR(EINVAL);1462 }···1466 init->sarea_priv_offset);14671468#if __OS_HAS_AGP1469- if (!dev_priv->is_pci) {1470 drm_core_ioremap(dev_priv->cp_ring, dev);1471 drm_core_ioremap(dev_priv->ring_rptr, dev);1472 drm_core_ioremap(dev->agp_buffer_map, dev);···1474 !dev_priv->ring_rptr->handle ||1475 !dev->agp_buffer_map->handle) {1476 DRM_ERROR("could not find ioremap agp regions!\n");1477- dev->dev_private = (void *)dev_priv;1478 radeon_do_cleanup_cp(dev);1479 return DRM_ERR(EINVAL);1480 }···1514 + RADEON_READ(RADEON_CONFIG_APER_SIZE);15151516#if __OS_HAS_AGP1517- if (!dev_priv->is_pci)1518 dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset1519 - dev->agp->base1520 + dev_priv->gart_vm_start);···1540 dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK;15411542#if __OS_HAS_AGP1543- if (!dev_priv->is_pci) {1544 /* Turn off PCI GART */1545 radeon_set_pcigart(dev_priv, 0);1546 } else···1550 if (dev_priv->pcigart_offset) {1551 dev_priv->gart_info.bus_addr =1552 dev_priv->pcigart_offset + dev_priv->fb_location;0000001553 dev_priv->gart_info.addr =1554- (unsigned long)drm_ioremap(dev_priv->gart_info.1555- bus_addr,1556- RADEON_PCIGART_TABLE_SIZE,1557- dev);15581559 dev_priv->gart_info.is_pcie =1560 !!(dev_priv->flags & CHIP_IS_PCIE);1561 dev_priv->gart_info.gart_table_location =1562 DRM_ATI_GART_FB;15631564- DRM_DEBUG("Setting phys_pci_gart to %08lX %08lX\n",1565 dev_priv->gart_info.addr,1566 dev_priv->pcigart_offset);1567 } else {1568 dev_priv->gart_info.gart_table_location =1569 DRM_ATI_GART_MAIN;1570- dev_priv->gart_info.addr =1571- dev_priv->gart_info.bus_addr = 0;1572 if (dev_priv->flags & CHIP_IS_PCIE) {1573 DRM_ERROR1574 ("Cannot use PCI Express without GART in FB memory\n");···15821583 if (!drm_ati_pcigart_init(dev, &dev_priv->gart_info)) {1584 DRM_ERROR("failed to init PCI GART!\n");1585- dev->dev_private = (void *)dev_priv;1586 radeon_do_cleanup_cp(dev);1587 return DRM_ERR(ENOMEM);1588 }···1594 radeon_cp_init_ring_buffer(dev, dev_priv);15951596 dev_priv->last_buf = 0;1597-1598- dev->dev_private = (void *)dev_priv;15991600 radeon_do_engine_reset(dev);1601···1613 drm_irq_uninstall(dev);16141615#if __OS_HAS_AGP1616- if (!dev_priv->is_pci) {1617- if (dev_priv->cp_ring != NULL)1618 drm_core_ioremapfree(dev_priv->cp_ring, dev);1619- if (dev_priv->ring_rptr != NULL)001620 drm_core_ioremapfree(dev_priv->ring_rptr, dev);001621 if (dev->agp_buffer_map != NULL) {1622 drm_core_ioremapfree(dev->agp_buffer_map, dev);1623 dev->agp_buffer_map = NULL;···1629 } else1630#endif1631 {1632- if (dev_priv->gart_info.bus_addr)0001633 if (!drm_ati_pcigart_cleanup(dev, &dev_priv->gart_info))1634 DRM_ERROR("failed to cleanup PCI GART!\n");016351636- if (dev_priv->gart_info.gart_table_location == DRM_ATI_GART_FB) {1637- drm_ioremapfree((void *)dev_priv->gart_info.addr,1638- RADEON_PCIGART_TABLE_SIZE, dev);1639 dev_priv->gart_info.addr = 0;1640 }1641 }1642-1643 /* only clear to the start of flags */1644 memset(dev_priv, 0, offsetof(drm_radeon_private_t, flags));1645···1668 DRM_DEBUG("Starting radeon_do_resume_cp()\n");16691670#if __OS_HAS_AGP1671- if (!dev_priv->is_pci) {1672 /* Turn off PCI GART */1673 radeon_set_pcigart(dev_priv, 0);1674 } else···2099 return ret;2100}21012102-int radeon_driver_preinit(struct drm_device *dev, unsigned long flags)2103{2104 drm_radeon_private_t *dev_priv;2105 int ret = 0;···2132 dev_priv->flags |= CHIP_IS_PCIE;21332134 DRM_DEBUG("%s card detected\n",2135- ((dev_priv->flags & CHIP_IS_AGP) ? "AGP" : "PCI"));2136 return ret;2137}21382139-int radeon_presetup(struct drm_device *dev)0002140{2141 int ret;2142 drm_local_map_t *map;···2160 return 0;2161}21622163-int radeon_driver_postcleanup(struct drm_device *dev)2164{2165 drm_radeon_private_t *dev_priv = dev->dev_private;21662167 DRM_DEBUG("\n");2168-2169 drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER);21702171 dev->dev_private = NULL;
···1+/* radeon_cp.c -- CP support for Radeon -*- linux-c -*- */2+/*3 * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.4 * Copyright 2000 VA Linux Systems, Inc., Fremont, California.5 * All Rights Reserved.···824 return RADEON_READ(RADEON_CLOCK_CNTL_DATA);825}826827+static int RADEON_READ_PCIE(drm_radeon_private_t *dev_priv, int addr)828{829 RADEON_WRITE8(RADEON_PCIE_INDEX, addr & 0xff);830 return RADEON_READ(RADEON_PCIE_DATA);···1125 | (dev_priv->fb_location >> 16));11261127#if __OS_HAS_AGP1128+ if (dev_priv->flags & CHIP_IS_AGP) {1129 RADEON_WRITE(RADEON_MC_AGP_LOCATION,1130 (((dev_priv->gart_vm_start - 1 +1131 dev_priv->gart_size) & 0xffff0000) |···1152 dev_priv->ring.tail = cur_read_ptr;11531154#if __OS_HAS_AGP1155+ if (dev_priv->flags & CHIP_IS_AGP) {1156 /* set RADEON_AGP_BASE here instead of relying on X from user space */1157 RADEON_WRITE(RADEON_AGP_BASE, (unsigned int)dev->agp->base);1158 RADEON_WRITE(RADEON_CP_RB_RPTR_ADDR,···1278/* Enable or disable PCI GART on the chip */1279static void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on)1280{1281+ u32 tmp;12821283 if (dev_priv->flags & CHIP_IS_PCIE) {1284 radeon_set_pciegart(dev_priv, on);1285 return;1286 }1287+1288+ tmp = RADEON_READ(RADEON_AIC_CNTL);12891290 if (on) {1291 RADEON_WRITE(RADEON_AIC_CNTL,···1312static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)1313{1314 drm_radeon_private_t *dev_priv = dev->dev_private;1315+1316 DRM_DEBUG("\n");13171318+ if (init->is_pci && (dev_priv->flags & CHIP_IS_AGP))1319+ {1320+ DRM_DEBUG("Forcing AGP card to PCI mode\n");1321+ dev_priv->flags &= ~CHIP_IS_AGP;1322+ }13231324+ if ((!(dev_priv->flags & CHIP_IS_AGP)) && !dev->sg) {1325 DRM_ERROR("PCI GART memory not allocated!\n");01326 radeon_do_cleanup_cp(dev);1327 return DRM_ERR(EINVAL);1328 }···1327 if (dev_priv->usec_timeout < 1 ||1328 dev_priv->usec_timeout > RADEON_MAX_USEC_TIMEOUT) {1329 DRM_DEBUG("TIMEOUT problem!\n");01330 radeon_do_cleanup_cp(dev);1331 return DRM_ERR(EINVAL);1332 }13331334+ switch(init->func) {1335 case RADEON_INIT_R200_CP:1336 dev_priv->microcode_version = UCODE_R200;1337 break;···1353 if ((init->cp_mode != RADEON_CSQ_PRIBM_INDDIS) &&1354 (init->cp_mode != RADEON_CSQ_PRIBM_INDBM)) {1355 DRM_DEBUG("BAD cp_mode (%x)!\n", init->cp_mode);01356 radeon_do_cleanup_cp(dev);1357 return DRM_ERR(EINVAL);1358 }···14161417 DRM_GETSAREA();1418001419 dev_priv->ring_offset = init->ring_offset;1420 dev_priv->ring_rptr_offset = init->ring_rptr_offset;1421 dev_priv->buffers_offset = init->buffers_offset;···14251426 if (!dev_priv->sarea) {1427 DRM_ERROR("could not find sarea!\n");01428 radeon_do_cleanup_cp(dev);1429 return DRM_ERR(EINVAL);1430 }143100000001432 dev_priv->cp_ring = drm_core_findmap(dev, init->ring_offset);1433 if (!dev_priv->cp_ring) {1434 DRM_ERROR("could not find cp ring region!\n");01435 radeon_do_cleanup_cp(dev);1436 return DRM_ERR(EINVAL);1437 }1438 dev_priv->ring_rptr = drm_core_findmap(dev, init->ring_rptr_offset);1439 if (!dev_priv->ring_rptr) {1440 DRM_ERROR("could not find ring read pointer!\n");01441 radeon_do_cleanup_cp(dev);1442 return DRM_ERR(EINVAL);1443 }···1455 dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);1456 if (!dev->agp_buffer_map) {1457 DRM_ERROR("could not find dma buffer region!\n");01458 radeon_do_cleanup_cp(dev);1459 return DRM_ERR(EINVAL);1460 }···1465 drm_core_findmap(dev, init->gart_textures_offset);1466 if (!dev_priv->gart_textures) {1467 DRM_ERROR("could not find GART texture region!\n");01468 radeon_do_cleanup_cp(dev);1469 return DRM_ERR(EINVAL);1470 }···1476 init->sarea_priv_offset);14771478#if __OS_HAS_AGP1479+ if (dev_priv->flags & CHIP_IS_AGP) {1480 drm_core_ioremap(dev_priv->cp_ring, dev);1481 drm_core_ioremap(dev_priv->ring_rptr, dev);1482 drm_core_ioremap(dev->agp_buffer_map, dev);···1484 !dev_priv->ring_rptr->handle ||1485 !dev->agp_buffer_map->handle) {1486 DRM_ERROR("could not find ioremap agp regions!\n");01487 radeon_do_cleanup_cp(dev);1488 return DRM_ERR(EINVAL);1489 }···1525 + RADEON_READ(RADEON_CONFIG_APER_SIZE);15261527#if __OS_HAS_AGP1528+ if (dev_priv->flags & CHIP_IS_AGP)1529 dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset1530 - dev->agp->base1531 + dev_priv->gart_vm_start);···1551 dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK;15521553#if __OS_HAS_AGP1554+ if (dev_priv->flags & CHIP_IS_AGP) {1555 /* Turn off PCI GART */1556 radeon_set_pcigart(dev_priv, 0);1557 } else···1561 if (dev_priv->pcigart_offset) {1562 dev_priv->gart_info.bus_addr =1563 dev_priv->pcigart_offset + dev_priv->fb_location;1564+ dev_priv->gart_info.mapping.offset =1565+ dev_priv->gart_info.bus_addr;1566+ dev_priv->gart_info.mapping.size =1567+ RADEON_PCIGART_TABLE_SIZE;1568+1569+ drm_core_ioremap(&dev_priv->gart_info.mapping, dev);1570 dev_priv->gart_info.addr =1571+ dev_priv->gart_info.mapping.handle;00015721573 dev_priv->gart_info.is_pcie =1574 !!(dev_priv->flags & CHIP_IS_PCIE);1575 dev_priv->gart_info.gart_table_location =1576 DRM_ATI_GART_FB;15771578+ DRM_DEBUG("Setting phys_pci_gart to %p %08lX\n",1579 dev_priv->gart_info.addr,1580 dev_priv->pcigart_offset);1581 } else {1582 dev_priv->gart_info.gart_table_location =1583 DRM_ATI_GART_MAIN;1584+ dev_priv->gart_info.addr = NULL;1585+ dev_priv->gart_info.bus_addr = 0;1586 if (dev_priv->flags & CHIP_IS_PCIE) {1587 DRM_ERROR1588 ("Cannot use PCI Express without GART in FB memory\n");···15901591 if (!drm_ati_pcigart_init(dev, &dev_priv->gart_info)) {1592 DRM_ERROR("failed to init PCI GART!\n");01593 radeon_do_cleanup_cp(dev);1594 return DRM_ERR(ENOMEM);1595 }···1603 radeon_cp_init_ring_buffer(dev, dev_priv);16041605 dev_priv->last_buf = 0;0016061607 radeon_do_engine_reset(dev);1608···1624 drm_irq_uninstall(dev);16251626#if __OS_HAS_AGP1627+ if (dev_priv->flags & CHIP_IS_AGP) {1628+ if (dev_priv->cp_ring != NULL) {1629 drm_core_ioremapfree(dev_priv->cp_ring, dev);1630+ dev_priv->cp_ring = NULL;1631+ }1632+ if (dev_priv->ring_rptr != NULL) {1633 drm_core_ioremapfree(dev_priv->ring_rptr, dev);1634+ dev_priv->ring_rptr = NULL;1635+ }1636 if (dev->agp_buffer_map != NULL) {1637 drm_core_ioremapfree(dev->agp_buffer_map, dev);1638 dev->agp_buffer_map = NULL;···1636 } else1637#endif1638 {1639+1640+ if (dev_priv->gart_info.bus_addr) {1641+ /* Turn off PCI GART */1642+ radeon_set_pcigart(dev_priv, 0);1643 if (!drm_ati_pcigart_cleanup(dev, &dev_priv->gart_info))1644 DRM_ERROR("failed to cleanup PCI GART!\n");1645+ }16461647+ if (dev_priv->gart_info.gart_table_location == DRM_ATI_GART_FB)1648+ {1649+ drm_core_ioremapfree(&dev_priv->gart_info.mapping, dev);1650 dev_priv->gart_info.addr = 0;1651 }1652 }01653 /* only clear to the start of flags */1654 memset(dev_priv, 0, offsetof(drm_radeon_private_t, flags));1655···1672 DRM_DEBUG("Starting radeon_do_resume_cp()\n");16731674#if __OS_HAS_AGP1675+ if (dev_priv->flags & CHIP_IS_AGP) {1676 /* Turn off PCI GART */1677 radeon_set_pcigart(dev_priv, 0);1678 } else···2103 return ret;2104}21052106+int radeon_driver_load(struct drm_device *dev, unsigned long flags)2107{2108 drm_radeon_private_t *dev_priv;2109 int ret = 0;···2136 dev_priv->flags |= CHIP_IS_PCIE;21372138 DRM_DEBUG("%s card detected\n",2139+ ((dev_priv->flags & CHIP_IS_AGP) ? "AGP" : (((dev_priv->flags & CHIP_IS_PCIE) ? "PCIE" : "PCI"))));2140 return ret;2141}21422143+/* Create mappings for registers and framebuffer so userland doesn't necessarily2144+ * have to find them.2145+ */2146+int radeon_driver_firstopen(struct drm_device *dev)2147{2148 int ret;2149 drm_local_map_t *map;···2161 return 0;2162}21632164+int radeon_driver_unload(struct drm_device *dev)2165{2166 drm_radeon_private_t *dev_priv = dev->dev_private;21672168 DRM_DEBUG("\n");02169 drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER);21702171 dev->dev_private = NULL;
+6
drivers/char/drm/radeon_drm.h
···624 int discard;625} drm_radeon_indirect_t;62600000627/* 1.3: An ioctl to get parameters that aren't available to the 3d628 * client any other way.629 */···645#define RADEON_PARAM_SAREA_HANDLE 9646#define RADEON_PARAM_GART_TEX_HANDLE 10647#define RADEON_PARAM_SCRATCH_OFFSET 110648649typedef struct drm_radeon_getparam {650 int param;
···624 int discard;625} drm_radeon_indirect_t;626627+/* enum for card type parameters */628+#define RADEON_CARD_PCI 0629+#define RADEON_CARD_AGP 1630+#define RADEON_CARD_PCIE 2631+632/* 1.3: An ioctl to get parameters that aren't available to the 3d633 * client any other way.634 */···640#define RADEON_PARAM_SAREA_HANDLE 9641#define RADEON_PARAM_GART_TEX_HANDLE 10642#define RADEON_PARAM_SCRATCH_OFFSET 11643+#define RADEON_PARAM_CARD_TYPE 12644645typedef struct drm_radeon_getparam {646 int param;
···1+/* sis_drv.h -- Private header for sis driver -*- linux-c -*- */2+/*3+ * Copyright 2005 Eric Anholt4+ * All Rights Reserved.5+ *6+ * Permission is hereby granted, free of charge, to any person obtaining a7+ * copy of this software and associated documentation files (the "Software"),8+ * to deal in the Software without restriction, including without limitation9+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,10+ * and/or sell copies of the Software, and to permit persons to whom the11+ * Software is furnished to do so, subject to the following conditions:12+ *13+ * The above copyright notice and this permission notice (including the next14+ * paragraph) shall be included in all copies or substantial portions of the15+ * Software.16+ *17+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR18+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,19+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL20+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER21+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,22+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE23+ * SOFTWARE.24+ *25+ */2627#ifndef __SIS_DRM_H__28#define __SIS_DRM_H__
···1-/* sis_drv.h -- Private header for sis driver -*- linux-c -*-2- *3 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.4 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.5 * All rights reserved.
···1+/* sis_drv.h -- Private header for sis driver -*- linux-c -*- */2+/*3 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.4 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.5 * All rights reserved.
+4-3
drivers/char/drm/sis_ds.h
···1-/* sis_ds.h -- Private header for Direct Rendering Manager -*- linux-c -*-2 * Created: Mon Jan 4 10:05:05 1999 by sclin@sis.com.tw3- *04 * Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan.5 * All rights reserved.6 *···3637#define SET_SIZE 50003839-typedef unsigned int ITEM_TYPE;4041typedef struct {42 ITEM_TYPE val;
···1+/* sis_ds.h -- Private header for Direct Rendering Manager -*- linux-c -*- 2 * Created: Mon Jan 4 10:05:05 1999 by sclin@sis.com.tw3+ */4+/*5 * Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan.6 * All rights reserved.7 *···3536#define SET_SIZE 50003738+typedef unsigned long ITEM_TYPE;3940typedef struct {41 ITEM_TYPE val;
···1/* tdfx.h -- 3dfx DRM template customization -*- linux-c -*-2 * Created: Wed Feb 14 12:32:32 2001 by gareth@valinux.com3- *04 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.5 * All Rights Reserved.6 *···3031#ifndef __TDFX_H__32#define __TDFX_H__33-34-/* This remains constant for all DRM template files.35- */36-#define DRM(x) tdfx_##x3738/* General customization:39 */
···1/* tdfx.h -- 3dfx DRM template customization -*- linux-c -*-2 * Created: Wed Feb 14 12:32:32 2001 by gareth@valinux.com3+ */4+/*5 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.6 * All Rights Reserved.7 *···2930#ifndef __TDFX_H__31#define __TDFX_H__00003233/* General customization:34 */
···1+/* via_dmablit.c -- PCI DMA BitBlt support for the VIA Unichrome/Pro2+ * 3+ * Copyright (C) 2005 Thomas Hellstrom, All Rights Reserved.4+ *5+ * Permission is hereby granted, free of charge, to any person obtaining a6+ * copy of this software and associated documentation files (the "Software"),7+ * to deal in the Software without restriction, including without limitation8+ * the rights to use, copy, modify, merge, publish, distribute, sub license,9+ * and/or sell copies of the Software, and to permit persons to whom the10+ * Software is furnished to do so, subject to the following conditions:11+ *12+ * The above copyright notice and this permission notice (including the13+ * next paragraph) shall be included in all copies or substantial portions14+ * of the Software.15+ *16+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR17+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,18+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL19+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 20+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 21+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 22+ * USE OR OTHER DEALINGS IN THE SOFTWARE.23+ *24+ * Authors: 25+ * Thomas Hellstrom.26+ * Partially based on code obtained from Digeo Inc.27+ */28+29+30+/*31+ * Unmaps the DMA mappings. 32+ * FIXME: Is this a NoOp on x86? Also 33+ * FIXME: What happens if this one is called and a pending blit has previously done 34+ * the same DMA mappings? 35+ */36+37+#include "drmP.h"38+#include "via_drm.h"39+#include "via_drv.h"40+#include "via_dmablit.h"41+42+#include <linux/pagemap.h>43+44+#define VIA_PGDN(x) (((unsigned long)(x)) & PAGE_MASK)45+#define VIA_PGOFF(x) (((unsigned long)(x)) & ~PAGE_MASK)46+#define VIA_PFN(x) ((unsigned long)(x) >> PAGE_SHIFT)47+48+typedef struct _drm_via_descriptor {49+ uint32_t mem_addr;50+ uint32_t dev_addr;51+ uint32_t size;52+ uint32_t next;53+} drm_via_descriptor_t;54+55+56+/*57+ * Unmap a DMA mapping.58+ */59+60+61+62+static void63+via_unmap_blit_from_device(struct pci_dev *pdev, drm_via_sg_info_t *vsg)64+{65+ int num_desc = vsg->num_desc;66+ unsigned cur_descriptor_page = num_desc / vsg->descriptors_per_page;67+ unsigned descriptor_this_page = num_desc % vsg->descriptors_per_page;68+ drm_via_descriptor_t *desc_ptr = vsg->desc_pages[cur_descriptor_page] + 69+ descriptor_this_page;70+ dma_addr_t next = vsg->chain_start;71+72+ while(num_desc--) {73+ if (descriptor_this_page-- == 0) {74+ cur_descriptor_page--;75+ descriptor_this_page = vsg->descriptors_per_page - 1;76+ desc_ptr = vsg->desc_pages[cur_descriptor_page] + 77+ descriptor_this_page;78+ }79+ dma_unmap_single(&pdev->dev, next, sizeof(*desc_ptr), DMA_TO_DEVICE);80+ dma_unmap_page(&pdev->dev, desc_ptr->mem_addr, desc_ptr->size, vsg->direction);81+ next = (dma_addr_t) desc_ptr->next;82+ desc_ptr--;83+ }84+}85+86+/*87+ * If mode = 0, count how many descriptors are needed.88+ * If mode = 1, Map the DMA pages for the device, put together and map also the descriptors.89+ * Descriptors are run in reverse order by the hardware because we are not allowed to update the90+ * 'next' field without syncing calls when the descriptor is already mapped.91+ */92+93+static void94+via_map_blit_for_device(struct pci_dev *pdev,95+ const drm_via_dmablit_t *xfer,96+ drm_via_sg_info_t *vsg, 97+ int mode)98+{99+ unsigned cur_descriptor_page = 0;100+ unsigned num_descriptors_this_page = 0;101+ unsigned char *mem_addr = xfer->mem_addr;102+ unsigned char *cur_mem;103+ unsigned char *first_addr = (unsigned char *)VIA_PGDN(mem_addr);104+ uint32_t fb_addr = xfer->fb_addr;105+ uint32_t cur_fb;106+ unsigned long line_len;107+ unsigned remaining_len;108+ int num_desc = 0;109+ int cur_line;110+ dma_addr_t next = 0 | VIA_DMA_DPR_EC;111+ drm_via_descriptor_t *desc_ptr = 0;112+113+ if (mode == 1) 114+ desc_ptr = vsg->desc_pages[cur_descriptor_page];115+116+ for (cur_line = 0; cur_line < xfer->num_lines; ++cur_line) {117+118+ line_len = xfer->line_length;119+ cur_fb = fb_addr;120+ cur_mem = mem_addr;121+122+ while (line_len > 0) {123+124+ remaining_len = min(PAGE_SIZE-VIA_PGOFF(cur_mem), line_len);125+ line_len -= remaining_len;126+127+ if (mode == 1) {128+ desc_ptr->mem_addr = 129+ dma_map_page(&pdev->dev, 130+ vsg->pages[VIA_PFN(cur_mem) - 131+ VIA_PFN(first_addr)],132+ VIA_PGOFF(cur_mem), remaining_len, 133+ vsg->direction);134+ desc_ptr->dev_addr = cur_fb;135+136+ desc_ptr->size = remaining_len;137+ desc_ptr->next = (uint32_t) next;138+ next = dma_map_single(&pdev->dev, desc_ptr, sizeof(*desc_ptr), 139+ DMA_TO_DEVICE);140+ desc_ptr++;141+ if (++num_descriptors_this_page >= vsg->descriptors_per_page) {142+ num_descriptors_this_page = 0;143+ desc_ptr = vsg->desc_pages[++cur_descriptor_page];144+ }145+ }146+147+ num_desc++;148+ cur_mem += remaining_len;149+ cur_fb += remaining_len;150+ }151+152+ mem_addr += xfer->mem_stride;153+ fb_addr += xfer->fb_stride;154+ }155+156+ if (mode == 1) {157+ vsg->chain_start = next;158+ vsg->state = dr_via_device_mapped;159+ }160+ vsg->num_desc = num_desc;161+}162+163+/*164+ * Function that frees up all resources for a blit. It is usable even if the 165+ * blit info has only be partially built as long as the status enum is consistent166+ * with the actual status of the used resources.167+ */168+169+170+void171+via_free_sg_info(struct pci_dev *pdev, drm_via_sg_info_t *vsg) 172+{173+ struct page *page;174+ int i;175+176+ switch(vsg->state) {177+ case dr_via_device_mapped:178+ via_unmap_blit_from_device(pdev, vsg);179+ case dr_via_desc_pages_alloc:180+ for (i=0; i<vsg->num_desc_pages; ++i) {181+ if (vsg->desc_pages[i] != NULL)182+ free_page((unsigned long)vsg->desc_pages[i]);183+ }184+ kfree(vsg->desc_pages);185+ case dr_via_pages_locked:186+ for (i=0; i<vsg->num_pages; ++i) {187+ if ( NULL != (page = vsg->pages[i])) {188+ if (! PageReserved(page) && (DMA_FROM_DEVICE == vsg->direction)) 189+ SetPageDirty(page);190+ page_cache_release(page);191+ }192+ }193+ case dr_via_pages_alloc:194+ vfree(vsg->pages);195+ default:196+ vsg->state = dr_via_sg_init;197+ }198+ if (vsg->bounce_buffer) {199+ vfree(vsg->bounce_buffer);200+ vsg->bounce_buffer = NULL;201+ }202+ vsg->free_on_sequence = 0;203+} 204+205+/*206+ * Fire a blit engine.207+ */208+209+static void210+via_fire_dmablit(drm_device_t *dev, drm_via_sg_info_t *vsg, int engine)211+{212+ drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;213+214+ VIA_WRITE(VIA_PCI_DMA_MAR0 + engine*0x10, 0);215+ VIA_WRITE(VIA_PCI_DMA_DAR0 + engine*0x10, 0);216+ VIA_WRITE(VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_DD | VIA_DMA_CSR_TD | 217+ VIA_DMA_CSR_DE);218+ VIA_WRITE(VIA_PCI_DMA_MR0 + engine*0x04, VIA_DMA_MR_CM | VIA_DMA_MR_TDIE);219+ VIA_WRITE(VIA_PCI_DMA_BCR0 + engine*0x10, 0);220+ VIA_WRITE(VIA_PCI_DMA_DPR0 + engine*0x10, vsg->chain_start);221+ VIA_WRITE(VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_DE | VIA_DMA_CSR_TS);222+}223+224+/*225+ * Obtain a page pointer array and lock all pages into system memory. A segmentation violation will226+ * occur here if the calling user does not have access to the submitted address.227+ */228+229+static int230+via_lock_all_dma_pages(drm_via_sg_info_t *vsg, drm_via_dmablit_t *xfer)231+{232+ int ret;233+ unsigned long first_pfn = VIA_PFN(xfer->mem_addr);234+ vsg->num_pages = VIA_PFN(xfer->mem_addr + (xfer->num_lines * xfer->mem_stride -1)) - 235+ first_pfn + 1;236+237+ if (NULL == (vsg->pages = vmalloc(sizeof(struct page *) * vsg->num_pages)))238+ return DRM_ERR(ENOMEM);239+ memset(vsg->pages, 0, sizeof(struct page *) * vsg->num_pages);240+ down_read(¤t->mm->mmap_sem);241+ ret = get_user_pages(current, current->mm, (unsigned long) xfer->mem_addr,242+ vsg->num_pages, vsg->direction, 0, vsg->pages, NULL);243+244+ up_read(¤t->mm->mmap_sem);245+ if (ret != vsg->num_pages) {246+ if (ret < 0) 247+ return ret;248+ vsg->state = dr_via_pages_locked;249+ return DRM_ERR(EINVAL);250+ }251+ vsg->state = dr_via_pages_locked;252+ DRM_DEBUG("DMA pages locked\n");253+ return 0;254+}255+256+/*257+ * Allocate DMA capable memory for the blit descriptor chain, and an array that keeps track of the258+ * pages we allocate. We don't want to use kmalloc for the descriptor chain because it may be259+ * quite large for some blits, and pages don't need to be contingous.260+ */261+262+static int 263+via_alloc_desc_pages(drm_via_sg_info_t *vsg)264+{265+ int i;266+267+ vsg->descriptors_per_page = PAGE_SIZE / sizeof( drm_via_descriptor_t);268+ vsg->num_desc_pages = (vsg->num_desc + vsg->descriptors_per_page - 1) / 269+ vsg->descriptors_per_page;270+271+ if (NULL == (vsg->desc_pages = kmalloc(sizeof(void *) * vsg->num_desc_pages, GFP_KERNEL))) 272+ return DRM_ERR(ENOMEM);273+274+ memset(vsg->desc_pages, 0, sizeof(void *) * vsg->num_desc_pages);275+ vsg->state = dr_via_desc_pages_alloc;276+ for (i=0; i<vsg->num_desc_pages; ++i) {277+ if (NULL == (vsg->desc_pages[i] = 278+ (drm_via_descriptor_t *) __get_free_page(GFP_KERNEL)))279+ return DRM_ERR(ENOMEM);280+ }281+ DRM_DEBUG("Allocated %d pages for %d descriptors.\n", vsg->num_desc_pages,282+ vsg->num_desc);283+ return 0;284+}285+286+static void287+via_abort_dmablit(drm_device_t *dev, int engine)288+{289+ drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;290+291+ VIA_WRITE(VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_TA);292+}293+294+static void295+via_dmablit_engine_off(drm_device_t *dev, int engine)296+{297+ drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;298+299+ VIA_WRITE(VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_TD | VIA_DMA_CSR_DD); 300+}301+302+303+304+/*305+ * The dmablit part of the IRQ handler. Trying to do only reasonably fast things here.306+ * The rest, like unmapping and freeing memory for done blits is done in a separate workqueue307+ * task. Basically the task of the interrupt handler is to submit a new blit to the engine, while308+ * the workqueue task takes care of processing associated with the old blit.309+ */310+311+void312+via_dmablit_handler(drm_device_t *dev, int engine, int from_irq)313+{314+ drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;315+ drm_via_blitq_t *blitq = dev_priv->blit_queues + engine;316+ int cur;317+ int done_transfer;318+ unsigned long irqsave=0;319+ uint32_t status = 0;320+321+ DRM_DEBUG("DMA blit handler called. engine = %d, from_irq = %d, blitq = 0x%lx\n",322+ engine, from_irq, (unsigned long) blitq);323+324+ if (from_irq) {325+ spin_lock(&blitq->blit_lock);326+ } else {327+ spin_lock_irqsave(&blitq->blit_lock, irqsave);328+ }329+330+ done_transfer = blitq->is_active && 331+ (( status = VIA_READ(VIA_PCI_DMA_CSR0 + engine*0x04)) & VIA_DMA_CSR_TD);332+ done_transfer = done_transfer || ( blitq->aborting && !(status & VIA_DMA_CSR_DE)); 333+334+ cur = blitq->cur;335+ if (done_transfer) {336+337+ blitq->blits[cur]->aborted = blitq->aborting;338+ blitq->done_blit_handle++;339+ DRM_WAKEUP(blitq->blit_queue + cur); 340+341+ cur++;342+ if (cur >= VIA_NUM_BLIT_SLOTS) 343+ cur = 0;344+ blitq->cur = cur;345+346+ /*347+ * Clear transfer done flag.348+ */349+350+ VIA_WRITE(VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_TD);351+352+ blitq->is_active = 0;353+ blitq->aborting = 0;354+ schedule_work(&blitq->wq); 355+356+ } else if (blitq->is_active && time_after_eq(jiffies, blitq->end)) {357+358+ /*359+ * Abort transfer after one second.360+ */361+362+ via_abort_dmablit(dev, engine);363+ blitq->aborting = 1;364+ blitq->end = jiffies + DRM_HZ;365+ }366+367+ if (!blitq->is_active) {368+ if (blitq->num_outstanding) {369+ via_fire_dmablit(dev, blitq->blits[cur], engine);370+ blitq->is_active = 1;371+ blitq->cur = cur;372+ blitq->num_outstanding--;373+ blitq->end = jiffies + DRM_HZ;374+ if (!timer_pending(&blitq->poll_timer)) {375+ blitq->poll_timer.expires = jiffies+1;376+ add_timer(&blitq->poll_timer);377+ }378+ } else {379+ if (timer_pending(&blitq->poll_timer)) {380+ del_timer(&blitq->poll_timer);381+ }382+ via_dmablit_engine_off(dev, engine);383+ }384+ } 385+386+ if (from_irq) {387+ spin_unlock(&blitq->blit_lock);388+ } else {389+ spin_unlock_irqrestore(&blitq->blit_lock, irqsave);390+ }391+} 392+393+394+395+/*396+ * Check whether this blit is still active, performing necessary locking.397+ */398+399+static int400+via_dmablit_active(drm_via_blitq_t *blitq, int engine, uint32_t handle, wait_queue_head_t **queue)401+{402+ unsigned long irqsave;403+ uint32_t slot;404+ int active;405+406+ spin_lock_irqsave(&blitq->blit_lock, irqsave);407+408+ /*409+ * Allow for handle wraparounds.410+ */411+412+ active = ((blitq->done_blit_handle - handle) > (1 << 23)) &&413+ ((blitq->cur_blit_handle - handle) <= (1 << 23));414+415+ if (queue && active) {416+ slot = handle - blitq->done_blit_handle + blitq->cur -1;417+ if (slot >= VIA_NUM_BLIT_SLOTS) {418+ slot -= VIA_NUM_BLIT_SLOTS;419+ }420+ *queue = blitq->blit_queue + slot;421+ }422+423+ spin_unlock_irqrestore(&blitq->blit_lock, irqsave);424+425+ return active;426+}427+428+/*429+ * Sync. Wait for at least three seconds for the blit to be performed.430+ */431+432+static int433+via_dmablit_sync(drm_device_t *dev, uint32_t handle, int engine) 434+{435+436+ drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;437+ drm_via_blitq_t *blitq = dev_priv->blit_queues + engine;438+ wait_queue_head_t *queue;439+ int ret = 0;440+441+ if (via_dmablit_active(blitq, engine, handle, &queue)) {442+ DRM_WAIT_ON(ret, *queue, 3 * DRM_HZ, 443+ !via_dmablit_active(blitq, engine, handle, NULL));444+ }445+ DRM_DEBUG("DMA blit sync handle 0x%x engine %d returned %d\n",446+ handle, engine, ret);447+448+ return ret;449+}450+451+452+/*453+ * A timer that regularly polls the blit engine in cases where we don't have interrupts:454+ * a) Broken hardware (typically those that don't have any video capture facility).455+ * b) Blit abort. The hardware doesn't send an interrupt when a blit is aborted.456+ * The timer and hardware IRQ's can and do work in parallel. If the hardware has457+ * irqs, it will shorten the latency somewhat.458+ */459+460+461+462+static void463+via_dmablit_timer(unsigned long data)464+{465+ drm_via_blitq_t *blitq = (drm_via_blitq_t *) data;466+ drm_device_t *dev = blitq->dev;467+ int engine = (int)468+ (blitq - ((drm_via_private_t *)dev->dev_private)->blit_queues);469+470+ DRM_DEBUG("Polling timer called for engine %d, jiffies %lu\n", engine, 471+ (unsigned long) jiffies);472+473+ via_dmablit_handler(dev, engine, 0);474+475+ if (!timer_pending(&blitq->poll_timer)) {476+ blitq->poll_timer.expires = jiffies+1;477+ add_timer(&blitq->poll_timer);478+ }479+ via_dmablit_handler(dev, engine, 0);480+481+}482+483+484+485+486+/*487+ * Workqueue task that frees data and mappings associated with a blit.488+ * Also wakes up waiting processes. Each of these tasks handles one489+ * blit engine only and may not be called on each interrupt.490+ */491+492+493+static void 494+via_dmablit_workqueue(void *data)495+{496+ drm_via_blitq_t *blitq = (drm_via_blitq_t *) data;497+ drm_device_t *dev = blitq->dev;498+ unsigned long irqsave;499+ drm_via_sg_info_t *cur_sg;500+ int cur_released;501+502+503+ DRM_DEBUG("Workqueue task called for blit engine %ld\n",(unsigned long) 504+ (blitq - ((drm_via_private_t *)dev->dev_private)->blit_queues));505+506+ spin_lock_irqsave(&blitq->blit_lock, irqsave);507+508+ while(blitq->serviced != blitq->cur) {509+510+ cur_released = blitq->serviced++;511+512+ DRM_DEBUG("Releasing blit slot %d\n", cur_released);513+514+ if (blitq->serviced >= VIA_NUM_BLIT_SLOTS) 515+ blitq->serviced = 0;516+517+ cur_sg = blitq->blits[cur_released];518+ blitq->num_free++;519+520+ spin_unlock_irqrestore(&blitq->blit_lock, irqsave);521+522+ DRM_WAKEUP(&blitq->busy_queue);523+524+ via_free_sg_info(dev->pdev, cur_sg);525+ kfree(cur_sg);526+527+ spin_lock_irqsave(&blitq->blit_lock, irqsave);528+ }529+530+ spin_unlock_irqrestore(&blitq->blit_lock, irqsave);531+}532+533+534+/*535+ * Init all blit engines. Currently we use two, but some hardware have 4.536+ */537+538+539+void540+via_init_dmablit(drm_device_t *dev)541+{542+ int i,j;543+ drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;544+ drm_via_blitq_t *blitq;545+546+ pci_set_master(dev->pdev); 547+548+ for (i=0; i< VIA_NUM_BLIT_ENGINES; ++i) {549+ blitq = dev_priv->blit_queues + i;550+ blitq->dev = dev;551+ blitq->cur_blit_handle = 0;552+ blitq->done_blit_handle = 0;553+ blitq->head = 0;554+ blitq->cur = 0;555+ blitq->serviced = 0;556+ blitq->num_free = VIA_NUM_BLIT_SLOTS;557+ blitq->num_outstanding = 0;558+ blitq->is_active = 0;559+ blitq->aborting = 0;560+ blitq->blit_lock = SPIN_LOCK_UNLOCKED;561+ for (j=0; j<VIA_NUM_BLIT_SLOTS; ++j) {562+ DRM_INIT_WAITQUEUE(blitq->blit_queue + j);563+ }564+ DRM_INIT_WAITQUEUE(&blitq->busy_queue);565+ INIT_WORK(&blitq->wq, via_dmablit_workqueue, blitq);566+ init_timer(&blitq->poll_timer);567+ blitq->poll_timer.function = &via_dmablit_timer;568+ blitq->poll_timer.data = (unsigned long) blitq;569+ } 570+}571+572+/*573+ * Build all info and do all mappings required for a blit.574+ */575+576+577+static int578+via_build_sg_info(drm_device_t *dev, drm_via_sg_info_t *vsg, drm_via_dmablit_t *xfer)579+{580+ int draw = xfer->to_fb;581+ int ret = 0;582+583+ vsg->direction = (draw) ? DMA_TO_DEVICE : DMA_FROM_DEVICE;584+ vsg->bounce_buffer = 0;585+586+ vsg->state = dr_via_sg_init;587+588+ if (xfer->num_lines <= 0 || xfer->line_length <= 0) {589+ DRM_ERROR("Zero size bitblt.\n");590+ return DRM_ERR(EINVAL);591+ }592+593+ /*594+ * Below check is a driver limitation, not a hardware one. We595+ * don't want to lock unused pages, and don't want to incoporate the596+ * extra logic of avoiding them. Make sure there are no. 597+ * (Not a big limitation anyway.)598+ */599+600+ if (((xfer->mem_stride - xfer->line_length) >= PAGE_SIZE) ||601+ (xfer->mem_stride > 2048*4)) {602+ DRM_ERROR("Too large system memory stride. Stride: %d, "603+ "Length: %d\n", xfer->mem_stride, xfer->line_length);604+ return DRM_ERR(EINVAL);605+ }606+607+ if (xfer->num_lines > 2048) {608+ DRM_ERROR("Too many PCI DMA bitblt lines.\n");609+ return DRM_ERR(EINVAL);610+ } 611+612+ /* 613+ * we allow a negative fb stride to allow flipping of images in614+ * transfer. 615+ */616+617+ if (xfer->mem_stride < xfer->line_length ||618+ abs(xfer->fb_stride) < xfer->line_length) {619+ DRM_ERROR("Invalid frame-buffer / memory stride.\n");620+ return DRM_ERR(EINVAL);621+ }622+623+ /*624+ * A hardware bug seems to be worked around if system memory addresses start on625+ * 16 byte boundaries. This seems a bit restrictive however. VIA is contacted626+ * about this. Meanwhile, impose the following restrictions:627+ */628+629+#ifdef VIA_BUGFREE630+ if ((((unsigned long)xfer->mem_addr & 3) != ((unsigned long)xfer->fb_addr & 3)) ||631+ ((xfer->mem_stride & 3) != (xfer->fb_stride & 3))) {632+ DRM_ERROR("Invalid DRM bitblt alignment.\n");633+ return DRM_ERR(EINVAL);634+ }635+#else636+ if ((((unsigned long)xfer->mem_addr & 15) ||637+ ((unsigned long)xfer->fb_addr & 3)) || (xfer->mem_stride & 15) ||638+ (xfer->fb_stride & 3)) {639+ DRM_ERROR("Invalid DRM bitblt alignment.\n");640+ return DRM_ERR(EINVAL);641+ } 642+#endif643+644+ if (0 != (ret = via_lock_all_dma_pages(vsg, xfer))) {645+ DRM_ERROR("Could not lock DMA pages.\n");646+ via_free_sg_info(dev->pdev, vsg);647+ return ret;648+ }649+650+ via_map_blit_for_device(dev->pdev, xfer, vsg, 0);651+ if (0 != (ret = via_alloc_desc_pages(vsg))) {652+ DRM_ERROR("Could not allocate DMA descriptor pages.\n");653+ via_free_sg_info(dev->pdev, vsg);654+ return ret;655+ }656+ via_map_blit_for_device(dev->pdev, xfer, vsg, 1);657+658+ return 0;659+}660+661+662+/*663+ * Reserve one free slot in the blit queue. Will wait for one second for one664+ * to become available. Otherwise -EBUSY is returned.665+ */666+667+static int 668+via_dmablit_grab_slot(drm_via_blitq_t *blitq, int engine)669+{670+ int ret=0;671+ unsigned long irqsave;672+673+ DRM_DEBUG("Num free is %d\n", blitq->num_free);674+ spin_lock_irqsave(&blitq->blit_lock, irqsave);675+ while(blitq->num_free == 0) {676+ spin_unlock_irqrestore(&blitq->blit_lock, irqsave);677+678+ DRM_WAIT_ON(ret, blitq->busy_queue, DRM_HZ, blitq->num_free > 0);679+ if (ret) {680+ return (DRM_ERR(EINTR) == ret) ? DRM_ERR(EAGAIN) : ret;681+ }682+683+ spin_lock_irqsave(&blitq->blit_lock, irqsave);684+ }685+686+ blitq->num_free--;687+ spin_unlock_irqrestore(&blitq->blit_lock, irqsave);688+689+ return 0;690+}691+692+/*693+ * Hand back a free slot if we changed our mind.694+ */695+696+static void 697+via_dmablit_release_slot(drm_via_blitq_t *blitq)698+{699+ unsigned long irqsave;700+701+ spin_lock_irqsave(&blitq->blit_lock, irqsave);702+ blitq->num_free++;703+ spin_unlock_irqrestore(&blitq->blit_lock, irqsave);704+ DRM_WAKEUP( &blitq->busy_queue );705+}706+707+/*708+ * Grab a free slot. Build blit info and queue a blit.709+ */710+711+712+static int 713+via_dmablit(drm_device_t *dev, drm_via_dmablit_t *xfer) 714+{715+ drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;716+ drm_via_sg_info_t *vsg;717+ drm_via_blitq_t *blitq;718+ int ret;719+ int engine;720+ unsigned long irqsave;721+722+ if (dev_priv == NULL) {723+ DRM_ERROR("Called without initialization.\n");724+ return DRM_ERR(EINVAL);725+ }726+727+ engine = (xfer->to_fb) ? 0 : 1;728+ blitq = dev_priv->blit_queues + engine;729+ if (0 != (ret = via_dmablit_grab_slot(blitq, engine))) {730+ return ret;731+ }732+ if (NULL == (vsg = kmalloc(sizeof(*vsg), GFP_KERNEL))) {733+ via_dmablit_release_slot(blitq);734+ return DRM_ERR(ENOMEM);735+ }736+ if (0 != (ret = via_build_sg_info(dev, vsg, xfer))) {737+ via_dmablit_release_slot(blitq);738+ kfree(vsg);739+ return ret;740+ }741+ spin_lock_irqsave(&blitq->blit_lock, irqsave);742+743+ blitq->blits[blitq->head++] = vsg;744+ if (blitq->head >= VIA_NUM_BLIT_SLOTS) 745+ blitq->head = 0;746+ blitq->num_outstanding++;747+ xfer->sync.sync_handle = ++blitq->cur_blit_handle; 748+749+ spin_unlock_irqrestore(&blitq->blit_lock, irqsave);750+ xfer->sync.engine = engine;751+752+ via_dmablit_handler(dev, engine, 0);753+754+ return 0;755+}756+757+/*758+ * Sync on a previously submitted blit. Note that the X server use signals extensively, and759+ * that there is a very big proability that this IOCTL will be interrupted by a signal. In that760+ * case it returns with -EAGAIN for the signal to be delivered. 761+ * The caller should then reissue the IOCTL. This is similar to what is being done for drmGetLock().762+ */763+764+int765+via_dma_blit_sync( DRM_IOCTL_ARGS )766+{767+ drm_via_blitsync_t sync;768+ int err;769+ DRM_DEVICE;770+771+ DRM_COPY_FROM_USER_IOCTL(sync, (drm_via_blitsync_t *)data, sizeof(sync));772+773+ if (sync.engine >= VIA_NUM_BLIT_ENGINES) 774+ return DRM_ERR(EINVAL);775+776+ err = via_dmablit_sync(dev, sync.sync_handle, sync.engine);777+778+ if (DRM_ERR(EINTR) == err)779+ err = DRM_ERR(EAGAIN);780+781+ return err;782+}783+784+785+/*786+ * Queue a blit and hand back a handle to be used for sync. This IOCTL may be interrupted by a signal787+ * while waiting for a free slot in the blit queue. In that case it returns with -EAGAIN and should 788+ * be reissued. See the above IOCTL code.789+ */790+791+int 792+via_dma_blit( DRM_IOCTL_ARGS )793+{794+ drm_via_dmablit_t xfer;795+ int err;796+ DRM_DEVICE;797+798+ DRM_COPY_FROM_USER_IOCTL(xfer, (drm_via_dmablit_t __user *)data, sizeof(xfer));799+800+ err = via_dmablit(dev, &xfer);801+802+ DRM_COPY_TO_USER_IOCTL((void __user *)data, xfer, sizeof(xfer));803+804+ return err;805+}
···1+/* via_dmablit.h -- PCI DMA BitBlt support for the VIA Unichrome/Pro2+ * 3+ * Copyright 2005 Thomas Hellstrom.4+ * All Rights Reserved.5+ *6+ * Permission is hereby granted, free of charge, to any person obtaining a7+ * copy of this software and associated documentation files (the "Software"),8+ * to deal in the Software without restriction, including without limitation9+ * the rights to use, copy, modify, merge, publish, distribute, sub license,10+ * and/or sell copies of the Software, and to permit persons to whom the11+ * Software is furnished to do so, subject to the following conditions:12+ *13+ * The above copyright notice and this permission notice (including the14+ * next paragraph) shall be included in all copies or substantial portions15+ * of the Software.16+ *17+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR18+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,19+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL20+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 21+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 22+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 23+ * USE OR OTHER DEALINGS IN THE SOFTWARE.24+ *25+ * Authors: 26+ * Thomas Hellstrom.27+ * Register info from Digeo Inc.28+ */29+30+#ifndef _VIA_DMABLIT_H31+#define _VIA_DMABLIT_H32+33+#include <linux/dma-mapping.h>34+35+#define VIA_NUM_BLIT_ENGINES 236+#define VIA_NUM_BLIT_SLOTS 837+38+struct _drm_via_descriptor;39+40+typedef struct _drm_via_sg_info {41+ struct page **pages;42+ unsigned long num_pages;43+ struct _drm_via_descriptor **desc_pages;44+ int num_desc_pages;45+ int num_desc;46+ enum dma_data_direction direction;47+ unsigned char *bounce_buffer;48+ dma_addr_t chain_start;49+ uint32_t free_on_sequence;50+ unsigned int descriptors_per_page;51+ int aborted;52+ enum {53+ dr_via_device_mapped,54+ dr_via_desc_pages_alloc,55+ dr_via_pages_locked,56+ dr_via_pages_alloc,57+ dr_via_sg_init58+ } state;59+} drm_via_sg_info_t;60+61+typedef struct _drm_via_blitq {62+ drm_device_t *dev;63+ uint32_t cur_blit_handle;64+ uint32_t done_blit_handle;65+ unsigned serviced;66+ unsigned head;67+ unsigned cur;68+ unsigned num_free;69+ unsigned num_outstanding;70+ unsigned long end; 71+ int aborting;72+ int is_active;73+ drm_via_sg_info_t *blits[VIA_NUM_BLIT_SLOTS];74+ spinlock_t blit_lock;75+ wait_queue_head_t blit_queue[VIA_NUM_BLIT_SLOTS];76+ wait_queue_head_t busy_queue;77+ struct work_struct wq;78+ struct timer_list poll_timer;79+} drm_via_blitq_t;80+81+82+/* 83+ * PCI DMA Registers84+ * Channels 2 & 3 don't seem to be implemented in hardware.85+ */86+87+#define VIA_PCI_DMA_MAR0 0xE40 /* Memory Address Register of Channel 0 */ 88+#define VIA_PCI_DMA_DAR0 0xE44 /* Device Address Register of Channel 0 */ 89+#define VIA_PCI_DMA_BCR0 0xE48 /* Byte Count Register of Channel 0 */ 90+#define VIA_PCI_DMA_DPR0 0xE4C /* Descriptor Pointer Register of Channel 0 */ 91+92+#define VIA_PCI_DMA_MAR1 0xE50 /* Memory Address Register of Channel 1 */ 93+#define VIA_PCI_DMA_DAR1 0xE54 /* Device Address Register of Channel 1 */ 94+#define VIA_PCI_DMA_BCR1 0xE58 /* Byte Count Register of Channel 1 */ 95+#define VIA_PCI_DMA_DPR1 0xE5C /* Descriptor Pointer Register of Channel 1 */ 96+97+#define VIA_PCI_DMA_MAR2 0xE60 /* Memory Address Register of Channel 2 */ 98+#define VIA_PCI_DMA_DAR2 0xE64 /* Device Address Register of Channel 2 */ 99+#define VIA_PCI_DMA_BCR2 0xE68 /* Byte Count Register of Channel 2 */ 100+#define VIA_PCI_DMA_DPR2 0xE6C /* Descriptor Pointer Register of Channel 2 */ 101+102+#define VIA_PCI_DMA_MAR3 0xE70 /* Memory Address Register of Channel 3 */ 103+#define VIA_PCI_DMA_DAR3 0xE74 /* Device Address Register of Channel 3 */ 104+#define VIA_PCI_DMA_BCR3 0xE78 /* Byte Count Register of Channel 3 */ 105+#define VIA_PCI_DMA_DPR3 0xE7C /* Descriptor Pointer Register of Channel 3 */ 106+107+#define VIA_PCI_DMA_MR0 0xE80 /* Mode Register of Channel 0 */ 108+#define VIA_PCI_DMA_MR1 0xE84 /* Mode Register of Channel 1 */ 109+#define VIA_PCI_DMA_MR2 0xE88 /* Mode Register of Channel 2 */ 110+#define VIA_PCI_DMA_MR3 0xE8C /* Mode Register of Channel 3 */ 111+112+#define VIA_PCI_DMA_CSR0 0xE90 /* Command/Status Register of Channel 0 */ 113+#define VIA_PCI_DMA_CSR1 0xE94 /* Command/Status Register of Channel 1 */ 114+#define VIA_PCI_DMA_CSR2 0xE98 /* Command/Status Register of Channel 2 */ 115+#define VIA_PCI_DMA_CSR3 0xE9C /* Command/Status Register of Channel 3 */ 116+117+#define VIA_PCI_DMA_PTR 0xEA0 /* Priority Type Register */ 118+119+/* Define for DMA engine */ 120+/* DPR */121+#define VIA_DMA_DPR_EC (1<<1) /* end of chain */122+#define VIA_DMA_DPR_DDIE (1<<2) /* descriptor done interrupt enable */123+#define VIA_DMA_DPR_DT (1<<3) /* direction of transfer (RO) */124+125+/* MR */126+#define VIA_DMA_MR_CM (1<<0) /* chaining mode */127+#define VIA_DMA_MR_TDIE (1<<1) /* transfer done interrupt enable */128+#define VIA_DMA_MR_HENDMACMD (1<<7) /* ? */129+130+/* CSR */131+#define VIA_DMA_CSR_DE (1<<0) /* DMA enable */132+#define VIA_DMA_CSR_TS (1<<1) /* transfer start */133+#define VIA_DMA_CSR_TA (1<<2) /* transfer abort */134+#define VIA_DMA_CSR_TD (1<<3) /* transfer done */135+#define VIA_DMA_CSR_DD (1<<4) /* descriptor done */136+#define VIA_DMA_DPR_EC (1<<1) /* end of chain */137+138+139+140+#endif
+42-16
drivers/char/drm/via_drm.h
···75#define DRM_VIA_CMDBUF_SIZE 0x0b76#define NOT_USED77#define DRM_VIA_WAIT_IRQ 0x0d007879#define DRM_IOCTL_VIA_ALLOCMEM DRM_IOWR(DRM_COMMAND_BASE + DRM_VIA_ALLOCMEM, drm_via_mem_t)80#define DRM_IOCTL_VIA_FREEMEM DRM_IOW( DRM_COMMAND_BASE + DRM_VIA_FREEMEM, drm_via_mem_t)···91#define DRM_IOCTL_VIA_CMDBUF_SIZE DRM_IOWR( DRM_COMMAND_BASE + DRM_VIA_CMDBUF_SIZE, \92 drm_via_cmdbuf_size_t)93#define DRM_IOCTL_VIA_WAIT_IRQ DRM_IOWR( DRM_COMMAND_BASE + DRM_VIA_WAIT_IRQ, drm_via_irqwait_t)009495/* Indices into buf.Setup where various bits of state are mirrored per96 * context and per buffer. These can be fired at the card as a unit,···107#define VIA_BACK 0x2108#define VIA_DEPTH 0x4109#define VIA_STENCIL 0x8110-#define VIDEO 0111-#define AGP 10000112typedef struct {113 uint32_t offset;114 uint32_t size;···200 unsigned int XvMCSubPicOn[VIA_NR_XVMC_PORTS];201 unsigned int XvMCCtxNoGrabbed; /* Last context to hold decoder */202000203} drm_via_sarea_t;204205typedef struct _drm_via_cmdbuf_size {···223224#define VIA_IRQ_FLAGS_MASK 0xF00000002250000000000226struct drm_via_wait_irq_request {227 unsigned irq;228 via_irq_seq_type_t type;···245 struct drm_wait_vblank_reply reply;246} drm_via_irqwait_t;247248-#ifdef __KERNEL__000249250-int via_fb_init(DRM_IOCTL_ARGS);251-int via_mem_alloc(DRM_IOCTL_ARGS);252-int via_mem_free(DRM_IOCTL_ARGS);253-int via_agp_init(DRM_IOCTL_ARGS);254-int via_map_init(DRM_IOCTL_ARGS);255-int via_decoder_futex(DRM_IOCTL_ARGS);256-int via_dma_init(DRM_IOCTL_ARGS);257-int via_cmdbuffer(DRM_IOCTL_ARGS);258-int via_flush_ioctl(DRM_IOCTL_ARGS);259-int via_pci_cmdbuffer(DRM_IOCTL_ARGS);260-int via_cmdbuf_size(DRM_IOCTL_ARGS);261-int via_wait_irq(DRM_IOCTL_ARGS);262263-#endif00000000264#endif /* _VIA_DRM_H_ */
···75#define DRM_VIA_CMDBUF_SIZE 0x0b76#define NOT_USED77#define DRM_VIA_WAIT_IRQ 0x0d78+#define DRM_VIA_DMA_BLIT 0x0e79+#define DRM_VIA_BLIT_SYNC 0x0f8081#define DRM_IOCTL_VIA_ALLOCMEM DRM_IOWR(DRM_COMMAND_BASE + DRM_VIA_ALLOCMEM, drm_via_mem_t)82#define DRM_IOCTL_VIA_FREEMEM DRM_IOW( DRM_COMMAND_BASE + DRM_VIA_FREEMEM, drm_via_mem_t)···89#define DRM_IOCTL_VIA_CMDBUF_SIZE DRM_IOWR( DRM_COMMAND_BASE + DRM_VIA_CMDBUF_SIZE, \90 drm_via_cmdbuf_size_t)91#define DRM_IOCTL_VIA_WAIT_IRQ DRM_IOWR( DRM_COMMAND_BASE + DRM_VIA_WAIT_IRQ, drm_via_irqwait_t)92+#define DRM_IOCTL_VIA_DMA_BLIT DRM_IOW(DRM_COMMAND_BASE + DRM_VIA_DMA_BLIT, drm_via_dmablit_t)93+#define DRM_IOCTL_VIA_BLIT_SYNC DRM_IOW(DRM_COMMAND_BASE + DRM_VIA_BLIT_SYNC, drm_via_blitsync_t)9495/* Indices into buf.Setup where various bits of state are mirrored per96 * context and per buffer. These can be fired at the card as a unit,···103#define VIA_BACK 0x2104#define VIA_DEPTH 0x4105#define VIA_STENCIL 0x8106+#define VIA_MEM_VIDEO 0 /* matches drm constant */107+#define VIA_MEM_AGP 1 /* matches drm constant */108+#define VIA_MEM_SYSTEM 2109+#define VIA_MEM_MIXED 3110+#define VIA_MEM_UNKNOWN 4111+112typedef struct {113 uint32_t offset;114 uint32_t size;···192 unsigned int XvMCSubPicOn[VIA_NR_XVMC_PORTS];193 unsigned int XvMCCtxNoGrabbed; /* Last context to hold decoder */194195+ /* Used by the 3d driver only at this point, for pageflipping:196+ */197+ unsigned int pfCurrentOffset;198} drm_via_sarea_t;199200typedef struct _drm_via_cmdbuf_size {···212213#define VIA_IRQ_FLAGS_MASK 0xF0000000214215+enum drm_via_irqs {216+ drm_via_irq_hqv0 = 0,217+ drm_via_irq_hqv1,218+ drm_via_irq_dma0_dd,219+ drm_via_irq_dma0_td,220+ drm_via_irq_dma1_dd,221+ drm_via_irq_dma1_td,222+ drm_via_irq_num223+};224+225struct drm_via_wait_irq_request {226 unsigned irq;227 via_irq_seq_type_t type;···224 struct drm_wait_vblank_reply reply;225} drm_via_irqwait_t;226227+typedef struct drm_via_blitsync {228+ uint32_t sync_handle;229+ unsigned engine;230+} drm_via_blitsync_t;231232+typedef struct drm_via_dmablit {233+ uint32_t num_lines;234+ uint32_t line_length;235+236+ uint32_t fb_addr;237+ uint32_t fb_stride;000000238239+ unsigned char *mem_addr;240+ uint32_t mem_stride;241+242+ int bounce_buffer;243+ int to_fb;244+245+ drm_via_blitsync_t sync;246+} drm_via_dmablit_t;247+248#endif /* _VIA_DRM_H_ */
···24#ifndef _VIA_DRV_H_25#define _VIA_DRV_H_2627-#define DRIVER_AUTHOR "VIA"2829#define DRIVER_NAME "via"30#define DRIVER_DESC "VIA Unichrome / Pro"31-#define DRIVER_DATE "20050523"3233#define DRIVER_MAJOR 234-#define DRIVER_MINOR 635-#define DRIVER_PATCHLEVEL 33637#include "via_verifier.h"380039#define VIA_PCI_BUF_SIZE 6000040#define VIA_FIRE_BUF_SIZE 102441-#define VIA_NUM_IRQS 24243typedef struct drm_via_ring_buffer {44- drm_map_t map;45 char *virtual_start;46} drm_via_ring_buffer_t;47···5859typedef struct drm_via_private {60 drm_via_sarea_t *sarea_priv;61- drm_map_t *sarea;62- drm_map_t *fb;63- drm_map_t *mmio;64 unsigned long agpAddr;65 wait_queue_head_t decoder_queue[VIA_NR_XVMC_LOCKS];66 char *dma_ptr;···84 maskarray_t *irq_masks;85 uint32_t irq_enable_mask;86 uint32_t irq_pending_mask;0087} drm_via_private_t;000008889/* VIA MMIO register access */90#define VIA_BASE ((dev_priv->mmio))···101#define VIA_READ8(reg) DRM_READ8(VIA_BASE, reg)102#define VIA_WRITE8(reg,val) DRM_WRITE8(VIA_BASE, reg, val)103000000000000000000000104extern int via_init_context(drm_device_t * dev, int context);105extern int via_final_context(drm_device_t * dev, int context);106107extern int via_do_cleanup_map(drm_device_t * dev);108-extern int via_map_init(struct inode *inode, struct file *filp,109- unsigned int cmd, unsigned long arg);110extern int via_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence);111112extern irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS);···139extern void via_init_futex(drm_via_private_t * dev_priv);140extern void via_cleanup_futex(drm_via_private_t * dev_priv);141extern void via_release_futex(drm_via_private_t * dev_priv, int context);00142143-extern int via_parse_command_stream(drm_device_t * dev, const uint32_t * buf,144- unsigned int size);145146#endif
···24#ifndef _VIA_DRV_H_25#define _VIA_DRV_H_2627+#define DRIVER_AUTHOR "Various"2829#define DRIVER_NAME "via"30#define DRIVER_DESC "VIA Unichrome / Pro"31+#define DRIVER_DATE "20051116"3233#define DRIVER_MAJOR 234+#define DRIVER_MINOR 735+#define DRIVER_PATCHLEVEL 43637#include "via_verifier.h"3839+#include "via_dmablit.h"40+41#define VIA_PCI_BUF_SIZE 6000042#define VIA_FIRE_BUF_SIZE 102443+#define VIA_NUM_IRQS 44445typedef struct drm_via_ring_buffer {46+ drm_local_map_t map;47 char *virtual_start;48} drm_via_ring_buffer_t;49···5657typedef struct drm_via_private {58 drm_via_sarea_t *sarea_priv;59+ drm_local_map_t *sarea;60+ drm_local_map_t *fb;61+ drm_local_map_t *mmio;62 unsigned long agpAddr;63 wait_queue_head_t decoder_queue[VIA_NR_XVMC_LOCKS];64 char *dma_ptr;···82 maskarray_t *irq_masks;83 uint32_t irq_enable_mask;84 uint32_t irq_pending_mask;85+ int *irq_map;86+ drm_via_blitq_t blit_queues[VIA_NUM_BLIT_ENGINES];87} drm_via_private_t;88+89+enum via_family {90+ VIA_OTHER = 0,91+ VIA_PRO_GROUP_A,92+};9394/* VIA MMIO register access */95#define VIA_BASE ((dev_priv->mmio))···92#define VIA_READ8(reg) DRM_READ8(VIA_BASE, reg)93#define VIA_WRITE8(reg,val) DRM_WRITE8(VIA_BASE, reg, val)9495+extern drm_ioctl_desc_t via_ioctls[];96+extern int via_max_ioctl;97+98+extern int via_fb_init(DRM_IOCTL_ARGS);99+extern int via_mem_alloc(DRM_IOCTL_ARGS);100+extern int via_mem_free(DRM_IOCTL_ARGS);101+extern int via_agp_init(DRM_IOCTL_ARGS);102+extern int via_map_init(DRM_IOCTL_ARGS);103+extern int via_decoder_futex(DRM_IOCTL_ARGS);104+extern int via_dma_init(DRM_IOCTL_ARGS);105+extern int via_cmdbuffer(DRM_IOCTL_ARGS);106+extern int via_flush_ioctl(DRM_IOCTL_ARGS);107+extern int via_pci_cmdbuffer(DRM_IOCTL_ARGS);108+extern int via_cmdbuf_size(DRM_IOCTL_ARGS);109+extern int via_wait_irq(DRM_IOCTL_ARGS);110+extern int via_dma_blit_sync( DRM_IOCTL_ARGS );111+extern int via_dma_blit( DRM_IOCTL_ARGS );112+113+extern int via_driver_load(drm_device_t *dev, unsigned long chipset);114+extern int via_driver_unload(drm_device_t *dev);115+116extern int via_init_context(drm_device_t * dev, int context);117extern int via_final_context(drm_device_t * dev, int context);118119extern int via_do_cleanup_map(drm_device_t * dev);00120extern int via_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence);121122extern irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS);···111extern void via_init_futex(drm_via_private_t * dev_priv);112extern void via_cleanup_futex(drm_via_private_t * dev_priv);113extern void via_release_futex(drm_via_private_t * dev_priv, int context);114+extern int via_driver_irq_wait(drm_device_t * dev, unsigned int irq,115+ int force_sequence, unsigned int *sequence);116117+extern void via_dmablit_handler(drm_device_t *dev, int engine, int from_irq);118+extern void via_init_dmablit(drm_device_t *dev);119120#endif
+1-8
drivers/char/drm/via_ds.c
···22 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER23 * DEALINGS IN THE SOFTWARE.24 */25-#include <linux/module.h>26-#include <linux/delay.h>27-#include <linux/errno.h>28-#include <linux/kernel.h>29-#include <linux/slab.h>30-#include <linux/poll.h>31-#include <linux/pci.h>32-#include <asm/io.h>3334#include "via_ds.h"35extern unsigned int VIA_DEBUG;
···22 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER23 * DEALINGS IN THE SOFTWARE.24 */25+#include "drmP.h"00000002627#include "via_ds.h"28extern unsigned int VIA_DEBUG;
+44-9
drivers/char/drm/via_irq.c
···50#define VIA_IRQ_HQV1_ENABLE (1 << 25)51#define VIA_IRQ_HQV0_PENDING (1 << 9)52#define VIA_IRQ_HQV1_PENDING (1 << 10)0000000005354/*55 * Device-specific IRQs go here. This type might need to be extended with···70 {VIA_IRQ_HQV0_ENABLE, VIA_IRQ_HQV0_PENDING, 0x000003D0, 0x00008010,71 0x00000000},72 {VIA_IRQ_HQV1_ENABLE, VIA_IRQ_HQV1_PENDING, 0x000013D0, 0x00008010,73- 0x00000000}000074};75static int via_num_pro_group_a =76 sizeof(via_pro_group_a_irqs) / sizeof(maskarray_t);07778-static maskarray_t via_unichrome_irqs[] = { };0000079static int via_num_unichrome = sizeof(via_unichrome_irqs) / sizeof(maskarray_t);08081static unsigned time_diff(struct timeval *now, struct timeval *then)82{···133 atomic_inc(&cur_irq->irq_received);134 DRM_WAKEUP(&cur_irq->irq_queue);135 handled = 1;00000136 }137 cur_irq++;138 }···190 return ret;191}192193-static int194via_driver_irq_wait(drm_device_t * dev, unsigned int irq, int force_sequence,195 unsigned int *sequence)196{···199 drm_via_irq_t *cur_irq = dev_priv->via_irqs;200 int ret = 0;201 maskarray_t *masks = dev_priv->irq_masks;0202203 DRM_DEBUG("%s\n", __FUNCTION__);204···208 return DRM_ERR(EINVAL);209 }210211- if (irq >= dev_priv->num_irqs) {212 DRM_ERROR("%s Trying to wait on unknown irq %d\n", __FUNCTION__,213 irq);214 return DRM_ERR(EINVAL);215 }216217- cur_irq += irq;218219- if (masks[irq][2] && !force_sequence) {00000000220 DRM_WAIT_ON(ret, cur_irq->irq_queue, 3 * DRM_HZ,221 ((VIA_READ(masks[irq][2]) & masks[irq][3]) ==222 masks[irq][4]));···260 via_pro_group_a_irqs : via_unichrome_irqs;261 dev_priv->num_irqs = (dev_priv->pro_group_a) ?262 via_num_pro_group_a : via_num_unichrome;00263264 for (i = 0; i < dev_priv->num_irqs; ++i) {265 atomic_set(&cur_irq->irq_received, 0);···277278 dev_priv->last_vblank_valid = 0;279280- // Clear VSync interrupt regs281 status = VIA_READ(VIA_REG_INTERRUPT);282 VIA_WRITE(VIA_REG_INTERRUPT, status &283 ~(dev_priv->irq_enable_mask));···327328int via_wait_irq(DRM_IOCTL_ARGS)329{330- drm_file_t *priv = filp->private_data;331- drm_device_t *dev = priv->head->dev;332 drm_via_irqwait_t __user *argp = (void __user *)data;333 drm_via_irqwait_t irqwait;334 struct timeval now;
···50#define VIA_IRQ_HQV1_ENABLE (1 << 25)51#define VIA_IRQ_HQV0_PENDING (1 << 9)52#define VIA_IRQ_HQV1_PENDING (1 << 10)53+#define VIA_IRQ_DMA0_DD_ENABLE (1 << 20)54+#define VIA_IRQ_DMA0_TD_ENABLE (1 << 21)55+#define VIA_IRQ_DMA1_DD_ENABLE (1 << 22)56+#define VIA_IRQ_DMA1_TD_ENABLE (1 << 23)57+#define VIA_IRQ_DMA0_DD_PENDING (1 << 4)58+#define VIA_IRQ_DMA0_TD_PENDING (1 << 5)59+#define VIA_IRQ_DMA1_DD_PENDING (1 << 6)60+#define VIA_IRQ_DMA1_TD_PENDING (1 << 7)61+6263/*64 * Device-specific IRQs go here. This type might need to be extended with···61 {VIA_IRQ_HQV0_ENABLE, VIA_IRQ_HQV0_PENDING, 0x000003D0, 0x00008010,62 0x00000000},63 {VIA_IRQ_HQV1_ENABLE, VIA_IRQ_HQV1_PENDING, 0x000013D0, 0x00008010,64+ 0x00000000},65+ {VIA_IRQ_DMA0_TD_ENABLE, VIA_IRQ_DMA0_TD_PENDING, VIA_PCI_DMA_CSR0,66+ VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008},67+ {VIA_IRQ_DMA1_TD_ENABLE, VIA_IRQ_DMA1_TD_PENDING, VIA_PCI_DMA_CSR1,68+ VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008},69};70static int via_num_pro_group_a =71 sizeof(via_pro_group_a_irqs) / sizeof(maskarray_t);72+static int via_irqmap_pro_group_a[] = {0, 1, -1, 2, -1, 3};7374+static maskarray_t via_unichrome_irqs[] = {75+ {VIA_IRQ_DMA0_TD_ENABLE, VIA_IRQ_DMA0_TD_PENDING, VIA_PCI_DMA_CSR0,76+ VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008},77+ {VIA_IRQ_DMA1_TD_ENABLE, VIA_IRQ_DMA1_TD_PENDING, VIA_PCI_DMA_CSR1,78+ VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008}79+};80static int via_num_unichrome = sizeof(via_unichrome_irqs) / sizeof(maskarray_t);81+static int via_irqmap_unichrome[] = {-1, -1, -1, 0, -1, 1};8283static unsigned time_diff(struct timeval *now, struct timeval *then)84{···113 atomic_inc(&cur_irq->irq_received);114 DRM_WAKEUP(&cur_irq->irq_queue);115 handled = 1;116+ if (dev_priv->irq_map[drm_via_irq_dma0_td] == i) {117+ via_dmablit_handler(dev, 0, 1);118+ } else if (dev_priv->irq_map[drm_via_irq_dma1_td] == i) {119+ via_dmablit_handler(dev, 1, 1);120+ }121 }122 cur_irq++;123 }···165 return ret;166}167168+int169via_driver_irq_wait(drm_device_t * dev, unsigned int irq, int force_sequence,170 unsigned int *sequence)171{···174 drm_via_irq_t *cur_irq = dev_priv->via_irqs;175 int ret = 0;176 maskarray_t *masks = dev_priv->irq_masks;177+ int real_irq;178179 DRM_DEBUG("%s\n", __FUNCTION__);180···182 return DRM_ERR(EINVAL);183 }184185+ if (irq >= drm_via_irq_num) {186 DRM_ERROR("%s Trying to wait on unknown irq %d\n", __FUNCTION__,187 irq);188 return DRM_ERR(EINVAL);189 }190191+ real_irq = dev_priv->irq_map[irq];192193+ if (real_irq < 0) {194+ DRM_ERROR("%s Video IRQ %d not available on this hardware.\n",195+ __FUNCTION__, irq);196+ return DRM_ERR(EINVAL);197+ }198+199+ cur_irq += real_irq;200+201+ if (masks[real_irq][2] && !force_sequence) {202 DRM_WAIT_ON(ret, cur_irq->irq_queue, 3 * DRM_HZ,203 ((VIA_READ(masks[irq][2]) & masks[irq][3]) ==204 masks[irq][4]));···226 via_pro_group_a_irqs : via_unichrome_irqs;227 dev_priv->num_irqs = (dev_priv->pro_group_a) ?228 via_num_pro_group_a : via_num_unichrome;229+ dev_priv->irq_map = (dev_priv->pro_group_a) ?230+ via_irqmap_pro_group_a : via_irqmap_unichrome;231232 for (i = 0; i < dev_priv->num_irqs; ++i) {233 atomic_set(&cur_irq->irq_received, 0);···241242 dev_priv->last_vblank_valid = 0;243244+ /* Clear VSync interrupt regs */245 status = VIA_READ(VIA_REG_INTERRUPT);246 VIA_WRITE(VIA_REG_INTERRUPT, status &247 ~(dev_priv->irq_enable_mask));···291292int via_wait_irq(DRM_IOCTL_ARGS)293{294+ DRM_DEVICE;0295 drm_via_irqwait_t __user *argp = (void __user *)data;296 drm_via_irqwait_t irqwait;297 struct timeval now;
···47 int agp_texture;48 int multitex;49 drm_device_t *dev;50- drm_map_t *map_cache;51 uint32_t vertex_count;52 int agp;53 const uint32_t *buf_start;···5556extern int via_verify_command_stream(const uint32_t * buf, unsigned int size,57 drm_device_t * dev, int agp);005859#endif
···47 int agp_texture;48 int multitex;49 drm_device_t *dev;50+ drm_local_map_t *map_cache;51 uint32_t vertex_count;52 int agp;53 const uint32_t *buf_start;···5556extern int via_verify_command_stream(const uint32_t * buf, unsigned int size,57 drm_device_t * dev, int agp);58+extern int via_parse_command_stream(drm_device_t *dev, const uint32_t *buf,59+ unsigned int size);6061#endif
+5-2
drivers/char/drm/via_video.c
···50 unsigned int i;51 volatile int *lock;5200053 for (i = 0; i < VIA_NR_XVMC_LOCKS; ++i) {54- lock = (int *)XVMCLOCKPTR(dev_priv->sarea_priv, i);55 if ((_DRM_LOCKING_CONTEXT(*lock) == context)) {56 if (_DRM_LOCK_IS_HELD(*lock)57 && (*lock & _DRM_LOCK_CONT)) {···82 if (fx.lock > VIA_NR_XVMC_LOCKS)83 return -EFAULT;8485- lock = (int *)XVMCLOCKPTR(sAPriv, fx.lock);8687 switch (fx.func) {88 case VIA_FUTEX_WAIT:
···50 unsigned int i;51 volatile int *lock;5253+ if (!dev_priv->sarea_priv)54+ return;55+56 for (i = 0; i < VIA_NR_XVMC_LOCKS; ++i) {57+ lock = (volatile int *)XVMCLOCKPTR(dev_priv->sarea_priv, i);58 if ((_DRM_LOCKING_CONTEXT(*lock) == context)) {59 if (_DRM_LOCK_IS_HELD(*lock)60 && (*lock & _DRM_LOCK_CONT)) {···79 if (fx.lock > VIA_NR_XVMC_LOCKS)80 return -EFAULT;8182+ lock = (volatile int *)XVMCLOCKPTR(sAPriv, fx.lock);8384 switch (fx.func) {85 case VIA_FUTEX_WAIT: