···9090#define DRM_MAX_ORDER 22 /**< Up to 2^22 bytes = 4MB */9191#define DRM_RAM_PERCENT 10 /**< How much system ram can we lock? */92929393-#define _DRM_LOCK_HELD 0x80000000 /**< Hardware lock is held */9494-#define _DRM_LOCK_CONT 0x40000000 /**< Hardware lock is contended */9393+#define _DRM_LOCK_HELD 0x80000000U /**< Hardware lock is held */9494+#define _DRM_LOCK_CONT 0x40000000U /**< Hardware lock is contended */9595#define _DRM_LOCK_IS_HELD(lock) ((lock) & _DRM_LOCK_HELD)9696#define _DRM_LOCK_IS_CONT(lock) ((lock) & _DRM_LOCK_CONT)9797#define _DRM_LOCKING_CONTEXT(lock) ((lock) & ~(_DRM_LOCK_HELD|_DRM_LOCK_CONT))
+72-50
drivers/char/drm/drmP.h
···144144/** \name Backward compatibility section */145145/*@{*/146146147147-#ifndef MODULE_LICENSE148148-#define MODULE_LICENSE(x)149149-#endif150150-151151-#ifndef preempt_disable152152-#define preempt_disable()153153-#define preempt_enable()154154-#endif155155-156156-#ifndef pte_offset_map157157-#define pte_offset_map pte_offset158158-#define pte_unmap(pte)159159-#endif160160-161147#define DRM_RPR_ARG(vma) vma,162148163149#define VM_OFFSET(vma) ((vma)->vm_pgoff << PAGE_SHIFT)···272286typedef int drm_ioctl_compat_t(struct file *filp, unsigned int cmd,273287 unsigned long arg);274288289289+#define DRM_AUTH 0x1290290+#define DRM_MASTER 0x2291291+#define DRM_ROOT_ONLY 0x4292292+275293typedef struct drm_ioctl_desc {276294 drm_ioctl_t *func;277277- int auth_needed;278278- int root_only;295295+ int flags;279296} drm_ioctl_desc_t;280297281298typedef struct drm_devstate {···373384/** File private data */374385typedef struct drm_file {375386 int authenticated;387387+ int master;376388 int minor;377389 pid_t pid;378390 uid_t uid;···522532typedef struct ati_pcigart_info {523533 int gart_table_location;524534 int is_pcie;525525- unsigned long addr;535535+ void *addr;526536 dma_addr_t bus_addr;537537+ drm_local_map_t mapping;527538} drm_ati_pcigart_info;528539529540/**···535544struct drm_device;536545537546struct drm_driver {538538- int (*preinit) (struct drm_device *, unsigned long flags);539539- void (*prerelease) (struct drm_device *, struct file * filp);540540- void (*pretakedown) (struct drm_device *);541541- int (*postcleanup) (struct drm_device *);542542- int (*presetup) (struct drm_device *);543543- int (*postsetup) (struct drm_device *);547547+ int (*load) (struct drm_device *, unsigned long flags);548548+ int (*firstopen) (struct drm_device *);549549+ int (*open) (struct drm_device *, drm_file_t *);550550+ void (*preclose) (struct drm_device *, struct file * filp);551551+ void (*postclose) (struct drm_device *, drm_file_t *);552552+ void (*lastclose) (struct drm_device *);553553+ int (*unload) (struct drm_device *);544554 int (*dma_ioctl) (DRM_IOCTL_ARGS);545545- int (*open_helper) (struct drm_device *, drm_file_t *);546546- void (*free_filp_priv) (struct drm_device *, drm_file_t *);547547- void (*release) (struct drm_device *, struct file * filp);548555 void (*dma_ready) (struct drm_device *);549556 int (*dma_quiescent) (struct drm_device *);550557 int (*context_ctor) (struct drm_device * dev, int context);···550561 int (*kernel_context_switch) (struct drm_device * dev, int old,551562 int new);552563 void (*kernel_context_switch_unlock) (struct drm_device * dev,553553- drm_lock_t * lock);564564+ drm_lock_t *lock);554565 int (*vblank_wait) (struct drm_device * dev, unsigned int *sequence);566566+ int (*dri_library_name) (struct drm_device *dev, char *buf);555567556568 /**557569 * Called by \c drm_device_is_agp. Typically used to determine if a···569579570580 /* these have to be filled in */571581572572- int (*postinit) (struct drm_device *, unsigned long flags);573573- irqreturn_t(*irq_handler) (DRM_IRQ_ARGS);582582+ irqreturn_t(*irq_handler) (DRM_IRQ_ARGS);574583 void (*irq_preinstall) (struct drm_device * dev);575584 void (*irq_postinstall) (struct drm_device * dev);576585 void (*irq_uninstall) (struct drm_device * dev);577586 void (*reclaim_buffers) (struct drm_device * dev, struct file * filp);587587+ void (*reclaim_buffers_locked) (struct drm_device *dev,588588+ struct file *filp);578589 unsigned long (*get_map_ofs) (drm_map_t * map);579590 unsigned long (*get_reg_ofs) (struct drm_device * dev);580591 void (*set_version) (struct drm_device * dev, drm_set_version_t * sv);581581- int (*version) (drm_version_t * version);592592+593593+ int major;594594+ int minor;595595+ int patchlevel;596596+ char *name;597597+ char *desc;598598+ char *date;599599+582600 u32 driver_features;583601 int dev_priv_size;584602 drm_ioctl_desc_t *ioctls;···750752{751753 return drm_core_check_feature(dev, DRIVER_USE_MTRR);752754}755755+756756+#define DRM_MTRR_WC MTRR_TYPE_WRCOMB757757+758758+static inline int drm_mtrr_add(unsigned long offset, unsigned long size,759759+ unsigned int flags)760760+{761761+ return mtrr_add(offset, size, flags, 1);762762+}763763+764764+static inline int drm_mtrr_del(int handle, unsigned long offset,765765+ unsigned long size, unsigned int flags)766766+{767767+ return mtrr_del(handle, offset, size);768768+}769769+753770#else754771#define drm_core_has_MTRR(dev) (0)772772+773773+#define DRM_MTRR_WC 0774774+775775+static inline int drm_mtrr_add(unsigned long offset, unsigned long size,776776+ unsigned int flags)777777+{778778+ return 0;779779+}780780+781781+static inline int drm_mtrr_del(int handle, unsigned long offset,782782+ unsigned long size, unsigned int flags)783783+{784784+ return 0;785785+}755786#endif756787757788/******************************************************************/758789/** \name Internal function definitions */759790/*@{*/760760-761761- /* Misc. support (drm_init.h) */762762-extern int drm_flags;763763-extern void drm_parse_options(char *s);764764-extern int drm_cpu_valid(void);765791766792 /* Driver support (drm_drv.h) */767793extern int drm_init(struct drm_driver *driver);···794772 unsigned int cmd, unsigned long arg);795773extern long drm_compat_ioctl(struct file *filp,796774 unsigned int cmd, unsigned long arg);797797-extern int drm_takedown(drm_device_t * dev);775775+extern int drm_lastclose(drm_device_t *dev);798776799777 /* Device support (drm_fops.h) */800778extern int drm_open(struct inode *inode, struct file *filp);801779extern int drm_stub_open(struct inode *inode, struct file *filp);802802-extern int drm_flush(struct file *filp);803780extern int drm_fasync(int fd, struct file *filp, int on);804781extern int drm_release(struct inode *inode, struct file *filp);805782···840819 unsigned int cmd, unsigned long arg);841820extern int drm_setversion(struct inode *inode, struct file *filp,842821 unsigned int cmd, unsigned long arg);822822+extern int drm_noop(struct inode *inode, struct file *filp,823823+ unsigned int cmd, unsigned long arg);843824844825 /* Context IOCTL support (drm_context.h) */845826extern int drm_resctx(struct inode *inode, struct file *filp,···880857extern int drm_authmagic(struct inode *inode, struct file *filp,881858 unsigned int cmd, unsigned long arg);882859883883- /* Placeholder for ioctls past */884884-extern int drm_noop(struct inode *inode, struct file *filp,885885- unsigned int cmd, unsigned long arg);886886-887860 /* Locking IOCTL support (drm_lock.h) */888861extern int drm_lock(struct inode *inode, struct file *filp,889862 unsigned int cmd, unsigned long arg);···892873 /* Buffer management support (drm_bufs.h) */893874extern int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request);894875extern int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request);876876+extern int drm_addbufs_fb(drm_device_t *dev, drm_buf_desc_t *request);895877extern int drm_addmap(drm_device_t * dev, unsigned int offset,896878 unsigned int size, drm_map_type_t type,897879 drm_map_flags_t flags, drm_local_map_t ** map_ptr);···928908 /* IRQ support (drm_irq.h) */929909extern int drm_control(struct inode *inode, struct file *filp,930910 unsigned int cmd, unsigned long arg);931931-extern int drm_irq_uninstall(drm_device_t * dev);932911extern irqreturn_t drm_irq_handler(DRM_IRQ_ARGS);912912+extern int drm_irq_uninstall(drm_device_t * dev);933913extern void drm_driver_irq_preinstall(drm_device_t * dev);934914extern void drm_driver_irq_postinstall(drm_device_t * dev);935915extern void drm_driver_irq_uninstall(drm_device_t * dev);···953933extern int drm_agp_info(drm_device_t * dev, drm_agp_info_t * info);954934extern int drm_agp_info_ioctl(struct inode *inode, struct file *filp,955935 unsigned int cmd, unsigned long arg);956956-extern int drm_agp_alloc(struct inode *inode, struct file *filp,936936+extern int drm_agp_alloc(drm_device_t *dev, drm_agp_buffer_t *request);937937+extern int drm_agp_alloc_ioctl(struct inode *inode, struct file *filp,957938 unsigned int cmd, unsigned long arg);958958-extern int drm_agp_free(struct inode *inode, struct file *filp,939939+extern int drm_agp_free(drm_device_t *dev, drm_agp_buffer_t *request);940940+extern int drm_agp_free_ioctl(struct inode *inode, struct file *filp,959941 unsigned int cmd, unsigned long arg);960960-extern int drm_agp_unbind(struct inode *inode, struct file *filp,942942+extern int drm_agp_unbind(drm_device_t *dev, drm_agp_binding_t *request);943943+extern int drm_agp_unbind_ioctl(struct inode *inode, struct file *filp,961944 unsigned int cmd, unsigned long arg);962962-extern int drm_agp_bind(struct inode *inode, struct file *filp,945945+extern int drm_agp_bind(drm_device_t *dev, drm_agp_binding_t *request);946946+extern int drm_agp_bind_ioctl(struct inode *inode, struct file *filp,963947 unsigned int cmd, unsigned long arg);964948extern DRM_AGP_MEM *drm_agp_allocate_memory(struct agp_bridge_data *bridge,965949 size_t pages, u32 type);···1015991 char *name);1016992extern void drm_sysfs_destroy(struct drm_sysfs_class *cs);1017993extern struct class_device *drm_sysfs_device_add(struct drm_sysfs_class *cs,10181018- dev_t dev,10191019- struct device *device,10201020- const char *fmt, ...);10211021-extern void drm_sysfs_device_remove(dev_t dev);994994+ drm_head_t *head);995995+extern void drm_sysfs_device_remove(struct class_device *class_dev);10229961023997/* Inline replacements for DRM_IOREMAP macros */1024998static __inline__ void drm_core_ioremap(struct drm_map *map,
+87-46
drivers/char/drm/drm_agpsupport.c
···11/**22- * \file drm_agpsupport.h22+ * \file drm_agpsupport.c33 * DRM support for AGP/GART backend44 *55 * \author Rickard E. (Rik) Faith <faith@valinux.com>···9191/**9292 * Acquire the AGP device.9393 *9494- * \param dev DRM device that is to acquire AGP9494+ * \param dev DRM device that is to acquire AGP.9595 * \return zero on success or a negative number on failure.9696 *9797 * Verifies the AGP device hasn't been acquired before and calls···134134/**135135 * Release the AGP device.136136 *137137- * \param dev DRM device that is to release AGP137137+ * \param dev DRM device that is to release AGP.138138 * \return zero on success or a negative number on failure.139139 *140140 * Verifies the AGP device has been acquired and calls \c agp_backend_release.···147147 dev->agp->acquired = 0;148148 return 0;149149}150150-151150EXPORT_SYMBOL(drm_agp_release);152151153152int drm_agp_release_ioctl(struct inode *inode, struct file *filp,···207208 * Verifies the AGP device is present and has been acquired, allocates the208209 * memory via alloc_agp() and creates a drm_agp_mem entry for it.209210 */210210-int drm_agp_alloc(struct inode *inode, struct file *filp,211211- unsigned int cmd, unsigned long arg)211211+int drm_agp_alloc(drm_device_t *dev, drm_agp_buffer_t *request)212212{213213- drm_file_t *priv = filp->private_data;214214- drm_device_t *dev = priv->head->dev;215215- drm_agp_buffer_t request;216213 drm_agp_mem_t *entry;217214 DRM_AGP_MEM *memory;218215 unsigned long pages;219216 u32 type;220220- drm_agp_buffer_t __user *argp = (void __user *)arg;221217222218 if (!dev->agp || !dev->agp->acquired)223219 return -EINVAL;224224- if (copy_from_user(&request, argp, sizeof(request)))225225- return -EFAULT;226220 if (!(entry = drm_alloc(sizeof(*entry), DRM_MEM_AGPLISTS)))227221 return -ENOMEM;228222229223 memset(entry, 0, sizeof(*entry));230224231231- pages = (request.size + PAGE_SIZE - 1) / PAGE_SIZE;232232- type = (u32) request.type;233233-225225+ pages = (request->size + PAGE_SIZE - 1) / PAGE_SIZE;226226+ type = (u32) request->type;234227 if (!(memory = drm_alloc_agp(dev, pages, type))) {235228 drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);236229 return -ENOMEM;···238247 dev->agp->memory->prev = entry;239248 dev->agp->memory = entry;240249241241- request.handle = entry->handle;242242- request.physical = memory->physical;250250+ request->handle = entry->handle;251251+ request->physical = memory->physical;252252+253253+ return 0;254254+}255255+EXPORT_SYMBOL(drm_agp_alloc);256256+257257+int drm_agp_alloc_ioctl(struct inode *inode, struct file *filp,258258+ unsigned int cmd, unsigned long arg)259259+{260260+ drm_file_t *priv = filp->private_data;261261+ drm_device_t *dev = priv->head->dev;262262+ drm_agp_buffer_t request;263263+ drm_agp_buffer_t __user *argp = (void __user *)arg;264264+ int err;265265+266266+ if (copy_from_user(&request, argp, sizeof(request)))267267+ return -EFAULT;268268+269269+ err = drm_agp_alloc(dev, &request);270270+ if (err)271271+ return err;243272244273 if (copy_to_user(argp, &request, sizeof(request))) {274274+ drm_agp_mem_t *entry = dev->agp->memory;275275+245276 dev->agp->memory = entry->next;246277 dev->agp->memory->prev = NULL;247247- drm_free_agp(memory, pages);278278+ drm_free_agp(entry->memory, entry->pages);248279 drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);249280 return -EFAULT;250281 }282282+251283 return 0;252284}253285···307293 * Verifies the AGP device is present and acquired, looks-up the AGP memory308294 * entry and passes it to the unbind_agp() function.309295 */310310-int drm_agp_unbind(struct inode *inode, struct file *filp,311311- unsigned int cmd, unsigned long arg)296296+int drm_agp_unbind(drm_device_t *dev, drm_agp_binding_t *request)312297{313313- drm_file_t *priv = filp->private_data;314314- drm_device_t *dev = priv->head->dev;315315- drm_agp_binding_t request;316298 drm_agp_mem_t *entry;317299 int ret;318300319301 if (!dev->agp || !dev->agp->acquired)320302 return -EINVAL;321321- if (copy_from_user322322- (&request, (drm_agp_binding_t __user *) arg, sizeof(request)))323323- return -EFAULT;324324- if (!(entry = drm_agp_lookup_entry(dev, request.handle)))303303+ if (!(entry = drm_agp_lookup_entry(dev, request->handle)))325304 return -EINVAL;326305 if (!entry->bound)327306 return -EINVAL;···322315 if (ret == 0)323316 entry->bound = 0;324317 return ret;318318+}319319+EXPORT_SYMBOL(drm_agp_unbind);320320+321321+int drm_agp_unbind_ioctl(struct inode *inode, struct file *filp,322322+ unsigned int cmd, unsigned long arg)323323+{324324+ drm_file_t *priv = filp->private_data;325325+ drm_device_t *dev = priv->head->dev;326326+ drm_agp_binding_t request;327327+328328+ if (copy_from_user329329+ (&request, (drm_agp_binding_t __user *) arg, sizeof(request)))330330+ return -EFAULT;331331+332332+ return drm_agp_unbind(dev, &request);325333}326334327335/**···352330 * is currently bound into the GATT. Looks-up the AGP memory entry and passes353331 * it to bind_agp() function.354332 */355355-int drm_agp_bind(struct inode *inode, struct file *filp,356356- unsigned int cmd, unsigned long arg)333333+int drm_agp_bind(drm_device_t *dev, drm_agp_binding_t *request)357334{358358- drm_file_t *priv = filp->private_data;359359- drm_device_t *dev = priv->head->dev;360360- drm_agp_binding_t request;361335 drm_agp_mem_t *entry;362336 int retcode;363337 int page;364338365339 if (!dev->agp || !dev->agp->acquired)366340 return -EINVAL;367367- if (copy_from_user368368- (&request, (drm_agp_binding_t __user *) arg, sizeof(request)))369369- return -EFAULT;370370- if (!(entry = drm_agp_lookup_entry(dev, request.handle)))341341+ if (!(entry = drm_agp_lookup_entry(dev, request->handle)))371342 return -EINVAL;372343 if (entry->bound)373344 return -EINVAL;374374- page = (request.offset + PAGE_SIZE - 1) / PAGE_SIZE;345345+ page = (request->offset + PAGE_SIZE - 1) / PAGE_SIZE;375346 if ((retcode = drm_bind_agp(entry->memory, page)))376347 return retcode;377348 entry->bound = dev->agp->base + (page << PAGE_SHIFT);378349 DRM_DEBUG("base = 0x%lx entry->bound = 0x%lx\n",379350 dev->agp->base, entry->bound);380351 return 0;352352+}353353+EXPORT_SYMBOL(drm_agp_bind);354354+355355+int drm_agp_bind_ioctl(struct inode *inode, struct file *filp,356356+ unsigned int cmd, unsigned long arg)357357+{358358+ drm_file_t *priv = filp->private_data;359359+ drm_device_t *dev = priv->head->dev;360360+ drm_agp_binding_t request;361361+362362+ if (copy_from_user363363+ (&request, (drm_agp_binding_t __user *) arg, sizeof(request)))364364+ return -EFAULT;365365+366366+ return drm_agp_bind(dev, &request);381367}382368383369/**···402372 * unbind_agp(). Frees it via free_agp() as well as the entry itself403373 * and unlinks from the doubly linked list it's inserted in.404374 */405405-int drm_agp_free(struct inode *inode, struct file *filp,406406- unsigned int cmd, unsigned long arg)375375+int drm_agp_free(drm_device_t *dev, drm_agp_buffer_t *request)407376{408408- drm_file_t *priv = filp->private_data;409409- drm_device_t *dev = priv->head->dev;410410- drm_agp_buffer_t request;411377 drm_agp_mem_t *entry;412378413379 if (!dev->agp || !dev->agp->acquired)414380 return -EINVAL;415415- if (copy_from_user416416- (&request, (drm_agp_buffer_t __user *) arg, sizeof(request)))417417- return -EFAULT;418418- if (!(entry = drm_agp_lookup_entry(dev, request.handle)))381381+ if (!(entry = drm_agp_lookup_entry(dev, request->handle)))419382 return -EINVAL;420383 if (entry->bound)421384 drm_unbind_agp(entry->memory);···425402 drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);426403 return 0;427404}405405+EXPORT_SYMBOL(drm_agp_free);406406+407407+int drm_agp_free_ioctl(struct inode *inode, struct file *filp,408408+ unsigned int cmd, unsigned long arg)409409+{410410+ drm_file_t *priv = filp->private_data;411411+ drm_device_t *dev = priv->head->dev;412412+ drm_agp_buffer_t request;413413+414414+ if (copy_from_user415415+ (&request, (drm_agp_buffer_t __user *) arg, sizeof(request)))416416+ return -EFAULT;417417+418418+ return drm_agp_free(dev, &request);419419+}428420429421/**430422 * Initialize the AGP resources.431423 *432424 * \return pointer to a drm_agp_head structure.433425 *426426+ * Gets the drm_agp_t structure which is made available by the agpgart module427427+ * via the inter_module_* functions. Creates and initializes a drm_agp_head428428+ * structure.434429 */435430drm_agp_head_t *drm_agp_init(drm_device_t * dev)436431{
+33-16
drivers/char/drm/drm_bufs.c
···3636#include <linux/vmalloc.h>3737#include "drmP.h"38383939-unsigned long drm_get_resource_start(drm_device_t * dev, unsigned int resource)3939+unsigned long drm_get_resource_start(drm_device_t *dev, unsigned int resource)4040{4141 return pci_resource_start(dev->pdev, resource);4242}4343-4443EXPORT_SYMBOL(drm_get_resource_start);45444646-unsigned long drm_get_resource_len(drm_device_t * dev, unsigned int resource)4545+unsigned long drm_get_resource_len(drm_device_t *dev, unsigned int resource)4746{4847 return pci_resource_len(dev->pdev, resource);4948}50495150EXPORT_SYMBOL(drm_get_resource_len);52515353-static drm_map_list_t *drm_find_matching_map(drm_device_t * dev,5454- drm_local_map_t * map)5252+static drm_map_list_t *drm_find_matching_map(drm_device_t *dev,5353+ drm_local_map_t *map)5554{5655 struct list_head *list;5756···73747475#ifdef _LP647576static __inline__ unsigned int HandleID(unsigned long lhandle,7676- drm_device_t * dev)7777+ drm_device_t *dev)7778{7879 static unsigned int map32_handle = START_RANGE;7980 unsigned int hash;···154155 case _DRM_REGISTERS:155156 case _DRM_FRAME_BUFFER:156157#if !defined(__sparc__) && !defined(__alpha__) && !defined(__ia64__) && !defined(__powerpc64__) && !defined(__x86_64__)157157- if (map->offset + map->size < map->offset ||158158+ if (map->offset + (map->size-1) < map->offset ||158159 map->offset < virt_to_phys(high_memory)) {159160 drm_free(map, sizeof(*map), DRM_MEM_MAPS);160161 return -EINVAL;···300301 return -EFAULT;301302 }302303304304+ if (!(capable(CAP_SYS_ADMIN) || map.type == _DRM_AGP))305305+ return -EPERM;306306+303307 err = drm_addmap_core(dev, map.offset, map.size, map.type, map.flags,304308 &maplist);305309···334332 *335333 * \sa drm_addmap336334 */337337-int drm_rmmap_locked(drm_device_t * dev, drm_local_map_t * map)335335+int drm_rmmap_locked(drm_device_t *dev, drm_local_map_t *map)338336{339337 struct list_head *list;340338 drm_map_list_t *r_list = NULL;···386384387385 return 0;388386}389389-390387EXPORT_SYMBOL(drm_rmmap_locked);391388392392-int drm_rmmap(drm_device_t * dev, drm_local_map_t * map)389389+int drm_rmmap(drm_device_t *dev, drm_local_map_t *map)393390{394391 int ret;395392···398397399398 return ret;400399}401401-402400EXPORT_SYMBOL(drm_rmmap);403401404402/* The rmmap ioctl appears to be unnecessary. All mappings are torn down on···548548 DRM_DEBUG("count: %d\n", count);549549 DRM_DEBUG("order: %d\n", order);550550 DRM_DEBUG("size: %d\n", size);551551- DRM_DEBUG("agp_offset: %lu\n", agp_offset);551551+ DRM_DEBUG("agp_offset: %lx\n", agp_offset);552552 DRM_DEBUG("alignment: %d\n", alignment);553553 DRM_DEBUG("page_order: %d\n", page_order);554554 DRM_DEBUG("total: %d\n", total);···649649 }650650651651 dma->buf_count += entry->buf_count;652652+ dma->seg_count += entry->seg_count;653653+ dma->page_count += byte_count >> PAGE_SHIFT;652654 dma->byte_count += byte_count;653655654656 DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count);···666664 atomic_dec(&dev->buf_alloc);667665 return 0;668666}669669-670667EXPORT_SYMBOL(drm_addbufs_agp);671668#endif /* __OS_HAS_AGP */672669···690689691690 if (!drm_core_check_feature(dev, DRIVER_PCI_DMA))692691 return -EINVAL;692692+693693 if (!dma)694694 return -EINVAL;695695+696696+ if (!capable(CAP_SYS_ADMIN))697697+ return -EPERM;695698696699 count = request->count;697700 order = drm_order(request->size);···887882 return 0;888883889884}890890-891885EXPORT_SYMBOL(drm_addbufs_pci);892886893887static int drm_addbufs_sg(drm_device_t * dev, drm_buf_desc_t * request)···911907912908 if (!dma)913909 return -EINVAL;910910+911911+ if (!capable(CAP_SYS_ADMIN))912912+ return -EPERM;914913915914 count = request->count;916915 order = drm_order(request->size);···10331026 }1034102710351028 dma->buf_count += entry->buf_count;10291029+ dma->seg_count += entry->seg_count;10301030+ dma->page_count += byte_count >> PAGE_SHIFT;10361031 dma->byte_count += byte_count;1037103210381033 DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count);···10511042 return 0;10521043}1053104410541054-static int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request)10451045+int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request)10551046{10561047 drm_device_dma_t *dma = dev->dma;10571048 drm_buf_entry_t *entry;···1073106410741065 if (!dma)10751066 return -EINVAL;10671067+10681068+ if (!capable(CAP_SYS_ADMIN))10691069+ return -EPERM;1076107010771071 count = request->count;10781072 order = drm_order(request->size);···11931181 }1194118211951183 dma->buf_count += entry->buf_count;11841184+ dma->seg_count += entry->seg_count;11851185+ dma->page_count += byte_count >> PAGE_SHIFT;11961186 dma->byte_count += byte_count;1197118711981188 DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count);···12101196 atomic_dec(&dev->buf_alloc);12111197 return 0;12121198}11991199+EXPORT_SYMBOL(drm_addbufs_fb);12001200+1213120112141202/**12151203 * Add buffers for DMA transfers (ioctl).···1593157715941578 return order;15951579}15961596-15971580EXPORT_SYMBOL(drm_order);15811581+15821582+
+1-1
drivers/char/drm/drm_context.c
···433433 if (ctx.handle != DRM_KERNEL_CONTEXT) {434434 if (dev->driver->context_ctor)435435 if (!dev->driver->context_ctor(dev, ctx.handle)) {436436- DRM_DEBUG( "Running out of ctxs or memory.\n");436436+ DRM_DEBUG("Running out of ctxs or memory.\n");437437 return -ENOMEM;438438 }439439 }
···3535 */36363737#include "drmP.h"3838+#include "drm_sarea.h"3839#include <linux/poll.h>39404041static int drm_open_helper(struct inode *inode, struct file *filp,···43424443static int drm_setup(drm_device_t * dev)4544{4545+ drm_local_map_t *map;4646 int i;4747 int ret;48484949- if (dev->driver->presetup) {5050- ret = dev->driver->presetup(dev);4949+ if (dev->driver->firstopen) {5050+ ret = dev->driver->firstopen(dev);5151 if (ret != 0)5252 return ret;5353 }5454+5555+ /* prebuild the SAREA */5656+ i = drm_addmap(dev, 0, SAREA_MAX, _DRM_SHM, _DRM_CONTAINS_LOCK, &map);5757+ if (i != 0)5858+ return i;54595560 atomic_set(&dev->ioctl_count, 0);5661 atomic_set(&dev->vma_count, 0);···116109 * drm_select_queue fails between the time the interrupt is117110 * initialized and the time the queues are initialized.118111 */119119- if (dev->driver->postsetup)120120- dev->driver->postsetup(dev);121112122113 return 0;123114}···159154160155 return retcode;161156}162162-163157EXPORT_SYMBOL(drm_open);158158+159159+/**160160+ * File \c open operation.161161+ *162162+ * \param inode device inode.163163+ * \param filp file pointer.164164+ *165165+ * Puts the dev->fops corresponding to the device minor number into166166+ * \p filp, call the \c open method, and restore the file operations.167167+ */168168+int drm_stub_open(struct inode *inode, struct file *filp)169169+{170170+ drm_device_t *dev = NULL;171171+ int minor = iminor(inode);172172+ int err = -ENODEV;173173+ struct file_operations *old_fops;174174+175175+ DRM_DEBUG("\n");176176+177177+ if (!((minor >= 0) && (minor < drm_cards_limit)))178178+ return -ENODEV;179179+180180+ if (!drm_heads[minor])181181+ return -ENODEV;182182+183183+ if (!(dev = drm_heads[minor]->dev))184184+ return -ENODEV;185185+186186+ old_fops = filp->f_op;187187+ filp->f_op = fops_get(&dev->driver->fops);188188+ if (filp->f_op->open && (err = filp->f_op->open(inode, filp))) {189189+ fops_put(filp->f_op);190190+ filp->f_op = fops_get(old_fops);191191+ }192192+ fops_put(old_fops);193193+194194+ return err;195195+}196196+197197+/**198198+ * Check whether DRI will run on this CPU.199199+ *200200+ * \return non-zero if the DRI will run on this CPU, or zero otherwise.201201+ */202202+static int drm_cpu_valid(void)203203+{204204+#if defined(__i386__)205205+ if (boot_cpu_data.x86 == 3)206206+ return 0; /* No cmpxchg on a 386 */207207+#endif208208+#if defined(__sparc__) && !defined(__sparc_v9__)209209+ return 0; /* No cmpxchg before v9 sparc. */210210+#endif211211+ return 1;212212+}213213+214214+/**215215+ * Called whenever a process opens /dev/drm.216216+ *217217+ * \param inode device inode.218218+ * \param filp file pointer.219219+ * \param dev device.220220+ * \return zero on success or a negative number on failure.221221+ *222222+ * Creates and initializes a drm_file structure for the file private data in \p223223+ * filp and add it into the double linked list in \p dev.224224+ */225225+static int drm_open_helper(struct inode *inode, struct file *filp,226226+ drm_device_t * dev)227227+{228228+ int minor = iminor(inode);229229+ drm_file_t *priv;230230+ int ret;231231+232232+ if (filp->f_flags & O_EXCL)233233+ return -EBUSY; /* No exclusive opens */234234+ if (!drm_cpu_valid())235235+ return -EINVAL;236236+237237+ DRM_DEBUG("pid = %d, minor = %d\n", current->pid, minor);238238+239239+ priv = drm_alloc(sizeof(*priv), DRM_MEM_FILES);240240+ if (!priv)241241+ return -ENOMEM;242242+243243+ memset(priv, 0, sizeof(*priv));244244+ filp->private_data = priv;245245+ priv->uid = current->euid;246246+ priv->pid = current->pid;247247+ priv->minor = minor;248248+ priv->head = drm_heads[minor];249249+ priv->ioctl_count = 0;250250+ /* for compatibility root is always authenticated */251251+ priv->authenticated = capable(CAP_SYS_ADMIN);252252+ priv->lock_count = 0;253253+254254+ if (dev->driver->open) {255255+ ret = dev->driver->open(dev, priv);256256+ if (ret < 0)257257+ goto out_free;258258+ }259259+260260+ down(&dev->struct_sem);261261+ if (!dev->file_last) {262262+ priv->next = NULL;263263+ priv->prev = NULL;264264+ dev->file_first = priv;265265+ dev->file_last = priv;266266+ /* first opener automatically becomes master */267267+ priv->master = 1;268268+ } else {269269+ priv->next = NULL;270270+ priv->prev = dev->file_last;271271+ dev->file_last->next = priv;272272+ dev->file_last = priv;273273+ }274274+ up(&dev->struct_sem);275275+276276+#ifdef __alpha__277277+ /*278278+ * Default the hose279279+ */280280+ if (!dev->hose) {281281+ struct pci_dev *pci_dev;282282+ pci_dev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, NULL);283283+ if (pci_dev) {284284+ dev->hose = pci_dev->sysdata;285285+ pci_dev_put(pci_dev);286286+ }287287+ if (!dev->hose) {288288+ struct pci_bus *b = pci_bus_b(pci_root_buses.next);289289+ if (b)290290+ dev->hose = b->sysdata;291291+ }292292+ }293293+#endif294294+295295+ return 0;296296+ out_free:297297+ drm_free(priv, sizeof(*priv), DRM_MEM_FILES);298298+ filp->private_data = NULL;299299+ return ret;300300+}301301+302302+/** No-op. */303303+int drm_fasync(int fd, struct file *filp, int on)304304+{305305+ drm_file_t *priv = filp->private_data;306306+ drm_device_t *dev = priv->head->dev;307307+ int retcode;308308+309309+ DRM_DEBUG("fd = %d, device = 0x%lx\n", fd,310310+ (long)old_encode_dev(priv->head->device));311311+ retcode = fasync_helper(fd, filp, on, &dev->buf_async);312312+ if (retcode < 0)313313+ return retcode;314314+ return 0;315315+}316316+EXPORT_SYMBOL(drm_fasync);164317165318/**166319 * Release file.···330167 * If the hardware lock is held then free it, and take it again for the kernel331168 * context since it's necessary to reclaim buffers. Unlink the file private332169 * data from its list and free it. Decreases the open count and if it reaches333333- * zero calls takedown().170170+ * zero calls drm_lastclose().334171 */335172int drm_release(struct inode *inode, struct file *filp)336173{···343180344181 DRM_DEBUG("open_count = %d\n", dev->open_count);345182346346- if (dev->driver->prerelease)347347- dev->driver->prerelease(dev, filp);183183+ if (dev->driver->preclose)184184+ dev->driver->preclose(dev, filp);348185349186 /* ========================================================350187 * Begin inline drm_release···360197 DRM_DEBUG("File %p released, freeing lock for context %d\n",361198 filp, _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));362199363363- if (dev->driver->release)364364- dev->driver->release(dev, filp);200200+ if (dev->driver->reclaim_buffers_locked)201201+ dev->driver->reclaim_buffers_locked(dev, filp);365202366203 drm_lock_free(dev, &dev->lock.hw_lock->lock,367204 _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));···370207 hardware at this point, possibly371208 processed via a callback to the X372209 server. */373373- } else if (dev->driver->release && priv->lock_count210210+ } else if (dev->driver->reclaim_buffers_locked && priv->lock_count374211 && dev->lock.hw_lock) {375212 /* The lock is required to reclaim buffers */376213 DECLARE_WAITQUEUE(entry, current);···400237 __set_current_state(TASK_RUNNING);401238 remove_wait_queue(&dev->lock.lock_queue, &entry);402239 if (!retcode) {403403- if (dev->driver->release)404404- dev->driver->release(dev, filp);240240+ dev->driver->reclaim_buffers_locked(dev, filp);405241 drm_lock_free(dev, &dev->lock.hw_lock->lock,406242 DRM_KERNEL_CONTEXT);407243 }408244 }409245410410- if (drm_core_check_feature(dev, DRIVER_HAVE_DMA)411411- && !dev->driver->release) {246246+ if (drm_core_check_feature(dev, DRIVER_HAVE_DMA) &&247247+ !dev->driver->reclaim_buffers_locked) {412248 dev->driver->reclaim_buffers(dev, filp);413249 }414250···454292 }455293 up(&dev->struct_sem);456294457457- if (dev->driver->free_filp_priv)458458- dev->driver->free_filp_priv(dev, priv);459459-295295+ if (dev->driver->postclose)296296+ dev->driver->postclose(dev, priv);460297 drm_free(priv, sizeof(*priv), DRM_MEM_FILES);461298462299 /* ========================================================···474313 }475314 spin_unlock(&dev->count_lock);476315 unlock_kernel();477477- return drm_takedown(dev);316316+ return drm_lastclose(dev);478317 }479318 spin_unlock(&dev->count_lock);480319···482321483322 return retcode;484323}485485-486324EXPORT_SYMBOL(drm_release);487487-488488-/**489489- * Called whenever a process opens /dev/drm.490490- *491491- * \param inode device inode.492492- * \param filp file pointer.493493- * \param dev device.494494- * \return zero on success or a negative number on failure.495495- *496496- * Creates and initializes a drm_file structure for the file private data in \p497497- * filp and add it into the double linked list in \p dev.498498- */499499-static int drm_open_helper(struct inode *inode, struct file *filp,500500- drm_device_t * dev)501501-{502502- int minor = iminor(inode);503503- drm_file_t *priv;504504- int ret;505505-506506- if (filp->f_flags & O_EXCL)507507- return -EBUSY; /* No exclusive opens */508508- if (!drm_cpu_valid())509509- return -EINVAL;510510-511511- DRM_DEBUG("pid = %d, minor = %d\n", current->pid, minor);512512-513513- priv = drm_alloc(sizeof(*priv), DRM_MEM_FILES);514514- if (!priv)515515- return -ENOMEM;516516-517517- memset(priv, 0, sizeof(*priv));518518- filp->private_data = priv;519519- priv->uid = current->euid;520520- priv->pid = current->pid;521521- priv->minor = minor;522522- priv->head = drm_heads[minor];523523- priv->ioctl_count = 0;524524- priv->authenticated = capable(CAP_SYS_ADMIN);525525- priv->lock_count = 0;526526-527527- if (dev->driver->open_helper) {528528- ret = dev->driver->open_helper(dev, priv);529529- if (ret < 0)530530- goto out_free;531531- }532532-533533- down(&dev->struct_sem);534534- if (!dev->file_last) {535535- priv->next = NULL;536536- priv->prev = NULL;537537- dev->file_first = priv;538538- dev->file_last = priv;539539- } else {540540- priv->next = NULL;541541- priv->prev = dev->file_last;542542- dev->file_last->next = priv;543543- dev->file_last = priv;544544- }545545- up(&dev->struct_sem);546546-547547-#ifdef __alpha__548548- /*549549- * Default the hose550550- */551551- if (!dev->hose) {552552- struct pci_dev *pci_dev;553553- pci_dev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, NULL);554554- if (pci_dev) {555555- dev->hose = pci_dev->sysdata;556556- pci_dev_put(pci_dev);557557- }558558- if (!dev->hose) {559559- struct pci_bus *b = pci_bus_b(pci_root_buses.next);560560- if (b)561561- dev->hose = b->sysdata;562562- }563563- }564564-#endif565565-566566- return 0;567567- out_free:568568- drm_free(priv, sizeof(*priv), DRM_MEM_FILES);569569- filp->private_data = NULL;570570- return ret;571571-}572572-573573-/** No-op. */574574-int drm_flush(struct file *filp)575575-{576576- drm_file_t *priv = filp->private_data;577577- drm_device_t *dev = priv->head->dev;578578-579579- DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n",580580- current->pid, (long)old_encode_dev(priv->head->device),581581- dev->open_count);582582- return 0;583583-}584584-585585-EXPORT_SYMBOL(drm_flush);586586-587587-/** No-op. */588588-int drm_fasync(int fd, struct file *filp, int on)589589-{590590- drm_file_t *priv = filp->private_data;591591- drm_device_t *dev = priv->head->dev;592592- int retcode;593593-594594- DRM_DEBUG("fd = %d, device = 0x%lx\n", fd,595595- (long)old_encode_dev(priv->head->device));596596- retcode = fasync_helper(fd, filp, on, &dev->buf_async);597597- if (retcode < 0)598598- return retcode;599599- return 0;600600-}601601-602602-EXPORT_SYMBOL(drm_fasync);603325604326/** No-op. */605327unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait)606328{607329 return 0;608330}609609-610331EXPORT_SYMBOL(drm_poll);
-53
drivers/char/drm/drm_init.c
···11-/**22- * \file drm_init.c33- * Setup/Cleanup for DRM44- *55- * \author Rickard E. (Rik) Faith <faith@valinux.com>66- * \author Gareth Hughes <gareth@valinux.com>77- */88-99-/*1010- * Created: Mon Jan 4 08:58:31 1999 by faith@valinux.com1111- *1212- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.1313- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.1414- * All Rights Reserved.1515- *1616- * Permission is hereby granted, free of charge, to any person obtaining a1717- * copy of this software and associated documentation files (the "Software"),1818- * to deal in the Software without restriction, including without limitation1919- * the rights to use, copy, modify, merge, publish, distribute, sublicense,2020- * and/or sell copies of the Software, and to permit persons to whom the2121- * Software is furnished to do so, subject to the following conditions:2222- *2323- * The above copyright notice and this permission notice (including the next2424- * paragraph) shall be included in all copies or substantial portions of the2525- * Software.2626- *2727- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR2828- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,2929- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL3030- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR3131- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,3232- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR3333- * OTHER DEALINGS IN THE SOFTWARE.3434- */3535-3636-#include "drmP.h"3737-3838-/**3939- * Check whether DRI will run on this CPU.4040- *4141- * \return non-zero if the DRI will run on this CPU, or zero otherwise.4242- */4343-int drm_cpu_valid(void)4444-{4545-#if defined(__i386__)4646- if (boot_cpu_data.x86 == 3)4747- return 0; /* No cmpxchg on a 386 */4848-#endif4949-#if defined(__sparc__) && !defined(__sparc_v9__)5050- return 0; /* No cmpxchg before v9 sparc. */5151-#endif5252- return 1;5353-}
···130130 /* dev->driver->kernel_context_switch isn't used by any of the x86131131 * drivers but is used by the Sparc driver.132132 */133133-134133 if (dev->driver->kernel_context_switch &&135134 dev->last_context != lock.context) {136135 dev->driver->kernel_context_switch(dev, dev->last_context,
-8
drivers/char/drm/drm_memory.c
···145145 return drm_agp_allocate_memory(dev->agp->bridge, pages, type);146146}147147148148-EXPORT_SYMBOL(drm_alloc_agp);149149-150148/** Wrapper around agp_free_memory() */151149int drm_free_agp(DRM_AGP_MEM * handle, int pages)152150{153151 return drm_agp_free_memory(handle) ? 0 : -EINVAL;154152}155155-156156-EXPORT_SYMBOL(drm_free_agp);157153158154/** Wrapper around agp_bind_memory() */159155int drm_bind_agp(DRM_AGP_MEM * handle, unsigned int start)···157161 return drm_agp_bind_memory(handle, start);158162}159163160160-EXPORT_SYMBOL(drm_bind_agp);161161-162164/** Wrapper around agp_unbind_memory() */163165int drm_unbind_agp(DRM_AGP_MEM * handle)164166{165167 return drm_agp_unbind_memory(handle);166168}167167-168168-EXPORT_SYMBOL(drm_unbind_agp);169169#endif /* agp */170170#endif /* debug_memory */
···1313#define DRM_ERR(d) -(d)1414/** Current process ID */1515#define DRM_CURRENTPID current->pid1616+#define DRM_SUSER(p) capable(CAP_SYS_ADMIN)1617#define DRM_UDELAY(d) udelay(d)1718/** Read a byte from a MMIO region */1819#define DRM_READ8(map, offset) readb(((void __iomem *)(map)->handle) + (offset))
···11/* i915_dma.c -- DMA support for the I915 -*- linux-c -*-22 */33-/**************************************************************************44- *33+/*54 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.65 * All Rights Reserved.76 *···2425 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE2526 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.2627 *2727- **************************************************************************/2828+ */28292930#include "drmP.h"3031#include "drm.h"···195196 return 0;196197}197198198198-static int i915_resume(drm_device_t * dev)199199+static int i915_dma_resume(drm_device_t * dev)199200{200201 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;201202···252253 retcode = i915_dma_cleanup(dev);253254 break;254255 case I915_RESUME_DMA:255255- retcode = i915_resume(dev);256256+ retcode = i915_dma_resume(dev);256257 break;257258 default:258259 retcode = -EINVAL;···653654 case I915_PARAM_ALLOW_BATCHBUFFER:654655 value = dev_priv->allow_batchbuffer ? 1 : 0;655656 break;657657+ case I915_PARAM_LAST_DISPATCH:658658+ value = READ_BREADCRUMB(dev_priv);659659+ break;656660 default:657661 DRM_ERROR("Unkown parameter %d\n", param.param);658662 return DRM_ERR(EINVAL);···701699 return 0;702700}703701704704-void i915_driver_pretakedown(drm_device_t * dev)702702+int i915_driver_load(drm_device_t *dev, unsigned long flags)703703+{704704+ /* i915 has 4 more counters */705705+ dev->counters += 4;706706+ dev->types[6] = _DRM_STAT_IRQ;707707+ dev->types[7] = _DRM_STAT_PRIMARY;708708+ dev->types[8] = _DRM_STAT_SECONDARY;709709+ dev->types[9] = _DRM_STAT_DMA;710710+711711+ return 0;712712+}713713+714714+void i915_driver_lastclose(drm_device_t * dev)705715{706716 if (dev->dev_private) {707717 drm_i915_private_t *dev_priv = dev->dev_private;···722708 i915_dma_cleanup(dev);723709}724710725725-void i915_driver_prerelease(drm_device_t * dev, DRMFILE filp)711711+void i915_driver_preclose(drm_device_t * dev, DRMFILE filp)726712{727713 if (dev->dev_private) {728714 drm_i915_private_t *dev_priv = dev->dev_private;···731717}732718733719drm_ioctl_desc_t i915_ioctls[] = {734734- [DRM_IOCTL_NR(DRM_I915_INIT)] = {i915_dma_init, 1, 1},735735- [DRM_IOCTL_NR(DRM_I915_FLUSH)] = {i915_flush_ioctl, 1, 0},736736- [DRM_IOCTL_NR(DRM_I915_FLIP)] = {i915_flip_bufs, 1, 0},737737- [DRM_IOCTL_NR(DRM_I915_BATCHBUFFER)] = {i915_batchbuffer, 1, 0},738738- [DRM_IOCTL_NR(DRM_I915_IRQ_EMIT)] = {i915_irq_emit, 1, 0},739739- [DRM_IOCTL_NR(DRM_I915_IRQ_WAIT)] = {i915_irq_wait, 1, 0},740740- [DRM_IOCTL_NR(DRM_I915_GETPARAM)] = {i915_getparam, 1, 0},741741- [DRM_IOCTL_NR(DRM_I915_SETPARAM)] = {i915_setparam, 1, 1},742742- [DRM_IOCTL_NR(DRM_I915_ALLOC)] = {i915_mem_alloc, 1, 0},743743- [DRM_IOCTL_NR(DRM_I915_FREE)] = {i915_mem_free, 1, 0},744744- [DRM_IOCTL_NR(DRM_I915_INIT_HEAP)] = {i915_mem_init_heap, 1, 1},745745- [DRM_IOCTL_NR(DRM_I915_CMDBUFFER)] = {i915_cmdbuffer, 1, 0}720720+ [DRM_IOCTL_NR(DRM_I915_INIT)] = {i915_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},721721+ [DRM_IOCTL_NR(DRM_I915_FLUSH)] = {i915_flush_ioctl, DRM_AUTH},722722+ [DRM_IOCTL_NR(DRM_I915_FLIP)] = {i915_flip_bufs, DRM_AUTH},723723+ [DRM_IOCTL_NR(DRM_I915_BATCHBUFFER)] = {i915_batchbuffer, DRM_AUTH},724724+ [DRM_IOCTL_NR(DRM_I915_IRQ_EMIT)] = {i915_irq_emit, DRM_AUTH},725725+ [DRM_IOCTL_NR(DRM_I915_IRQ_WAIT)] = {i915_irq_wait, DRM_AUTH},726726+ [DRM_IOCTL_NR(DRM_I915_GETPARAM)] = {i915_getparam, DRM_AUTH},727727+ [DRM_IOCTL_NR(DRM_I915_SETPARAM)] = {i915_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},728728+ [DRM_IOCTL_NR(DRM_I915_ALLOC)] = {i915_mem_alloc, DRM_AUTH},729729+ [DRM_IOCTL_NR(DRM_I915_FREE)] = {i915_mem_free, DRM_AUTH},730730+ [DRM_IOCTL_NR(DRM_I915_INIT_HEAP)] = {i915_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},731731+ [DRM_IOCTL_NR(DRM_I915_CMDBUFFER)] = {i915_cmdbuffer, DRM_AUTH}746732};747733748734int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
+3-3
drivers/char/drm/i915_drm.h
···11-/**************************************************************************22- *11+/*32 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.43 * All Rights Reserved.54 *···2223 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE2324 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.2425 *2525- **************************************************************************/2626+ */26272728#ifndef _I915_DRM_H_2829#define _I915_DRM_H_···151152 */152153#define I915_PARAM_IRQ_ACTIVE 1153154#define I915_PARAM_ALLOW_BATCHBUFFER 2155155+#define I915_PARAM_LAST_DISPATCH 3154156155157typedef struct drm_i915_getparam {156158 int param;
+23-43
drivers/char/drm/i915_drv.c
···11/* i915_drv.c -- i830,i845,i855,i865,i915 driver -*- linux-c -*-22 */33-/**************************************************************************33+/*44 *55 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.66 * All Rights Reserved.···2525 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE2626 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.2727 *2828- **************************************************************************/2828+ */29293030#include "drmP.h"3131#include "drm.h"···34343535#include "drm_pciids.h"36363737-static int postinit(struct drm_device *dev, unsigned long flags)3838-{3939- dev->counters += 4;4040- dev->types[6] = _DRM_STAT_IRQ;4141- dev->types[7] = _DRM_STAT_PRIMARY;4242- dev->types[8] = _DRM_STAT_SECONDARY;4343- dev->types[9] = _DRM_STAT_DMA;4444-4545- DRM_INFO("Initialized %s %d.%d.%d %s on minor %d: %s\n",4646- DRIVER_NAME,4747- DRIVER_MAJOR,4848- DRIVER_MINOR,4949- DRIVER_PATCHLEVEL,5050- DRIVER_DATE, dev->primary.minor, pci_pretty_name(dev->pdev)5151- );5252- return 0;5353-}5454-5555-static int version(drm_version_t * version)5656-{5757- int len;5858-5959- version->version_major = DRIVER_MAJOR;6060- version->version_minor = DRIVER_MINOR;6161- version->version_patchlevel = DRIVER_PATCHLEVEL;6262- DRM_COPY(version->name, DRIVER_NAME);6363- DRM_COPY(version->date, DRIVER_DATE);6464- DRM_COPY(version->desc, DRIVER_DESC);6565- return 0;6666-}6767-6837static struct pci_device_id pciidlist[] = {6938 i915_PCI_IDS7039};71407241static struct drm_driver driver = {4242+ /* don't use mtrr's here, the Xserver or user space app should4343+ * deal with them for intel hardware.4444+ */7345 .driver_features =7474- DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR |7575- DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED,7676- .pretakedown = i915_driver_pretakedown,7777- .prerelease = i915_driver_prerelease,4646+ DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | /* DRIVER_USE_MTRR |*/4747+ DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL,4848+ .load = i915_driver_load,4949+ .lastclose = i915_driver_lastclose,5050+ .preclose = i915_driver_preclose,7851 .device_is_agp = i915_driver_device_is_agp,5252+ .vblank_wait = i915_driver_vblank_wait,7953 .irq_preinstall = i915_driver_irq_preinstall,8054 .irq_postinstall = i915_driver_irq_postinstall,8155 .irq_uninstall = i915_driver_irq_uninstall,···5783 .reclaim_buffers = drm_core_reclaim_buffers,5884 .get_map_ofs = drm_core_get_map_ofs,5985 .get_reg_ofs = drm_core_get_reg_ofs,6060- .postinit = postinit,6161- .version = version,6286 .ioctls = i915_ioctls,6387 .fops = {6488 .owner = THIS_MODULE,···6997#ifdef CONFIG_COMPAT7098 .compat_ioctl = i915_compat_ioctl,7199#endif7272- },100100+ },101101+73102 .pci_driver = {7474- .name = DRIVER_NAME,7575- .id_table = pciidlist,7676- }103103+ .name = DRIVER_NAME,104104+ .id_table = pciidlist,105105+ },106106+107107+ .name = DRIVER_NAME,108108+ .desc = DRIVER_DESC,109109+ .date = DRIVER_DATE,110110+ .major = DRIVER_MAJOR,111111+ .minor = DRIVER_MINOR,112112+ .patchlevel = DRIVER_PATCHLEVEL,77113};7811479115static int __init i915_init(void)
+26-18
drivers/char/drm/i915_drv.h
···11/* i915_drv.h -- Private header for the I915 driver -*- linux-c -*-22 */33-/**************************************************************************33+/*44 *55 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.66 * All Rights Reserved.···2525 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE2626 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.2727 *2828- **************************************************************************/2828+ */29293030#ifndef _I915_DRV_H_3131#define _I915_DRV_H_···37373838#define DRIVER_NAME "i915"3939#define DRIVER_DESC "Intel Graphics"4040-#define DRIVER_DATE "20040405"4040+#define DRIVER_DATE "20051209"41414242/* Interface history:4343 *4444 * 1.1: Original.4545+ * 1.2: Add Power Management4646+ * 1.3: Add vblank support4547 */4648#define DRIVER_MAJOR 14747-#define DRIVER_MINOR 14949+#define DRIVER_MINOR 34850#define DRIVER_PATCHLEVEL 04949-5050-/* We use our own dma mechanisms, not the drm template code. However,5151- * the shared IRQ code is useful to us:5252- */5353-#define __HAVE_PM 154515552typedef struct _drm_i915_ring_buffer {5653 int tail_mask;···9497 int tex_lru_log_granularity;9598 int allow_batchbuffer;9699 struct mem_block *agp_heap;100100+ unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds;97101} drm_i915_private_t;9810299103extern drm_ioctl_desc_t i915_ioctls[];···102104103105 /* i915_dma.c */104106extern void i915_kernel_lost_context(drm_device_t * dev);105105-extern void i915_driver_pretakedown(drm_device_t * dev);106106-extern void i915_driver_prerelease(drm_device_t * dev, DRMFILE filp);107107+extern int i915_driver_load(struct drm_device *, unsigned long flags);108108+extern void i915_driver_lastclose(drm_device_t * dev);109109+extern void i915_driver_preclose(drm_device_t * dev, DRMFILE filp);107110extern int i915_driver_device_is_agp(drm_device_t * dev);111111+extern long i915_compat_ioctl(struct file *filp, unsigned int cmd,112112+ unsigned long arg);108113109114/* i915_irq.c */110115extern int i915_irq_emit(DRM_IOCTL_ARGS);111116extern int i915_irq_wait(DRM_IOCTL_ARGS);112117118118+extern int i915_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence);113119extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS);114120extern void i915_driver_irq_preinstall(drm_device_t * dev);115121extern void i915_driver_irq_postinstall(drm_device_t * dev);···127125extern void i915_mem_release(drm_device_t * dev,128126 DRMFILE filp, struct mem_block *heap);129127130130-extern long i915_compat_ioctl(struct file *filp, unsigned int cmd,131131- unsigned long arg);132132-133133-#define I915_READ(reg) DRM_READ32(dev_priv->mmio_map, reg)134134-#define I915_WRITE(reg,val) DRM_WRITE32(dev_priv->mmio_map, reg, val)135135-#define I915_READ16(reg) DRM_READ16(dev_priv->mmio_map, reg)136136-#define I915_WRITE16(reg,val) DRM_WRITE16(dev_priv->mmio_map, reg, val)128128+#define I915_READ(reg) DRM_READ32(dev_priv->mmio_map, (reg))129129+#define I915_WRITE(reg,val) DRM_WRITE32(dev_priv->mmio_map, (reg), (val))130130+#define I915_READ16(reg) DRM_READ16(dev_priv->mmio_map, (reg))131131+#define I915_WRITE16(reg,val) DRM_WRITE16(dev_priv->mmio_map, (reg), (val))137132138133#define I915_VERBOSE 0139134···194195#define PPCR 0x61204195196#define PPCR_ON (1<<0)196197198198+#define DVOB 0x61140199199+#define DVOB_ON (1<<31)200200+#define DVOC 0x61160201201+#define DVOC_ON (1<<31)202202+#define LVDS 0x61180203203+#define LVDS_ON (1<<31)204204+197205#define ADPA 0x61100198206#define ADPA_DPMS_MASK (~(3<<10))199207#define ADPA_DPMS_ON (0<<10)···263257#define ASYNC_FLIP (1<<22)264258265259#define CMD_OP_DESTBUFFER_INFO ((0x3<<29)|(0x1d<<24)|(0x8e<<16)|1)260260+261261+#define READ_BREADCRUMB(dev_priv) (((u32 *)(dev_priv->hw_status_page))[5])266262267263#endif
+39-9
drivers/char/drm/i915_irq.c
···11-/* i915_dma.c -- DMA support for the I915 -*- linux-c -*-11+/* i915_irq.c -- IRQ support for the I915 -*- linux-c -*-22 */33-/**************************************************************************44- *33+/*54 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.65 * All Rights Reserved.76 *···2425 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE2526 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.2627 *2727- **************************************************************************/2828+ */28292930#include "drmP.h"3031#include "drm.h"3132#include "i915_drm.h"3233#include "i915_drv.h"33343434-#define USER_INT_FLAG 0x23535+#define USER_INT_FLAG (1<<1)3636+#define VSYNC_PIPEB_FLAG (1<<5)3737+#define VSYNC_PIPEA_FLAG (1<<7)3838+3539#define MAX_NOPID ((u32)~0)3636-#define READ_BREADCRUMB(dev_priv) (((u32*)(dev_priv->hw_status_page))[5])37403841irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)3942{···4443 u16 temp;45444645 temp = I915_READ16(I915REG_INT_IDENTITY_R);4747- temp &= USER_INT_FLAG;4646+ temp &= (USER_INT_FLAG | VSYNC_PIPEA_FLAG);48474948 DRM_DEBUG("%s flag=%08x\n", __FUNCTION__, temp);5049···5251 return IRQ_NONE;53525453 I915_WRITE16(I915REG_INT_IDENTITY_R, temp);5555- DRM_WAKEUP(&dev_priv->irq_queue);5454+5555+ if (temp & USER_INT_FLAG)5656+ DRM_WAKEUP(&dev_priv->irq_queue);5757+5858+ if (temp & VSYNC_PIPEA_FLAG) {5959+ atomic_inc(&dev->vbl_received);6060+ DRM_WAKEUP(&dev->vbl_queue);6161+ drm_vbl_send_signals(dev);6262+ }56635764 return IRQ_HANDLED;5865}···110101 dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);111102 return ret;112103}104104+105105+int i915_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence)106106+{107107+ drm_i915_private_t *dev_priv = dev->dev_private;108108+ unsigned int cur_vblank;109109+ int ret = 0;110110+111111+ if (!dev_priv) {112112+ DRM_ERROR("%s called with no initialization\n", __FUNCTION__);113113+ return DRM_ERR(EINVAL);114114+ }115115+116116+ DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,117117+ (((cur_vblank = atomic_read(&dev->vbl_received))118118+ - *sequence) <= (1<<23)));119119+120120+ *sequence = cur_vblank;121121+122122+ return ret;123123+}124124+113125114126/* Needs the lock as it touches the ring.115127 */···195165{196166 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;197167198198- I915_WRITE16(I915REG_INT_ENABLE_R, USER_INT_FLAG);168168+ I915_WRITE16(I915REG_INT_ENABLE_R, USER_INT_FLAG | VSYNC_PIPEA_FLAG);199169 DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);200170}201171
+2-3
drivers/char/drm/i915_mem.c
···11/* i915_mem.c -- Simple agp/fb memory manager for i915 -*- linux-c -*-22 */33-/**************************************************************************44- *33+/*54 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.65 * All Rights Reserved.76 *···2425 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE2526 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.2627 *2727- **************************************************************************/2828+ */28292930#include "drmP.h"3031#include "drm.h"
+100-62
drivers/char/drm/mga_dma.c
···4444#define MGA_DEFAULT_USEC_TIMEOUT 100004545#define MGA_FREELIST_DEBUG 046464747-static int mga_do_cleanup_dma(drm_device_t * dev);4747+#define MINIMAL_CLEANUP 04848+#define FULL_CLEANUP 14949+static int mga_do_cleanup_dma(drm_device_t *dev, int full_cleanup);48504951/* ================================================================5052 * Engine control···393391 * DMA initialization, cleanup394392 */395393396396-int mga_driver_preinit(drm_device_t * dev, unsigned long flags)394394+int mga_driver_load(drm_device_t * dev, unsigned long flags)397395{398396 drm_mga_private_t *dev_priv;399397···406404407405 dev_priv->usec_timeout = MGA_DEFAULT_USEC_TIMEOUT;408406 dev_priv->chipset = flags;407407+408408+ dev_priv->mmio_base = drm_get_resource_start(dev, 1);409409+ dev_priv->mmio_size = drm_get_resource_len(dev, 1);410410+411411+ dev->counters += 3;412412+ dev->types[6] = _DRM_STAT_IRQ;413413+ dev->types[7] = _DRM_STAT_PRIMARY;414414+ dev->types[8] = _DRM_STAT_SECONDARY;409415410416 return 0;411417}···448438 drm_buf_desc_t req;449439 drm_agp_mode_t mode;450440 drm_agp_info_t info;441441+ drm_agp_buffer_t agp_req;442442+ drm_agp_binding_t bind_req;451443452444 /* Acquire AGP. */453445 err = drm_agp_acquire(dev);454446 if (err) {455455- DRM_ERROR("Unable to acquire AGP\n");447447+ DRM_ERROR("Unable to acquire AGP: %d\n", err);456448 return err;457449 }458450459451 err = drm_agp_info(dev, &info);460452 if (err) {461461- DRM_ERROR("Unable to get AGP info\n");453453+ DRM_ERROR("Unable to get AGP info: %d\n", err);462454 return err;463455 }464456···484472 }485473486474 /* Allocate and bind AGP memory. */487487- dev_priv->agp_pages = agp_size / PAGE_SIZE;488488- dev_priv->agp_mem = drm_alloc_agp(dev, dev_priv->agp_pages, 0);489489- if (dev_priv->agp_mem == NULL) {490490- dev_priv->agp_pages = 0;475475+ agp_req.size = agp_size;476476+ agp_req.type = 0;477477+ err = drm_agp_alloc(dev, &agp_req);478478+ if (err) {479479+ dev_priv->agp_size = 0;491480 DRM_ERROR("Unable to allocate %uMB AGP memory\n",492481 dma_bs->agp_size);493493- return DRM_ERR(ENOMEM);482482+ return err;494483 }484484+485485+ dev_priv->agp_size = agp_size;486486+ dev_priv->agp_handle = agp_req.handle;495487496496- err = drm_bind_agp(dev_priv->agp_mem, 0);488488+ bind_req.handle = agp_req.handle;489489+ bind_req.offset = 0;490490+ err = drm_agp_bind(dev, &bind_req);497491 if (err) {498498- DRM_ERROR("Unable to bind AGP memory\n");492492+ DRM_ERROR("Unable to bind AGP memory: %d\n", err);499493 return err;500494 }501495···515497 err = drm_addmap(dev, offset, warp_size,516498 _DRM_AGP, _DRM_READ_ONLY, &dev_priv->warp);517499 if (err) {518518- DRM_ERROR("Unable to map WARP microcode\n");500500+ DRM_ERROR("Unable to map WARP microcode: %d\n", err);519501 return err;520502 }521503···523505 err = drm_addmap(dev, offset, dma_bs->primary_size,524506 _DRM_AGP, _DRM_READ_ONLY, &dev_priv->primary);525507 if (err) {526526- DRM_ERROR("Unable to map primary DMA region\n");508508+ DRM_ERROR("Unable to map primary DMA region: %d\n", err);527509 return err;528510 }529511···531513 err = drm_addmap(dev, offset, secondary_size,532514 _DRM_AGP, 0, &dev->agp_buffer_map);533515 if (err) {534534- DRM_ERROR("Unable to map secondary DMA region\n");516516+ DRM_ERROR("Unable to map secondary DMA region: %d\n", err);535517 return err;536518 }537519···543525544526 err = drm_addbufs_agp(dev, &req);545527 if (err) {546546- DRM_ERROR("Unable to add secondary DMA buffers\n");528528+ DRM_ERROR("Unable to add secondary DMA buffers: %d\n", err);547529 return err;530530+ }531531+532532+ {533533+ drm_map_list_t *_entry;534534+ unsigned long agp_token = 0;535535+536536+ list_for_each_entry(_entry, &dev->maplist->head, head) {537537+ if (_entry->map == dev->agp_buffer_map)538538+ agp_token = _entry->user_token;539539+ }540540+ if (!agp_token)541541+ return -EFAULT;542542+543543+ dev->agp_buffer_token = agp_token;548544 }549545550546 offset += secondary_size;551547 err = drm_addmap(dev, offset, agp_size - offset,552548 _DRM_AGP, 0, &dev_priv->agp_textures);553549 if (err) {554554- DRM_ERROR("Unable to map AGP texture region\n");550550+ DRM_ERROR("Unable to map AGP texture region %d\n", err);555551 return err;556552 }557553···635603 err = drm_addmap(dev, 0, warp_size, _DRM_CONSISTENT,636604 _DRM_READ_ONLY, &dev_priv->warp);637605 if (err != 0) {638638- DRM_ERROR("Unable to create mapping for WARP microcode\n");606606+ DRM_ERROR("Unable to create mapping for WARP microcode: %d\n",607607+ err);639608 return err;640609 }641610···655622 }656623657624 if (err != 0) {658658- DRM_ERROR("Unable to allocate primary DMA region\n");625625+ DRM_ERROR("Unable to allocate primary DMA region: %d\n", err);659626 return DRM_ERR(ENOMEM);660627 }661628···679646 }680647681648 if (bin_count == 0) {682682- DRM_ERROR("Unable to add secondary DMA buffers\n");649649+ DRM_ERROR("Unable to add secondary DMA buffers: %d\n", err);683650 return err;684651 }685652···715682 err = drm_addmap(dev, dev_priv->mmio_base, dev_priv->mmio_size,716683 _DRM_REGISTERS, _DRM_READ_ONLY, &dev_priv->mmio);717684 if (err) {718718- DRM_ERROR("Unable to map MMIO region\n");685685+ DRM_ERROR("Unable to map MMIO region: %d\n", err);719686 return err;720687 }721688···723690 _DRM_READ_ONLY | _DRM_LOCKED | _DRM_KERNEL,724691 &dev_priv->status);725692 if (err) {726726- DRM_ERROR("Unable to map status region\n");693693+ DRM_ERROR("Unable to map status region: %d\n", err);727694 return err;728695 }729696···741708 */742709743710 if (err) {744744- mga_do_cleanup_dma(dev);711711+ mga_do_cleanup_dma(dev, MINIMAL_CLEANUP);745712 }746713747714 /* Not only do we want to try and initialized PCI cards for PCI DMA,···764731 DRM_DEVICE;765732 drm_mga_dma_bootstrap_t bootstrap;766733 int err;734734+ static const int modes[] = { 0, 1, 2, 2, 4, 4, 4, 4 };735735+ const drm_mga_private_t *const dev_priv =736736+ (drm_mga_private_t *) dev->dev_private;767737768738 DRM_COPY_FROM_USER_IOCTL(bootstrap,769739 (drm_mga_dma_bootstrap_t __user *) data,770740 sizeof(bootstrap));771741772742 err = mga_do_dma_bootstrap(dev, &bootstrap);773773- if (!err) {774774- static const int modes[] = { 0, 1, 2, 2, 4, 4, 4, 4 };775775- const drm_mga_private_t *const dev_priv =776776- (drm_mga_private_t *) dev->dev_private;777777-778778- if (dev_priv->agp_textures != NULL) {779779- bootstrap.texture_handle =780780- dev_priv->agp_textures->offset;781781- bootstrap.texture_size = dev_priv->agp_textures->size;782782- } else {783783- bootstrap.texture_handle = 0;784784- bootstrap.texture_size = 0;785785- }786786-787787- bootstrap.agp_mode = modes[bootstrap.agp_mode & 0x07];788788- if (DRM_COPY_TO_USER((void __user *)data, &bootstrap,789789- sizeof(bootstrap))) {790790- err = DRM_ERR(EFAULT);791791- }792792- } else {793793- mga_do_cleanup_dma(dev);743743+ if (err) {744744+ mga_do_cleanup_dma(dev, FULL_CLEANUP);745745+ return err;794746 }747747+748748+ if (dev_priv->agp_textures != NULL) {749749+ bootstrap.texture_handle = dev_priv->agp_textures->offset;750750+ bootstrap.texture_size = dev_priv->agp_textures->size;751751+ } else {752752+ bootstrap.texture_handle = 0;753753+ bootstrap.texture_size = 0;754754+ }755755+756756+ bootstrap.agp_mode = modes[bootstrap.agp_mode & 0x07];757757+ DRM_COPY_TO_USER_IOCTL((drm_mga_dma_bootstrap_t __user *)data,758758+ bootstrap, sizeof(bootstrap));795759796760 return err;797761}···883853884854 ret = mga_warp_install_microcode(dev_priv);885855 if (ret < 0) {886886- DRM_ERROR("failed to install WARP ucode!\n");856856+ DRM_ERROR("failed to install WARP ucode!: %d\n", ret);887857 return ret;888858 }889859890860 ret = mga_warp_init(dev_priv);891861 if (ret < 0) {892892- DRM_ERROR("failed to init WARP engine!\n");862862+ DRM_ERROR("failed to init WARP engine!: %d\n", ret);893863 return ret;894864 }895865···934904 return 0;935905}936906937937-static int mga_do_cleanup_dma(drm_device_t * dev)907907+static int mga_do_cleanup_dma(drm_device_t *dev, int full_cleanup)938908{939909 int err = 0;940910 DRM_DEBUG("\n");···962932963933 if (dev_priv->used_new_dma_init) {964934#if __OS_HAS_AGP965965- if (dev_priv->agp_mem != NULL) {966966- dev_priv->agp_textures = NULL;967967- drm_unbind_agp(dev_priv->agp_mem);935935+ if (dev_priv->agp_handle != 0) {936936+ drm_agp_binding_t unbind_req;937937+ drm_agp_buffer_t free_req;968938969969- drm_free_agp(dev_priv->agp_mem,970970- dev_priv->agp_pages);971971- dev_priv->agp_pages = 0;972972- dev_priv->agp_mem = NULL;939939+ unbind_req.handle = dev_priv->agp_handle;940940+ drm_agp_unbind(dev, &unbind_req);941941+942942+ free_req.handle = dev_priv->agp_handle;943943+ drm_agp_free(dev, &free_req);944944+945945+ dev_priv->agp_textures = NULL;946946+ dev_priv->agp_size = 0;947947+ dev_priv->agp_handle = 0;973948 }974949975950 if ((dev->agp != NULL) && dev->agp->acquired) {976951 err = drm_agp_release(dev);977952 }978953#endif979979- dev_priv->used_new_dma_init = 0;980954 }981955982956 dev_priv->warp = NULL;983957 dev_priv->primary = NULL;984984- dev_priv->mmio = NULL;985985- dev_priv->status = NULL;986958 dev_priv->sarea = NULL;987959 dev_priv->sarea_priv = NULL;988960 dev->agp_buffer_map = NULL;961961+962962+ if (full_cleanup) {963963+ dev_priv->mmio = NULL;964964+ dev_priv->status = NULL;965965+ dev_priv->used_new_dma_init = 0;966966+ }989967990968 memset(&dev_priv->prim, 0, sizeof(dev_priv->prim));991969 dev_priv->warp_pipe = 0;···1005967 }1006968 }100796910081008- return err;970970+ return 0;1009971}10109721011973int mga_dma_init(DRM_IOCTL_ARGS)···1023985 case MGA_INIT_DMA:1024986 err = mga_do_init_dma(dev, &init);1025987 if (err) {10261026- (void)mga_do_cleanup_dma(dev);988988+ (void)mga_do_cleanup_dma(dev, FULL_CLEANUP);1027989 }1028990 return err;1029991 case MGA_CLEANUP_DMA:10301030- return mga_do_cleanup_dma(dev);992992+ return mga_do_cleanup_dma(dev, FULL_CLEANUP);1031993 }10329941033995 return DRM_ERR(EINVAL);···11561118/**11571119 * Called just before the module is unloaded.11581120 */11591159-int mga_driver_postcleanup(drm_device_t * dev)11211121+int mga_driver_unload(drm_device_t * dev)11601122{11611123 drm_free(dev->dev_private, sizeof(drm_mga_private_t), DRM_MEM_DRIVER);11621124 dev->dev_private = NULL;···11671129/**11681130 * Called when the last opener of the device is closed.11691131 */11701170-void mga_driver_pretakedown(drm_device_t * dev)11321132+void mga_driver_lastclose(drm_device_t * dev)11711133{11721172- mga_do_cleanup_dma(dev);11341134+ mga_do_cleanup_dma(dev, FULL_CLEANUP);11731135}1174113611751137int mga_driver_dma_quiescent(drm_device_t * dev)
···11-/* r128_cce.c -- ATI Rage 128 driver -*- linux-c -*-11+/* r128_cce.c -- ATI Rage 128 driver -*- linux-c -*- 22 * Created: Wed Apr 5 19:24:19 2000 by kevin@precisioninsight.com33- *33+ */44+/*45 * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.56 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.67 * All Rights Reserved.···560559 if (dev_priv->is_pci) {561560#endif562561 dev_priv->gart_info.gart_table_location = DRM_ATI_GART_MAIN;563563- dev_priv->gart_info.addr = dev_priv->gart_info.bus_addr = 0;562562+ dev_priv->gart_info.addr = NULL;563563+ dev_priv->gart_info.bus_addr = 0;564564 dev_priv->gart_info.is_pcie = 0;565565 if (!drm_ati_pcigart_init(dev, &dev_priv->gart_info)) {566566 DRM_ERROR("failed to init PCI GART!\n");···603601 drm_core_ioremapfree(dev_priv->cce_ring, dev);604602 if (dev_priv->ring_rptr != NULL)605603 drm_core_ioremapfree(dev_priv->ring_rptr, dev);606606- if (dev->agp_buffer_map != NULL)604604+ if (dev->agp_buffer_map != NULL) {607605 drm_core_ioremapfree(dev->agp_buffer_map, dev);606606+ dev->agp_buffer_map = NULL;607607+ }608608 } else609609#endif610610 {611611 if (dev_priv->gart_info.bus_addr)612612 if (!drm_ati_pcigart_cleanup(dev,613613- &dev_priv->614614- gart_info))613613+ &dev_priv->gart_info))615614 DRM_ERROR616615 ("failed to cleanup PCI GART!\n");617616 }
+2-2
drivers/char/drm/r128_drm.h
···11/* r128_drm.h -- Public header for the r128 driver -*- linux-c -*-22 * Created: Wed Apr 5 19:24:19 2000 by kevin@precisioninsight.com33- *44- * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.33+ */44+/* Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.55 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.66 * All rights reserved.77 *
···11/* r128_drv.h -- Private header for r128 driver -*- linux-c -*-22 * Created: Mon Dec 13 09:51:11 1999 by faith@precisioninsight.com33- *44- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.33+ */44+/* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.55 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.66 * All rights reserved.77 *···154154extern void r128_driver_irq_preinstall(drm_device_t * dev);155155extern void r128_driver_irq_postinstall(drm_device_t * dev);156156extern void r128_driver_irq_uninstall(drm_device_t * dev);157157-extern void r128_driver_pretakedown(drm_device_t * dev);158158-extern void r128_driver_prerelease(drm_device_t * dev, DRMFILE filp);157157+extern void r128_driver_lastclose(drm_device_t * dev);158158+extern void r128_driver_preclose(drm_device_t * dev, DRMFILE filp);159159160160extern long r128_compat_ioctl(struct file *filp, unsigned int cmd,161161 unsigned long arg);
+2-2
drivers/char/drm/r128_irq.c
···11-/* r128_irq.c -- IRQ handling for radeon -*- linux-c -*-22- *11+/* r128_irq.c -- IRQ handling for radeon -*- linux-c -*- */22+/*33 * Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.44 *55 * The Weather Channel (TM) funded Tungsten Graphics to develop the
···5252 * Emit up to R300_SIMULTANEOUS_CLIPRECTS cliprects from the given command5353 * buffer, starting with index n.5454 */5555-static int r300_emit_cliprects(drm_radeon_private_t * dev_priv,5656- drm_radeon_kcmd_buffer_t * cmdbuf, int n)5555+static int r300_emit_cliprects(drm_radeon_private_t *dev_priv,5656+ drm_radeon_kcmd_buffer_t *cmdbuf, int n)5757{5858 drm_clip_rect_t box;5959 int nr;···216216 ADD_RANGE(R300_TX_UNK1_0, 16);217217 ADD_RANGE(R300_TX_SIZE_0, 16);218218 ADD_RANGE(R300_TX_FORMAT_0, 16);219219+ ADD_RANGE(R300_TX_PITCH_0, 16);219220 /* Texture offset is dangerous and needs more checking */220221 ADD_RANGE_MARK(R300_TX_OFFSET_0, 16, MARK_CHECK_OFFSET);221222 ADD_RANGE(R300_TX_UNK4_0, 16);···243242244243 /* we expect offsets passed to the framebuffer to be either within video memory or245244 within AGP space */246246-static __inline__ int r300_check_offset(drm_radeon_private_t * dev_priv,245245+static __inline__ int r300_check_offset(drm_radeon_private_t *dev_priv,247246 u32 offset)248247{249248 /* we realy want to check against end of video aperture···318317 *319318 * Note that checks are performed on contents and addresses of the registers320319 */321321-static __inline__ int r300_emit_packet0(drm_radeon_private_t * dev_priv,322322- drm_radeon_kcmd_buffer_t * cmdbuf,320320+static __inline__ int r300_emit_packet0(drm_radeon_private_t *dev_priv,321321+ drm_radeon_kcmd_buffer_t *cmdbuf,323322 drm_r300_cmd_header_t header)324323{325324 int reg;···364363 * the graphics card.365364 * Called by r300_do_cp_cmdbuf.366365 */367367-static __inline__ int r300_emit_vpu(drm_radeon_private_t * dev_priv,368368- drm_radeon_kcmd_buffer_t * cmdbuf,366366+static __inline__ int r300_emit_vpu(drm_radeon_private_t *dev_priv,367367+ drm_radeon_kcmd_buffer_t *cmdbuf,369368 drm_r300_cmd_header_t header)370369{371370 int sz;···401400 * Emit a clear packet from userspace.402401 * Called by r300_emit_packet3.403402 */404404-static __inline__ int r300_emit_clear(drm_radeon_private_t * dev_priv,405405- drm_radeon_kcmd_buffer_t * cmdbuf)403403+static __inline__ int r300_emit_clear(drm_radeon_private_t *dev_priv,404404+ drm_radeon_kcmd_buffer_t *cmdbuf)406405{407406 RING_LOCALS;408407···422421 return 0;423422}424423425425-static __inline__ int r300_emit_3d_load_vbpntr(drm_radeon_private_t * dev_priv,426426- drm_radeon_kcmd_buffer_t * cmdbuf,424424+static __inline__ int r300_emit_3d_load_vbpntr(drm_radeon_private_t *dev_priv,425425+ drm_radeon_kcmd_buffer_t *cmdbuf,427426 u32 header)428427{429428 int count, i, k;···490489 return 0;491490}492491493493-static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t * dev_priv,494494- drm_radeon_kcmd_buffer_t * cmdbuf)492492+static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t *dev_priv,493493+ drm_radeon_kcmd_buffer_t *cmdbuf)495494{496495 u32 header;497496 int count;···555554 * Emit a rendering packet3 from userspace.556555 * Called by r300_do_cp_cmdbuf.557556 */558558-static __inline__ int r300_emit_packet3(drm_radeon_private_t * dev_priv,559559- drm_radeon_kcmd_buffer_t * cmdbuf,557557+static __inline__ int r300_emit_packet3(drm_radeon_private_t *dev_priv,558558+ drm_radeon_kcmd_buffer_t *cmdbuf,560559 drm_r300_cmd_header_t header)561560{562561 int n;···624623/**625624 * Emit the sequence to pacify R300.626625 */627627-static __inline__ void r300_pacify(drm_radeon_private_t * dev_priv)626626+static __inline__ void r300_pacify(drm_radeon_private_t *dev_priv)628627{629628 RING_LOCALS;630629···658657 * commands on the DMA ring buffer.659658 * Called by the ioctl handler function radeon_cp_cmdbuf.660659 */661661-int r300_do_cp_cmdbuf(drm_device_t * dev,660660+int r300_do_cp_cmdbuf(drm_device_t *dev,662661 DRMFILE filp,663663- drm_file_t * filp_priv, drm_radeon_kcmd_buffer_t * cmdbuf)662662+ drm_file_t *filp_priv,663663+ drm_radeon_kcmd_buffer_t *cmdbuf)664664{665665 drm_radeon_private_t *dev_priv = dev->dev_private;666666 drm_device_dma_t *dma = dev->dma;
···11-/* radeon_cp.c -- CP support for Radeon -*- linux-c -*-22- *11+/* radeon_cp.c -- CP support for Radeon -*- linux-c -*- */22+/*33 * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.44 * Copyright 2000 VA Linux Systems, Inc., Fremont, California.55 * All Rights Reserved.···824824 return RADEON_READ(RADEON_CLOCK_CNTL_DATA);825825}826826827827-static int RADEON_READ_PCIE(drm_radeon_private_t * dev_priv, int addr)827827+static int RADEON_READ_PCIE(drm_radeon_private_t *dev_priv, int addr)828828{829829 RADEON_WRITE8(RADEON_PCIE_INDEX, addr & 0xff);830830 return RADEON_READ(RADEON_PCIE_DATA);···11251125 | (dev_priv->fb_location >> 16));1126112611271127#if __OS_HAS_AGP11281128- if (!dev_priv->is_pci) {11281128+ if (dev_priv->flags & CHIP_IS_AGP) {11291129 RADEON_WRITE(RADEON_MC_AGP_LOCATION,11301130 (((dev_priv->gart_vm_start - 1 +11311131 dev_priv->gart_size) & 0xffff0000) |···11521152 dev_priv->ring.tail = cur_read_ptr;1153115311541154#if __OS_HAS_AGP11551155- if (!dev_priv->is_pci) {11551155+ if (dev_priv->flags & CHIP_IS_AGP) {11561156 /* set RADEON_AGP_BASE here instead of relying on X from user space */11571157 RADEON_WRITE(RADEON_AGP_BASE, (unsigned int)dev->agp->base);11581158 RADEON_WRITE(RADEON_CP_RB_RPTR_ADDR,···12781278/* Enable or disable PCI GART on the chip */12791279static void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on)12801280{12811281- u32 tmp = RADEON_READ(RADEON_AIC_CNTL);12811281+ u32 tmp;1282128212831283 if (dev_priv->flags & CHIP_IS_PCIE) {12841284 radeon_set_pciegart(dev_priv, on);12851285 return;12861286 }12871287+12881288+ tmp = RADEON_READ(RADEON_AIC_CNTL);1287128912881290 if (on) {12891291 RADEON_WRITE(RADEON_AIC_CNTL,···13141312static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)13151313{13161314 drm_radeon_private_t *dev_priv = dev->dev_private;13151315+13171316 DRM_DEBUG("\n");1318131713191319- dev_priv->is_pci = init->is_pci;13181318+ if (init->is_pci && (dev_priv->flags & CHIP_IS_AGP))13191319+ {13201320+ DRM_DEBUG("Forcing AGP card to PCI mode\n");13211321+ dev_priv->flags &= ~CHIP_IS_AGP;13221322+ }1320132313211321- if (dev_priv->is_pci && !dev->sg) {13241324+ if ((!(dev_priv->flags & CHIP_IS_AGP)) && !dev->sg) {13221325 DRM_ERROR("PCI GART memory not allocated!\n");13231323- dev->dev_private = (void *)dev_priv;13241326 radeon_do_cleanup_cp(dev);13251327 return DRM_ERR(EINVAL);13261328 }···13331327 if (dev_priv->usec_timeout < 1 ||13341328 dev_priv->usec_timeout > RADEON_MAX_USEC_TIMEOUT) {13351329 DRM_DEBUG("TIMEOUT problem!\n");13361336- dev->dev_private = (void *)dev_priv;13371330 radeon_do_cleanup_cp(dev);13381331 return DRM_ERR(EINVAL);13391332 }1340133313411341- switch (init->func) {13341334+ switch(init->func) {13421335 case RADEON_INIT_R200_CP:13431336 dev_priv->microcode_version = UCODE_R200;13441337 break;···13581353 if ((init->cp_mode != RADEON_CSQ_PRIBM_INDDIS) &&13591354 (init->cp_mode != RADEON_CSQ_PRIBM_INDBM)) {13601355 DRM_DEBUG("BAD cp_mode (%x)!\n", init->cp_mode);13611361- dev->dev_private = (void *)dev_priv;13621356 radeon_do_cleanup_cp(dev);13631357 return DRM_ERR(EINVAL);13641358 }···1420141614211417 DRM_GETSAREA();1422141814231423- dev_priv->fb_offset = init->fb_offset;14241424- dev_priv->mmio_offset = init->mmio_offset;14251419 dev_priv->ring_offset = init->ring_offset;14261420 dev_priv->ring_rptr_offset = init->ring_rptr_offset;14271421 dev_priv->buffers_offset = init->buffers_offset;···1427142514281426 if (!dev_priv->sarea) {14291427 DRM_ERROR("could not find sarea!\n");14301430- dev->dev_private = (void *)dev_priv;14311428 radeon_do_cleanup_cp(dev);14321429 return DRM_ERR(EINVAL);14331430 }1434143114351435- dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset);14361436- if (!dev_priv->mmio) {14371437- DRM_ERROR("could not find mmio region!\n");14381438- dev->dev_private = (void *)dev_priv;14391439- radeon_do_cleanup_cp(dev);14401440- return DRM_ERR(EINVAL);14411441- }14421432 dev_priv->cp_ring = drm_core_findmap(dev, init->ring_offset);14431433 if (!dev_priv->cp_ring) {14441434 DRM_ERROR("could not find cp ring region!\n");14451445- dev->dev_private = (void *)dev_priv;14461435 radeon_do_cleanup_cp(dev);14471436 return DRM_ERR(EINVAL);14481437 }14491438 dev_priv->ring_rptr = drm_core_findmap(dev, init->ring_rptr_offset);14501439 if (!dev_priv->ring_rptr) {14511440 DRM_ERROR("could not find ring read pointer!\n");14521452- dev->dev_private = (void *)dev_priv;14531441 radeon_do_cleanup_cp(dev);14541442 return DRM_ERR(EINVAL);14551443 }···14471455 dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);14481456 if (!dev->agp_buffer_map) {14491457 DRM_ERROR("could not find dma buffer region!\n");14501450- dev->dev_private = (void *)dev_priv;14511458 radeon_do_cleanup_cp(dev);14521459 return DRM_ERR(EINVAL);14531460 }···14561465 drm_core_findmap(dev, init->gart_textures_offset);14571466 if (!dev_priv->gart_textures) {14581467 DRM_ERROR("could not find GART texture region!\n");14591459- dev->dev_private = (void *)dev_priv;14601468 radeon_do_cleanup_cp(dev);14611469 return DRM_ERR(EINVAL);14621470 }···14661476 init->sarea_priv_offset);1467147714681478#if __OS_HAS_AGP14691469- if (!dev_priv->is_pci) {14791479+ if (dev_priv->flags & CHIP_IS_AGP) {14701480 drm_core_ioremap(dev_priv->cp_ring, dev);14711481 drm_core_ioremap(dev_priv->ring_rptr, dev);14721482 drm_core_ioremap(dev->agp_buffer_map, dev);···14741484 !dev_priv->ring_rptr->handle ||14751485 !dev->agp_buffer_map->handle) {14761486 DRM_ERROR("could not find ioremap agp regions!\n");14771477- dev->dev_private = (void *)dev_priv;14781487 radeon_do_cleanup_cp(dev);14791488 return DRM_ERR(EINVAL);14801489 }···15141525 + RADEON_READ(RADEON_CONFIG_APER_SIZE);1515152615161527#if __OS_HAS_AGP15171517- if (!dev_priv->is_pci)15281528+ if (dev_priv->flags & CHIP_IS_AGP)15181529 dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset15191530 - dev->agp->base15201531 + dev_priv->gart_vm_start);···15401551 dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK;1541155215421553#if __OS_HAS_AGP15431543- if (!dev_priv->is_pci) {15541554+ if (dev_priv->flags & CHIP_IS_AGP) {15441555 /* Turn off PCI GART */15451556 radeon_set_pcigart(dev_priv, 0);15461557 } else···15501561 if (dev_priv->pcigart_offset) {15511562 dev_priv->gart_info.bus_addr =15521563 dev_priv->pcigart_offset + dev_priv->fb_location;15641564+ dev_priv->gart_info.mapping.offset =15651565+ dev_priv->gart_info.bus_addr;15661566+ dev_priv->gart_info.mapping.size =15671567+ RADEON_PCIGART_TABLE_SIZE;15681568+15691569+ drm_core_ioremap(&dev_priv->gart_info.mapping, dev);15531570 dev_priv->gart_info.addr =15541554- (unsigned long)drm_ioremap(dev_priv->gart_info.15551555- bus_addr,15561556- RADEON_PCIGART_TABLE_SIZE,15571557- dev);15711571+ dev_priv->gart_info.mapping.handle;1558157215591573 dev_priv->gart_info.is_pcie =15601574 !!(dev_priv->flags & CHIP_IS_PCIE);15611575 dev_priv->gart_info.gart_table_location =15621576 DRM_ATI_GART_FB;1563157715641564- DRM_DEBUG("Setting phys_pci_gart to %08lX %08lX\n",15781578+ DRM_DEBUG("Setting phys_pci_gart to %p %08lX\n",15651579 dev_priv->gart_info.addr,15661580 dev_priv->pcigart_offset);15671581 } else {15681582 dev_priv->gart_info.gart_table_location =15691583 DRM_ATI_GART_MAIN;15701570- dev_priv->gart_info.addr =15711571- dev_priv->gart_info.bus_addr = 0;15841584+ dev_priv->gart_info.addr = NULL;15851585+ dev_priv->gart_info.bus_addr = 0;15721586 if (dev_priv->flags & CHIP_IS_PCIE) {15731587 DRM_ERROR15741588 ("Cannot use PCI Express without GART in FB memory\n");···1582159015831591 if (!drm_ati_pcigart_init(dev, &dev_priv->gart_info)) {15841592 DRM_ERROR("failed to init PCI GART!\n");15851585- dev->dev_private = (void *)dev_priv;15861593 radeon_do_cleanup_cp(dev);15871594 return DRM_ERR(ENOMEM);15881595 }···15941603 radeon_cp_init_ring_buffer(dev, dev_priv);1595160415961605 dev_priv->last_buf = 0;15971597-15981598- dev->dev_private = (void *)dev_priv;1599160616001607 radeon_do_engine_reset(dev);16011608···16131624 drm_irq_uninstall(dev);1614162516151626#if __OS_HAS_AGP16161616- if (!dev_priv->is_pci) {16171617- if (dev_priv->cp_ring != NULL)16271627+ if (dev_priv->flags & CHIP_IS_AGP) {16281628+ if (dev_priv->cp_ring != NULL) {16181629 drm_core_ioremapfree(dev_priv->cp_ring, dev);16191619- if (dev_priv->ring_rptr != NULL)16301630+ dev_priv->cp_ring = NULL;16311631+ }16321632+ if (dev_priv->ring_rptr != NULL) {16201633 drm_core_ioremapfree(dev_priv->ring_rptr, dev);16341634+ dev_priv->ring_rptr = NULL;16351635+ }16211636 if (dev->agp_buffer_map != NULL) {16221637 drm_core_ioremapfree(dev->agp_buffer_map, dev);16231638 dev->agp_buffer_map = NULL;···16291636 } else16301637#endif16311638 {16321632- if (dev_priv->gart_info.bus_addr)16391639+16401640+ if (dev_priv->gart_info.bus_addr) {16411641+ /* Turn off PCI GART */16421642+ radeon_set_pcigart(dev_priv, 0);16331643 if (!drm_ati_pcigart_cleanup(dev, &dev_priv->gart_info))16341644 DRM_ERROR("failed to cleanup PCI GART!\n");16451645+ }1635164616361636- if (dev_priv->gart_info.gart_table_location == DRM_ATI_GART_FB) {16371637- drm_ioremapfree((void *)dev_priv->gart_info.addr,16381638- RADEON_PCIGART_TABLE_SIZE, dev);16471647+ if (dev_priv->gart_info.gart_table_location == DRM_ATI_GART_FB)16481648+ {16491649+ drm_core_ioremapfree(&dev_priv->gart_info.mapping, dev);16391650 dev_priv->gart_info.addr = 0;16401651 }16411652 }16421642-16431653 /* only clear to the start of flags */16441654 memset(dev_priv, 0, offsetof(drm_radeon_private_t, flags));16451655···16681672 DRM_DEBUG("Starting radeon_do_resume_cp()\n");1669167316701674#if __OS_HAS_AGP16711671- if (!dev_priv->is_pci) {16751675+ if (dev_priv->flags & CHIP_IS_AGP) {16721676 /* Turn off PCI GART */16731677 radeon_set_pcigart(dev_priv, 0);16741678 } else···20992103 return ret;21002104}2101210521022102-int radeon_driver_preinit(struct drm_device *dev, unsigned long flags)21062106+int radeon_driver_load(struct drm_device *dev, unsigned long flags)21032107{21042108 drm_radeon_private_t *dev_priv;21052109 int ret = 0;···21322136 dev_priv->flags |= CHIP_IS_PCIE;2133213721342138 DRM_DEBUG("%s card detected\n",21352135- ((dev_priv->flags & CHIP_IS_AGP) ? "AGP" : "PCI"));21392139+ ((dev_priv->flags & CHIP_IS_AGP) ? "AGP" : (((dev_priv->flags & CHIP_IS_PCIE) ? "PCIE" : "PCI"))));21362140 return ret;21372141}2138214221392139-int radeon_presetup(struct drm_device *dev)21432143+/* Create mappings for registers and framebuffer so userland doesn't necessarily21442144+ * have to find them.21452145+ */21462146+int radeon_driver_firstopen(struct drm_device *dev)21402147{21412148 int ret;21422149 drm_local_map_t *map;···21602161 return 0;21612162}2162216321632163-int radeon_driver_postcleanup(struct drm_device *dev)21642164+int radeon_driver_unload(struct drm_device *dev)21642165{21652166 drm_radeon_private_t *dev_priv = dev->dev_private;2166216721672168 DRM_DEBUG("\n");21682168-21692169 drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER);2170217021712171 dev->dev_private = NULL;
+6
drivers/char/drm/radeon_drm.h
···624624 int discard;625625} drm_radeon_indirect_t;626626627627+/* enum for card type parameters */628628+#define RADEON_CARD_PCI 0629629+#define RADEON_CARD_AGP 1630630+#define RADEON_CARD_PCIE 2631631+627632/* 1.3: An ioctl to get parameters that aren't available to the 3d628633 * client any other way.629634 */···645640#define RADEON_PARAM_SAREA_HANDLE 9646641#define RADEON_PARAM_GART_TEX_HANDLE 10647642#define RADEON_PARAM_SCRATCH_OFFSET 11643643+#define RADEON_PARAM_CARD_TYPE 12648644649645typedef struct drm_radeon_getparam {650646 int param;
···11-/* savage_drv.h -- Private header for the savage driver22- *11+/* savage_drv.h -- Private header for the savage driver */22+/*33 * Copyright 2004 Felix Kuehling44 * All Rights Reserved.55 *···192192 /* Err, there is a macro wait_event in include/linux/wait.h.193193 * Avoid unwanted macro expansion. */194194 void (*emit_clip_rect) (struct drm_savage_private * dev_priv,195195- drm_clip_rect_t * pbox);195195+ const drm_clip_rect_t * pbox);196196 void (*dma_flush) (struct drm_savage_private * dev_priv);197197} drm_savage_private_t;198198···208208extern void savage_dma_wait(drm_savage_private_t * dev_priv, unsigned int page);209209extern uint32_t *savage_dma_alloc(drm_savage_private_t * dev_priv,210210 unsigned int n);211211-extern int savage_preinit(drm_device_t * dev, unsigned long chipset);212212-extern int savage_postcleanup(drm_device_t * dev);211211+extern int savage_driver_load(drm_device_t *dev, unsigned long chipset);212212+extern int savage_driver_firstopen(drm_device_t *dev);213213+extern void savage_driver_lastclose(drm_device_t *dev);214214+extern int savage_driver_unload(drm_device_t *dev);213215extern int savage_do_cleanup_bci(drm_device_t * dev);214216extern void savage_reclaim_buffers(drm_device_t * dev, DRMFILE filp);215217216218/* state functions */217219extern void savage_emit_clip_rect_s3d(drm_savage_private_t * dev_priv,218218- drm_clip_rect_t * pbox);220220+ const drm_clip_rect_t * pbox);219221extern void savage_emit_clip_rect_s4(drm_savage_private_t * dev_priv,220220- drm_clip_rect_t * pbox);222222+ const drm_clip_rect_t * pbox);221223222224#define SAVAGE_FB_SIZE_S3 0x01000000 /* 16MB */223225#define SAVAGE_FB_SIZE_S4 0x02000000 /* 32MB */···502500503501#define BCI_WRITE( val ) *bci_ptr++ = (uint32_t)(val)504502505505-#define BCI_COPY_FROM_USER(src,n) do { \506506- unsigned int i; \507507- for (i = 0; i < n; ++i) { \508508- uint32_t val; \509509- DRM_GET_USER_UNCHECKED(val, &((uint32_t*)(src))[i]); \510510- BCI_WRITE(val); \511511- } \512512-} while(0)513513-514503/*515504 * command DMA support516505 */···527534528535#define DMA_WRITE( val ) *dma_ptr++ = (uint32_t)(val)529536530530-#define DMA_COPY_FROM_USER(src,n) do { \531531- DRM_COPY_FROM_USER_UNCHECKED(dma_ptr, (src), (n)*4); \537537+#define DMA_COPY(src, n) do { \538538+ memcpy(dma_ptr, (src), (n)*4); \532539 dma_ptr += n; \533540} while(0)534541
+164-160
drivers/char/drm/savage_state.c
···2727#include "savage_drv.h"28282929void savage_emit_clip_rect_s3d(drm_savage_private_t * dev_priv,3030- drm_clip_rect_t * pbox)3030+ const drm_clip_rect_t * pbox)3131{3232 uint32_t scstart = dev_priv->state.s3d.new_scstart;3333 uint32_t scend = dev_priv->state.s3d.new_scend;···5353}54545555void savage_emit_clip_rect_s4(drm_savage_private_t * dev_priv,5656- drm_clip_rect_t * pbox)5656+ const drm_clip_rect_t * pbox)5757{5858 uint32_t drawctrl0 = dev_priv->state.s4.new_drawctrl0;5959 uint32_t drawctrl1 = dev_priv->state.s4.new_drawctrl1;···115115116116#define SAVE_STATE(reg,where) \117117 if(start <= reg && start+count > reg) \118118- DRM_GET_USER_UNCHECKED(dev_priv->state.where, ®s[reg-start])118118+ dev_priv->state.where = regs[reg - start]119119#define SAVE_STATE_MASK(reg,where,mask) do { \120120 if(start <= reg && start+count > reg) { \121121 uint32_t tmp; \122122- DRM_GET_USER_UNCHECKED(tmp, ®s[reg-start]); \122122+ tmp = regs[reg - start]; \123123 dev_priv->state.where = (tmp & (mask)) | \124124 (dev_priv->state.where & ~(mask)); \125125 } \126126} while (0)127127+127128static int savage_verify_state_s3d(drm_savage_private_t * dev_priv,128129 unsigned int start, unsigned int count,129129- const uint32_t __user * regs)130130+ const uint32_t *regs)130131{131132 if (start < SAVAGE_TEXPALADDR_S3D ||132133 start + count - 1 > SAVAGE_DESTTEXRWWATERMARK_S3D) {···149148 SAVE_STATE(SAVAGE_TEXADDR_S3D, s3d.texaddr);150149 if (dev_priv->state.s3d.texctrl & SAVAGE_TEXCTRL_TEXEN_MASK)151150 return savage_verify_texaddr(dev_priv, 0,152152- dev_priv->state.s3d.153153- texaddr);151151+ dev_priv->state.s3d.texaddr);154152 }155153156154 return 0;···157157158158static int savage_verify_state_s4(drm_savage_private_t * dev_priv,159159 unsigned int start, unsigned int count,160160- const uint32_t __user * regs)160160+ const uint32_t *regs)161161{162162 int ret = 0;163163···174174 ~SAVAGE_SCISSOR_MASK_S4);175175176176 /* if any texture regs were changed ... */177177- if (start <= SAVAGE_TEXDESCR_S4 && start + count > SAVAGE_TEXPALADDR_S4) {177177+ if (start <= SAVAGE_TEXDESCR_S4 &&178178+ start + count > SAVAGE_TEXPALADDR_S4) {178179 /* ... check texture state */179180 SAVE_STATE(SAVAGE_TEXDESCR_S4, s4.texdescr);180181 SAVE_STATE(SAVAGE_TEXADDR0_S4, s4.texaddr0);181182 SAVE_STATE(SAVAGE_TEXADDR1_S4, s4.texaddr1);182183 if (dev_priv->state.s4.texdescr & SAVAGE_TEXDESCR_TEX0EN_MASK)183183- ret |=184184- savage_verify_texaddr(dev_priv, 0,185185- dev_priv->state.s4.texaddr0);184184+ ret |= savage_verify_texaddr(dev_priv, 0,185185+ dev_priv->state.s4.texaddr0);186186 if (dev_priv->state.s4.texdescr & SAVAGE_TEXDESCR_TEX1EN_MASK)187187- ret |=188188- savage_verify_texaddr(dev_priv, 1,189189- dev_priv->state.s4.texaddr1);187187+ ret |= savage_verify_texaddr(dev_priv, 1,188188+ dev_priv->state.s4.texaddr1);190189 }191190192191 return ret;···196197197198static int savage_dispatch_state(drm_savage_private_t * dev_priv,198199 const drm_savage_cmd_header_t * cmd_header,199199- const uint32_t __user * regs)200200+ const uint32_t *regs)200201{201202 unsigned int count = cmd_header->state.count;202203 unsigned int start = cmd_header->state.start;···207208208209 if (!count)209210 return 0;210210-211211- if (DRM_VERIFYAREA_READ(regs, count * 4))212212- return DRM_ERR(EFAULT);213211214212 if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {215213 ret = savage_verify_state_s3d(dev_priv, start, count, regs);···232236 /* scissor regs are emitted in savage_dispatch_draw */233237 if (start < SAVAGE_DRAWCTRL0_S4) {234238 if (start + count > SAVAGE_DRAWCTRL1_S4 + 1)235235- count2 =236236- count - (SAVAGE_DRAWCTRL1_S4 + 1 - start);239239+ count2 = count -240240+ (SAVAGE_DRAWCTRL1_S4 + 1 - start);237241 if (start + count > SAVAGE_DRAWCTRL0_S4)238242 count = SAVAGE_DRAWCTRL0_S4 - start;239243 } else if (start <= SAVAGE_DRAWCTRL1_S4) {···259263 while (count > 0) {260264 unsigned int n = count < 255 ? count : 255;261265 DMA_SET_REGISTERS(start, n);262262- DMA_COPY_FROM_USER(regs, n);266266+ DMA_COPY(regs, n);263267 count -= n;264268 start += n;265269 regs += n;···417421418422static int savage_dispatch_vb_prim(drm_savage_private_t * dev_priv,419423 const drm_savage_cmd_header_t * cmd_header,420420- const uint32_t __user * vtxbuf,421421- unsigned int vb_size, unsigned int vb_stride)424424+ const uint32_t *vtxbuf, unsigned int vb_size,425425+ unsigned int vb_stride)422426{423427 unsigned char reorder = 0;424428 unsigned int prim = cmd_header->prim.prim;···503507504508 for (i = start; i < start + count; ++i) {505509 unsigned int j = i + reorder[i % 3];506506- DMA_COPY_FROM_USER(&vtxbuf[vb_stride * j],507507- vtx_size);510510+ DMA_COPY(&vtxbuf[vb_stride * j], vtx_size);508511 }509512510513 DMA_COMMIT();···512517 DMA_DRAW_PRIMITIVE(count, prim, skip);513518514519 if (vb_stride == vtx_size) {515515- DMA_COPY_FROM_USER(&vtxbuf[vb_stride * start],516516- vtx_size * count);520520+ DMA_COPY(&vtxbuf[vb_stride * start], 521521+ vtx_size * count);517522 } else {518523 for (i = start; i < start + count; ++i) {519519- DMA_COPY_FROM_USER(&vtxbuf520520- [vb_stride * i],521521- vtx_size);524524+ DMA_COPY(&vtxbuf [vb_stride * i],525525+ vtx_size);522526 }523527 }524528···535541536542static int savage_dispatch_dma_idx(drm_savage_private_t * dev_priv,537543 const drm_savage_cmd_header_t * cmd_header,538538- const uint16_t __user * usr_idx,544544+ const uint16_t *idx,539545 const drm_buf_t * dmabuf)540546{541547 unsigned char reorder = 0;···622628 while (n != 0) {623629 /* Can emit up to 255 indices (85 triangles) at once. */624630 unsigned int count = n > 255 ? 255 : n;625625- /* Is it ok to allocate 510 bytes on the stack in an ioctl? */626626- uint16_t idx[255];627631628628- /* Copy and check indices */629629- DRM_COPY_FROM_USER_UNCHECKED(idx, usr_idx, count * 2);632632+ /* check indices */630633 for (i = 0; i < count; ++i) {631634 if (idx[i] > dmabuf->total / 32) {632635 DRM_ERROR("idx[%u]=%u out of range (0-%u)\n",···643652644653 for (i = 1; i + 1 < count; i += 2)645654 BCI_WRITE(idx[i + reorder[i % 3]] |646646- (idx[i + 1 + reorder[(i + 1) % 3]] <<647647- 16));655655+ (idx[i + 1 +656656+ reorder[(i + 1) % 3]] << 16));648657 if (i < count)649658 BCI_WRITE(idx[i + reorder[i % 3]]);650659 } else if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {···665674 BCI_WRITE(idx[i]);666675 }667676668668- usr_idx += count;677677+ idx += count;669678 n -= count;670679671680 prim |= BCI_CMD_DRAW_CONT;···676685677686static int savage_dispatch_vb_idx(drm_savage_private_t * dev_priv,678687 const drm_savage_cmd_header_t * cmd_header,679679- const uint16_t __user * usr_idx,680680- const uint32_t __user * vtxbuf,688688+ const uint16_t *idx,689689+ const uint32_t *vtxbuf,681690 unsigned int vb_size, unsigned int vb_stride)682691{683692 unsigned char reorder = 0;···742751 while (n != 0) {743752 /* Can emit up to 255 vertices (85 triangles) at once. */744753 unsigned int count = n > 255 ? 255 : n;745745- /* Is it ok to allocate 510 bytes on the stack in an ioctl? */746746- uint16_t idx[255];747747-748748- /* Copy and check indices */749749- DRM_COPY_FROM_USER_UNCHECKED(idx, usr_idx, count * 2);754754+755755+ /* Check indices */750756 for (i = 0; i < count; ++i) {751757 if (idx[i] > vb_size / (vb_stride * 4)) {752758 DRM_ERROR("idx[%u]=%u out of range (0-%u)\n",···763775764776 for (i = 0; i < count; ++i) {765777 unsigned int j = idx[i + reorder[i % 3]];766766- DMA_COPY_FROM_USER(&vtxbuf[vb_stride * j],767767- vtx_size);778778+ DMA_COPY(&vtxbuf[vb_stride * j], vtx_size);768779 }769780770781 DMA_COMMIT();···773786774787 for (i = 0; i < count; ++i) {775788 unsigned int j = idx[i];776776- DMA_COPY_FROM_USER(&vtxbuf[vb_stride * j],777777- vtx_size);789789+ DMA_COPY(&vtxbuf[vb_stride * j], vtx_size);778790 }779791780792 DMA_COMMIT();781793 }782794783783- usr_idx += count;795795+ idx += count;784796 n -= count;785797786798 prim |= BCI_CMD_DRAW_CONT;···790804791805static int savage_dispatch_clear(drm_savage_private_t * dev_priv,792806 const drm_savage_cmd_header_t * cmd_header,793793- const drm_savage_cmd_header_t __user * data,807807+ const drm_savage_cmd_header_t *data,794808 unsigned int nbox,795795- const drm_clip_rect_t __user * usr_boxes)809809+ const drm_clip_rect_t *boxes)796810{797797- unsigned int flags = cmd_header->clear0.flags, mask, value;811811+ unsigned int flags = cmd_header->clear0.flags;798812 unsigned int clear_cmd;799813 unsigned int i, nbufs;800814 DMA_LOCALS;801815802816 if (nbox == 0)803817 return 0;804804-805805- DRM_GET_USER_UNCHECKED(mask, &data->clear1.mask);806806- DRM_GET_USER_UNCHECKED(value, &data->clear1.value);807818808819 clear_cmd = BCI_CMD_RECT | BCI_CMD_RECT_XP | BCI_CMD_RECT_YP |809820 BCI_CMD_SEND_COLOR | BCI_CMD_DEST_PBD_NEW;···811828 if (nbufs == 0)812829 return 0;813830814814- if (mask != 0xffffffff) {831831+ if (data->clear1.mask != 0xffffffff) {815832 /* set mask */816833 BEGIN_DMA(2);817834 DMA_SET_REGISTERS(SAVAGE_BITPLANEWTMASK, 1);818818- DMA_WRITE(mask);835835+ DMA_WRITE(data->clear1.mask);819836 DMA_COMMIT();820837 }821838 for (i = 0; i < nbox; ++i) {822822- drm_clip_rect_t box;823839 unsigned int x, y, w, h;824840 unsigned int buf;825825- DRM_COPY_FROM_USER_UNCHECKED(&box, &usr_boxes[i], sizeof(box));826826- x = box.x1, y = box.y1;827827- w = box.x2 - box.x1;828828- h = box.y2 - box.y1;841841+ x = boxes[i].x1, y = boxes[i].y1;842842+ w = boxes[i].x2 - boxes[i].x1;843843+ h = boxes[i].y2 - boxes[i].y1;829844 BEGIN_DMA(nbufs * 6);830845 for (buf = SAVAGE_FRONT; buf <= SAVAGE_DEPTH; buf <<= 1) {831846 if (!(flags & buf))···843862 DMA_WRITE(dev_priv->depth_bd);844863 break;845864 }846846- DMA_WRITE(value);865865+ DMA_WRITE(data->clear1.value);847866 DMA_WRITE(BCI_X_Y(x, y));848867 DMA_WRITE(BCI_W_H(w, h));849868 }850869 DMA_COMMIT();851870 }852852- if (mask != 0xffffffff) {871871+ if (data->clear1.mask != 0xffffffff) {853872 /* reset mask */854873 BEGIN_DMA(2);855874 DMA_SET_REGISTERS(SAVAGE_BITPLANEWTMASK, 1);···861880}862881863882static int savage_dispatch_swap(drm_savage_private_t * dev_priv,864864- unsigned int nbox,865865- const drm_clip_rect_t __user * usr_boxes)883883+ unsigned int nbox, const drm_clip_rect_t *boxes)866884{867885 unsigned int swap_cmd;868886 unsigned int i;···875895 BCI_CMD_SET_ROP(swap_cmd, 0xCC);876896877897 for (i = 0; i < nbox; ++i) {878878- drm_clip_rect_t box;879879- DRM_COPY_FROM_USER_UNCHECKED(&box, &usr_boxes[i], sizeof(box));880880-881898 BEGIN_DMA(6);882899 DMA_WRITE(swap_cmd);883900 DMA_WRITE(dev_priv->back_offset);884901 DMA_WRITE(dev_priv->back_bd);885885- DMA_WRITE(BCI_X_Y(box.x1, box.y1));886886- DMA_WRITE(BCI_X_Y(box.x1, box.y1));887887- DMA_WRITE(BCI_W_H(box.x2 - box.x1, box.y2 - box.y1));902902+ DMA_WRITE(BCI_X_Y(boxes[i].x1, boxes[i].y1));903903+ DMA_WRITE(BCI_X_Y(boxes[i].x1, boxes[i].y1));904904+ DMA_WRITE(BCI_W_H(boxes[i].x2 - boxes[i].x1,905905+ boxes[i].y2 - boxes[i].y1));888906 DMA_COMMIT();889907 }890908···890912}891913892914static int savage_dispatch_draw(drm_savage_private_t * dev_priv,893893- const drm_savage_cmd_header_t __user * start,894894- const drm_savage_cmd_header_t __user * end,915915+ const drm_savage_cmd_header_t *start,916916+ const drm_savage_cmd_header_t *end,895917 const drm_buf_t * dmabuf,896896- const unsigned int __user * usr_vtxbuf,918918+ const unsigned int *vtxbuf,897919 unsigned int vb_size, unsigned int vb_stride,898920 unsigned int nbox,899899- const drm_clip_rect_t __user * usr_boxes)921921+ const drm_clip_rect_t *boxes)900922{901923 unsigned int i, j;902924 int ret;903925904926 for (i = 0; i < nbox; ++i) {905905- drm_clip_rect_t box;906906- const drm_savage_cmd_header_t __user *usr_cmdbuf;907907- DRM_COPY_FROM_USER_UNCHECKED(&box, &usr_boxes[i], sizeof(box));908908- dev_priv->emit_clip_rect(dev_priv, &box);927927+ const drm_savage_cmd_header_t *cmdbuf;928928+ dev_priv->emit_clip_rect(dev_priv, &boxes[i]);909929910910- usr_cmdbuf = start;911911- while (usr_cmdbuf < end) {930930+ cmdbuf = start;931931+ while (cmdbuf < end) {912932 drm_savage_cmd_header_t cmd_header;913913- DRM_COPY_FROM_USER_UNCHECKED(&cmd_header, usr_cmdbuf,914914- sizeof(cmd_header));915915- usr_cmdbuf++;933933+ cmd_header = *cmdbuf;934934+ cmdbuf++;916935 switch (cmd_header.cmd.cmd) {917936 case SAVAGE_CMD_DMA_PRIM:918918- ret =919919- savage_dispatch_dma_prim(dev_priv,920920- &cmd_header,921921- dmabuf);937937+ ret = savage_dispatch_dma_prim(938938+ dev_priv, &cmd_header, dmabuf);922939 break;923940 case SAVAGE_CMD_VB_PRIM:924924- ret =925925- savage_dispatch_vb_prim(dev_priv,926926- &cmd_header,927927- (const uint32_t928928- __user *)929929- usr_vtxbuf, vb_size,930930- vb_stride);941941+ ret = savage_dispatch_vb_prim(942942+ dev_priv, &cmd_header,943943+ vtxbuf, vb_size, vb_stride);931944 break;932945 case SAVAGE_CMD_DMA_IDX:933946 j = (cmd_header.idx.count + 3) / 4;934947 /* j was check in savage_bci_cmdbuf */935935- ret =936936- savage_dispatch_dma_idx(dev_priv,937937- &cmd_header,938938- (const uint16_t939939- __user *)940940- usr_cmdbuf, dmabuf);941941- usr_cmdbuf += j;948948+ ret = savage_dispatch_dma_idx(dev_priv,949949+ &cmd_header, (const uint16_t *)cmdbuf,950950+ dmabuf);951951+ cmdbuf += j;942952 break;943953 case SAVAGE_CMD_VB_IDX:944954 j = (cmd_header.idx.count + 3) / 4;945955 /* j was check in savage_bci_cmdbuf */946946- ret =947947- savage_dispatch_vb_idx(dev_priv,948948- &cmd_header,949949- (const uint16_t950950- __user *)usr_cmdbuf,951951- (const uint32_t952952- __user *)usr_vtxbuf,953953- vb_size, vb_stride);954954- usr_cmdbuf += j;956956+ ret = savage_dispatch_vb_idx(dev_priv,957957+ &cmd_header, (const uint16_t *)cmdbuf,958958+ (const uint32_t *)vtxbuf, vb_size, 959959+ vb_stride);960960+ cmdbuf += j;955961 break;956962 default:957963 /* What's the best return code? EFAULT? */···960998 drm_device_dma_t *dma = dev->dma;961999 drm_buf_t *dmabuf;9621000 drm_savage_cmdbuf_t cmdbuf;963963- drm_savage_cmd_header_t __user *usr_cmdbuf;964964- drm_savage_cmd_header_t __user *first_draw_cmd;965965- unsigned int __user *usr_vtxbuf;966966- drm_clip_rect_t __user *usr_boxes;10011001+ drm_savage_cmd_header_t *kcmd_addr = NULL;10021002+ drm_savage_cmd_header_t *first_draw_cmd;10031003+ unsigned int *kvb_addr = NULL;10041004+ drm_clip_rect_t *kbox_addr = NULL;9671005 unsigned int i, j;9681006 int ret = 0;9691007···9861024 dmabuf = NULL;9871025 }9881026989989- usr_cmdbuf = (drm_savage_cmd_header_t __user *) cmdbuf.cmd_addr;990990- usr_vtxbuf = (unsigned int __user *)cmdbuf.vb_addr;991991- usr_boxes = (drm_clip_rect_t __user *) cmdbuf.box_addr;992992- if ((cmdbuf.size && DRM_VERIFYAREA_READ(usr_cmdbuf, cmdbuf.size * 8)) ||993993- (cmdbuf.vb_size && DRM_VERIFYAREA_READ(usr_vtxbuf, cmdbuf.vb_size))994994- || (cmdbuf.nbox995995- && DRM_VERIFYAREA_READ(usr_boxes,996996- cmdbuf.nbox * sizeof(drm_clip_rect_t))))997997- return DRM_ERR(EFAULT);10271027+ /* Copy the user buffers into kernel temporary areas. This hasn't been10281028+ * a performance loss compared to VERIFYAREA_READ/10291029+ * COPY_FROM_USER_UNCHECKED when done in other drivers, and is correct10301030+ * for locking on FreeBSD.10311031+ */10321032+ if (cmdbuf.size) {10331033+ kcmd_addr = drm_alloc(cmdbuf.size * 8, DRM_MEM_DRIVER);10341034+ if (kcmd_addr == NULL)10351035+ return ENOMEM;10361036+10371037+ if (DRM_COPY_FROM_USER(kcmd_addr, cmdbuf.cmd_addr,10381038+ cmdbuf.size * 8))10391039+ {10401040+ drm_free(kcmd_addr, cmdbuf.size * 8, DRM_MEM_DRIVER);10411041+ return DRM_ERR(EFAULT);10421042+ }10431043+ cmdbuf.cmd_addr = kcmd_addr;10441044+ }10451045+ if (cmdbuf.vb_size) {10461046+ kvb_addr = drm_alloc(cmdbuf.vb_size, DRM_MEM_DRIVER);10471047+ if (kvb_addr == NULL) {10481048+ ret = DRM_ERR(ENOMEM);10491049+ goto done;10501050+ }10511051+10521052+ if (DRM_COPY_FROM_USER(kvb_addr, cmdbuf.vb_addr,10531053+ cmdbuf.vb_size)) {10541054+ ret = DRM_ERR(EFAULT);10551055+ goto done;10561056+ }10571057+ cmdbuf.vb_addr = kvb_addr;10581058+ }10591059+ if (cmdbuf.nbox) {10601060+ kbox_addr = drm_alloc(cmdbuf.nbox * sizeof(drm_clip_rect_t),10611061+ DRM_MEM_DRIVER);10621062+ if (kbox_addr == NULL) {10631063+ ret = DRM_ERR(ENOMEM);10641064+ goto done;10651065+ }10661066+10671067+ if (DRM_COPY_FROM_USER(kbox_addr, cmdbuf.box_addr,10681068+ cmdbuf.nbox * sizeof(drm_clip_rect_t))) {10691069+ ret = DRM_ERR(EFAULT);10701070+ goto done;10711071+ }10721072+ cmdbuf.box_addr = kbox_addr;10731073+ }99810749991075 /* Make sure writes to DMA buffers are finished before sending10001076 * DMA commands to the graphics hardware. */···10461046 first_draw_cmd = NULL;10471047 while (i < cmdbuf.size) {10481048 drm_savage_cmd_header_t cmd_header;10491049- DRM_COPY_FROM_USER_UNCHECKED(&cmd_header, usr_cmdbuf,10501050- sizeof(cmd_header));10511051- usr_cmdbuf++;10491049+ cmd_header = *(drm_savage_cmd_header_t *)cmdbuf.cmd_addr;10501050+ cmdbuf.cmd_addr++;10521051 i++;1053105210541053 /* Group drawing commands with same state to minimize···10671068 case SAVAGE_CMD_DMA_PRIM:10681069 case SAVAGE_CMD_VB_PRIM:10691070 if (!first_draw_cmd)10701070- first_draw_cmd = usr_cmdbuf - 1;10711071- usr_cmdbuf += j;10711071+ first_draw_cmd = cmdbuf.cmd_addr - 1;10721072+ cmdbuf.cmd_addr += j;10721073 i += j;10731074 break;10741075 default:10751076 if (first_draw_cmd) {10761076- ret =10771077- savage_dispatch_draw(dev_priv,10781078- first_draw_cmd,10791079- usr_cmdbuf - 1, dmabuf,10801080- usr_vtxbuf,10811081- cmdbuf.vb_size,10821082- cmdbuf.vb_stride,10831083- cmdbuf.nbox,10841084- usr_boxes);10771077+ ret = savage_dispatch_draw(10781078+ dev_priv, first_draw_cmd,10791079+ cmdbuf.cmd_addr - 1,10801080+ dmabuf, cmdbuf.vb_addr, cmdbuf.vb_size,10811081+ cmdbuf.vb_stride,10821082+ cmdbuf.nbox, cmdbuf.box_addr);10851083 if (ret != 0)10861084 return ret;10871085 first_draw_cmd = NULL;···10941098 DRM_ERROR("command SAVAGE_CMD_STATE extends "10951099 "beyond end of command buffer\n");10961100 DMA_FLUSH();10971097- return DRM_ERR(EINVAL);11011101+ ret = DRM_ERR(EINVAL);11021102+ goto done;10981103 }10991104 ret = savage_dispatch_state(dev_priv, &cmd_header,11001100- (uint32_t __user *)11011101- usr_cmdbuf);11021102- usr_cmdbuf += j;11051105+ (const uint32_t *)cmdbuf.cmd_addr);11061106+ cmdbuf.cmd_addr += j;11031107 i += j;11041108 break;11051109 case SAVAGE_CMD_CLEAR:···11071111 DRM_ERROR("command SAVAGE_CMD_CLEAR extends "11081112 "beyond end of command buffer\n");11091113 DMA_FLUSH();11101110- return DRM_ERR(EINVAL);11141114+ ret = DRM_ERR(EINVAL);11151115+ goto done;11111116 }11121117 ret = savage_dispatch_clear(dev_priv, &cmd_header,11131113- usr_cmdbuf,11141114- cmdbuf.nbox, usr_boxes);11151115- usr_cmdbuf++;11181118+ cmdbuf.cmd_addr,11191119+ cmdbuf.nbox, cmdbuf.box_addr);11201120+ cmdbuf.cmd_addr++;11161121 i++;11171122 break;11181123 case SAVAGE_CMD_SWAP:11191119- ret = savage_dispatch_swap(dev_priv,11201120- cmdbuf.nbox, usr_boxes);11241124+ ret = savage_dispatch_swap(dev_priv, cmdbuf.nbox,11251125+ cmdbuf.box_addr);11211126 break;11221127 default:11231128 DRM_ERROR("invalid command 0x%x\n", cmd_header.cmd.cmd);11241129 DMA_FLUSH();11251125- return DRM_ERR(EINVAL);11301130+ ret = DRM_ERR(EINVAL);11311131+ goto done;11261132 }1127113311281134 if (ret != 0) {11291135 DMA_FLUSH();11301130- return ret;11361136+ goto done;11311137 }11321138 }1133113911341140 if (first_draw_cmd) {11351135- ret =11361136- savage_dispatch_draw(dev_priv, first_draw_cmd, usr_cmdbuf,11371137- dmabuf, usr_vtxbuf, cmdbuf.vb_size,11381138- cmdbuf.vb_stride, cmdbuf.nbox,11391139- usr_boxes);11411141+ ret = savage_dispatch_draw (11421142+ dev_priv, first_draw_cmd, cmdbuf.cmd_addr, dmabuf,11431143+ cmdbuf.vb_addr, cmdbuf.vb_size, cmdbuf.vb_stride,11441144+ cmdbuf.nbox, cmdbuf.box_addr);11401145 if (ret != 0) {11411146 DMA_FLUSH();11421142- return ret;11471147+ goto done;11431148 }11441149 }11451150···11541157 savage_freelist_put(dev, dmabuf);11551158 }1156115911571157- return 0;11601160+done:11611161+ /* If we didn't need to allocate them, these'll be NULL */11621162+ drm_free(kcmd_addr, cmdbuf.size * 8, DRM_MEM_DRIVER);11631163+ drm_free(kvb_addr, cmdbuf.vb_size, DRM_MEM_DRIVER);11641164+ drm_free(kbox_addr, cmdbuf.nbox * sizeof(drm_clip_rect_t),11651165+ DRM_MEM_DRIVER);11661166+11671167+ return ret;11581168}
+25
drivers/char/drm/sis_drm.h
···11+/* sis_drv.h -- Private header for sis driver -*- linux-c -*- */22+/*33+ * Copyright 2005 Eric Anholt44+ * All Rights Reserved.55+ *66+ * Permission is hereby granted, free of charge, to any person obtaining a77+ * copy of this software and associated documentation files (the "Software"),88+ * to deal in the Software without restriction, including without limitation99+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,1010+ * and/or sell copies of the Software, and to permit persons to whom the1111+ * Software is furnished to do so, subject to the following conditions:1212+ *1313+ * The above copyright notice and this permission notice (including the next1414+ * paragraph) shall be included in all copies or substantial portions of the1515+ * Software.1616+ *1717+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR1818+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,1919+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL2020+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER2121+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,2222+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE2323+ * SOFTWARE.2424+ *2525+ */126227#ifndef __SIS_DRM_H__328#define __SIS_DRM_H__
···11+/* via_dmablit.c -- PCI DMA BitBlt support for the VIA Unichrome/Pro22+ * 33+ * Copyright (C) 2005 Thomas Hellstrom, All Rights Reserved.44+ *55+ * Permission is hereby granted, free of charge, to any person obtaining a66+ * copy of this software and associated documentation files (the "Software"),77+ * to deal in the Software without restriction, including without limitation88+ * the rights to use, copy, modify, merge, publish, distribute, sub license,99+ * and/or sell copies of the Software, and to permit persons to whom the1010+ * Software is furnished to do so, subject to the following conditions:1111+ *1212+ * The above copyright notice and this permission notice (including the1313+ * next paragraph) shall be included in all copies or substantial portions1414+ * of the Software.1515+ *1616+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR1717+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,1818+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL1919+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 2020+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 2121+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 2222+ * USE OR OTHER DEALINGS IN THE SOFTWARE.2323+ *2424+ * Authors: 2525+ * Thomas Hellstrom.2626+ * Partially based on code obtained from Digeo Inc.2727+ */2828+2929+3030+/*3131+ * Unmaps the DMA mappings. 3232+ * FIXME: Is this a NoOp on x86? Also 3333+ * FIXME: What happens if this one is called and a pending blit has previously done 3434+ * the same DMA mappings? 3535+ */3636+3737+#include "drmP.h"3838+#include "via_drm.h"3939+#include "via_drv.h"4040+#include "via_dmablit.h"4141+4242+#include <linux/pagemap.h>4343+4444+#define VIA_PGDN(x) (((unsigned long)(x)) & PAGE_MASK)4545+#define VIA_PGOFF(x) (((unsigned long)(x)) & ~PAGE_MASK)4646+#define VIA_PFN(x) ((unsigned long)(x) >> PAGE_SHIFT)4747+4848+typedef struct _drm_via_descriptor {4949+ uint32_t mem_addr;5050+ uint32_t dev_addr;5151+ uint32_t size;5252+ uint32_t next;5353+} drm_via_descriptor_t;5454+5555+5656+/*5757+ * Unmap a DMA mapping.5858+ */5959+6060+6161+6262+static void6363+via_unmap_blit_from_device(struct pci_dev *pdev, drm_via_sg_info_t *vsg)6464+{6565+ int num_desc = vsg->num_desc;6666+ unsigned cur_descriptor_page = num_desc / vsg->descriptors_per_page;6767+ unsigned descriptor_this_page = num_desc % vsg->descriptors_per_page;6868+ drm_via_descriptor_t *desc_ptr = vsg->desc_pages[cur_descriptor_page] + 6969+ descriptor_this_page;7070+ dma_addr_t next = vsg->chain_start;7171+7272+ while(num_desc--) {7373+ if (descriptor_this_page-- == 0) {7474+ cur_descriptor_page--;7575+ descriptor_this_page = vsg->descriptors_per_page - 1;7676+ desc_ptr = vsg->desc_pages[cur_descriptor_page] + 7777+ descriptor_this_page;7878+ }7979+ dma_unmap_single(&pdev->dev, next, sizeof(*desc_ptr), DMA_TO_DEVICE);8080+ dma_unmap_page(&pdev->dev, desc_ptr->mem_addr, desc_ptr->size, vsg->direction);8181+ next = (dma_addr_t) desc_ptr->next;8282+ desc_ptr--;8383+ }8484+}8585+8686+/*8787+ * If mode = 0, count how many descriptors are needed.8888+ * If mode = 1, Map the DMA pages for the device, put together and map also the descriptors.8989+ * Descriptors are run in reverse order by the hardware because we are not allowed to update the9090+ * 'next' field without syncing calls when the descriptor is already mapped.9191+ */9292+9393+static void9494+via_map_blit_for_device(struct pci_dev *pdev,9595+ const drm_via_dmablit_t *xfer,9696+ drm_via_sg_info_t *vsg, 9797+ int mode)9898+{9999+ unsigned cur_descriptor_page = 0;100100+ unsigned num_descriptors_this_page = 0;101101+ unsigned char *mem_addr = xfer->mem_addr;102102+ unsigned char *cur_mem;103103+ unsigned char *first_addr = (unsigned char *)VIA_PGDN(mem_addr);104104+ uint32_t fb_addr = xfer->fb_addr;105105+ uint32_t cur_fb;106106+ unsigned long line_len;107107+ unsigned remaining_len;108108+ int num_desc = 0;109109+ int cur_line;110110+ dma_addr_t next = 0 | VIA_DMA_DPR_EC;111111+ drm_via_descriptor_t *desc_ptr = 0;112112+113113+ if (mode == 1) 114114+ desc_ptr = vsg->desc_pages[cur_descriptor_page];115115+116116+ for (cur_line = 0; cur_line < xfer->num_lines; ++cur_line) {117117+118118+ line_len = xfer->line_length;119119+ cur_fb = fb_addr;120120+ cur_mem = mem_addr;121121+122122+ while (line_len > 0) {123123+124124+ remaining_len = min(PAGE_SIZE-VIA_PGOFF(cur_mem), line_len);125125+ line_len -= remaining_len;126126+127127+ if (mode == 1) {128128+ desc_ptr->mem_addr = 129129+ dma_map_page(&pdev->dev, 130130+ vsg->pages[VIA_PFN(cur_mem) - 131131+ VIA_PFN(first_addr)],132132+ VIA_PGOFF(cur_mem), remaining_len, 133133+ vsg->direction);134134+ desc_ptr->dev_addr = cur_fb;135135+136136+ desc_ptr->size = remaining_len;137137+ desc_ptr->next = (uint32_t) next;138138+ next = dma_map_single(&pdev->dev, desc_ptr, sizeof(*desc_ptr), 139139+ DMA_TO_DEVICE);140140+ desc_ptr++;141141+ if (++num_descriptors_this_page >= vsg->descriptors_per_page) {142142+ num_descriptors_this_page = 0;143143+ desc_ptr = vsg->desc_pages[++cur_descriptor_page];144144+ }145145+ }146146+147147+ num_desc++;148148+ cur_mem += remaining_len;149149+ cur_fb += remaining_len;150150+ }151151+152152+ mem_addr += xfer->mem_stride;153153+ fb_addr += xfer->fb_stride;154154+ }155155+156156+ if (mode == 1) {157157+ vsg->chain_start = next;158158+ vsg->state = dr_via_device_mapped;159159+ }160160+ vsg->num_desc = num_desc;161161+}162162+163163+/*164164+ * Function that frees up all resources for a blit. It is usable even if the 165165+ * blit info has only be partially built as long as the status enum is consistent166166+ * with the actual status of the used resources.167167+ */168168+169169+170170+void171171+via_free_sg_info(struct pci_dev *pdev, drm_via_sg_info_t *vsg) 172172+{173173+ struct page *page;174174+ int i;175175+176176+ switch(vsg->state) {177177+ case dr_via_device_mapped:178178+ via_unmap_blit_from_device(pdev, vsg);179179+ case dr_via_desc_pages_alloc:180180+ for (i=0; i<vsg->num_desc_pages; ++i) {181181+ if (vsg->desc_pages[i] != NULL)182182+ free_page((unsigned long)vsg->desc_pages[i]);183183+ }184184+ kfree(vsg->desc_pages);185185+ case dr_via_pages_locked:186186+ for (i=0; i<vsg->num_pages; ++i) {187187+ if ( NULL != (page = vsg->pages[i])) {188188+ if (! PageReserved(page) && (DMA_FROM_DEVICE == vsg->direction)) 189189+ SetPageDirty(page);190190+ page_cache_release(page);191191+ }192192+ }193193+ case dr_via_pages_alloc:194194+ vfree(vsg->pages);195195+ default:196196+ vsg->state = dr_via_sg_init;197197+ }198198+ if (vsg->bounce_buffer) {199199+ vfree(vsg->bounce_buffer);200200+ vsg->bounce_buffer = NULL;201201+ }202202+ vsg->free_on_sequence = 0;203203+} 204204+205205+/*206206+ * Fire a blit engine.207207+ */208208+209209+static void210210+via_fire_dmablit(drm_device_t *dev, drm_via_sg_info_t *vsg, int engine)211211+{212212+ drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;213213+214214+ VIA_WRITE(VIA_PCI_DMA_MAR0 + engine*0x10, 0);215215+ VIA_WRITE(VIA_PCI_DMA_DAR0 + engine*0x10, 0);216216+ VIA_WRITE(VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_DD | VIA_DMA_CSR_TD | 217217+ VIA_DMA_CSR_DE);218218+ VIA_WRITE(VIA_PCI_DMA_MR0 + engine*0x04, VIA_DMA_MR_CM | VIA_DMA_MR_TDIE);219219+ VIA_WRITE(VIA_PCI_DMA_BCR0 + engine*0x10, 0);220220+ VIA_WRITE(VIA_PCI_DMA_DPR0 + engine*0x10, vsg->chain_start);221221+ VIA_WRITE(VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_DE | VIA_DMA_CSR_TS);222222+}223223+224224+/*225225+ * Obtain a page pointer array and lock all pages into system memory. A segmentation violation will226226+ * occur here if the calling user does not have access to the submitted address.227227+ */228228+229229+static int230230+via_lock_all_dma_pages(drm_via_sg_info_t *vsg, drm_via_dmablit_t *xfer)231231+{232232+ int ret;233233+ unsigned long first_pfn = VIA_PFN(xfer->mem_addr);234234+ vsg->num_pages = VIA_PFN(xfer->mem_addr + (xfer->num_lines * xfer->mem_stride -1)) - 235235+ first_pfn + 1;236236+237237+ if (NULL == (vsg->pages = vmalloc(sizeof(struct page *) * vsg->num_pages)))238238+ return DRM_ERR(ENOMEM);239239+ memset(vsg->pages, 0, sizeof(struct page *) * vsg->num_pages);240240+ down_read(¤t->mm->mmap_sem);241241+ ret = get_user_pages(current, current->mm, (unsigned long) xfer->mem_addr,242242+ vsg->num_pages, vsg->direction, 0, vsg->pages, NULL);243243+244244+ up_read(¤t->mm->mmap_sem);245245+ if (ret != vsg->num_pages) {246246+ if (ret < 0) 247247+ return ret;248248+ vsg->state = dr_via_pages_locked;249249+ return DRM_ERR(EINVAL);250250+ }251251+ vsg->state = dr_via_pages_locked;252252+ DRM_DEBUG("DMA pages locked\n");253253+ return 0;254254+}255255+256256+/*257257+ * Allocate DMA capable memory for the blit descriptor chain, and an array that keeps track of the258258+ * pages we allocate. We don't want to use kmalloc for the descriptor chain because it may be259259+ * quite large for some blits, and pages don't need to be contingous.260260+ */261261+262262+static int 263263+via_alloc_desc_pages(drm_via_sg_info_t *vsg)264264+{265265+ int i;266266+267267+ vsg->descriptors_per_page = PAGE_SIZE / sizeof( drm_via_descriptor_t);268268+ vsg->num_desc_pages = (vsg->num_desc + vsg->descriptors_per_page - 1) / 269269+ vsg->descriptors_per_page;270270+271271+ if (NULL == (vsg->desc_pages = kmalloc(sizeof(void *) * vsg->num_desc_pages, GFP_KERNEL))) 272272+ return DRM_ERR(ENOMEM);273273+274274+ memset(vsg->desc_pages, 0, sizeof(void *) * vsg->num_desc_pages);275275+ vsg->state = dr_via_desc_pages_alloc;276276+ for (i=0; i<vsg->num_desc_pages; ++i) {277277+ if (NULL == (vsg->desc_pages[i] = 278278+ (drm_via_descriptor_t *) __get_free_page(GFP_KERNEL)))279279+ return DRM_ERR(ENOMEM);280280+ }281281+ DRM_DEBUG("Allocated %d pages for %d descriptors.\n", vsg->num_desc_pages,282282+ vsg->num_desc);283283+ return 0;284284+}285285+286286+static void287287+via_abort_dmablit(drm_device_t *dev, int engine)288288+{289289+ drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;290290+291291+ VIA_WRITE(VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_TA);292292+}293293+294294+static void295295+via_dmablit_engine_off(drm_device_t *dev, int engine)296296+{297297+ drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;298298+299299+ VIA_WRITE(VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_TD | VIA_DMA_CSR_DD); 300300+}301301+302302+303303+304304+/*305305+ * The dmablit part of the IRQ handler. Trying to do only reasonably fast things here.306306+ * The rest, like unmapping and freeing memory for done blits is done in a separate workqueue307307+ * task. Basically the task of the interrupt handler is to submit a new blit to the engine, while308308+ * the workqueue task takes care of processing associated with the old blit.309309+ */310310+311311+void312312+via_dmablit_handler(drm_device_t *dev, int engine, int from_irq)313313+{314314+ drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;315315+ drm_via_blitq_t *blitq = dev_priv->blit_queues + engine;316316+ int cur;317317+ int done_transfer;318318+ unsigned long irqsave=0;319319+ uint32_t status = 0;320320+321321+ DRM_DEBUG("DMA blit handler called. engine = %d, from_irq = %d, blitq = 0x%lx\n",322322+ engine, from_irq, (unsigned long) blitq);323323+324324+ if (from_irq) {325325+ spin_lock(&blitq->blit_lock);326326+ } else {327327+ spin_lock_irqsave(&blitq->blit_lock, irqsave);328328+ }329329+330330+ done_transfer = blitq->is_active && 331331+ (( status = VIA_READ(VIA_PCI_DMA_CSR0 + engine*0x04)) & VIA_DMA_CSR_TD);332332+ done_transfer = done_transfer || ( blitq->aborting && !(status & VIA_DMA_CSR_DE)); 333333+334334+ cur = blitq->cur;335335+ if (done_transfer) {336336+337337+ blitq->blits[cur]->aborted = blitq->aborting;338338+ blitq->done_blit_handle++;339339+ DRM_WAKEUP(blitq->blit_queue + cur); 340340+341341+ cur++;342342+ if (cur >= VIA_NUM_BLIT_SLOTS) 343343+ cur = 0;344344+ blitq->cur = cur;345345+346346+ /*347347+ * Clear transfer done flag.348348+ */349349+350350+ VIA_WRITE(VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_TD);351351+352352+ blitq->is_active = 0;353353+ blitq->aborting = 0;354354+ schedule_work(&blitq->wq); 355355+356356+ } else if (blitq->is_active && time_after_eq(jiffies, blitq->end)) {357357+358358+ /*359359+ * Abort transfer after one second.360360+ */361361+362362+ via_abort_dmablit(dev, engine);363363+ blitq->aborting = 1;364364+ blitq->end = jiffies + DRM_HZ;365365+ }366366+367367+ if (!blitq->is_active) {368368+ if (blitq->num_outstanding) {369369+ via_fire_dmablit(dev, blitq->blits[cur], engine);370370+ blitq->is_active = 1;371371+ blitq->cur = cur;372372+ blitq->num_outstanding--;373373+ blitq->end = jiffies + DRM_HZ;374374+ if (!timer_pending(&blitq->poll_timer)) {375375+ blitq->poll_timer.expires = jiffies+1;376376+ add_timer(&blitq->poll_timer);377377+ }378378+ } else {379379+ if (timer_pending(&blitq->poll_timer)) {380380+ del_timer(&blitq->poll_timer);381381+ }382382+ via_dmablit_engine_off(dev, engine);383383+ }384384+ } 385385+386386+ if (from_irq) {387387+ spin_unlock(&blitq->blit_lock);388388+ } else {389389+ spin_unlock_irqrestore(&blitq->blit_lock, irqsave);390390+ }391391+} 392392+393393+394394+395395+/*396396+ * Check whether this blit is still active, performing necessary locking.397397+ */398398+399399+static int400400+via_dmablit_active(drm_via_blitq_t *blitq, int engine, uint32_t handle, wait_queue_head_t **queue)401401+{402402+ unsigned long irqsave;403403+ uint32_t slot;404404+ int active;405405+406406+ spin_lock_irqsave(&blitq->blit_lock, irqsave);407407+408408+ /*409409+ * Allow for handle wraparounds.410410+ */411411+412412+ active = ((blitq->done_blit_handle - handle) > (1 << 23)) &&413413+ ((blitq->cur_blit_handle - handle) <= (1 << 23));414414+415415+ if (queue && active) {416416+ slot = handle - blitq->done_blit_handle + blitq->cur -1;417417+ if (slot >= VIA_NUM_BLIT_SLOTS) {418418+ slot -= VIA_NUM_BLIT_SLOTS;419419+ }420420+ *queue = blitq->blit_queue + slot;421421+ }422422+423423+ spin_unlock_irqrestore(&blitq->blit_lock, irqsave);424424+425425+ return active;426426+}427427+428428+/*429429+ * Sync. Wait for at least three seconds for the blit to be performed.430430+ */431431+432432+static int433433+via_dmablit_sync(drm_device_t *dev, uint32_t handle, int engine) 434434+{435435+436436+ drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;437437+ drm_via_blitq_t *blitq = dev_priv->blit_queues + engine;438438+ wait_queue_head_t *queue;439439+ int ret = 0;440440+441441+ if (via_dmablit_active(blitq, engine, handle, &queue)) {442442+ DRM_WAIT_ON(ret, *queue, 3 * DRM_HZ, 443443+ !via_dmablit_active(blitq, engine, handle, NULL));444444+ }445445+ DRM_DEBUG("DMA blit sync handle 0x%x engine %d returned %d\n",446446+ handle, engine, ret);447447+448448+ return ret;449449+}450450+451451+452452+/*453453+ * A timer that regularly polls the blit engine in cases where we don't have interrupts:454454+ * a) Broken hardware (typically those that don't have any video capture facility).455455+ * b) Blit abort. The hardware doesn't send an interrupt when a blit is aborted.456456+ * The timer and hardware IRQ's can and do work in parallel. If the hardware has457457+ * irqs, it will shorten the latency somewhat.458458+ */459459+460460+461461+462462+static void463463+via_dmablit_timer(unsigned long data)464464+{465465+ drm_via_blitq_t *blitq = (drm_via_blitq_t *) data;466466+ drm_device_t *dev = blitq->dev;467467+ int engine = (int)468468+ (blitq - ((drm_via_private_t *)dev->dev_private)->blit_queues);469469+470470+ DRM_DEBUG("Polling timer called for engine %d, jiffies %lu\n", engine, 471471+ (unsigned long) jiffies);472472+473473+ via_dmablit_handler(dev, engine, 0);474474+475475+ if (!timer_pending(&blitq->poll_timer)) {476476+ blitq->poll_timer.expires = jiffies+1;477477+ add_timer(&blitq->poll_timer);478478+ }479479+ via_dmablit_handler(dev, engine, 0);480480+481481+}482482+483483+484484+485485+486486+/*487487+ * Workqueue task that frees data and mappings associated with a blit.488488+ * Also wakes up waiting processes. Each of these tasks handles one489489+ * blit engine only and may not be called on each interrupt.490490+ */491491+492492+493493+static void 494494+via_dmablit_workqueue(void *data)495495+{496496+ drm_via_blitq_t *blitq = (drm_via_blitq_t *) data;497497+ drm_device_t *dev = blitq->dev;498498+ unsigned long irqsave;499499+ drm_via_sg_info_t *cur_sg;500500+ int cur_released;501501+502502+503503+ DRM_DEBUG("Workqueue task called for blit engine %ld\n",(unsigned long) 504504+ (blitq - ((drm_via_private_t *)dev->dev_private)->blit_queues));505505+506506+ spin_lock_irqsave(&blitq->blit_lock, irqsave);507507+508508+ while(blitq->serviced != blitq->cur) {509509+510510+ cur_released = blitq->serviced++;511511+512512+ DRM_DEBUG("Releasing blit slot %d\n", cur_released);513513+514514+ if (blitq->serviced >= VIA_NUM_BLIT_SLOTS) 515515+ blitq->serviced = 0;516516+517517+ cur_sg = blitq->blits[cur_released];518518+ blitq->num_free++;519519+520520+ spin_unlock_irqrestore(&blitq->blit_lock, irqsave);521521+522522+ DRM_WAKEUP(&blitq->busy_queue);523523+524524+ via_free_sg_info(dev->pdev, cur_sg);525525+ kfree(cur_sg);526526+527527+ spin_lock_irqsave(&blitq->blit_lock, irqsave);528528+ }529529+530530+ spin_unlock_irqrestore(&blitq->blit_lock, irqsave);531531+}532532+533533+534534+/*535535+ * Init all blit engines. Currently we use two, but some hardware have 4.536536+ */537537+538538+539539+void540540+via_init_dmablit(drm_device_t *dev)541541+{542542+ int i,j;543543+ drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;544544+ drm_via_blitq_t *blitq;545545+546546+ pci_set_master(dev->pdev); 547547+548548+ for (i=0; i< VIA_NUM_BLIT_ENGINES; ++i) {549549+ blitq = dev_priv->blit_queues + i;550550+ blitq->dev = dev;551551+ blitq->cur_blit_handle = 0;552552+ blitq->done_blit_handle = 0;553553+ blitq->head = 0;554554+ blitq->cur = 0;555555+ blitq->serviced = 0;556556+ blitq->num_free = VIA_NUM_BLIT_SLOTS;557557+ blitq->num_outstanding = 0;558558+ blitq->is_active = 0;559559+ blitq->aborting = 0;560560+ blitq->blit_lock = SPIN_LOCK_UNLOCKED;561561+ for (j=0; j<VIA_NUM_BLIT_SLOTS; ++j) {562562+ DRM_INIT_WAITQUEUE(blitq->blit_queue + j);563563+ }564564+ DRM_INIT_WAITQUEUE(&blitq->busy_queue);565565+ INIT_WORK(&blitq->wq, via_dmablit_workqueue, blitq);566566+ init_timer(&blitq->poll_timer);567567+ blitq->poll_timer.function = &via_dmablit_timer;568568+ blitq->poll_timer.data = (unsigned long) blitq;569569+ } 570570+}571571+572572+/*573573+ * Build all info and do all mappings required for a blit.574574+ */575575+576576+577577+static int578578+via_build_sg_info(drm_device_t *dev, drm_via_sg_info_t *vsg, drm_via_dmablit_t *xfer)579579+{580580+ int draw = xfer->to_fb;581581+ int ret = 0;582582+583583+ vsg->direction = (draw) ? DMA_TO_DEVICE : DMA_FROM_DEVICE;584584+ vsg->bounce_buffer = 0;585585+586586+ vsg->state = dr_via_sg_init;587587+588588+ if (xfer->num_lines <= 0 || xfer->line_length <= 0) {589589+ DRM_ERROR("Zero size bitblt.\n");590590+ return DRM_ERR(EINVAL);591591+ }592592+593593+ /*594594+ * Below check is a driver limitation, not a hardware one. We595595+ * don't want to lock unused pages, and don't want to incoporate the596596+ * extra logic of avoiding them. Make sure there are no. 597597+ * (Not a big limitation anyway.)598598+ */599599+600600+ if (((xfer->mem_stride - xfer->line_length) >= PAGE_SIZE) ||601601+ (xfer->mem_stride > 2048*4)) {602602+ DRM_ERROR("Too large system memory stride. Stride: %d, "603603+ "Length: %d\n", xfer->mem_stride, xfer->line_length);604604+ return DRM_ERR(EINVAL);605605+ }606606+607607+ if (xfer->num_lines > 2048) {608608+ DRM_ERROR("Too many PCI DMA bitblt lines.\n");609609+ return DRM_ERR(EINVAL);610610+ } 611611+612612+ /* 613613+ * we allow a negative fb stride to allow flipping of images in614614+ * transfer. 615615+ */616616+617617+ if (xfer->mem_stride < xfer->line_length ||618618+ abs(xfer->fb_stride) < xfer->line_length) {619619+ DRM_ERROR("Invalid frame-buffer / memory stride.\n");620620+ return DRM_ERR(EINVAL);621621+ }622622+623623+ /*624624+ * A hardware bug seems to be worked around if system memory addresses start on625625+ * 16 byte boundaries. This seems a bit restrictive however. VIA is contacted626626+ * about this. Meanwhile, impose the following restrictions:627627+ */628628+629629+#ifdef VIA_BUGFREE630630+ if ((((unsigned long)xfer->mem_addr & 3) != ((unsigned long)xfer->fb_addr & 3)) ||631631+ ((xfer->mem_stride & 3) != (xfer->fb_stride & 3))) {632632+ DRM_ERROR("Invalid DRM bitblt alignment.\n");633633+ return DRM_ERR(EINVAL);634634+ }635635+#else636636+ if ((((unsigned long)xfer->mem_addr & 15) ||637637+ ((unsigned long)xfer->fb_addr & 3)) || (xfer->mem_stride & 15) ||638638+ (xfer->fb_stride & 3)) {639639+ DRM_ERROR("Invalid DRM bitblt alignment.\n");640640+ return DRM_ERR(EINVAL);641641+ } 642642+#endif643643+644644+ if (0 != (ret = via_lock_all_dma_pages(vsg, xfer))) {645645+ DRM_ERROR("Could not lock DMA pages.\n");646646+ via_free_sg_info(dev->pdev, vsg);647647+ return ret;648648+ }649649+650650+ via_map_blit_for_device(dev->pdev, xfer, vsg, 0);651651+ if (0 != (ret = via_alloc_desc_pages(vsg))) {652652+ DRM_ERROR("Could not allocate DMA descriptor pages.\n");653653+ via_free_sg_info(dev->pdev, vsg);654654+ return ret;655655+ }656656+ via_map_blit_for_device(dev->pdev, xfer, vsg, 1);657657+658658+ return 0;659659+}660660+661661+662662+/*663663+ * Reserve one free slot in the blit queue. Will wait for one second for one664664+ * to become available. Otherwise -EBUSY is returned.665665+ */666666+667667+static int 668668+via_dmablit_grab_slot(drm_via_blitq_t *blitq, int engine)669669+{670670+ int ret=0;671671+ unsigned long irqsave;672672+673673+ DRM_DEBUG("Num free is %d\n", blitq->num_free);674674+ spin_lock_irqsave(&blitq->blit_lock, irqsave);675675+ while(blitq->num_free == 0) {676676+ spin_unlock_irqrestore(&blitq->blit_lock, irqsave);677677+678678+ DRM_WAIT_ON(ret, blitq->busy_queue, DRM_HZ, blitq->num_free > 0);679679+ if (ret) {680680+ return (DRM_ERR(EINTR) == ret) ? DRM_ERR(EAGAIN) : ret;681681+ }682682+683683+ spin_lock_irqsave(&blitq->blit_lock, irqsave);684684+ }685685+686686+ blitq->num_free--;687687+ spin_unlock_irqrestore(&blitq->blit_lock, irqsave);688688+689689+ return 0;690690+}691691+692692+/*693693+ * Hand back a free slot if we changed our mind.694694+ */695695+696696+static void 697697+via_dmablit_release_slot(drm_via_blitq_t *blitq)698698+{699699+ unsigned long irqsave;700700+701701+ spin_lock_irqsave(&blitq->blit_lock, irqsave);702702+ blitq->num_free++;703703+ spin_unlock_irqrestore(&blitq->blit_lock, irqsave);704704+ DRM_WAKEUP( &blitq->busy_queue );705705+}706706+707707+/*708708+ * Grab a free slot. Build blit info and queue a blit.709709+ */710710+711711+712712+static int 713713+via_dmablit(drm_device_t *dev, drm_via_dmablit_t *xfer) 714714+{715715+ drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;716716+ drm_via_sg_info_t *vsg;717717+ drm_via_blitq_t *blitq;718718+ int ret;719719+ int engine;720720+ unsigned long irqsave;721721+722722+ if (dev_priv == NULL) {723723+ DRM_ERROR("Called without initialization.\n");724724+ return DRM_ERR(EINVAL);725725+ }726726+727727+ engine = (xfer->to_fb) ? 0 : 1;728728+ blitq = dev_priv->blit_queues + engine;729729+ if (0 != (ret = via_dmablit_grab_slot(blitq, engine))) {730730+ return ret;731731+ }732732+ if (NULL == (vsg = kmalloc(sizeof(*vsg), GFP_KERNEL))) {733733+ via_dmablit_release_slot(blitq);734734+ return DRM_ERR(ENOMEM);735735+ }736736+ if (0 != (ret = via_build_sg_info(dev, vsg, xfer))) {737737+ via_dmablit_release_slot(blitq);738738+ kfree(vsg);739739+ return ret;740740+ }741741+ spin_lock_irqsave(&blitq->blit_lock, irqsave);742742+743743+ blitq->blits[blitq->head++] = vsg;744744+ if (blitq->head >= VIA_NUM_BLIT_SLOTS) 745745+ blitq->head = 0;746746+ blitq->num_outstanding++;747747+ xfer->sync.sync_handle = ++blitq->cur_blit_handle; 748748+749749+ spin_unlock_irqrestore(&blitq->blit_lock, irqsave);750750+ xfer->sync.engine = engine;751751+752752+ via_dmablit_handler(dev, engine, 0);753753+754754+ return 0;755755+}756756+757757+/*758758+ * Sync on a previously submitted blit. Note that the X server use signals extensively, and759759+ * that there is a very big proability that this IOCTL will be interrupted by a signal. In that760760+ * case it returns with -EAGAIN for the signal to be delivered. 761761+ * The caller should then reissue the IOCTL. This is similar to what is being done for drmGetLock().762762+ */763763+764764+int765765+via_dma_blit_sync( DRM_IOCTL_ARGS )766766+{767767+ drm_via_blitsync_t sync;768768+ int err;769769+ DRM_DEVICE;770770+771771+ DRM_COPY_FROM_USER_IOCTL(sync, (drm_via_blitsync_t *)data, sizeof(sync));772772+773773+ if (sync.engine >= VIA_NUM_BLIT_ENGINES) 774774+ return DRM_ERR(EINVAL);775775+776776+ err = via_dmablit_sync(dev, sync.sync_handle, sync.engine);777777+778778+ if (DRM_ERR(EINTR) == err)779779+ err = DRM_ERR(EAGAIN);780780+781781+ return err;782782+}783783+784784+785785+/*786786+ * Queue a blit and hand back a handle to be used for sync. This IOCTL may be interrupted by a signal787787+ * while waiting for a free slot in the blit queue. In that case it returns with -EAGAIN and should 788788+ * be reissued. See the above IOCTL code.789789+ */790790+791791+int 792792+via_dma_blit( DRM_IOCTL_ARGS )793793+{794794+ drm_via_dmablit_t xfer;795795+ int err;796796+ DRM_DEVICE;797797+798798+ DRM_COPY_FROM_USER_IOCTL(xfer, (drm_via_dmablit_t __user *)data, sizeof(xfer));799799+800800+ err = via_dmablit(dev, &xfer);801801+802802+ DRM_COPY_TO_USER_IOCTL((void __user *)data, xfer, sizeof(xfer));803803+804804+ return err;805805+}
+140
drivers/char/drm/via_dmablit.h
···11+/* via_dmablit.h -- PCI DMA BitBlt support for the VIA Unichrome/Pro22+ * 33+ * Copyright 2005 Thomas Hellstrom.44+ * All Rights Reserved.55+ *66+ * Permission is hereby granted, free of charge, to any person obtaining a77+ * copy of this software and associated documentation files (the "Software"),88+ * to deal in the Software without restriction, including without limitation99+ * the rights to use, copy, modify, merge, publish, distribute, sub license,1010+ * and/or sell copies of the Software, and to permit persons to whom the1111+ * Software is furnished to do so, subject to the following conditions:1212+ *1313+ * The above copyright notice and this permission notice (including the1414+ * next paragraph) shall be included in all copies or substantial portions1515+ * of the Software.1616+ *1717+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR1818+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,1919+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL2020+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 2121+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 2222+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 2323+ * USE OR OTHER DEALINGS IN THE SOFTWARE.2424+ *2525+ * Authors: 2626+ * Thomas Hellstrom.2727+ * Register info from Digeo Inc.2828+ */2929+3030+#ifndef _VIA_DMABLIT_H3131+#define _VIA_DMABLIT_H3232+3333+#include <linux/dma-mapping.h>3434+3535+#define VIA_NUM_BLIT_ENGINES 23636+#define VIA_NUM_BLIT_SLOTS 83737+3838+struct _drm_via_descriptor;3939+4040+typedef struct _drm_via_sg_info {4141+ struct page **pages;4242+ unsigned long num_pages;4343+ struct _drm_via_descriptor **desc_pages;4444+ int num_desc_pages;4545+ int num_desc;4646+ enum dma_data_direction direction;4747+ unsigned char *bounce_buffer;4848+ dma_addr_t chain_start;4949+ uint32_t free_on_sequence;5050+ unsigned int descriptors_per_page;5151+ int aborted;5252+ enum {5353+ dr_via_device_mapped,5454+ dr_via_desc_pages_alloc,5555+ dr_via_pages_locked,5656+ dr_via_pages_alloc,5757+ dr_via_sg_init5858+ } state;5959+} drm_via_sg_info_t;6060+6161+typedef struct _drm_via_blitq {6262+ drm_device_t *dev;6363+ uint32_t cur_blit_handle;6464+ uint32_t done_blit_handle;6565+ unsigned serviced;6666+ unsigned head;6767+ unsigned cur;6868+ unsigned num_free;6969+ unsigned num_outstanding;7070+ unsigned long end; 7171+ int aborting;7272+ int is_active;7373+ drm_via_sg_info_t *blits[VIA_NUM_BLIT_SLOTS];7474+ spinlock_t blit_lock;7575+ wait_queue_head_t blit_queue[VIA_NUM_BLIT_SLOTS];7676+ wait_queue_head_t busy_queue;7777+ struct work_struct wq;7878+ struct timer_list poll_timer;7979+} drm_via_blitq_t;8080+8181+8282+/* 8383+ * PCI DMA Registers8484+ * Channels 2 & 3 don't seem to be implemented in hardware.8585+ */8686+8787+#define VIA_PCI_DMA_MAR0 0xE40 /* Memory Address Register of Channel 0 */ 8888+#define VIA_PCI_DMA_DAR0 0xE44 /* Device Address Register of Channel 0 */ 8989+#define VIA_PCI_DMA_BCR0 0xE48 /* Byte Count Register of Channel 0 */ 9090+#define VIA_PCI_DMA_DPR0 0xE4C /* Descriptor Pointer Register of Channel 0 */ 9191+9292+#define VIA_PCI_DMA_MAR1 0xE50 /* Memory Address Register of Channel 1 */ 9393+#define VIA_PCI_DMA_DAR1 0xE54 /* Device Address Register of Channel 1 */ 9494+#define VIA_PCI_DMA_BCR1 0xE58 /* Byte Count Register of Channel 1 */ 9595+#define VIA_PCI_DMA_DPR1 0xE5C /* Descriptor Pointer Register of Channel 1 */ 9696+9797+#define VIA_PCI_DMA_MAR2 0xE60 /* Memory Address Register of Channel 2 */ 9898+#define VIA_PCI_DMA_DAR2 0xE64 /* Device Address Register of Channel 2 */ 9999+#define VIA_PCI_DMA_BCR2 0xE68 /* Byte Count Register of Channel 2 */ 100100+#define VIA_PCI_DMA_DPR2 0xE6C /* Descriptor Pointer Register of Channel 2 */ 101101+102102+#define VIA_PCI_DMA_MAR3 0xE70 /* Memory Address Register of Channel 3 */ 103103+#define VIA_PCI_DMA_DAR3 0xE74 /* Device Address Register of Channel 3 */ 104104+#define VIA_PCI_DMA_BCR3 0xE78 /* Byte Count Register of Channel 3 */ 105105+#define VIA_PCI_DMA_DPR3 0xE7C /* Descriptor Pointer Register of Channel 3 */ 106106+107107+#define VIA_PCI_DMA_MR0 0xE80 /* Mode Register of Channel 0 */ 108108+#define VIA_PCI_DMA_MR1 0xE84 /* Mode Register of Channel 1 */ 109109+#define VIA_PCI_DMA_MR2 0xE88 /* Mode Register of Channel 2 */ 110110+#define VIA_PCI_DMA_MR3 0xE8C /* Mode Register of Channel 3 */ 111111+112112+#define VIA_PCI_DMA_CSR0 0xE90 /* Command/Status Register of Channel 0 */ 113113+#define VIA_PCI_DMA_CSR1 0xE94 /* Command/Status Register of Channel 1 */ 114114+#define VIA_PCI_DMA_CSR2 0xE98 /* Command/Status Register of Channel 2 */ 115115+#define VIA_PCI_DMA_CSR3 0xE9C /* Command/Status Register of Channel 3 */ 116116+117117+#define VIA_PCI_DMA_PTR 0xEA0 /* Priority Type Register */ 118118+119119+/* Define for DMA engine */ 120120+/* DPR */121121+#define VIA_DMA_DPR_EC (1<<1) /* end of chain */122122+#define VIA_DMA_DPR_DDIE (1<<2) /* descriptor done interrupt enable */123123+#define VIA_DMA_DPR_DT (1<<3) /* direction of transfer (RO) */124124+125125+/* MR */126126+#define VIA_DMA_MR_CM (1<<0) /* chaining mode */127127+#define VIA_DMA_MR_TDIE (1<<1) /* transfer done interrupt enable */128128+#define VIA_DMA_MR_HENDMACMD (1<<7) /* ? */129129+130130+/* CSR */131131+#define VIA_DMA_CSR_DE (1<<0) /* DMA enable */132132+#define VIA_DMA_CSR_TS (1<<1) /* transfer start */133133+#define VIA_DMA_CSR_TA (1<<2) /* transfer abort */134134+#define VIA_DMA_CSR_TD (1<<3) /* transfer done */135135+#define VIA_DMA_CSR_DD (1<<4) /* descriptor done */136136+#define VIA_DMA_DPR_EC (1<<1) /* end of chain */137137+138138+139139+140140+#endif
+42-16
drivers/char/drm/via_drm.h
···7575#define DRM_VIA_CMDBUF_SIZE 0x0b7676#define NOT_USED7777#define DRM_VIA_WAIT_IRQ 0x0d7878+#define DRM_VIA_DMA_BLIT 0x0e7979+#define DRM_VIA_BLIT_SYNC 0x0f78807981#define DRM_IOCTL_VIA_ALLOCMEM DRM_IOWR(DRM_COMMAND_BASE + DRM_VIA_ALLOCMEM, drm_via_mem_t)8082#define DRM_IOCTL_VIA_FREEMEM DRM_IOW( DRM_COMMAND_BASE + DRM_VIA_FREEMEM, drm_via_mem_t)···9189#define DRM_IOCTL_VIA_CMDBUF_SIZE DRM_IOWR( DRM_COMMAND_BASE + DRM_VIA_CMDBUF_SIZE, \9290 drm_via_cmdbuf_size_t)9391#define DRM_IOCTL_VIA_WAIT_IRQ DRM_IOWR( DRM_COMMAND_BASE + DRM_VIA_WAIT_IRQ, drm_via_irqwait_t)9292+#define DRM_IOCTL_VIA_DMA_BLIT DRM_IOW(DRM_COMMAND_BASE + DRM_VIA_DMA_BLIT, drm_via_dmablit_t)9393+#define DRM_IOCTL_VIA_BLIT_SYNC DRM_IOW(DRM_COMMAND_BASE + DRM_VIA_BLIT_SYNC, drm_via_blitsync_t)94949595/* Indices into buf.Setup where various bits of state are mirrored per9696 * context and per buffer. These can be fired at the card as a unit,···107103#define VIA_BACK 0x2108104#define VIA_DEPTH 0x4109105#define VIA_STENCIL 0x8110110-#define VIDEO 0111111-#define AGP 1106106+#define VIA_MEM_VIDEO 0 /* matches drm constant */107107+#define VIA_MEM_AGP 1 /* matches drm constant */108108+#define VIA_MEM_SYSTEM 2109109+#define VIA_MEM_MIXED 3110110+#define VIA_MEM_UNKNOWN 4111111+112112typedef struct {113113 uint32_t offset;114114 uint32_t size;···200192 unsigned int XvMCSubPicOn[VIA_NR_XVMC_PORTS];201193 unsigned int XvMCCtxNoGrabbed; /* Last context to hold decoder */202194195195+ /* Used by the 3d driver only at this point, for pageflipping:196196+ */197197+ unsigned int pfCurrentOffset;203198} drm_via_sarea_t;204199205200typedef struct _drm_via_cmdbuf_size {···223212224213#define VIA_IRQ_FLAGS_MASK 0xF0000000225214215215+enum drm_via_irqs {216216+ drm_via_irq_hqv0 = 0,217217+ drm_via_irq_hqv1,218218+ drm_via_irq_dma0_dd,219219+ drm_via_irq_dma0_td,220220+ drm_via_irq_dma1_dd,221221+ drm_via_irq_dma1_td,222222+ drm_via_irq_num223223+};224224+226225struct drm_via_wait_irq_request {227226 unsigned irq;228227 via_irq_seq_type_t type;···245224 struct drm_wait_vblank_reply reply;246225} drm_via_irqwait_t;247226248248-#ifdef __KERNEL__227227+typedef struct drm_via_blitsync {228228+ uint32_t sync_handle;229229+ unsigned engine;230230+} drm_via_blitsync_t;249231250250-int via_fb_init(DRM_IOCTL_ARGS);251251-int via_mem_alloc(DRM_IOCTL_ARGS);252252-int via_mem_free(DRM_IOCTL_ARGS);253253-int via_agp_init(DRM_IOCTL_ARGS);254254-int via_map_init(DRM_IOCTL_ARGS);255255-int via_decoder_futex(DRM_IOCTL_ARGS);256256-int via_dma_init(DRM_IOCTL_ARGS);257257-int via_cmdbuffer(DRM_IOCTL_ARGS);258258-int via_flush_ioctl(DRM_IOCTL_ARGS);259259-int via_pci_cmdbuffer(DRM_IOCTL_ARGS);260260-int via_cmdbuf_size(DRM_IOCTL_ARGS);261261-int via_wait_irq(DRM_IOCTL_ARGS);232232+typedef struct drm_via_dmablit {233233+ uint32_t num_lines;234234+ uint32_t line_length;235235+236236+ uint32_t fb_addr;237237+ uint32_t fb_stride;262238263263-#endif239239+ unsigned char *mem_addr;240240+ uint32_t mem_stride;241241+242242+ int bounce_buffer;243243+ int to_fb;244244+245245+ drm_via_blitsync_t sync;246246+} drm_via_dmablit_t;247247+264248#endif /* _VIA_DRM_H_ */
···2424#ifndef _VIA_DRV_H_2525#define _VIA_DRV_H_26262727-#define DRIVER_AUTHOR "VIA"2727+#define DRIVER_AUTHOR "Various"28282929#define DRIVER_NAME "via"3030#define DRIVER_DESC "VIA Unichrome / Pro"3131-#define DRIVER_DATE "20050523"3131+#define DRIVER_DATE "20051116"32323333#define DRIVER_MAJOR 23434-#define DRIVER_MINOR 63535-#define DRIVER_PATCHLEVEL 33434+#define DRIVER_MINOR 73535+#define DRIVER_PATCHLEVEL 436363737#include "via_verifier.h"38383939+#include "via_dmablit.h"4040+3941#define VIA_PCI_BUF_SIZE 600004042#define VIA_FIRE_BUF_SIZE 10244141-#define VIA_NUM_IRQS 24343+#define VIA_NUM_IRQS 442444345typedef struct drm_via_ring_buffer {4444- drm_map_t map;4646+ drm_local_map_t map;4547 char *virtual_start;4648} drm_via_ring_buffer_t;4749···58565957typedef struct drm_via_private {6058 drm_via_sarea_t *sarea_priv;6161- drm_map_t *sarea;6262- drm_map_t *fb;6363- drm_map_t *mmio;5959+ drm_local_map_t *sarea;6060+ drm_local_map_t *fb;6161+ drm_local_map_t *mmio;6462 unsigned long agpAddr;6563 wait_queue_head_t decoder_queue[VIA_NR_XVMC_LOCKS];6664 char *dma_ptr;···8482 maskarray_t *irq_masks;8583 uint32_t irq_enable_mask;8684 uint32_t irq_pending_mask;8585+ int *irq_map;8686+ drm_via_blitq_t blit_queues[VIA_NUM_BLIT_ENGINES];8787} drm_via_private_t;8888+8989+enum via_family {9090+ VIA_OTHER = 0,9191+ VIA_PRO_GROUP_A,9292+};88938994/* VIA MMIO register access */9095#define VIA_BASE ((dev_priv->mmio))···10192#define VIA_READ8(reg) DRM_READ8(VIA_BASE, reg)10293#define VIA_WRITE8(reg,val) DRM_WRITE8(VIA_BASE, reg, val)103949595+extern drm_ioctl_desc_t via_ioctls[];9696+extern int via_max_ioctl;9797+9898+extern int via_fb_init(DRM_IOCTL_ARGS);9999+extern int via_mem_alloc(DRM_IOCTL_ARGS);100100+extern int via_mem_free(DRM_IOCTL_ARGS);101101+extern int via_agp_init(DRM_IOCTL_ARGS);102102+extern int via_map_init(DRM_IOCTL_ARGS);103103+extern int via_decoder_futex(DRM_IOCTL_ARGS);104104+extern int via_dma_init(DRM_IOCTL_ARGS);105105+extern int via_cmdbuffer(DRM_IOCTL_ARGS);106106+extern int via_flush_ioctl(DRM_IOCTL_ARGS);107107+extern int via_pci_cmdbuffer(DRM_IOCTL_ARGS);108108+extern int via_cmdbuf_size(DRM_IOCTL_ARGS);109109+extern int via_wait_irq(DRM_IOCTL_ARGS);110110+extern int via_dma_blit_sync( DRM_IOCTL_ARGS );111111+extern int via_dma_blit( DRM_IOCTL_ARGS );112112+113113+extern int via_driver_load(drm_device_t *dev, unsigned long chipset);114114+extern int via_driver_unload(drm_device_t *dev);115115+104116extern int via_init_context(drm_device_t * dev, int context);105117extern int via_final_context(drm_device_t * dev, int context);106118107119extern int via_do_cleanup_map(drm_device_t * dev);108108-extern int via_map_init(struct inode *inode, struct file *filp,109109- unsigned int cmd, unsigned long arg);110120extern int via_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence);111121112122extern irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS);···139111extern void via_init_futex(drm_via_private_t * dev_priv);140112extern void via_cleanup_futex(drm_via_private_t * dev_priv);141113extern void via_release_futex(drm_via_private_t * dev_priv, int context);114114+extern int via_driver_irq_wait(drm_device_t * dev, unsigned int irq,115115+ int force_sequence, unsigned int *sequence);142116143143-extern int via_parse_command_stream(drm_device_t * dev, const uint32_t * buf,144144- unsigned int size);117117+extern void via_dmablit_handler(drm_device_t *dev, int engine, int from_irq);118118+extern void via_init_dmablit(drm_device_t *dev);145119146120#endif
+1-8
drivers/char/drm/via_ds.c
···2222 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER2323 * DEALINGS IN THE SOFTWARE.2424 */2525-#include <linux/module.h>2626-#include <linux/delay.h>2727-#include <linux/errno.h>2828-#include <linux/kernel.h>2929-#include <linux/slab.h>3030-#include <linux/poll.h>3131-#include <linux/pci.h>3232-#include <asm/io.h>2525+#include "drmP.h"33263427#include "via_ds.h"3528extern unsigned int VIA_DEBUG;
+44-9
drivers/char/drm/via_irq.c
···5050#define VIA_IRQ_HQV1_ENABLE (1 << 25)5151#define VIA_IRQ_HQV0_PENDING (1 << 9)5252#define VIA_IRQ_HQV1_PENDING (1 << 10)5353+#define VIA_IRQ_DMA0_DD_ENABLE (1 << 20)5454+#define VIA_IRQ_DMA0_TD_ENABLE (1 << 21)5555+#define VIA_IRQ_DMA1_DD_ENABLE (1 << 22)5656+#define VIA_IRQ_DMA1_TD_ENABLE (1 << 23)5757+#define VIA_IRQ_DMA0_DD_PENDING (1 << 4)5858+#define VIA_IRQ_DMA0_TD_PENDING (1 << 5)5959+#define VIA_IRQ_DMA1_DD_PENDING (1 << 6)6060+#define VIA_IRQ_DMA1_TD_PENDING (1 << 7)6161+53625463/*5564 * Device-specific IRQs go here. This type might need to be extended with···7061 {VIA_IRQ_HQV0_ENABLE, VIA_IRQ_HQV0_PENDING, 0x000003D0, 0x00008010,7162 0x00000000},7263 {VIA_IRQ_HQV1_ENABLE, VIA_IRQ_HQV1_PENDING, 0x000013D0, 0x00008010,7373- 0x00000000}6464+ 0x00000000},6565+ {VIA_IRQ_DMA0_TD_ENABLE, VIA_IRQ_DMA0_TD_PENDING, VIA_PCI_DMA_CSR0,6666+ VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008},6767+ {VIA_IRQ_DMA1_TD_ENABLE, VIA_IRQ_DMA1_TD_PENDING, VIA_PCI_DMA_CSR1,6868+ VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008},7469};7570static int via_num_pro_group_a =7671 sizeof(via_pro_group_a_irqs) / sizeof(maskarray_t);7272+static int via_irqmap_pro_group_a[] = {0, 1, -1, 2, -1, 3};77737878-static maskarray_t via_unichrome_irqs[] = { };7474+static maskarray_t via_unichrome_irqs[] = {7575+ {VIA_IRQ_DMA0_TD_ENABLE, VIA_IRQ_DMA0_TD_PENDING, VIA_PCI_DMA_CSR0,7676+ VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008},7777+ {VIA_IRQ_DMA1_TD_ENABLE, VIA_IRQ_DMA1_TD_PENDING, VIA_PCI_DMA_CSR1,7878+ VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008}7979+};7980static int via_num_unichrome = sizeof(via_unichrome_irqs) / sizeof(maskarray_t);8181+static int via_irqmap_unichrome[] = {-1, -1, -1, 0, -1, 1};80828183static unsigned time_diff(struct timeval *now, struct timeval *then)8284{···133113 atomic_inc(&cur_irq->irq_received);134114 DRM_WAKEUP(&cur_irq->irq_queue);135115 handled = 1;116116+ if (dev_priv->irq_map[drm_via_irq_dma0_td] == i) {117117+ via_dmablit_handler(dev, 0, 1);118118+ } else if (dev_priv->irq_map[drm_via_irq_dma1_td] == i) {119119+ via_dmablit_handler(dev, 1, 1);120120+ }136121 }137122 cur_irq++;138123 }···190165 return ret;191166}192167193193-static int168168+int194169via_driver_irq_wait(drm_device_t * dev, unsigned int irq, int force_sequence,195170 unsigned int *sequence)196171{···199174 drm_via_irq_t *cur_irq = dev_priv->via_irqs;200175 int ret = 0;201176 maskarray_t *masks = dev_priv->irq_masks;177177+ int real_irq;202178203179 DRM_DEBUG("%s\n", __FUNCTION__);204180···208182 return DRM_ERR(EINVAL);209183 }210184211211- if (irq >= dev_priv->num_irqs) {185185+ if (irq >= drm_via_irq_num) {212186 DRM_ERROR("%s Trying to wait on unknown irq %d\n", __FUNCTION__,213187 irq);214188 return DRM_ERR(EINVAL);215189 }216190217217- cur_irq += irq;191191+ real_irq = dev_priv->irq_map[irq];218192219219- if (masks[irq][2] && !force_sequence) {193193+ if (real_irq < 0) {194194+ DRM_ERROR("%s Video IRQ %d not available on this hardware.\n",195195+ __FUNCTION__, irq);196196+ return DRM_ERR(EINVAL);197197+ }198198+199199+ cur_irq += real_irq;200200+201201+ if (masks[real_irq][2] && !force_sequence) {220202 DRM_WAIT_ON(ret, cur_irq->irq_queue, 3 * DRM_HZ,221203 ((VIA_READ(masks[irq][2]) & masks[irq][3]) ==222204 masks[irq][4]));···260226 via_pro_group_a_irqs : via_unichrome_irqs;261227 dev_priv->num_irqs = (dev_priv->pro_group_a) ?262228 via_num_pro_group_a : via_num_unichrome;229229+ dev_priv->irq_map = (dev_priv->pro_group_a) ?230230+ via_irqmap_pro_group_a : via_irqmap_unichrome;263231264232 for (i = 0; i < dev_priv->num_irqs; ++i) {265233 atomic_set(&cur_irq->irq_received, 0);···277241278242 dev_priv->last_vblank_valid = 0;279243280280- // Clear VSync interrupt regs244244+ /* Clear VSync interrupt regs */281245 status = VIA_READ(VIA_REG_INTERRUPT);282246 VIA_WRITE(VIA_REG_INTERRUPT, status &283247 ~(dev_priv->irq_enable_mask));···327291328292int via_wait_irq(DRM_IOCTL_ARGS)329293{330330- drm_file_t *priv = filp->private_data;331331- drm_device_t *dev = priv->head->dev;294294+ DRM_DEVICE;332295 drm_via_irqwait_t __user *argp = (void __user *)data;333296 drm_via_irqwait_t irqwait;334297 struct timeval now;
···4242static int via_fb_alloc(drm_via_mem_t * mem);4343static int via_fb_free(drm_via_mem_t * mem);44444545-static int add_alloc_set(int context, int type, unsigned int val)4545+static int add_alloc_set(int context, int type, unsigned long val)4646{4747 int i, retval = 0;4848···5656 return retval;5757}58585959-static int del_alloc_set(int context, int type, unsigned int val)5959+static int del_alloc_set(int context, int type, unsigned long val)6060{6161 int i, retval = 0;6262···199199 sizeof(mem));200200201201 switch (mem.type) {202202- case VIDEO:202202+ case VIA_MEM_VIDEO:203203 if (via_fb_alloc(&mem) < 0)204204 return -EFAULT;205205 DRM_COPY_TO_USER_IOCTL((drm_via_mem_t __user *) data, mem,206206 sizeof(mem));207207 return 0;208208- case AGP:208208+ case VIA_MEM_AGP:209209 if (via_agp_alloc(&mem) < 0)210210 return -EFAULT;211211 DRM_COPY_TO_USER_IOCTL((drm_via_mem_t __user *) data, mem,···232232 if (block) {233233 fb.offset = block->ofs;234234 fb.free = (unsigned long)block;235235- if (!add_alloc_set(fb.context, VIDEO, fb.free)) {235235+ if (!add_alloc_set(fb.context, VIA_MEM_VIDEO, fb.free)) {236236 DRM_DEBUG("adding to allocation set fails\n");237237 via_mmFreeMem((PMemBlock) fb.free);238238 retval = -1;···269269 if (block) {270270 agp.offset = block->ofs;271271 agp.free = (unsigned long)block;272272- if (!add_alloc_set(agp.context, AGP, agp.free)) {272272+ if (!add_alloc_set(agp.context, VIA_MEM_AGP, agp.free)) {273273 DRM_DEBUG("adding to allocation set fails\n");274274 via_mmFreeMem((PMemBlock) agp.free);275275 retval = -1;···297297298298 switch (mem.type) {299299300300- case VIDEO:300300+ case VIA_MEM_VIDEO:301301 if (via_fb_free(&mem) == 0)302302 return 0;303303 break;304304- case AGP:304304+ case VIA_MEM_AGP:305305 if (via_agp_free(&mem) == 0)306306 return 0;307307 break;···329329330330 via_mmFreeMem((PMemBlock) fb.free);331331332332- if (!del_alloc_set(fb.context, VIDEO, fb.free)) {332332+ if (!del_alloc_set(fb.context, VIA_MEM_VIDEO, fb.free)) {333333 retval = -1;334334 }335335···352352353353 via_mmFreeMem((PMemBlock) agp.free);354354355355- if (!del_alloc_set(agp.context, AGP, agp.free)) {355355+ if (!del_alloc_set(agp.context, VIA_MEM_AGP, agp.free)) {356356 retval = -1;357357 }358358
···4747 int agp_texture;4848 int multitex;4949 drm_device_t *dev;5050- drm_map_t *map_cache;5050+ drm_local_map_t *map_cache;5151 uint32_t vertex_count;5252 int agp;5353 const uint32_t *buf_start;···55555656extern int via_verify_command_stream(const uint32_t * buf, unsigned int size,5757 drm_device_t * dev, int agp);5858+extern int via_parse_command_stream(drm_device_t *dev, const uint32_t *buf,5959+ unsigned int size);58605961#endif
+5-2
drivers/char/drm/via_video.c
···5050 unsigned int i;5151 volatile int *lock;52525353+ if (!dev_priv->sarea_priv)5454+ return;5555+5356 for (i = 0; i < VIA_NR_XVMC_LOCKS; ++i) {5454- lock = (int *)XVMCLOCKPTR(dev_priv->sarea_priv, i);5757+ lock = (volatile int *)XVMCLOCKPTR(dev_priv->sarea_priv, i);5558 if ((_DRM_LOCKING_CONTEXT(*lock) == context)) {5659 if (_DRM_LOCK_IS_HELD(*lock)5760 && (*lock & _DRM_LOCK_CONT)) {···8279 if (fx.lock > VIA_NR_XVMC_LOCKS)8380 return -EFAULT;84818585- lock = (int *)XVMCLOCKPTR(sAPriv, fx.lock);8282+ lock = (volatile int *)XVMCLOCKPTR(sAPriv, fx.lock);86838784 switch (fx.func) {8885 case VIA_FUTEX_WAIT: