Commit d985c108 authored by Dave Airlie's avatar Dave Airlie Committed by Dave Airlie

drm: major update from CVS for radeon and core

This patch pull in a lot of changes from CVS to the main core DRM,
and updates the radeon driver to 1.21.0 that supports r300 texrect
and radeon card type ioctl.
Signed-off-by: default avatarDave Airlie <airlied@linux.ie>
parent b0cae664
...@@ -550,7 +550,7 @@ struct drm_driver { ...@@ -550,7 +550,7 @@ struct drm_driver {
int (*kernel_context_switch) (struct drm_device * dev, int old, int (*kernel_context_switch) (struct drm_device * dev, int old,
int new); int new);
void (*kernel_context_switch_unlock) (struct drm_device * dev, void (*kernel_context_switch_unlock) (struct drm_device * dev,
drm_lock_t * lock); drm_lock_t *lock);
int (*vblank_wait) (struct drm_device * dev, unsigned int *sequence); int (*vblank_wait) (struct drm_device * dev, unsigned int *sequence);
int (*dri_library_name) (struct drm_device *dev, char *buf); int (*dri_library_name) (struct drm_device *dev, char *buf);
...@@ -574,12 +574,11 @@ struct drm_driver { ...@@ -574,12 +574,11 @@ struct drm_driver {
void (*irq_postinstall) (struct drm_device * dev); void (*irq_postinstall) (struct drm_device * dev);
void (*irq_uninstall) (struct drm_device * dev); void (*irq_uninstall) (struct drm_device * dev);
void (*reclaim_buffers) (struct drm_device * dev, struct file * filp); void (*reclaim_buffers) (struct drm_device * dev, struct file * filp);
void (*reclaim_buffers_locked) (struct drm_device *drv, void (*reclaim_buffers_locked) (struct drm_device *dev,
struct file *filp); struct file *filp);
unsigned long (*get_map_ofs) (drm_map_t * map); unsigned long (*get_map_ofs) (drm_map_t * map);
unsigned long (*get_reg_ofs) (struct drm_device * dev); unsigned long (*get_reg_ofs) (struct drm_device * dev);
void (*set_version) (struct drm_device * dev, drm_set_version_t * sv); void (*set_version) (struct drm_device * dev, drm_set_version_t * sv);
int (*version) (drm_version_t * version);
int major; int major;
int minor; int minor;
...@@ -774,10 +773,6 @@ static inline int drm_mtrr_del(int handle, unsigned long offset, ...@@ -774,10 +773,6 @@ static inline int drm_mtrr_del(int handle, unsigned long offset,
/** \name Internal function definitions */ /** \name Internal function definitions */
/*@{*/ /*@{*/
/* Misc. support (drm_init.h) */
extern int drm_flags;
extern void drm_parse_options(char *s);
/* Driver support (drm_drv.h) */ /* Driver support (drm_drv.h) */
extern int drm_init(struct drm_driver *driver); extern int drm_init(struct drm_driver *driver);
extern void drm_exit(struct drm_driver *driver); extern void drm_exit(struct drm_driver *driver);
...@@ -831,6 +826,8 @@ extern int drm_getstats(struct inode *inode, struct file *filp, ...@@ -831,6 +826,8 @@ extern int drm_getstats(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg); unsigned int cmd, unsigned long arg);
extern int drm_setversion(struct inode *inode, struct file *filp, extern int drm_setversion(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg); unsigned int cmd, unsigned long arg);
extern int drm_noop(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
/* Context IOCTL support (drm_context.h) */ /* Context IOCTL support (drm_context.h) */
extern int drm_resctx(struct inode *inode, struct file *filp, extern int drm_resctx(struct inode *inode, struct file *filp,
...@@ -867,10 +864,6 @@ extern int drm_rmdraw(struct inode *inode, struct file *filp, ...@@ -867,10 +864,6 @@ extern int drm_rmdraw(struct inode *inode, struct file *filp,
extern int drm_getmagic(struct inode *inode, struct file *filp, extern int drm_getmagic(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg); unsigned int cmd, unsigned long arg);
extern int drm_authmagic(struct inode *inode, struct file *filp, extern int drm_authmagic(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
/* Placeholder for ioctls past */
extern int drm_noop(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg); unsigned int cmd, unsigned long arg);
/* Locking IOCTL support (drm_lock.h) */ /* Locking IOCTL support (drm_lock.h) */
...@@ -885,6 +878,7 @@ extern int drm_lock_free(drm_device_t * dev, ...@@ -885,6 +878,7 @@ extern int drm_lock_free(drm_device_t * dev,
/* Buffer management support (drm_bufs.h) */ /* Buffer management support (drm_bufs.h) */
extern int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request); extern int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request);
extern int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request); extern int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request);
extern int drm_addbufs_fb(drm_device_t *dev, drm_buf_desc_t *request);
extern int drm_addmap(drm_device_t * dev, unsigned int offset, extern int drm_addmap(drm_device_t * dev, unsigned int offset,
unsigned int size, drm_map_type_t type, unsigned int size, drm_map_type_t type,
drm_map_flags_t flags, drm_local_map_t ** map_ptr); drm_map_flags_t flags, drm_local_map_t ** map_ptr);
...@@ -920,8 +914,8 @@ extern void drm_core_reclaim_buffers(drm_device_t * dev, struct file *filp); ...@@ -920,8 +914,8 @@ extern void drm_core_reclaim_buffers(drm_device_t * dev, struct file *filp);
/* IRQ support (drm_irq.h) */ /* IRQ support (drm_irq.h) */
extern int drm_control(struct inode *inode, struct file *filp, extern int drm_control(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg); unsigned int cmd, unsigned long arg);
extern int drm_irq_uninstall(drm_device_t * dev);
extern irqreturn_t drm_irq_handler(DRM_IRQ_ARGS); extern irqreturn_t drm_irq_handler(DRM_IRQ_ARGS);
extern int drm_irq_uninstall(drm_device_t * dev);
extern void drm_driver_irq_preinstall(drm_device_t * dev); extern void drm_driver_irq_preinstall(drm_device_t * dev);
extern void drm_driver_irq_postinstall(drm_device_t * dev); extern void drm_driver_irq_postinstall(drm_device_t * dev);
extern void drm_driver_irq_uninstall(drm_device_t * dev); extern void drm_driver_irq_uninstall(drm_device_t * dev);
......
/** /**
* \file drm_agpsupport.h * \file drm_agpsupport.c
* DRM support for AGP/GART backend * DRM support for AGP/GART backend
* *
* \author Rickard E. (Rik) Faith <faith@valinux.com> * \author Rickard E. (Rik) Faith <faith@valinux.com>
...@@ -91,7 +91,7 @@ int drm_agp_info_ioctl(struct inode *inode, struct file *filp, ...@@ -91,7 +91,7 @@ int drm_agp_info_ioctl(struct inode *inode, struct file *filp,
/** /**
* Acquire the AGP device. * Acquire the AGP device.
* *
* \param dev DRM device that is to acquire AGP * \param dev DRM device that is to acquire AGP.
* \return zero on success or a negative number on failure. * \return zero on success or a negative number on failure.
* *
* Verifies the AGP device hasn't been acquired before and calls * Verifies the AGP device hasn't been acquired before and calls
...@@ -134,7 +134,7 @@ int drm_agp_acquire_ioctl(struct inode *inode, struct file *filp, ...@@ -134,7 +134,7 @@ int drm_agp_acquire_ioctl(struct inode *inode, struct file *filp,
/** /**
* Release the AGP device. * Release the AGP device.
* *
* \param dev DRM device that is to release AGP * \param dev DRM device that is to release AGP.
* \return zero on success or a negative number on failure. * \return zero on success or a negative number on failure.
* *
* Verifies the AGP device has been acquired and calls \c agp_backend_release. * Verifies the AGP device has been acquired and calls \c agp_backend_release.
...@@ -147,7 +147,6 @@ int drm_agp_release(drm_device_t * dev) ...@@ -147,7 +147,6 @@ int drm_agp_release(drm_device_t * dev)
dev->agp->acquired = 0; dev->agp->acquired = 0;
return 0; return 0;
} }
EXPORT_SYMBOL(drm_agp_release); EXPORT_SYMBOL(drm_agp_release);
int drm_agp_release_ioctl(struct inode *inode, struct file *filp, int drm_agp_release_ioctl(struct inode *inode, struct file *filp,
...@@ -447,6 +446,9 @@ int drm_agp_free_ioctl(struct inode *inode, struct file *filp, ...@@ -447,6 +446,9 @@ int drm_agp_free_ioctl(struct inode *inode, struct file *filp,
* *
* \return pointer to a drm_agp_head structure. * \return pointer to a drm_agp_head structure.
* *
* Gets the drm_agp_t structure which is made available by the agpgart module
* via the inter_module_* functions. Creates and initializes a drm_agp_head
* structure.
*/ */
drm_agp_head_t *drm_agp_init(drm_device_t * dev) drm_agp_head_t *drm_agp_init(drm_device_t * dev)
{ {
......
...@@ -36,22 +36,21 @@ ...@@ -36,22 +36,21 @@
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include "drmP.h" #include "drmP.h"
unsigned long drm_get_resource_start(drm_device_t * dev, unsigned int resource) unsigned long drm_get_resource_start(drm_device_t *dev, unsigned int resource)
{ {
return pci_resource_start(dev->pdev, resource); return pci_resource_start(dev->pdev, resource);
} }
EXPORT_SYMBOL(drm_get_resource_start); EXPORT_SYMBOL(drm_get_resource_start);
unsigned long drm_get_resource_len(drm_device_t * dev, unsigned int resource) unsigned long drm_get_resource_len(drm_device_t *dev, unsigned int resource)
{ {
return pci_resource_len(dev->pdev, resource); return pci_resource_len(dev->pdev, resource);
} }
EXPORT_SYMBOL(drm_get_resource_len); EXPORT_SYMBOL(drm_get_resource_len);
static drm_map_list_t *drm_find_matching_map(drm_device_t * dev, static drm_map_list_t *drm_find_matching_map(drm_device_t *dev,
drm_local_map_t * map) drm_local_map_t *map)
{ {
struct list_head *list; struct list_head *list;
...@@ -74,7 +73,7 @@ static drm_map_list_t *drm_find_matching_map(drm_device_t * dev, ...@@ -74,7 +73,7 @@ static drm_map_list_t *drm_find_matching_map(drm_device_t * dev,
#ifdef _LP64 #ifdef _LP64
static __inline__ unsigned int HandleID(unsigned long lhandle, static __inline__ unsigned int HandleID(unsigned long lhandle,
drm_device_t * dev) drm_device_t *dev)
{ {
static unsigned int map32_handle = START_RANGE; static unsigned int map32_handle = START_RANGE;
unsigned int hash; unsigned int hash;
...@@ -301,6 +300,9 @@ int drm_addmap_ioctl(struct inode *inode, struct file *filp, ...@@ -301,6 +300,9 @@ int drm_addmap_ioctl(struct inode *inode, struct file *filp,
return -EFAULT; return -EFAULT;
} }
if (!(capable(CAP_SYS_ADMIN) || map.type == _DRM_AGP))
return -EPERM;
err = drm_addmap_core(dev, map.offset, map.size, map.type, map.flags, err = drm_addmap_core(dev, map.offset, map.size, map.type, map.flags,
&maplist); &maplist);
...@@ -332,7 +334,7 @@ int drm_addmap_ioctl(struct inode *inode, struct file *filp, ...@@ -332,7 +334,7 @@ int drm_addmap_ioctl(struct inode *inode, struct file *filp,
* *
* \sa drm_addmap * \sa drm_addmap
*/ */
int drm_rmmap_locked(drm_device_t * dev, drm_local_map_t * map) int drm_rmmap_locked(drm_device_t *dev, drm_local_map_t *map)
{ {
struct list_head *list; struct list_head *list;
drm_map_list_t *r_list = NULL; drm_map_list_t *r_list = NULL;
...@@ -384,10 +386,9 @@ int drm_rmmap_locked(drm_device_t * dev, drm_local_map_t * map) ...@@ -384,10 +386,9 @@ int drm_rmmap_locked(drm_device_t * dev, drm_local_map_t * map)
return 0; return 0;
} }
EXPORT_SYMBOL(drm_rmmap_locked); EXPORT_SYMBOL(drm_rmmap_locked);
int drm_rmmap(drm_device_t * dev, drm_local_map_t * map) int drm_rmmap(drm_device_t *dev, drm_local_map_t *map)
{ {
int ret; int ret;
...@@ -397,7 +398,6 @@ int drm_rmmap(drm_device_t * dev, drm_local_map_t * map) ...@@ -397,7 +398,6 @@ int drm_rmmap(drm_device_t * dev, drm_local_map_t * map)
return ret; return ret;
} }
EXPORT_SYMBOL(drm_rmmap); EXPORT_SYMBOL(drm_rmmap);
/* The rmmap ioctl appears to be unnecessary. All mappings are torn down on /* The rmmap ioctl appears to be unnecessary. All mappings are torn down on
...@@ -548,7 +548,7 @@ int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request) ...@@ -548,7 +548,7 @@ int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request)
DRM_DEBUG("count: %d\n", count); DRM_DEBUG("count: %d\n", count);
DRM_DEBUG("order: %d\n", order); DRM_DEBUG("order: %d\n", order);
DRM_DEBUG("size: %d\n", size); DRM_DEBUG("size: %d\n", size);
DRM_DEBUG("agp_offset: %lu\n", agp_offset); DRM_DEBUG("agp_offset: %lx\n", agp_offset);
DRM_DEBUG("alignment: %d\n", alignment); DRM_DEBUG("alignment: %d\n", alignment);
DRM_DEBUG("page_order: %d\n", page_order); DRM_DEBUG("page_order: %d\n", page_order);
DRM_DEBUG("total: %d\n", total); DRM_DEBUG("total: %d\n", total);
...@@ -649,6 +649,8 @@ int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request) ...@@ -649,6 +649,8 @@ int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request)
} }
dma->buf_count += entry->buf_count; dma->buf_count += entry->buf_count;
dma->seg_count += entry->seg_count;
dma->page_count += byte_count >> PAGE_SHIFT;
dma->byte_count += byte_count; dma->byte_count += byte_count;
DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count); DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count);
...@@ -664,7 +666,6 @@ int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request) ...@@ -664,7 +666,6 @@ int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request)
atomic_dec(&dev->buf_alloc); atomic_dec(&dev->buf_alloc);
return 0; return 0;
} }
EXPORT_SYMBOL(drm_addbufs_agp); EXPORT_SYMBOL(drm_addbufs_agp);
#endif /* __OS_HAS_AGP */ #endif /* __OS_HAS_AGP */
...@@ -689,9 +690,13 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request) ...@@ -689,9 +690,13 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request)
if (!drm_core_check_feature(dev, DRIVER_PCI_DMA)) if (!drm_core_check_feature(dev, DRIVER_PCI_DMA))
return -EINVAL; return -EINVAL;
if (!dma) if (!dma)
return -EINVAL; return -EINVAL;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
count = request->count; count = request->count;
order = drm_order(request->size); order = drm_order(request->size);
size = 1 << order; size = 1 << order;
...@@ -882,7 +887,6 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request) ...@@ -882,7 +887,6 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request)
return 0; return 0;
} }
EXPORT_SYMBOL(drm_addbufs_pci); EXPORT_SYMBOL(drm_addbufs_pci);
static int drm_addbufs_sg(drm_device_t * dev, drm_buf_desc_t * request) static int drm_addbufs_sg(drm_device_t * dev, drm_buf_desc_t * request)
...@@ -908,6 +912,9 @@ static int drm_addbufs_sg(drm_device_t * dev, drm_buf_desc_t * request) ...@@ -908,6 +912,9 @@ static int drm_addbufs_sg(drm_device_t * dev, drm_buf_desc_t * request)
if (!dma) if (!dma)
return -EINVAL; return -EINVAL;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
count = request->count; count = request->count;
order = drm_order(request->size); order = drm_order(request->size);
size = 1 << order; size = 1 << order;
...@@ -1026,6 +1033,8 @@ static int drm_addbufs_sg(drm_device_t * dev, drm_buf_desc_t * request) ...@@ -1026,6 +1033,8 @@ static int drm_addbufs_sg(drm_device_t * dev, drm_buf_desc_t * request)
} }
dma->buf_count += entry->buf_count; dma->buf_count += entry->buf_count;
dma->seg_count += entry->seg_count;
dma->page_count += byte_count >> PAGE_SHIFT;
dma->byte_count += byte_count; dma->byte_count += byte_count;
DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count); DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count);
...@@ -1042,7 +1051,7 @@ static int drm_addbufs_sg(drm_device_t * dev, drm_buf_desc_t * request) ...@@ -1042,7 +1051,7 @@ static int drm_addbufs_sg(drm_device_t * dev, drm_buf_desc_t * request)
return 0; return 0;
} }
static int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request) int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request)
{ {
drm_device_dma_t *dma = dev->dma; drm_device_dma_t *dma = dev->dma;
drm_buf_entry_t *entry; drm_buf_entry_t *entry;
...@@ -1065,6 +1074,9 @@ static int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request) ...@@ -1065,6 +1074,9 @@ static int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request)
if (!dma) if (!dma)
return -EINVAL; return -EINVAL;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
count = request->count; count = request->count;
order = drm_order(request->size); order = drm_order(request->size);
size = 1 << order; size = 1 << order;
...@@ -1181,6 +1193,8 @@ static int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request) ...@@ -1181,6 +1193,8 @@ static int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request)
} }
dma->buf_count += entry->buf_count; dma->buf_count += entry->buf_count;
dma->seg_count += entry->seg_count;
dma->page_count += byte_count >> PAGE_SHIFT;
dma->byte_count += byte_count; dma->byte_count += byte_count;
DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count); DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count);
...@@ -1196,6 +1210,8 @@ static int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request) ...@@ -1196,6 +1210,8 @@ static int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request)
atomic_dec(&dev->buf_alloc); atomic_dec(&dev->buf_alloc);
return 0; return 0;
} }
EXPORT_SYMBOL(drm_addbufs_fb);
/** /**
* Add buffers for DMA transfers (ioctl). * Add buffers for DMA transfers (ioctl).
...@@ -1577,5 +1593,6 @@ int drm_order(unsigned long size) ...@@ -1577,5 +1593,6 @@ int drm_order(unsigned long size)
return order; return order;
} }
EXPORT_SYMBOL(drm_order); EXPORT_SYMBOL(drm_order);
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
*/ */
#include "drmP.h" #include "drmP.h"
#include "drm_sarea.h"
#include <linux/poll.h> #include <linux/poll.h>
static int drm_open_helper(struct inode *inode, struct file *filp, static int drm_open_helper(struct inode *inode, struct file *filp,
...@@ -42,6 +43,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp, ...@@ -42,6 +43,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
static int drm_setup(drm_device_t * dev) static int drm_setup(drm_device_t * dev)
{ {
drm_local_map_t *map;
int i; int i;
int ret; int ret;
...@@ -51,6 +53,11 @@ static int drm_setup(drm_device_t * dev) ...@@ -51,6 +53,11 @@ static int drm_setup(drm_device_t * dev)
return ret; return ret;
} }
/* prebuild the SAREA */
i = drm_addmap(dev, 0, SAREA_MAX, _DRM_SHM, _DRM_CONTAINS_LOCK, &map);
if (i != 0)
return i;
atomic_set(&dev->ioctl_count, 0); atomic_set(&dev->ioctl_count, 0);
atomic_set(&dev->vma_count, 0); atomic_set(&dev->vma_count, 0);
dev->buf_use = 0; dev->buf_use = 0;
...@@ -152,9 +159,167 @@ int drm_open(struct inode *inode, struct file *filp) ...@@ -152,9 +159,167 @@ int drm_open(struct inode *inode, struct file *filp)
return retcode; return retcode;
} }
EXPORT_SYMBOL(drm_open); EXPORT_SYMBOL(drm_open);
/**
* File \c open operation.
*
* \param inode device inode.
* \param filp file pointer.
*
* Puts the dev->fops corresponding to the device minor number into
* \p filp, call the \c open method, and restore the file operations.
*/
int drm_stub_open(struct inode *inode, struct file *filp)
{
drm_device_t *dev = NULL;
int minor = iminor(inode);
int err = -ENODEV;
struct file_operations *old_fops;
DRM_DEBUG("\n");
if (!((minor >= 0) && (minor < drm_cards_limit)))
return -ENODEV;
if (!drm_heads[minor])
return -ENODEV;
if (!(dev = drm_heads[minor]->dev))
return -ENODEV;
old_fops = filp->f_op;
filp->f_op = fops_get(&dev->driver->fops);
if (filp->f_op->open && (err = filp->f_op->open(inode, filp))) {
fops_put(filp->f_op);
filp->f_op = fops_get(old_fops);
}
fops_put(old_fops);
return err;
}
/**
* Check whether DRI will run on this CPU.
*
* \return non-zero if the DRI will run on this CPU, or zero otherwise.
*/
static int drm_cpu_valid(void)
{
#if defined(__i386__)
if (boot_cpu_data.x86 == 3)
return 0; /* No cmpxchg on a 386 */
#endif
#if defined(__sparc__) && !defined(__sparc_v9__)
return 0; /* No cmpxchg before v9 sparc. */
#endif
return 1;
}
/**
* Called whenever a process opens /dev/drm.
*
* \param inode device inode.
* \param filp file pointer.
* \param dev device.
* \return zero on success or a negative number on failure.
*
* Creates and initializes a drm_file structure for the file private data in \p
* filp and add it into the double linked list in \p dev.
*/
static int drm_open_helper(struct inode *inode, struct file *filp,
drm_device_t * dev)
{
int minor = iminor(inode);
drm_file_t *priv;
int ret;
if (filp->f_flags & O_EXCL)
return -EBUSY; /* No exclusive opens */
if (!drm_cpu_valid())
return -EINVAL;
DRM_DEBUG("pid = %d, minor = %d\n", current->pid, minor);
priv = drm_alloc(sizeof(*priv), DRM_MEM_FILES);
if (!priv)
return -ENOMEM;
memset(priv, 0, sizeof(*priv));
filp->private_data = priv;
priv->uid = current->euid;
priv->pid = current->pid;
priv->minor = minor;
priv->head = drm_heads[minor];
priv->ioctl_count = 0;
/* for compatibility root is always authenticated */
priv->authenticated = capable(CAP_SYS_ADMIN);
priv->lock_count = 0;
if (dev->driver->open) {
ret = dev->driver->open(dev, priv);
if (ret < 0)
goto out_free;
}
down(&dev->struct_sem);
if (!dev->file_last) {
priv->next = NULL;
priv->prev = NULL;
dev->file_first = priv;
dev->file_last = priv;
/* first opener automatically becomes master */
priv->master = 1;
} else {
priv->next = NULL;
priv->prev = dev->file_last;
dev->file_last->next = priv;
dev->file_last = priv;
}
up(&dev->struct_sem);
#ifdef __alpha__
/*
* Default the hose
*/
if (!dev->hose) {
struct pci_dev *pci_dev;
pci_dev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, NULL);
if (pci_dev) {
dev->hose = pci_dev->sysdata;
pci_dev_put(pci_dev);
}
if (!dev->hose) {
struct pci_bus *b = pci_bus_b(pci_root_buses.next);
if (b)
dev->hose = b->sysdata;
}
}
#endif
return 0;
out_free:
drm_free(priv, sizeof(*priv), DRM_MEM_FILES);
filp->private_data = NULL;
return ret;
}
/** No-op. */
int drm_fasync(int fd, struct file *filp, int on)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
int retcode;
DRM_DEBUG("fd = %d, device = 0x%lx\n", fd,
(long)old_encode_dev(priv->head->device));
retcode = fasync_helper(fd, filp, on, &dev->buf_async);
if (retcode < 0)
return retcode;
return 0;
}
EXPORT_SYMBOL(drm_fasync);
/** /**
* Release file. * Release file.
* *
...@@ -291,7 +456,6 @@ int drm_release(struct inode *inode, struct file *filp) ...@@ -291,7 +456,6 @@ int drm_release(struct inode *inode, struct file *filp)
if (dev->driver->postclose) if (dev->driver->postclose)
dev->driver->postclose(dev, priv); dev->driver->postclose(dev, priv);
drm_free(priv, sizeof(*priv), DRM_MEM_FILES); drm_free(priv, sizeof(*priv), DRM_MEM_FILES);
/* ======================================================== /* ========================================================
...@@ -318,132 +482,11 @@ int drm_release(struct inode *inode, struct file *filp) ...@@ -318,132 +482,11 @@ int drm_release(struct inode *inode, struct file *filp)
return retcode; return retcode;
} }
EXPORT_SYMBOL(drm_release); EXPORT_SYMBOL(drm_release);
/**
* Check whether DRI will run on this CPU.
*
* \return non-zero if the DRI will run on this CPU, or zero otherwise.
*/
static int drm_cpu_valid(void)
{
#if defined(__i386__)
if (boot_cpu_data.x86 == 3)
return 0; /* No cmpxchg on a 386 */
#endif
#if defined(__sparc__) && !defined(__sparc_v9__)
return 0; /* No cmpxchg before v9 sparc. */
#endif
return 1;
}
/**
* Called whenever a process opens /dev/drm.
*
* \param inode device inode.
* \param filp file pointer.
* \param dev device.
* \return zero on success or a negative number on failure.
*
* Creates and initializes a drm_file structure for the file private data in \p
* filp and add it into the double linked list in \p dev.
*/
static int drm_open_helper(struct inode *inode, struct file *filp,
drm_device_t * dev)
{
int minor = iminor(inode);
drm_file_t *priv;
int ret;
if (filp->f_flags & O_EXCL)
return -EBUSY; /* No exclusive opens */
if (!drm_cpu_valid())
return -EINVAL;
DRM_DEBUG("pid = %d, minor = %d\n", current->pid, minor);
priv = drm_alloc(sizeof(*priv), DRM_MEM_FILES);
if (!priv)
return -ENOMEM;
memset(priv, 0, sizeof(*priv));
filp->private_data = priv;
priv->uid = current->euid;
priv->pid = current->pid;
priv->minor = minor;
priv->head = drm_heads[minor];
priv->ioctl_count = 0;
priv->authenticated = capable(CAP_SYS_ADMIN);
priv->lock_count = 0;
if (dev->driver->open) {
ret = dev->driver->open(dev, priv);
if (ret < 0)
goto out_free;
}
down(&dev->struct_sem);
if (!dev->file_last) {
priv->next = NULL;
priv->prev = NULL;
dev->file_first = priv;
dev->file_last = priv;
} else {
priv->next = NULL;
priv->prev = dev->file_last;
dev->file_last->next = priv;
dev->file_last = priv;
}
up(&dev->struct_sem);
#ifdef __alpha__
/*
* Default the hose
*/
if (!dev->hose) {
struct pci_dev *pci_dev;
pci_dev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, NULL);
if (pci_dev) {
dev->hose = pci_dev->sysdata;
pci_dev_put(pci_dev);
}
if (!dev->hose) {
struct pci_bus *b = pci_bus_b(pci_root_buses.next);
if (b)
dev->hose = b->sysdata;
}
}
#endif
return 0;
out_free:
drm_free(priv, sizeof(*priv), DRM_MEM_FILES);
filp->private_data = NULL;
return ret;
}
/** No-op. */
int drm_fasync(int fd, struct file *filp, int on)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
int retcode;
DRM_DEBUG("fd = %d, device = 0x%lx\n", fd,
(long)old_encode_dev(priv->head->device));
retcode = fasync_helper(fd, filp, on, &dev->buf_async);
if (retcode < 0)
return retcode;
return 0;
}
EXPORT_SYMBOL(drm_fasync);
/** No-op. */ /** No-op. */
unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait) unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait)
{ {
return 0; return 0;
} }
EXPORT_SYMBOL(drm_poll); EXPORT_SYMBOL(drm_poll);
...@@ -104,6 +104,9 @@ int drm_lock(struct inode *inode, struct file *filp, ...@@ -104,6 +104,9 @@ int drm_lock(struct inode *inode, struct file *filp,
__set_current_state(TASK_RUNNING); __set_current_state(TASK_RUNNING);
remove_wait_queue(&dev->lock.lock_queue, &entry); remove_wait_queue(&dev->lock.lock_queue, &entry);
DRM_DEBUG( "%d %s\n", lock.context, ret ? "interrupted" : "has lock" );
if (ret) return ret;
sigemptyset(&dev->sigmask); sigemptyset(&dev->sigmask);
sigaddset(&dev->sigmask, SIGSTOP); sigaddset(&dev->sigmask, SIGSTOP);
sigaddset(&dev->sigmask, SIGTSTP); sigaddset(&dev->sigmask, SIGTSTP);
...@@ -116,21 +119,20 @@ int drm_lock(struct inode *inode, struct file *filp, ...@@ -116,21 +119,20 @@ int drm_lock(struct inode *inode, struct file *filp,
if (dev->driver->dma_ready && (lock.flags & _DRM_LOCK_READY)) if (dev->driver->dma_ready && (lock.flags & _DRM_LOCK_READY))
dev->driver->dma_ready(dev); dev->driver->dma_ready(dev);
if (dev->driver->dma_quiescent && (lock.flags & _DRM_LOCK_QUIESCENT)) if (dev->driver->dma_quiescent && (lock.flags & _DRM_LOCK_QUIESCENT)) {
return dev->driver->dma_quiescent(dev); if (dev->driver->dma_quiescent(dev)) {
DRM_DEBUG( "%d waiting for DMA quiescent\n", lock.context);
/* dev->driver->kernel_context_switch isn't used by any of the x86 return DRM_ERR(EBUSY);
* drivers but is used by the Sparc driver. }
*/ }
if (dev->driver->kernel_context_switch && if (dev->driver->kernel_context_switch &&
dev->last_context != lock.context) { dev->last_context != lock.context) {
dev->driver->kernel_context_switch(dev, dev->last_context, dev->driver->kernel_context_switch(dev, dev->last_context,
lock.context); lock.context);
} }
DRM_DEBUG("%d %s\n", lock.context, ret ? "interrupted" : "has lock");
return ret; return 0;
} }
/** /**
......
...@@ -128,43 +128,6 @@ static int drm_fill_in_dev(drm_device_t * dev, struct pci_dev *pdev, ...@@ -128,43 +128,6 @@ static int drm_fill_in_dev(drm_device_t * dev, struct pci_dev *pdev,
return retcode; return retcode;
} }
/**
* File \c open operation.
*
* \param inode device inode.
* \param filp file pointer.
*
* Puts the dev->fops corresponding to the device minor number into
* \p filp, call the \c open method, and restore the file operations.
*/
int drm_stub_open(struct inode *inode, struct file *filp)
{
drm_device_t *dev = NULL;
int minor = iminor(inode);
int err = -ENODEV;
struct file_operations *old_fops;
DRM_DEBUG("\n");
if (!((minor >= 0) && (minor < drm_cards_limit)))
return -ENODEV;
if (!drm_heads[minor])
return -ENODEV;
if (!(dev = drm_heads[minor]->dev))
return -ENODEV;
old_fops = filp->f_op;
filp->f_op = fops_get(&dev->driver->fops);
if (filp->f_op->open && (err = filp->f_op->open(inode, filp))) {
fops_put(filp->f_op);
filp->f_op = fops_get(old_fops);
}
fops_put(old_fops);
return err;
}
/** /**
* Get a secondary minor number. * Get a secondary minor number.
......
...@@ -52,8 +52,8 @@ static const int r300_cliprect_cntl[4] = { ...@@ -52,8 +52,8 @@ static const int r300_cliprect_cntl[4] = {
* Emit up to R300_SIMULTANEOUS_CLIPRECTS cliprects from the given command * Emit up to R300_SIMULTANEOUS_CLIPRECTS cliprects from the given command
* buffer, starting with index n. * buffer, starting with index n.
*/ */
static int r300_emit_cliprects(drm_radeon_private_t * dev_priv, static int r300_emit_cliprects(drm_radeon_private_t *dev_priv,
drm_radeon_kcmd_buffer_t * cmdbuf, int n) drm_radeon_kcmd_buffer_t *cmdbuf, int n)
{ {
drm_clip_rect_t box; drm_clip_rect_t box;
int nr; int nr;
...@@ -216,6 +216,7 @@ void r300_init_reg_flags(void) ...@@ -216,6 +216,7 @@ void r300_init_reg_flags(void)
ADD_RANGE(R300_TX_UNK1_0, 16); ADD_RANGE(R300_TX_UNK1_0, 16);
ADD_RANGE(R300_TX_SIZE_0, 16); ADD_RANGE(R300_TX_SIZE_0, 16);
ADD_RANGE(R300_TX_FORMAT_0, 16); ADD_RANGE(R300_TX_FORMAT_0, 16);
ADD_RANGE(R300_TX_PITCH_0, 16);
/* Texture offset is dangerous and needs more checking */ /* Texture offset is dangerous and needs more checking */
ADD_RANGE_MARK(R300_TX_OFFSET_0, 16, MARK_CHECK_OFFSET); ADD_RANGE_MARK(R300_TX_OFFSET_0, 16, MARK_CHECK_OFFSET);
ADD_RANGE(R300_TX_UNK4_0, 16); ADD_RANGE(R300_TX_UNK4_0, 16);
...@@ -242,7 +243,7 @@ static __inline__ int r300_check_range(unsigned reg, int count) ...@@ -242,7 +243,7 @@ static __inline__ int r300_check_range(unsigned reg, int count)
/* we expect offsets passed to the framebuffer to be either within video memory or /* we expect offsets passed to the framebuffer to be either within video memory or
within AGP space */ within AGP space */
static __inline__ int r300_check_offset(drm_radeon_private_t * dev_priv, static __inline__ int r300_check_offset(drm_radeon_private_t *dev_priv,
u32 offset) u32 offset)
{ {
/* we realy want to check against end of video aperture /* we realy want to check against end of video aperture
...@@ -317,8 +318,8 @@ static __inline__ int r300_emit_carefully_checked_packet0(drm_radeon_private_t * ...@@ -317,8 +318,8 @@ static __inline__ int r300_emit_carefully_checked_packet0(drm_radeon_private_t *
* *
* Note that checks are performed on contents and addresses of the registers * Note that checks are performed on contents and addresses of the registers
*/ */
static __inline__ int r300_emit_packet0(drm_radeon_private_t * dev_priv, static __inline__ int r300_emit_packet0(drm_radeon_private_t *dev_priv,
drm_radeon_kcmd_buffer_t * cmdbuf, drm_radeon_kcmd_buffer_t *cmdbuf,
drm_r300_cmd_header_t header) drm_r300_cmd_header_t header)
{ {
int reg; int reg;
...@@ -363,8 +364,8 @@ static __inline__ int r300_emit_packet0(drm_radeon_private_t * dev_priv, ...@@ -363,8 +364,8 @@ static __inline__ int r300_emit_packet0(drm_radeon_private_t * dev_priv,
* the graphics card. * the graphics card.
* Called by r300_do_cp_cmdbuf. * Called by r300_do_cp_cmdbuf.
*/ */
static __inline__ int r300_emit_vpu(drm_radeon_private_t * dev_priv, static __inline__ int r300_emit_vpu(drm_radeon_private_t *dev_priv,
drm_radeon_kcmd_buffer_t * cmdbuf, drm_radeon_kcmd_buffer_t *cmdbuf,
drm_r300_cmd_header_t header) drm_r300_cmd_header_t header)
{ {
int sz; int sz;
...@@ -400,8 +401,8 @@ static __inline__ int r300_emit_vpu(drm_radeon_private_t * dev_priv, ...@@ -400,8 +401,8 @@ static __inline__ int r300_emit_vpu(drm_radeon_private_t * dev_priv,
* Emit a clear packet from userspace. * Emit a clear packet from userspace.
* Called by r300_emit_packet3. * Called by r300_emit_packet3.
*/ */
static __inline__ int r300_emit_clear(drm_radeon_private_t * dev_priv, static __inline__ int r300_emit_clear(drm_radeon_private_t *dev_priv,
drm_radeon_kcmd_buffer_t * cmdbuf) drm_radeon_kcmd_buffer_t *cmdbuf)
{ {
RING_LOCALS; RING_LOCALS;
...@@ -421,8 +422,8 @@ static __inline__ int r300_emit_clear(drm_radeon_private_t * dev_priv, ...@@ -421,8 +422,8 @@ static __inline__ int r300_emit_clear(drm_radeon_private_t * dev_priv,
return 0; return 0;
} }
static __inline__ int r300_emit_3d_load_vbpntr(drm_radeon_private_t * dev_priv, static __inline__ int r300_emit_3d_load_vbpntr(drm_radeon_private_t *dev_priv,
drm_radeon_kcmd_buffer_t * cmdbuf, drm_radeon_kcmd_buffer_t *cmdbuf,
u32 header) u32 header)
{ {
int count, i, k; int count, i, k;
...@@ -489,8 +490,8 @@ static __inline__ int r300_emit_3d_load_vbpntr(drm_radeon_private_t * dev_priv, ...@@ -489,8 +490,8 @@ static __inline__ int r300_emit_3d_load_vbpntr(drm_radeon_private_t * dev_priv,
return 0; return 0;
} }
static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t * dev_priv, static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t *dev_priv,
drm_radeon_kcmd_buffer_t * cmdbuf) drm_radeon_kcmd_buffer_t *cmdbuf)
{ {
u32 header; u32 header;
int count; int count;
...@@ -554,8 +555,8 @@ static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t * dev_priv, ...@@ -554,8 +555,8 @@ static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t * dev_priv,
* Emit a rendering packet3 from userspace. * Emit a rendering packet3 from userspace.
* Called by r300_do_cp_cmdbuf. * Called by r300_do_cp_cmdbuf.
*/ */
static __inline__ int r300_emit_packet3(drm_radeon_private_t * dev_priv, static __inline__ int r300_emit_packet3(drm_radeon_private_t *dev_priv,
drm_radeon_kcmd_buffer_t * cmdbuf, drm_radeon_kcmd_buffer_t *cmdbuf,
drm_r300_cmd_header_t header) drm_r300_cmd_header_t header)
{ {
int n; int n;
...@@ -623,7 +624,7 @@ static __inline__ int r300_emit_packet3(drm_radeon_private_t * dev_priv, ...@@ -623,7 +624,7 @@ static __inline__ int r300_emit_packet3(drm_radeon_private_t * dev_priv,
/** /**
* Emit the sequence to pacify R300. * Emit the sequence to pacify R300.
*/ */
static __inline__ void r300_pacify(drm_radeon_private_t * dev_priv) static __inline__ void r300_pacify(drm_radeon_private_t *dev_priv)
{ {
RING_LOCALS; RING_LOCALS;
...@@ -657,9 +658,10 @@ static void r300_discard_buffer(drm_device_t * dev, drm_buf_t * buf) ...@@ -657,9 +658,10 @@ static void r300_discard_buffer(drm_device_t * dev, drm_buf_t * buf)
* commands on the DMA ring buffer. * commands on the DMA ring buffer.
* Called by the ioctl handler function radeon_cp_cmdbuf. * Called by the ioctl handler function radeon_cp_cmdbuf.
*/ */
int r300_do_cp_cmdbuf(drm_device_t * dev, int r300_do_cp_cmdbuf(drm_device_t *dev,
DRMFILE filp, DRMFILE filp,
drm_file_t * filp_priv, drm_radeon_kcmd_buffer_t * cmdbuf) drm_file_t *filp_priv,
drm_radeon_kcmd_buffer_t *cmdbuf)
{ {
drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_private_t *dev_priv = dev->dev_private;
drm_device_dma_t *dma = dev->dma; drm_device_dma_t *dma = dev->dma;
......
...@@ -797,6 +797,7 @@ I am fairly certain that they are correct unless stated otherwise in comments. ...@@ -797,6 +797,7 @@ I am fairly certain that they are correct unless stated otherwise in comments.
# define R300_TX_FORMAT_YUV_MODE 0x00800000 # define R300_TX_FORMAT_YUV_MODE 0x00800000
#define R300_TX_PITCH_0 0x4500
#define R300_TX_OFFSET_0 0x4540 #define R300_TX_OFFSET_0 0x4540
/* BEGIN: Guess from R200 */ /* BEGIN: Guess from R200 */
# define R300_TXO_ENDIAN_NO_SWAP (0 << 0) # define R300_TXO_ENDIAN_NO_SWAP (0 << 0)
......
...@@ -824,7 +824,7 @@ static int RADEON_READ_PLL(drm_device_t * dev, int addr) ...@@ -824,7 +824,7 @@ static int RADEON_READ_PLL(drm_device_t * dev, int addr)
return RADEON_READ(RADEON_CLOCK_CNTL_DATA); return RADEON_READ(RADEON_CLOCK_CNTL_DATA);
} }
static int RADEON_READ_PCIE(drm_radeon_private_t * dev_priv, int addr) static int RADEON_READ_PCIE(drm_radeon_private_t *dev_priv, int addr)
{ {
RADEON_WRITE8(RADEON_PCIE_INDEX, addr & 0xff); RADEON_WRITE8(RADEON_PCIE_INDEX, addr & 0xff);
return RADEON_READ(RADEON_PCIE_DATA); return RADEON_READ(RADEON_PCIE_DATA);
...@@ -1125,7 +1125,7 @@ static void radeon_cp_init_ring_buffer(drm_device_t * dev, ...@@ -1125,7 +1125,7 @@ static void radeon_cp_init_ring_buffer(drm_device_t * dev,
| (dev_priv->fb_location >> 16)); | (dev_priv->fb_location >> 16));
#if __OS_HAS_AGP #if __OS_HAS_AGP
if (!dev_priv->is_pci) { if (dev_priv->flags & CHIP_IS_AGP) {
RADEON_WRITE(RADEON_MC_AGP_LOCATION, RADEON_WRITE(RADEON_MC_AGP_LOCATION,
(((dev_priv->gart_vm_start - 1 + (((dev_priv->gart_vm_start - 1 +
dev_priv->gart_size) & 0xffff0000) | dev_priv->gart_size) & 0xffff0000) |
...@@ -1152,7 +1152,7 @@ static void radeon_cp_init_ring_buffer(drm_device_t * dev, ...@@ -1152,7 +1152,7 @@ static void radeon_cp_init_ring_buffer(drm_device_t * dev,
dev_priv->ring.tail = cur_read_ptr; dev_priv->ring.tail = cur_read_ptr;
#if __OS_HAS_AGP #if __OS_HAS_AGP
if (!dev_priv->is_pci) { if (dev_priv->flags & CHIP_IS_AGP) {
/* set RADEON_AGP_BASE here instead of relying on X from user space */ /* set RADEON_AGP_BASE here instead of relying on X from user space */
RADEON_WRITE(RADEON_AGP_BASE, (unsigned int)dev->agp->base); RADEON_WRITE(RADEON_AGP_BASE, (unsigned int)dev->agp->base);
RADEON_WRITE(RADEON_CP_RB_RPTR_ADDR, RADEON_WRITE(RADEON_CP_RB_RPTR_ADDR,
...@@ -1278,13 +1278,15 @@ static void radeon_set_pciegart(drm_radeon_private_t * dev_priv, int on) ...@@ -1278,13 +1278,15 @@ static void radeon_set_pciegart(drm_radeon_private_t * dev_priv, int on)
/* Enable or disable PCI GART on the chip */ /* Enable or disable PCI GART on the chip */
static void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on) static void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on)
{ {
u32 tmp = RADEON_READ(RADEON_AIC_CNTL); u32 tmp;
if (dev_priv->flags & CHIP_IS_PCIE) { if (dev_priv->flags & CHIP_IS_PCIE) {
radeon_set_pciegart(dev_priv, on); radeon_set_pciegart(dev_priv, on);
return; return;
} }
tmp = RADEON_READ(RADEON_AIC_CNTL);
if (on) { if (on) {
RADEON_WRITE(RADEON_AIC_CNTL, RADEON_WRITE(RADEON_AIC_CNTL,
tmp | RADEON_PCIGART_TRANSLATE_EN); tmp | RADEON_PCIGART_TRANSLATE_EN);
...@@ -1311,14 +1313,18 @@ static void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on) ...@@ -1311,14 +1313,18 @@ static void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on)
static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
{ {
drm_radeon_private_t *dev_priv = dev->dev_private;; drm_radeon_private_t *dev_priv = dev->dev_private;
DRM_DEBUG("\n"); DRM_DEBUG("\n");
dev_priv->is_pci = init->is_pci; if (init->is_pci && (dev_priv->flags & CHIP_IS_AGP))
{
DRM_DEBUG("Forcing AGP card to PCI mode\n");
dev_priv->flags &= ~CHIP_IS_AGP;
}
if (dev_priv->is_pci && !dev->sg) { if ((!(dev_priv->flags & CHIP_IS_AGP)) && !dev->sg) {
DRM_ERROR("PCI GART memory not allocated!\n"); DRM_ERROR("PCI GART memory not allocated!\n");
dev->dev_private = (void *)dev_priv;
radeon_do_cleanup_cp(dev); radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL); return DRM_ERR(EINVAL);
} }
...@@ -1327,12 +1333,11 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) ...@@ -1327,12 +1333,11 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
if (dev_priv->usec_timeout < 1 || if (dev_priv->usec_timeout < 1 ||
dev_priv->usec_timeout > RADEON_MAX_USEC_TIMEOUT) { dev_priv->usec_timeout > RADEON_MAX_USEC_TIMEOUT) {
DRM_DEBUG("TIMEOUT problem!\n"); DRM_DEBUG("TIMEOUT problem!\n");
dev->dev_private = (void *)dev_priv;
radeon_do_cleanup_cp(dev); radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL); return DRM_ERR(EINVAL);
} }
switch (init->func) { switch(init->func) {
case RADEON_INIT_R200_CP: case RADEON_INIT_R200_CP:
dev_priv->microcode_version = UCODE_R200; dev_priv->microcode_version = UCODE_R200;
break; break;
...@@ -1353,7 +1358,6 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) ...@@ -1353,7 +1358,6 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
if ((init->cp_mode != RADEON_CSQ_PRIBM_INDDIS) && if ((init->cp_mode != RADEON_CSQ_PRIBM_INDDIS) &&
(init->cp_mode != RADEON_CSQ_PRIBM_INDBM)) { (init->cp_mode != RADEON_CSQ_PRIBM_INDBM)) {
DRM_DEBUG("BAD cp_mode (%x)!\n", init->cp_mode); DRM_DEBUG("BAD cp_mode (%x)!\n", init->cp_mode);
dev->dev_private = (void *)dev_priv;
radeon_do_cleanup_cp(dev); radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL); return DRM_ERR(EINVAL);
} }
...@@ -1416,8 +1420,6 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) ...@@ -1416,8 +1420,6 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
DRM_GETSAREA(); DRM_GETSAREA();
dev_priv->fb_offset = init->fb_offset;
dev_priv->mmio_offset = init->mmio_offset;
dev_priv->ring_offset = init->ring_offset; dev_priv->ring_offset = init->ring_offset;
dev_priv->ring_rptr_offset = init->ring_rptr_offset; dev_priv->ring_rptr_offset = init->ring_rptr_offset;
dev_priv->buffers_offset = init->buffers_offset; dev_priv->buffers_offset = init->buffers_offset;
...@@ -1425,29 +1427,19 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) ...@@ -1425,29 +1427,19 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
if (!dev_priv->sarea) { if (!dev_priv->sarea) {
DRM_ERROR("could not find sarea!\n"); DRM_ERROR("could not find sarea!\n");
dev->dev_private = (void *)dev_priv;
radeon_do_cleanup_cp(dev); radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL); return DRM_ERR(EINVAL);
} }
dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset);
if (!dev_priv->mmio) {
DRM_ERROR("could not find mmio region!\n");
dev->dev_private = (void *)dev_priv;
radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL);
}
dev_priv->cp_ring = drm_core_findmap(dev, init->ring_offset); dev_priv->cp_ring = drm_core_findmap(dev, init->ring_offset);
if (!dev_priv->cp_ring) { if (!dev_priv->cp_ring) {
DRM_ERROR("could not find cp ring region!\n"); DRM_ERROR("could not find cp ring region!\n");
dev->dev_private = (void *)dev_priv;
radeon_do_cleanup_cp(dev); radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL); return DRM_ERR(EINVAL);
} }
dev_priv->ring_rptr = drm_core_findmap(dev, init->ring_rptr_offset); dev_priv->ring_rptr = drm_core_findmap(dev, init->ring_rptr_offset);
if (!dev_priv->ring_rptr) { if (!dev_priv->ring_rptr) {
DRM_ERROR("could not find ring read pointer!\n"); DRM_ERROR("could not find ring read pointer!\n");
dev->dev_private = (void *)dev_priv;
radeon_do_cleanup_cp(dev); radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL); return DRM_ERR(EINVAL);
} }
...@@ -1455,7 +1447,6 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) ...@@ -1455,7 +1447,6 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset); dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
if (!dev->agp_buffer_map) { if (!dev->agp_buffer_map) {
DRM_ERROR("could not find dma buffer region!\n"); DRM_ERROR("could not find dma buffer region!\n");
dev->dev_private = (void *)dev_priv;
radeon_do_cleanup_cp(dev); radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL); return DRM_ERR(EINVAL);
} }
...@@ -1465,7 +1456,6 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) ...@@ -1465,7 +1456,6 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
drm_core_findmap(dev, init->gart_textures_offset); drm_core_findmap(dev, init->gart_textures_offset);
if (!dev_priv->gart_textures) { if (!dev_priv->gart_textures) {
DRM_ERROR("could not find GART texture region!\n"); DRM_ERROR("could not find GART texture region!\n");
dev->dev_private = (void *)dev_priv;
radeon_do_cleanup_cp(dev); radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL); return DRM_ERR(EINVAL);
} }
...@@ -1476,7 +1466,7 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) ...@@ -1476,7 +1466,7 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
init->sarea_priv_offset); init->sarea_priv_offset);
#if __OS_HAS_AGP #if __OS_HAS_AGP
if (!dev_priv->is_pci) { if (dev_priv->flags & CHIP_IS_AGP) {
drm_core_ioremap(dev_priv->cp_ring, dev); drm_core_ioremap(dev_priv->cp_ring, dev);
drm_core_ioremap(dev_priv->ring_rptr, dev); drm_core_ioremap(dev_priv->ring_rptr, dev);
drm_core_ioremap(dev->agp_buffer_map, dev); drm_core_ioremap(dev->agp_buffer_map, dev);
...@@ -1484,7 +1474,6 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) ...@@ -1484,7 +1474,6 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
!dev_priv->ring_rptr->handle || !dev_priv->ring_rptr->handle ||
!dev->agp_buffer_map->handle) { !dev->agp_buffer_map->handle) {
DRM_ERROR("could not find ioremap agp regions!\n"); DRM_ERROR("could not find ioremap agp regions!\n");
dev->dev_private = (void *)dev_priv;
radeon_do_cleanup_cp(dev); radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL); return DRM_ERR(EINVAL);
} }
...@@ -1525,7 +1514,7 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) ...@@ -1525,7 +1514,7 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
+ RADEON_READ(RADEON_CONFIG_APER_SIZE); + RADEON_READ(RADEON_CONFIG_APER_SIZE);
#if __OS_HAS_AGP #if __OS_HAS_AGP
if (!dev_priv->is_pci) if (dev_priv->flags & CHIP_IS_AGP)
dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset
- dev->agp->base - dev->agp->base
+ dev_priv->gart_vm_start); + dev_priv->gart_vm_start);
...@@ -1551,7 +1540,7 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) ...@@ -1551,7 +1540,7 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK; dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK;
#if __OS_HAS_AGP #if __OS_HAS_AGP
if (!dev_priv->is_pci) { if (dev_priv->flags & CHIP_IS_AGP) {
/* Turn off PCI GART */ /* Turn off PCI GART */
radeon_set_pcigart(dev_priv, 0); radeon_set_pcigart(dev_priv, 0);
} else } else
...@@ -1593,7 +1582,6 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) ...@@ -1593,7 +1582,6 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
if (!drm_ati_pcigart_init(dev, &dev_priv->gart_info)) { if (!drm_ati_pcigart_init(dev, &dev_priv->gart_info)) {
DRM_ERROR("failed to init PCI GART!\n"); DRM_ERROR("failed to init PCI GART!\n");
dev->dev_private = (void *)dev_priv;
radeon_do_cleanup_cp(dev); radeon_do_cleanup_cp(dev);
return DRM_ERR(ENOMEM); return DRM_ERR(ENOMEM);
} }
...@@ -1607,8 +1595,6 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) ...@@ -1607,8 +1595,6 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
dev_priv->last_buf = 0; dev_priv->last_buf = 0;
dev->dev_private = (void *)dev_priv;
radeon_do_engine_reset(dev); radeon_do_engine_reset(dev);
return 0; return 0;
...@@ -1627,11 +1613,15 @@ static int radeon_do_cleanup_cp(drm_device_t * dev) ...@@ -1627,11 +1613,15 @@ static int radeon_do_cleanup_cp(drm_device_t * dev)
drm_irq_uninstall(dev); drm_irq_uninstall(dev);
#if __OS_HAS_AGP #if __OS_HAS_AGP
if (!dev_priv->is_pci) { if (dev_priv->flags & CHIP_IS_AGP) {
if (dev_priv->cp_ring != NULL) if (dev_priv->cp_ring != NULL) {
drm_core_ioremapfree(dev_priv->cp_ring, dev); drm_core_ioremapfree(dev_priv->cp_ring, dev);
if (dev_priv->ring_rptr != NULL) dev_priv->cp_ring = NULL;
}
if (dev_priv->ring_rptr != NULL) {
drm_core_ioremapfree(dev_priv->ring_rptr, dev); drm_core_ioremapfree(dev_priv->ring_rptr, dev);
dev_priv->ring_rptr = NULL;
}
if (dev->agp_buffer_map != NULL) { if (dev->agp_buffer_map != NULL) {
drm_core_ioremapfree(dev->agp_buffer_map, dev); drm_core_ioremapfree(dev->agp_buffer_map, dev);
dev->agp_buffer_map = NULL; dev->agp_buffer_map = NULL;
...@@ -1639,16 +1629,20 @@ static int radeon_do_cleanup_cp(drm_device_t * dev) ...@@ -1639,16 +1629,20 @@ static int radeon_do_cleanup_cp(drm_device_t * dev)
} else } else
#endif #endif
{ {
if (dev_priv->gart_info.bus_addr)
if (dev_priv->gart_info.bus_addr) {
/* Turn off PCI GART */
radeon_set_pcigart(dev_priv, 0);
if (!drm_ati_pcigart_cleanup(dev, &dev_priv->gart_info)) if (!drm_ati_pcigart_cleanup(dev, &dev_priv->gart_info))
DRM_ERROR("failed to cleanup PCI GART!\n"); DRM_ERROR("failed to cleanup PCI GART!\n");
}
if (dev_priv->gart_info.gart_table_location == DRM_ATI_GART_FB) { if (dev_priv->gart_info.gart_table_location == DRM_ATI_GART_FB)
{
drm_core_ioremapfree(&dev_priv->gart_info.mapping, dev); drm_core_ioremapfree(&dev_priv->gart_info.mapping, dev);
dev_priv->gart_info.addr = 0; dev_priv->gart_info.addr = 0;
} }
} }
/* only clear to the start of flags */ /* only clear to the start of flags */
memset(dev_priv, 0, offsetof(drm_radeon_private_t, flags)); memset(dev_priv, 0, offsetof(drm_radeon_private_t, flags));
...@@ -1674,7 +1668,7 @@ static int radeon_do_resume_cp(drm_device_t * dev) ...@@ -1674,7 +1668,7 @@ static int radeon_do_resume_cp(drm_device_t * dev)
DRM_DEBUG("Starting radeon_do_resume_cp()\n"); DRM_DEBUG("Starting radeon_do_resume_cp()\n");
#if __OS_HAS_AGP #if __OS_HAS_AGP
if (!dev_priv->is_pci) { if (dev_priv->flags & CHIP_IS_AGP) {
/* Turn off PCI GART */ /* Turn off PCI GART */
radeon_set_pcigart(dev_priv, 0); radeon_set_pcigart(dev_priv, 0);
} else } else
...@@ -2138,7 +2132,7 @@ int radeon_driver_load(struct drm_device *dev, unsigned long flags) ...@@ -2138,7 +2132,7 @@ int radeon_driver_load(struct drm_device *dev, unsigned long flags)
dev_priv->flags |= CHIP_IS_PCIE; dev_priv->flags |= CHIP_IS_PCIE;
DRM_DEBUG("%s card detected\n", DRM_DEBUG("%s card detected\n",
((dev_priv->flags & CHIP_IS_AGP) ? "AGP" : "PCI")); ((dev_priv->flags & CHIP_IS_AGP) ? "AGP" : (((dev_priv->flags & CHIP_IS_PCIE) ? "PCIE" : "PCI"))));
return ret; return ret;
} }
...@@ -2171,7 +2165,6 @@ int radeon_driver_unload(struct drm_device *dev) ...@@ -2171,7 +2165,6 @@ int radeon_driver_unload(struct drm_device *dev)
drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_private_t *dev_priv = dev->dev_private;
DRM_DEBUG("\n"); DRM_DEBUG("\n");
drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER); drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER);
dev->dev_private = NULL; dev->dev_private = NULL;
......
...@@ -624,6 +624,11 @@ typedef struct drm_radeon_indirect { ...@@ -624,6 +624,11 @@ typedef struct drm_radeon_indirect {
int discard; int discard;
} drm_radeon_indirect_t; } drm_radeon_indirect_t;
/* enum for card type parameters */
#define RADEON_CARD_PCI 0
#define RADEON_CARD_AGP 1
#define RADEON_CARD_PCIE 2
/* 1.3: An ioctl to get parameters that aren't available to the 3d /* 1.3: An ioctl to get parameters that aren't available to the 3d
* client any other way. * client any other way.
*/ */
...@@ -640,6 +645,7 @@ typedef struct drm_radeon_indirect { ...@@ -640,6 +645,7 @@ typedef struct drm_radeon_indirect {
#define RADEON_PARAM_SAREA_HANDLE 9 #define RADEON_PARAM_SAREA_HANDLE 9
#define RADEON_PARAM_GART_TEX_HANDLE 10 #define RADEON_PARAM_GART_TEX_HANDLE 10
#define RADEON_PARAM_SCRATCH_OFFSET 11 #define RADEON_PARAM_SCRATCH_OFFSET 11
#define RADEON_PARAM_CARD_TYPE 12
typedef struct drm_radeon_getparam { typedef struct drm_radeon_getparam {
int param; int param;
......
...@@ -38,7 +38,7 @@ ...@@ -38,7 +38,7 @@
#define DRIVER_NAME "radeon" #define DRIVER_NAME "radeon"
#define DRIVER_DESC "ATI Radeon" #define DRIVER_DESC "ATI Radeon"
#define DRIVER_DATE "20050911" #define DRIVER_DATE "20051229"
/* Interface history: /* Interface history:
* *
...@@ -73,7 +73,7 @@ ...@@ -73,7 +73,7 @@
* 1.11- Add packet R200_EMIT_RB3D_BLENDCOLOR to support GL_EXT_blend_color * 1.11- Add packet R200_EMIT_RB3D_BLENDCOLOR to support GL_EXT_blend_color
* and GL_EXT_blend_[func|equation]_separate on r200 * and GL_EXT_blend_[func|equation]_separate on r200
* 1.12- Add R300 CP microcode support - this just loads the CP on r300 * 1.12- Add R300 CP microcode support - this just loads the CP on r300
* (No 3D support yet - just microcode loading) * (No 3D support yet - just microcode loading).
* 1.13- Add packet R200_EMIT_TCL_POINT_SPRITE_CNTL for ARB_point_parameters * 1.13- Add packet R200_EMIT_TCL_POINT_SPRITE_CNTL for ARB_point_parameters
* - Add hyperz support, add hyperz flags to clear ioctl. * - Add hyperz support, add hyperz flags to clear ioctl.
* 1.14- Add support for color tiling * 1.14- Add support for color tiling
...@@ -88,14 +88,13 @@ ...@@ -88,14 +88,13 @@
* R200_EMIT_PP_TXFILTER_0-5, 2 more regs) and R200_EMIT_ATF_TFACTOR * R200_EMIT_PP_TXFILTER_0-5, 2 more regs) and R200_EMIT_ATF_TFACTOR
* (replaces R200_EMIT_TFACTOR_0 (8 consts instead of 6) * (replaces R200_EMIT_TFACTOR_0 (8 consts instead of 6)
* 1.19- Add support for gart table in FB memory and PCIE r300 * 1.19- Add support for gart table in FB memory and PCIE r300
* 1.20- Add support for r300 texrect
* 1.21- Add support for card type getparam
*/ */
#define DRIVER_MAJOR 1 #define DRIVER_MAJOR 1
#define DRIVER_MINOR 19 #define DRIVER_MINOR 21
#define DRIVER_PATCHLEVEL 0 #define DRIVER_PATCHLEVEL 0
#define GET_RING_HEAD(dev_priv) DRM_READ32( (dev_priv)->ring_rptr, 0 )
#define SET_RING_HEAD(dev_priv,val) DRM_WRITE32( (dev_priv)->ring_rptr, 0, (val) )
/* /*
* Radeon chip families * Radeon chip families
*/ */
...@@ -138,6 +137,9 @@ enum radeon_chip_flags { ...@@ -138,6 +137,9 @@ enum radeon_chip_flags {
CHIP_IS_PCIE = 0x00200000UL, CHIP_IS_PCIE = 0x00200000UL,
}; };
#define GET_RING_HEAD(dev_priv) DRM_READ32( (dev_priv)->ring_rptr, 0 )
#define SET_RING_HEAD(dev_priv,val) DRM_WRITE32( (dev_priv)->ring_rptr, 0, (val) )
typedef struct drm_radeon_freelist { typedef struct drm_radeon_freelist {
unsigned int age; unsigned int age;
drm_buf_t *buf; drm_buf_t *buf;
...@@ -214,8 +216,6 @@ typedef struct drm_radeon_private { ...@@ -214,8 +216,6 @@ typedef struct drm_radeon_private {
int microcode_version; int microcode_version;
int is_pci;
struct { struct {
u32 boxes; u32 boxes;
int freelist_timeouts; int freelist_timeouts;
...@@ -247,8 +247,6 @@ typedef struct drm_radeon_private { ...@@ -247,8 +247,6 @@ typedef struct drm_radeon_private {
drm_radeon_depth_clear_t depth_clear; drm_radeon_depth_clear_t depth_clear;
unsigned long fb_offset;
unsigned long mmio_offset;
unsigned long ring_offset; unsigned long ring_offset;
unsigned long ring_rptr_offset; unsigned long ring_rptr_offset;
unsigned long buffers_offset; unsigned long buffers_offset;
...@@ -362,6 +360,8 @@ extern int r300_do_cp_cmdbuf(drm_device_t * dev, DRMFILE filp, ...@@ -362,6 +360,8 @@ extern int r300_do_cp_cmdbuf(drm_device_t * dev, DRMFILE filp,
*/ */
#define RADEON_AGP_COMMAND 0x0f60 #define RADEON_AGP_COMMAND 0x0f60
#define RADEON_AGP_COMMAND_PCI_CONFIG 0x0060 /* offset in PCI config */
# define RADEON_AGP_ENABLE (1<<8)
#define RADEON_AUX_SCISSOR_CNTL 0x26f0 #define RADEON_AUX_SCISSOR_CNTL 0x26f0
# define RADEON_EXCLUSIVE_SCISSOR_0 (1 << 24) # define RADEON_EXCLUSIVE_SCISSOR_0 (1 << 24)
# define RADEON_EXCLUSIVE_SCISSOR_1 (1 << 25) # define RADEON_EXCLUSIVE_SCISSOR_1 (1 << 25)
...@@ -377,6 +377,7 @@ extern int r300_do_cp_cmdbuf(drm_device_t * dev, DRMFILE filp, ...@@ -377,6 +377,7 @@ extern int r300_do_cp_cmdbuf(drm_device_t * dev, DRMFILE filp,
# define RADEON_PLL_WR_EN (1 << 7) # define RADEON_PLL_WR_EN (1 << 7)
#define RADEON_CLOCK_CNTL_INDEX 0x0008 #define RADEON_CLOCK_CNTL_INDEX 0x0008
#define RADEON_CONFIG_APER_SIZE 0x0108 #define RADEON_CONFIG_APER_SIZE 0x0108
#define RADEON_CONFIG_MEMSIZE 0x00f8
#define RADEON_CRTC_OFFSET 0x0224 #define RADEON_CRTC_OFFSET 0x0224
#define RADEON_CRTC_OFFSET_CNTL 0x0228 #define RADEON_CRTC_OFFSET_CNTL 0x0228
# define RADEON_CRTC_TILE_EN (1 << 15) # define RADEON_CRTC_TILE_EN (1 << 15)
...@@ -648,6 +649,8 @@ extern int r300_do_cp_cmdbuf(drm_device_t * dev, DRMFILE filp, ...@@ -648,6 +649,8 @@ extern int r300_do_cp_cmdbuf(drm_device_t * dev, DRMFILE filp,
#define RADEON_WAIT_UNTIL 0x1720 #define RADEON_WAIT_UNTIL 0x1720
# define RADEON_WAIT_CRTC_PFLIP (1 << 0) # define RADEON_WAIT_CRTC_PFLIP (1 << 0)
# define RADEON_WAIT_2D_IDLE (1 << 14)
# define RADEON_WAIT_3D_IDLE (1 << 15)
# define RADEON_WAIT_2D_IDLECLEAN (1 << 16) # define RADEON_WAIT_2D_IDLECLEAN (1 << 16)
# define RADEON_WAIT_3D_IDLECLEAN (1 << 17) # define RADEON_WAIT_3D_IDLECLEAN (1 << 17)
# define RADEON_WAIT_HOST_IDLECLEAN (1 << 18) # define RADEON_WAIT_HOST_IDLECLEAN (1 << 18)
...@@ -1102,7 +1105,6 @@ do { \ ...@@ -1102,7 +1105,6 @@ do { \
write = 0; \ write = 0; \
_tab += _i; \ _tab += _i; \
} \ } \
\
while (_size > 0) { \ while (_size > 0) { \
*(ring + write) = *_tab++; \ *(ring + write) = *_tab++; \
write++; \ write++; \
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment