mirror of
https://gitlab.freedesktop.org/mesa/drm.git
synced 2025-12-24 16:00:13 +01:00
Merge branch 'master' into bo-set-pin
This commit is contained in:
commit
0055fd5c35
52 changed files with 1788 additions and 1030 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -51,6 +51,7 @@ sis.kld
|
|||
stamp-h1
|
||||
tdfx.kld
|
||||
via.kld
|
||||
tests/auth
|
||||
tests/dristat
|
||||
tests/drmstat
|
||||
tests/getclient
|
||||
|
|
|
|||
|
|
@ -377,6 +377,7 @@ do { \
|
|||
} while (0)
|
||||
|
||||
#if defined(__FreeBSD__) && __FreeBSD_version > 500000
|
||||
/* Returns -errno to shared code */
|
||||
#define DRM_WAIT_ON( ret, queue, timeout, condition ) \
|
||||
for ( ret = 0 ; !ret && !(condition) ; ) { \
|
||||
DRM_UNLOCK(); \
|
||||
|
|
@ -388,11 +389,12 @@ for ( ret = 0 ; !ret && !(condition) ; ) { \
|
|||
DRM_LOCK(); \
|
||||
}
|
||||
#else
|
||||
/* Returns -errno to shared code */
|
||||
#define DRM_WAIT_ON( ret, queue, timeout, condition ) \
|
||||
for ( ret = 0 ; !ret && !(condition) ; ) { \
|
||||
int s = spldrm(); \
|
||||
if (!(condition)) \
|
||||
ret = tsleep( &(queue), PZERO | PCATCH, \
|
||||
ret = -tsleep( &(queue), PZERO | PCATCH, \
|
||||
"drmwtq", (timeout) ); \
|
||||
splx(s); \
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/* drm_auth.h -- IOCTLs for authentication -*- linux-c -*-
|
||||
/* drm_auth.c -- IOCTLs for authentication -*- linux-c -*-
|
||||
* Created: Tue Feb 2 08:37:54 1999 by faith@valinux.com
|
||||
*/
|
||||
/*-
|
||||
|
|
@ -38,11 +38,16 @@ static int drm_hash_magic(drm_magic_t magic)
|
|||
return magic & (DRM_HASH_SIZE-1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the file private associated with the given magic number.
|
||||
*/
|
||||
static drm_file_t *drm_find_file(drm_device_t *dev, drm_magic_t magic)
|
||||
{
|
||||
drm_magic_entry_t *pt;
|
||||
int hash = drm_hash_magic(magic);
|
||||
|
||||
DRM_SPINLOCK_ASSERT(&dev->dev_lock);
|
||||
|
||||
for (pt = dev->magiclist[hash].head; pt; pt = pt->next) {
|
||||
if (pt->magic == magic) {
|
||||
return pt->priv;
|
||||
|
|
@ -52,6 +57,10 @@ static drm_file_t *drm_find_file(drm_device_t *dev, drm_magic_t magic)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts the given magic number into the hash table of used magic number
|
||||
* lists.
|
||||
*/
|
||||
static int drm_add_magic(drm_device_t *dev, drm_file_t *priv, drm_magic_t magic)
|
||||
{
|
||||
int hash;
|
||||
|
|
@ -59,6 +68,8 @@ static int drm_add_magic(drm_device_t *dev, drm_file_t *priv, drm_magic_t magic)
|
|||
|
||||
DRM_DEBUG("%d\n", magic);
|
||||
|
||||
DRM_SPINLOCK_ASSERT(&dev->dev_lock);
|
||||
|
||||
hash = drm_hash_magic(magic);
|
||||
entry = malloc(sizeof(*entry), M_DRM, M_ZERO | M_NOWAIT);
|
||||
if (!entry) return ENOMEM;
|
||||
|
|
@ -79,16 +90,21 @@ static int drm_add_magic(drm_device_t *dev, drm_file_t *priv, drm_magic_t magic)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the given magic number from the hash table of used magic number
|
||||
* lists.
|
||||
*/
|
||||
static int drm_remove_magic(drm_device_t *dev, drm_magic_t magic)
|
||||
{
|
||||
drm_magic_entry_t *prev = NULL;
|
||||
drm_magic_entry_t *pt;
|
||||
int hash;
|
||||
|
||||
DRM_SPINLOCK_ASSERT(&dev->dev_lock);
|
||||
|
||||
DRM_DEBUG("%d\n", magic);
|
||||
hash = drm_hash_magic(magic);
|
||||
|
||||
DRM_LOCK();
|
||||
for (pt = dev->magiclist[hash].head; pt; prev = pt, pt = pt->next) {
|
||||
if (pt->magic == magic) {
|
||||
if (dev->magiclist[hash].head == pt) {
|
||||
|
|
@ -100,16 +116,22 @@ static int drm_remove_magic(drm_device_t *dev, drm_magic_t magic)
|
|||
if (prev) {
|
||||
prev->next = pt->next;
|
||||
}
|
||||
DRM_UNLOCK();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
DRM_UNLOCK();
|
||||
|
||||
free(pt, M_DRM);
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the client, this returns a unique magic number to be authorized
|
||||
* by the master.
|
||||
*
|
||||
* The master may use its own knowledge of the client (such as the X
|
||||
* connection that the magic is passed over) to determine if the magic number
|
||||
* should be authenticated.
|
||||
*/
|
||||
int drm_getmagic(drm_device_t *dev, void *data, struct drm_file *file_priv)
|
||||
{
|
||||
static drm_magic_t sequence = 0;
|
||||
|
|
@ -122,15 +144,15 @@ int drm_getmagic(drm_device_t *dev, void *data, struct drm_file *file_priv)
|
|||
DRM_LOCK();
|
||||
do {
|
||||
int old = sequence;
|
||||
|
||||
|
||||
auth->magic = old+1;
|
||||
|
||||
|
||||
if (!atomic_cmpset_int(&sequence, old, auth->magic))
|
||||
continue;
|
||||
} while (drm_find_file(dev, auth->magic));
|
||||
file_priv->magic = auth->magic;
|
||||
DRM_UNLOCK();
|
||||
drm_add_magic(dev, file_priv, auth->magic);
|
||||
DRM_UNLOCK();
|
||||
}
|
||||
|
||||
DRM_DEBUG("%u\n", auth->magic);
|
||||
|
|
@ -138,6 +160,9 @@ int drm_getmagic(drm_device_t *dev, void *data, struct drm_file *file_priv)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks the client associated with the given magic number as authenticated.
|
||||
*/
|
||||
int drm_authmagic(drm_device_t *dev, void *data, struct drm_file *file_priv)
|
||||
{
|
||||
drm_auth_t *auth = data;
|
||||
|
|
|
|||
|
|
@ -121,6 +121,7 @@ int drm_dma(drm_device_t *dev, void *data, struct drm_file *file_priv)
|
|||
{
|
||||
|
||||
if (dev->driver.dma_ioctl) {
|
||||
/* shared code returns -errno */
|
||||
return -dev->driver.dma_ioctl(dev, data, file_priv);
|
||||
} else {
|
||||
DRM_DEBUG("DMA ioctl on driver with no dma handler\n");
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ drm_drawable_compare(struct bsd_drm_drawable_info *a,
|
|||
{
|
||||
if (a->handle > b->handle)
|
||||
return 1;
|
||||
if (a->handle > b->handle)
|
||||
if (a->handle < b->handle)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -93,6 +93,7 @@ int drm_open_helper(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p,
|
|||
priv->authenticated = DRM_SUSER(p);
|
||||
|
||||
if (dev->driver.open) {
|
||||
/* shared code returns -errno */
|
||||
retcode = -dev->driver.open(dev, priv);
|
||||
if (retcode != 0) {
|
||||
free(priv, M_DRM);
|
||||
|
|
|
|||
|
|
@ -241,6 +241,7 @@ int drm_wait_vblank(drm_device_t *dev, void *data, struct drm_file *file_priv)
|
|||
ret = EINVAL;
|
||||
} else {
|
||||
DRM_LOCK();
|
||||
/* shared code returns -errno */
|
||||
ret = -dev->driver.vblank_wait(dev,
|
||||
&vblwait->request.sequence);
|
||||
DRM_UNLOCK();
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ i915-objs := i915_drv.o i915_dma.o i915_irq.o i915_mem.o i915_fence.o \
|
|||
i915_buffer.o
|
||||
nouveau-objs := nouveau_drv.o nouveau_state.o nouveau_fifo.o nouveau_mem.o \
|
||||
nouveau_object.o nouveau_irq.o nouveau_notifier.o \
|
||||
nouveau_sgdma.o \
|
||||
nouveau_sgdma.o nouveau_dma.o \
|
||||
nv04_timer.o \
|
||||
nv04_mc.o nv40_mc.o nv50_mc.o \
|
||||
nv04_fb.o nv10_fb.o nv40_fb.o \
|
||||
|
|
|
|||
|
|
@ -911,6 +911,8 @@ extern void drm_exit(struct drm_driver *driver);
|
|||
extern void drm_cleanup_pci(struct pci_dev *pdev);
|
||||
extern int drm_ioctl(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg);
|
||||
extern long drm_unlocked_ioctl(struct file *filp,
|
||||
unsigned int cmd, unsigned long arg);
|
||||
extern long drm_compat_ioctl(struct file *filp,
|
||||
unsigned int cmd, unsigned long arg);
|
||||
|
||||
|
|
@ -1073,6 +1075,7 @@ extern void drm_core_reclaim_buffers(struct drm_device *dev,
|
|||
extern int drm_control(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
extern irqreturn_t drm_irq_handler(DRM_IRQ_ARGS);
|
||||
extern int drm_irq_install(struct drm_device *dev);
|
||||
extern int drm_irq_uninstall(struct drm_device *dev);
|
||||
extern void drm_driver_irq_preinstall(struct drm_device *dev);
|
||||
extern void drm_driver_irq_postinstall(struct drm_device *dev);
|
||||
|
|
|
|||
|
|
@ -183,7 +183,6 @@ int drm_agp_enable(struct drm_device *dev, struct drm_agp_mode mode)
|
|||
#else
|
||||
agp_enable(dev->agp->bridge, mode.mode);
|
||||
#endif
|
||||
dev->agp->base = dev->agp->agp_info.aper_base;
|
||||
dev->agp->enabled = 1;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -441,6 +440,7 @@ struct drm_agp_head *drm_agp_init(struct drm_device *dev)
|
|||
INIT_LIST_HEAD(&head->memory);
|
||||
head->cant_use_aperture = head->agp_info.cant_use_aperture;
|
||||
head->page_mask = head->agp_info.page_mask;
|
||||
head->base = head->agp_info.aper_base;
|
||||
return head;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -516,7 +516,7 @@ static void drm_bo_base_deref_locked(struct drm_file * file_priv,
|
|||
drm_bo_usage_deref_locked(&bo);
|
||||
}
|
||||
|
||||
static void drm_bo_usage_deref_unlocked(struct drm_buffer_object ** bo)
|
||||
void drm_bo_usage_deref_unlocked(struct drm_buffer_object ** bo)
|
||||
{
|
||||
struct drm_buffer_object *tmp_bo = *bo;
|
||||
struct drm_device *dev = tmp_bo->dev;
|
||||
|
|
@ -529,6 +529,7 @@ static void drm_bo_usage_deref_unlocked(struct drm_buffer_object ** bo)
|
|||
mutex_unlock(&dev->struct_mutex);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(drm_bo_usage_deref_unlocked);
|
||||
|
||||
/*
|
||||
* Note. The caller has to register (if applicable)
|
||||
|
|
@ -1669,10 +1670,10 @@ int drm_buffer_object_create(struct drm_device *dev,
|
|||
drm_bo_usage_deref_unlocked(&bo);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_buffer_object_create);
|
||||
|
||||
static int drm_bo_add_user_object(struct drm_file *file_priv,
|
||||
struct drm_buffer_object *bo,
|
||||
int shareable)
|
||||
int drm_bo_add_user_object(struct drm_file *file_priv,
|
||||
struct drm_buffer_object *bo, int shareable)
|
||||
{
|
||||
struct drm_device *dev = file_priv->head->dev;
|
||||
int ret;
|
||||
|
|
@ -1691,6 +1692,7 @@ static int drm_bo_add_user_object(struct drm_file *file_priv,
|
|||
mutex_unlock(&dev->struct_mutex);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_bo_add_user_object);
|
||||
|
||||
static int drm_bo_lock_test(struct drm_device * dev, struct drm_file *file_priv)
|
||||
{
|
||||
|
|
@ -1719,7 +1721,7 @@ int drm_bo_op_ioctl(struct drm_device *dev, void *data, struct drm_file *file_pr
|
|||
if (next != 0) {
|
||||
curuserarg = (void __user *)next;
|
||||
if (copy_from_user(&curarg, curuserarg,
|
||||
sizeof(arg)) != 0)
|
||||
sizeof(curarg)) != 0)
|
||||
return -EFAULT;
|
||||
arg = &curarg;
|
||||
}
|
||||
|
|
@ -1728,7 +1730,7 @@ int drm_bo_op_ioctl(struct drm_device *dev, void *data, struct drm_file *file_pr
|
|||
next = arg->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
req = &arg->d.req;
|
||||
ret = 0;
|
||||
switch (req->op) {
|
||||
case drm_bo_validate:
|
||||
|
|
@ -1767,7 +1769,7 @@ int drm_bo_op_ioctl(struct drm_device *dev, void *data, struct drm_file *file_pr
|
|||
arg->d.rep.bo_info = rep;
|
||||
if (arg != data) {
|
||||
if (copy_to_user(curuserarg, &curarg,
|
||||
sizeof(arg)) != 0)
|
||||
sizeof(curarg)) != 0)
|
||||
return -EFAULT;
|
||||
}
|
||||
} while (next != 0);
|
||||
|
|
|
|||
|
|
@ -128,6 +128,7 @@ int drm_mem_reg_ioremap(struct drm_device * dev, struct drm_bo_mem_reg * mem,
|
|||
*virtual = addr;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_mem_reg_ioremap);
|
||||
|
||||
/**
|
||||
* \c Unmap mapping obtained using drm_bo_ioremap
|
||||
|
|
|
|||
|
|
@ -223,11 +223,17 @@ static int drm_addmap_core(struct drm_device *dev, unsigned int offset,
|
|||
#ifdef __alpha__
|
||||
map->offset += dev->hose->mem_space->start;
|
||||
#endif
|
||||
/* Note: dev->agp->base may actually be 0 when the DRM
|
||||
* is not in control of AGP space. But if user space is
|
||||
* it should already have added the AGP base itself.
|
||||
/* In some cases (i810 driver), user space may have already
|
||||
* added the AGP base itself, because dev->agp->base previously
|
||||
* only got set during AGP enable. So, only add the base
|
||||
* address if the map's offset isn't already within the
|
||||
* aperture.
|
||||
*/
|
||||
map->offset += dev->agp->base;
|
||||
if (map->offset < dev->agp->base ||
|
||||
map->offset > dev->agp->base +
|
||||
dev->agp->agp_info.aper_size * 1024 * 1024) {
|
||||
map->offset += dev->agp->base;
|
||||
}
|
||||
map->mtrr = dev->agp->agp_mtrr; /* for getmap */
|
||||
|
||||
/* This assumes the DRM is in total control of AGP space.
|
||||
|
|
|
|||
|
|
@ -574,6 +574,12 @@ static int drm_version(struct drm_device *dev, void *data,
|
|||
*/
|
||||
int drm_ioctl(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
return drm_unlocked_ioctl(filp, cmd, arg);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_ioctl);
|
||||
|
||||
long drm_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct drm_file *file_priv = filp->private_data;
|
||||
struct drm_device *dev = file_priv->head->dev;
|
||||
|
|
@ -651,7 +657,7 @@ err_i1:
|
|||
DRM_DEBUG("ret = %d\n", retcode);
|
||||
return retcode;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_ioctl);
|
||||
EXPORT_SYMBOL(drm_unlocked_ioctl);
|
||||
|
||||
drm_local_map_t *drm_getsarea(struct drm_device *dev)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -520,9 +520,10 @@ void drm_fence_manager_init(struct drm_device * dev)
|
|||
struct drm_fence_class_manager *class;
|
||||
struct drm_fence_driver *fed = dev->driver->fence_driver;
|
||||
int i;
|
||||
unsigned long flags;
|
||||
|
||||
rwlock_init(&fm->lock);
|
||||
write_lock(&fm->lock);
|
||||
write_lock_irqsave(&fm->lock, flags);
|
||||
fm->initialized = 0;
|
||||
if (!fed)
|
||||
goto out_unlock;
|
||||
|
|
@ -541,7 +542,7 @@ void drm_fence_manager_init(struct drm_device * dev)
|
|||
|
||||
atomic_set(&fm->count, 0);
|
||||
out_unlock:
|
||||
write_unlock(&fm->lock);
|
||||
write_unlock_irqrestore(&fm->lock, flags);
|
||||
}
|
||||
|
||||
void drm_fence_manager_takedown(struct drm_device * dev)
|
||||
|
|
@ -597,7 +598,6 @@ int drm_fence_create_ioctl(struct drm_device *dev, void *data, struct drm_file *
|
|||
* usage > 0. No need to lock dev->struct_mutex;
|
||||
*/
|
||||
|
||||
atomic_inc(&fence->usage);
|
||||
arg->handle = fence->base.hash.key;
|
||||
|
||||
read_lock_irqsave(&fm->lock, flags);
|
||||
|
|
@ -830,7 +830,7 @@ int drm_fence_buffers_ioctl(struct drm_device *dev, void *data, struct drm_file
|
|||
DRM_FENCE_FLAG_SHAREABLE);
|
||||
if (ret)
|
||||
return ret;
|
||||
atomic_inc(&fence->usage);
|
||||
|
||||
arg->handle = fence->base.hash.key;
|
||||
|
||||
read_lock_irqsave(&fm->lock, flags);
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ int drm_irq_by_busid(struct drm_device *dev, void *data,
|
|||
* \c drm_driver_irq_preinstall() and \c drm_driver_irq_postinstall() functions
|
||||
* before and after the installation.
|
||||
*/
|
||||
static int drm_irq_install(struct drm_device * dev)
|
||||
int drm_irq_install(struct drm_device * dev)
|
||||
{
|
||||
int ret;
|
||||
unsigned long sh_flags = 0;
|
||||
|
|
@ -140,6 +140,7 @@ static int drm_irq_install(struct drm_device * dev)
|
|||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_irq_install);
|
||||
|
||||
/**
|
||||
* Uninstall the IRQ handler.
|
||||
|
|
|
|||
|
|
@ -484,6 +484,17 @@ extern int drm_bo_mem_space(struct drm_buffer_object * bo,
|
|||
struct drm_bo_mem_reg * mem, int no_wait);
|
||||
extern int drm_bo_move_buffer(struct drm_buffer_object * bo, uint32_t new_mem_flags,
|
||||
int no_wait, int move_unfenced);
|
||||
extern int drm_buffer_object_create(struct drm_device *dev, unsigned long size,
|
||||
enum drm_bo_type type, uint64_t mask,
|
||||
uint32_t hint, uint32_t page_alignment,
|
||||
unsigned long buffer_start,
|
||||
struct drm_buffer_object **bo);
|
||||
extern int drm_bo_init_mm(struct drm_device *dev, unsigned type,
|
||||
unsigned long p_offset, unsigned long p_size);
|
||||
extern int drm_bo_clean_mm(struct drm_device *dev, unsigned mem_type);
|
||||
extern int drm_bo_add_user_object(struct drm_file *file_priv,
|
||||
struct drm_buffer_object *bo, int sharable);
|
||||
extern void drm_bo_usage_deref_unlocked(struct drm_buffer_object **bo);
|
||||
|
||||
/*
|
||||
* Buffer object memory move helpers.
|
||||
|
|
@ -503,6 +514,11 @@ extern int drm_bo_move_accel_cleanup(struct drm_buffer_object * bo,
|
|||
uint32_t fence_flags,
|
||||
struct drm_bo_mem_reg * new_mem);
|
||||
|
||||
extern int drm_mem_reg_ioremap(struct drm_device *dev,
|
||||
struct drm_bo_mem_reg *mem, void **virtual);
|
||||
extern void drm_mem_reg_iounmap(struct drm_device *dev,
|
||||
struct drm_bo_mem_reg *mem, void *virtual);
|
||||
|
||||
#ifdef CONFIG_DEBUG_MUTEXES
|
||||
#define DRM_ASSERT_LOCKED(_mutex) \
|
||||
BUG_ON(!mutex_is_locked(_mutex) || \
|
||||
|
|
|
|||
1
linux-core/nouveau_dma.c
Symbolic link
1
linux-core/nouveau_dma.c
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
../shared-core/nouveau_dma.c
|
||||
1
linux-core/nouveau_dma.h
Symbolic link
1
linux-core/nouveau_dma.h
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
../shared-core/nouveau_dma.h
|
||||
|
|
@ -69,7 +69,7 @@ nouveau_sgdma_clear(struct drm_ttm_backend *be)
|
|||
if (nvbe->is_bound)
|
||||
be->func->unbind(be);
|
||||
|
||||
for (d = 0; d < nvbe->pages_populated; d--) {
|
||||
for (d = 0; d < nvbe->pages_populated; d++) {
|
||||
pci_unmap_page(nvbe->dev->pdev, nvbe->pagelist[d],
|
||||
NV_CTXDMA_PAGE_SIZE,
|
||||
PCI_DMA_BIDIRECTIONAL);
|
||||
|
|
@ -211,7 +211,7 @@ nouveau_sgdma_init(struct drm_device *dev)
|
|||
obj_size = (aper_size >> NV_CTXDMA_PAGE_SHIFT) * 8;
|
||||
}
|
||||
|
||||
if ((ret = nouveau_gpuobj_new(dev, -1, obj_size, 16,
|
||||
if ((ret = nouveau_gpuobj_new(dev, NULL, obj_size, 16,
|
||||
NVOBJ_FLAG_ALLOW_NO_REFS |
|
||||
NVOBJ_FLAG_ZERO_ALLOC |
|
||||
NVOBJ_FLAG_ZERO_FREE, &gpuobj))) {
|
||||
|
|
|
|||
|
|
@ -510,8 +510,9 @@
|
|||
0x10de 0x0091 NV_40 "GeForce 7800 GTX"
|
||||
0x10de 0x0092 NV_40 "GeForce 7800 GT"
|
||||
0x10de 0x0093 NV_40 "GeForce 7800 GS"
|
||||
0x10de 0x0095 NV_40 "GeForce 7800 SLI"
|
||||
0x10de 0x0098 NV_40 "GeForce Go 7800"
|
||||
0x10de 0x0099 NV_40 "GE Force Go 7800 GTX"
|
||||
0x10de 0x0099 NV_40 "GeForce Go 7800 GTX"
|
||||
0x10de 0x009d NV_40 "Quadro FX4500"
|
||||
0x10de 0x00a0 NV_04 "Aladdin TNT2"
|
||||
0x10de 0x00c0 NV_40 "GeForce 6800 GS"
|
||||
|
|
@ -547,13 +548,16 @@
|
|||
0x10de 0x0113 NV_11 "Quadro2 MXR/EX/Go"
|
||||
0x10de 0x0140 NV_40 "GeForce 6600 GT"
|
||||
0x10de 0x0141 NV_40 "GeForce 6600"
|
||||
0x10de 0x0142 NV_40 "GeForce 6600 PCIe"
|
||||
0x10de 0x0142 NV_40 "GeForce 6600 LE"
|
||||
0x10de 0x0143 NV_40 "GeForce 6600 VE"
|
||||
0x10de 0x0144 NV_40 "GeForce Go 6600"
|
||||
0x10de 0x0145 NV_40 "GeForce 6610 XL"
|
||||
0x10de 0x0146 NV_40 "Geforce Go 6600TE/6200TE"
|
||||
0x10de 0x0147 NV_40 "GeForce 6700 XL"
|
||||
0x10de 0x0148 NV_40 "GeForce Go 6600"
|
||||
0x10de 0x0149 NV_40 "GeForce Go 6600 GT"
|
||||
0x10de 0x014a NV_40 "Quadro NVS 440"
|
||||
0x10de 0x014c NV_40 "Quadro FX 550"
|
||||
0x10de 0x014d NV_17 "Quadro FX 550"
|
||||
0x10de 0x014e NV_40 "Quadro FX 540"
|
||||
0x10de 0x014f NV_40 "GeForce 6200"
|
||||
|
|
@ -561,6 +565,7 @@
|
|||
0x10de 0x0151 NV_15 "GeForce2 Ti"
|
||||
0x10de 0x0152 NV_15 "GeForce2 Ultra, Bladerunner"
|
||||
0x10de 0x0153 NV_15 "Quadro2 Pro"
|
||||
0x10de 0x0160 NV_44 "GeForce 6500"
|
||||
0x10de 0x0161 NV_44 "GeForce 6200 TurboCache(TM)"
|
||||
0x10de 0x0162 NV_44 "GeForce 6200 SE TurboCache (TM)"
|
||||
0x10de 0x0163 NV_44 "GeForce 6200 LE"
|
||||
|
|
@ -569,6 +574,7 @@
|
|||
0x10de 0x0166 NV_44 "GeForce Go 6400"
|
||||
0x10de 0x0167 NV_44 "GeForce Go 6200 TurboCache"
|
||||
0x10de 0x0168 NV_44 "GeForce Go 6200 TurboCache"
|
||||
0x10de 0x0169 NV_44 "GeForce 6250"
|
||||
0x10de 0x0170 NV_17 "GeForce4 MX 460"
|
||||
0x10de 0x0171 NV_17 "GeForce4 MX 440"
|
||||
0x10de 0x0172 NV_17 "GeForce4 MX 420"
|
||||
|
|
@ -601,11 +607,16 @@
|
|||
0x10de 0x019e NV_50 "Quadro FX 4600"
|
||||
0x10de 0x01a0 NV_11|NV_NFORCE "GeForce2 MX Integrated Graphics"
|
||||
0x10de 0x01d1 NV_44 "GeForce 7300 LE"
|
||||
0x10de 0x01d3 NV_44 "Geforce 7300 SE"
|
||||
0x10de 0x01d6 NV_44 "GeForce Go 7200"
|
||||
0x10de 0x01d7 NV_44 "Quadro NVS 110M / GeForce Go 7300"
|
||||
0x10de 0x01d8 NV_44 "GeForce Go 7400"
|
||||
0x10de 0x01d9 NV_44 "GeForce Go 7400 GS"
|
||||
0x10de 0x01da NV_44 "Quadro NVS 110M"
|
||||
0x10de 0x01db NV_44 "Quadro NVS 120M"
|
||||
0x10de 0x01dc NV_44 "Quadro FX 350M"
|
||||
0x10de 0x01dd NV_44 "GeForce 7500 LE"
|
||||
0x10de 0x01de NV_44 "Quadro FX 350"
|
||||
0x10de 0x01df NV_44 "GeForce 7300 GS"
|
||||
0x10de 0x01f0 NV_17|NV_NFORCE2 "GeForce4 MX - nForce GPU"
|
||||
0x10de 0x0200 NV_20 "GeForce3"
|
||||
|
|
@ -617,9 +628,12 @@
|
|||
0x10de 0x0215 NV_40 "GeForce 6800 GT"
|
||||
0x10de 0x0218 NV_40 "GeForce 6800 XT"
|
||||
0x10de 0x0221 NV_44 "GeForce 6200"
|
||||
0x10de 0x0222 NV_44 "GeForce 6200 A-LE"
|
||||
0x10de 0x0240 NV_44 "GeForce 6150"
|
||||
0x10de 0x0241 NV_44 "GeForce 6150 LE"
|
||||
0x10de 0x0242 NV_44 "GeForce 6100"
|
||||
0x10de 0x0244 NV_44 "GeForce 6150 Go"
|
||||
0x10de 0x0244 NV_44 "GeForce Go 6150"
|
||||
0x10de 0x0247 NV_44 "GeForce Go 6100"
|
||||
0x10de 0x0250 NV_25 "GeForce4 Ti 4600"
|
||||
0x10de 0x0251 NV_25 "GeForce4 Ti 4400"
|
||||
0x10de 0x0252 NV_25 "GeForce4 Ti"
|
||||
|
|
@ -700,7 +714,15 @@
|
|||
0x10de 0x0391 NV_40 "GeForce 7600 GT"
|
||||
0x10de 0x0392 NV_40 "GeForce 7600 GS"
|
||||
0x10de 0x0393 NV_40 "GeForce 7300 GT"
|
||||
0x10de 0x0394 NV_40 "GeForce 7600 LE"
|
||||
0x10de 0x0395 NV_40 "GeForce 7300 GT"
|
||||
0x10de 0x0397 NV_40 "GeForce Go 7700"
|
||||
0x10de 0x0398 NV_40 "GeForce Go 7600"
|
||||
0x10de 0x0399 NV_40 "GeForce Go 7600 GT"
|
||||
0x10de 0x039a NV_40 "Quadro NVS 300M"
|
||||
0x10de 0x039b NV_40 "GeForce Go 7900 SE"
|
||||
0x10de 0x039c NV_40 "Quadro FX 550M"
|
||||
0x10de 0x039e NV_40 "Quadro FX 560"
|
||||
0x10de 0x03d0 NV_44 "GeForce 6100 nForce 430"
|
||||
0x10de 0x03d1 NV_44 "GeForce 6100 nForce 405"
|
||||
0x10de 0x03d2 NV_44 "GeForce 6100 nForce 400"
|
||||
|
|
|
|||
|
|
@ -546,9 +546,15 @@ static int i915_dispatch_batchbuffer(struct drm_device * dev,
|
|||
|
||||
if (dev_priv->use_mi_batchbuffer_start) {
|
||||
BEGIN_LP_RING(2);
|
||||
OUT_RING(MI_BATCH_BUFFER_START | (2 << 6));
|
||||
OUT_RING(batch->start | MI_BATCH_NON_SECURE);
|
||||
if (IS_I965G(dev)) {
|
||||
OUT_RING(MI_BATCH_BUFFER_START | (2 << 6) | MI_BATCH_NON_SECURE_I965);
|
||||
OUT_RING(batch->start);
|
||||
} else {
|
||||
OUT_RING(MI_BATCH_BUFFER_START | (2 << 6));
|
||||
OUT_RING(batch->start | MI_BATCH_NON_SECURE);
|
||||
}
|
||||
ADVANCE_LP_RING();
|
||||
|
||||
} else {
|
||||
BEGIN_LP_RING(4);
|
||||
OUT_RING(MI_BATCH_BUFFER);
|
||||
|
|
|
|||
|
|
@ -364,6 +364,8 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
|
|||
#define MI_BATCH_BUFFER_END (0xA<<23)
|
||||
#define MI_BATCH_NON_SECURE (1)
|
||||
|
||||
#define MI_BATCH_NON_SECURE_I965 (1<<8)
|
||||
|
||||
#define MI_WAIT_FOR_EVENT ((0x3<<23))
|
||||
#define MI_WAIT_FOR_PLANE_B_FLIP (1<<6)
|
||||
#define MI_WAIT_FOR_PLANE_A_FLIP (1<<2)
|
||||
|
|
|
|||
177
shared-core/nouveau_dma.c
Normal file
177
shared-core/nouveau_dma.c
Normal file
|
|
@ -0,0 +1,177 @@
|
|||
/*
|
||||
* Copyright (C) 2007 Ben Skeggs.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial
|
||||
* portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
#include "nouveau_drv.h"
|
||||
#include "nouveau_dma.h"
|
||||
|
||||
#define SKIPS 8
|
||||
|
||||
int
|
||||
nouveau_dma_channel_init(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_drm_channel *dchan = &dev_priv->channel;
|
||||
struct nouveau_gpuobj *gpuobj = NULL;
|
||||
struct mem_block *pushbuf;
|
||||
int grclass, ret, i;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
pushbuf = nouveau_mem_alloc(dev, 0, 0x8000,
|
||||
NOUVEAU_MEM_FB | NOUVEAU_MEM_MAPPED,
|
||||
(struct drm_file *)-2);
|
||||
if (!pushbuf) {
|
||||
DRM_ERROR("Failed to allocate DMA push buffer\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Allocate channel */
|
||||
ret = nouveau_fifo_alloc(dev, &dchan->chan, (struct drm_file *)-2,
|
||||
pushbuf, NvDmaFB, NvDmaTT);
|
||||
if (ret) {
|
||||
DRM_ERROR("Error allocating GPU channel: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
DRM_DEBUG("Using FIFO channel %d\n", dchan->chan->id);
|
||||
|
||||
/* Map push buffer */
|
||||
drm_core_ioremap(dchan->chan->pushbuf_mem->map, dev);
|
||||
if (!dchan->chan->pushbuf_mem->map->handle) {
|
||||
DRM_ERROR("Failed to ioremap push buffer\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
dchan->pushbuf = (void*)dchan->chan->pushbuf_mem->map->handle;
|
||||
|
||||
/* Initialise DMA vars */
|
||||
dchan->max = (dchan->chan->pushbuf_mem->size >> 2) - 2;
|
||||
dchan->put = dchan->chan->pushbuf_base >> 2;
|
||||
dchan->cur = dchan->put;
|
||||
dchan->free = dchan->max - dchan->cur;
|
||||
|
||||
/* Insert NOPS for SKIPS */
|
||||
dchan->free -= SKIPS;
|
||||
dchan->push_free = SKIPS;
|
||||
for (i=0; i<SKIPS; i++)
|
||||
OUT_RING(0);
|
||||
|
||||
/* NV_MEMORY_TO_MEMORY_FORMAT requires a notifier */
|
||||
if ((ret = nouveau_notifier_alloc(dchan->chan, NvNotify0, 1,
|
||||
&dchan->notify0_offset))) {
|
||||
DRM_ERROR("Error allocating NvNotify0: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* We use NV_MEMORY_TO_MEMORY_FORMAT for buffer moves */
|
||||
if (dev_priv->card_type < NV_50) grclass = NV_MEMORY_TO_MEMORY_FORMAT;
|
||||
else grclass = NV50_MEMORY_TO_MEMORY_FORMAT;
|
||||
if ((ret = nouveau_gpuobj_gr_new(dchan->chan, grclass, &gpuobj))) {
|
||||
DRM_ERROR("Error creating NvM2MF: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((ret = nouveau_gpuobj_ref_add(dev, dchan->chan, NvM2MF,
|
||||
gpuobj, NULL))) {
|
||||
DRM_ERROR("Error referencing NvM2MF: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
dchan->m2mf_dma_source = NvDmaFB;
|
||||
dchan->m2mf_dma_destin = NvDmaFB;
|
||||
|
||||
BEGIN_RING(NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_NAME, 1);
|
||||
OUT_RING (NvM2MF);
|
||||
BEGIN_RING(NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_SET_DMA_NOTIFY, 1);
|
||||
OUT_RING (NvNotify0);
|
||||
BEGIN_RING(NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_SET_DMA_SOURCE, 2);
|
||||
OUT_RING (dchan->m2mf_dma_source);
|
||||
OUT_RING (dchan->m2mf_dma_destin);
|
||||
FIRE_RING();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
nouveau_dma_channel_takedown(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_drm_channel *dchan = &dev_priv->channel;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
if (dchan->chan) {
|
||||
nouveau_fifo_free(dchan->chan);
|
||||
dchan->chan = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#define RING_SKIPS 8
|
||||
|
||||
#define READ_GET() ((NV_READ(NV03_FIFO_REGS_DMAGET(dchan->chan->id)) - \
|
||||
dchan->chan->pushbuf_base) >> 2)
|
||||
#define WRITE_PUT(val) do { \
|
||||
NV_WRITE(NV03_FIFO_REGS_DMAPUT(dchan->chan->id), \
|
||||
((val) << 2) + dchan->chan->pushbuf_base); \
|
||||
} while(0)
|
||||
|
||||
int
|
||||
nouveau_dma_wait(struct drm_device *dev, int size)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_drm_channel *dchan = &dev_priv->channel;
|
||||
uint32_t get;
|
||||
|
||||
while (dchan->free < size) {
|
||||
get = READ_GET();
|
||||
|
||||
if (dchan->put >= get) {
|
||||
dchan->free = dchan->max - dchan->cur;
|
||||
|
||||
if (dchan->free < size) {
|
||||
dchan->push_free = 1;
|
||||
OUT_RING(0x20000000|dchan->chan->pushbuf_base);
|
||||
if (get <= RING_SKIPS) {
|
||||
/*corner case - will be idle*/
|
||||
if (dchan->put <= RING_SKIPS)
|
||||
WRITE_PUT(RING_SKIPS + 1);
|
||||
|
||||
do {
|
||||
get = READ_GET();
|
||||
} while (get <= RING_SKIPS);
|
||||
}
|
||||
|
||||
WRITE_PUT(RING_SKIPS);
|
||||
dchan->cur = dchan->put = RING_SKIPS;
|
||||
dchan->free = get - (RING_SKIPS + 1);
|
||||
}
|
||||
} else {
|
||||
dchan->free = get - dchan->cur - 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
98
shared-core/nouveau_dma.h
Normal file
98
shared-core/nouveau_dma.h
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* Copyright (C) 2007 Ben Skeggs.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial
|
||||
* portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __NOUVEAU_DMA_H__
|
||||
#define __NOUVEAU_DMA_H__
|
||||
|
||||
typedef enum {
|
||||
NvSubM2MF = 0,
|
||||
} nouveau_subchannel_id_t;
|
||||
|
||||
typedef enum {
|
||||
NvM2MF = 0x80039001,
|
||||
NvDmaFB = 0x8003d001,
|
||||
NvDmaTT = 0x8003d002,
|
||||
NvNotify0 = 0x8003d003
|
||||
} nouveau_object_handle_t;
|
||||
|
||||
#define NV_MEMORY_TO_MEMORY_FORMAT 0x00000039
|
||||
#define NV_MEMORY_TO_MEMORY_FORMAT_NAME 0x00000000
|
||||
#define NV_MEMORY_TO_MEMORY_FORMAT_SET_REF 0x00000050
|
||||
#define NV_MEMORY_TO_MEMORY_FORMAT_NOP 0x00000100
|
||||
#define NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY 0x00000104
|
||||
#define NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY_STYLE_WRITE 0x00000000
|
||||
#define NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY_STYLE_WRITE_LE_AWAKEN 0x00000001
|
||||
#define NV_MEMORY_TO_MEMORY_FORMAT_SET_DMA_NOTIFY 0x00000180
|
||||
#define NV_MEMORY_TO_MEMORY_FORMAT_SET_DMA_SOURCE 0x00000184
|
||||
#define NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN 0x0000030c
|
||||
|
||||
#define NV50_MEMORY_TO_MEMORY_FORMAT 0x00005039
|
||||
#define NV50_MEMORY_TO_MEMORY_FORMAT_UNK200 0x00000200
|
||||
#define NV50_MEMORY_TO_MEMORY_FORMAT_UNK21C 0x0000021c
|
||||
#define NV50_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN_HIGH 0x00000238
|
||||
#define NV50_MEMORY_TO_MEMORY_FORMAT_OFFSET_OUT_HIGH 0x0000023c
|
||||
|
||||
#define BEGIN_RING(subc, mthd, cnt) do { \
|
||||
int push_size = (cnt) + 1; \
|
||||
if (dchan->push_free) { \
|
||||
DRM_ERROR("prior packet incomplete: %d\n", dchan->push_free); \
|
||||
break; \
|
||||
} \
|
||||
if (dchan->free < push_size) { \
|
||||
if (nouveau_dma_wait(dev, push_size)) { \
|
||||
DRM_ERROR("FIFO timeout\n"); \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
dchan->free -= push_size; \
|
||||
dchan->push_free = push_size; \
|
||||
OUT_RING(((cnt)<<18) | ((subc)<<15) | mthd); \
|
||||
} while(0)
|
||||
|
||||
#define OUT_RING(data) do { \
|
||||
if (dchan->push_free == 0) { \
|
||||
DRM_ERROR("no space left in packet\n"); \
|
||||
break; \
|
||||
} \
|
||||
dchan->pushbuf[dchan->cur++] = (data); \
|
||||
dchan->push_free--; \
|
||||
} while(0)
|
||||
|
||||
#define FIRE_RING() do { \
|
||||
if (dchan->push_free) { \
|
||||
DRM_ERROR("packet incomplete: %d\n", dchan->push_free); \
|
||||
break; \
|
||||
} \
|
||||
if (dchan->cur != dchan->put) { \
|
||||
DRM_MEMORYBARRIER(); \
|
||||
dchan->put = dchan->cur; \
|
||||
NV_WRITE(NV03_FIFO_REGS_DMAPUT(dchan->chan->id), \
|
||||
(dchan->put<<2)); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -25,9 +25,9 @@
|
|||
#ifndef __NOUVEAU_DRM_H__
|
||||
#define __NOUVEAU_DRM_H__
|
||||
|
||||
#define NOUVEAU_DRM_HEADER_PATCHLEVEL 9
|
||||
#define NOUVEAU_DRM_HEADER_PATCHLEVEL 10
|
||||
|
||||
struct drm_nouveau_fifo_alloc {
|
||||
struct drm_nouveau_channel_alloc {
|
||||
uint32_t fb_ctxdma_handle;
|
||||
uint32_t tt_ctxdma_handle;
|
||||
|
||||
|
|
@ -44,6 +44,10 @@ struct drm_nouveau_fifo_alloc {
|
|||
int notifier_size;
|
||||
};
|
||||
|
||||
struct drm_nouveau_channel_free {
|
||||
int channel;
|
||||
};
|
||||
|
||||
struct drm_nouveau_grobj_alloc {
|
||||
int channel;
|
||||
uint32_t handle;
|
||||
|
|
@ -53,7 +57,7 @@ struct drm_nouveau_grobj_alloc {
|
|||
#define NOUVEAU_MEM_ACCESS_RO 1
|
||||
#define NOUVEAU_MEM_ACCESS_WO 2
|
||||
#define NOUVEAU_MEM_ACCESS_RW 3
|
||||
struct drm_nouveau_notifier_alloc {
|
||||
struct drm_nouveau_notifierobj_alloc {
|
||||
int channel;
|
||||
uint32_t handle;
|
||||
int count;
|
||||
|
|
@ -61,6 +65,11 @@ struct drm_nouveau_notifier_alloc {
|
|||
uint32_t offset;
|
||||
};
|
||||
|
||||
struct drm_nouveau_gpuobj_free {
|
||||
int channel;
|
||||
uint32_t handle;
|
||||
};
|
||||
|
||||
#define NOUVEAU_MEM_FB 0x00000001
|
||||
#define NOUVEAU_MEM_AGP 0x00000002
|
||||
#define NOUVEAU_MEM_FB_ACCEPTABLE 0x00000004
|
||||
|
|
@ -95,6 +104,7 @@ struct drm_nouveau_mem_free {
|
|||
#define NOUVEAU_GETPARAM_FB_SIZE 8
|
||||
#define NOUVEAU_GETPARAM_AGP_SIZE 9
|
||||
#define NOUVEAU_GETPARAM_PCI_PHYSICAL 10
|
||||
#define NOUVEAU_GETPARAM_CHIPSET_ID 11
|
||||
struct drm_nouveau_getparam {
|
||||
uint64_t param;
|
||||
uint64_t value;
|
||||
|
|
@ -141,13 +151,16 @@ struct drm_nouveau_sarea {
|
|||
unsigned int nbox;
|
||||
};
|
||||
|
||||
#define DRM_NOUVEAU_FIFO_ALLOC 0x00
|
||||
#define DRM_NOUVEAU_GROBJ_ALLOC 0x01
|
||||
#define DRM_NOUVEAU_NOTIFIER_ALLOC 0x02
|
||||
#define DRM_NOUVEAU_MEM_ALLOC 0x03
|
||||
#define DRM_NOUVEAU_MEM_FREE 0x04
|
||||
#define DRM_NOUVEAU_GETPARAM 0x05
|
||||
#define DRM_NOUVEAU_SETPARAM 0x06
|
||||
#define DRM_NOUVEAU_CARD_INIT 0x00
|
||||
#define DRM_NOUVEAU_GETPARAM 0x01
|
||||
#define DRM_NOUVEAU_SETPARAM 0x02
|
||||
#define DRM_NOUVEAU_CHANNEL_ALLOC 0x03
|
||||
#define DRM_NOUVEAU_CHANNEL_FREE 0x04
|
||||
#define DRM_NOUVEAU_GROBJ_ALLOC 0x05
|
||||
#define DRM_NOUVEAU_NOTIFIEROBJ_ALLOC 0x06
|
||||
#define DRM_NOUVEAU_GPUOBJ_FREE 0x07
|
||||
#define DRM_NOUVEAU_MEM_ALLOC 0x08
|
||||
#define DRM_NOUVEAU_MEM_FREE 0x09
|
||||
|
||||
#endif /* __NOUVEAU_DRM_H__ */
|
||||
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@
|
|||
|
||||
#define DRIVER_MAJOR 0
|
||||
#define DRIVER_MINOR 0
|
||||
#define DRIVER_PATCHLEVEL 9
|
||||
#define DRIVER_PATCHLEVEL 10
|
||||
|
||||
#define NOUVEAU_FAMILY 0x0000FFFF
|
||||
#define NOUVEAU_FLAGS 0xFFFF0000
|
||||
|
|
@ -67,8 +67,7 @@ enum nouveau_flags {
|
|||
#define NVOBJ_FLAG_ZERO_FREE (1 << 2)
|
||||
#define NVOBJ_FLAG_FAKE (1 << 3)
|
||||
struct nouveau_gpuobj {
|
||||
struct nouveau_gpuobj *next;
|
||||
struct nouveau_gpuobj *prev;
|
||||
struct list_head list;
|
||||
|
||||
int im_channel;
|
||||
struct mem_block *im_pramin;
|
||||
|
|
@ -80,10 +79,13 @@ struct nouveau_gpuobj {
|
|||
|
||||
uint32_t engine;
|
||||
uint32_t class;
|
||||
|
||||
void (*dtor)(struct drm_device *, struct nouveau_gpuobj *);
|
||||
void *priv;
|
||||
};
|
||||
|
||||
struct nouveau_gpuobj_ref {
|
||||
struct nouveau_gpuobj_ref *next;
|
||||
struct list_head list;
|
||||
|
||||
struct nouveau_gpuobj *gpuobj;
|
||||
uint32_t instance;
|
||||
|
|
@ -92,8 +94,11 @@ struct nouveau_gpuobj_ref {
|
|||
int handle;
|
||||
};
|
||||
|
||||
struct nouveau_fifo
|
||||
struct nouveau_channel
|
||||
{
|
||||
struct drm_device *dev;
|
||||
int id;
|
||||
|
||||
/* owner of this fifo */
|
||||
struct drm_file *file_priv;
|
||||
/* mapping of the fifo itself */
|
||||
|
|
@ -126,7 +131,23 @@ struct nouveau_fifo
|
|||
struct nouveau_gpuobj_ref *ramin; /* Private instmem */
|
||||
struct mem_block *ramin_heap; /* Private PRAMIN heap */
|
||||
struct nouveau_gpuobj_ref *ramht; /* Hash table */
|
||||
struct nouveau_gpuobj_ref *ramht_refs; /* Objects referenced by RAMHT */
|
||||
struct list_head ramht_refs; /* Objects referenced by RAMHT */
|
||||
};
|
||||
|
||||
struct nouveau_drm_channel {
|
||||
struct nouveau_channel *chan;
|
||||
|
||||
/* DMA state */
|
||||
int max, put, cur, free;
|
||||
int push_free;
|
||||
volatile uint32_t *pushbuf;
|
||||
|
||||
/* Notifiers */
|
||||
uint32_t notify0_offset;
|
||||
|
||||
/* Buffer moves */
|
||||
uint32_t m2mf_dma_source;
|
||||
uint32_t m2mf_dma_destin;
|
||||
};
|
||||
|
||||
struct nouveau_config {
|
||||
|
|
@ -136,57 +157,64 @@ struct nouveau_config {
|
|||
} cmdbuf;
|
||||
};
|
||||
|
||||
struct nouveau_engine_func {
|
||||
struct {
|
||||
void *priv;
|
||||
struct nouveau_instmem_engine {
|
||||
void *priv;
|
||||
|
||||
int (*init)(struct drm_device *dev);
|
||||
void (*takedown)(struct drm_device *dev);
|
||||
int (*init)(struct drm_device *dev);
|
||||
void (*takedown)(struct drm_device *dev);
|
||||
|
||||
int (*populate)(struct drm_device *, struct nouveau_gpuobj *,
|
||||
uint32_t *size);
|
||||
void (*clear)(struct drm_device *, struct nouveau_gpuobj *);
|
||||
int (*bind)(struct drm_device *, struct nouveau_gpuobj *);
|
||||
int (*unbind)(struct drm_device *, struct nouveau_gpuobj *);
|
||||
} instmem;
|
||||
int (*populate)(struct drm_device *, struct nouveau_gpuobj *,
|
||||
uint32_t *size);
|
||||
void (*clear)(struct drm_device *, struct nouveau_gpuobj *);
|
||||
int (*bind)(struct drm_device *, struct nouveau_gpuobj *);
|
||||
int (*unbind)(struct drm_device *, struct nouveau_gpuobj *);
|
||||
};
|
||||
|
||||
struct {
|
||||
int (*init)(struct drm_device *dev);
|
||||
void (*takedown)(struct drm_device *dev);
|
||||
} mc;
|
||||
struct nouveau_mc_engine {
|
||||
int (*init)(struct drm_device *dev);
|
||||
void (*takedown)(struct drm_device *dev);
|
||||
};
|
||||
|
||||
struct {
|
||||
int (*init)(struct drm_device *dev);
|
||||
uint64_t (*read)(struct drm_device *dev);
|
||||
void (*takedown)(struct drm_device *dev);
|
||||
} timer;
|
||||
struct nouveau_timer_engine {
|
||||
int (*init)(struct drm_device *dev);
|
||||
void (*takedown)(struct drm_device *dev);
|
||||
uint64_t (*read)(struct drm_device *dev);
|
||||
};
|
||||
|
||||
struct {
|
||||
int (*init)(struct drm_device *dev);
|
||||
void (*takedown)(struct drm_device *dev);
|
||||
} fb;
|
||||
struct nouveau_fb_engine {
|
||||
int (*init)(struct drm_device *dev);
|
||||
void (*takedown)(struct drm_device *dev);
|
||||
};
|
||||
|
||||
struct {
|
||||
int (*init)(struct drm_device *);
|
||||
void (*takedown)(struct drm_device *);
|
||||
struct nouveau_fifo_engine {
|
||||
void *priv;
|
||||
|
||||
int (*create_context)(struct drm_device *, int channel);
|
||||
void (*destroy_context)(struct drm_device *, int channel);
|
||||
int (*load_context)(struct drm_device *, int channel);
|
||||
int (*save_context)(struct drm_device *, int channel);
|
||||
} graph;
|
||||
int (*init)(struct drm_device *);
|
||||
void (*takedown)(struct drm_device *);
|
||||
|
||||
struct {
|
||||
void *priv;
|
||||
int (*create_context)(struct nouveau_channel *);
|
||||
void (*destroy_context)(struct nouveau_channel *);
|
||||
int (*load_context)(struct nouveau_channel *);
|
||||
int (*save_context)(struct nouveau_channel *);
|
||||
};
|
||||
|
||||
int (*init)(struct drm_device *);
|
||||
void (*takedown)(struct drm_device *);
|
||||
struct nouveau_pgraph_engine {
|
||||
int (*init)(struct drm_device *);
|
||||
void (*takedown)(struct drm_device *);
|
||||
|
||||
int (*create_context)(struct drm_device *, int channel);
|
||||
void (*destroy_context)(struct drm_device *, int channel);
|
||||
int (*load_context)(struct drm_device *, int channel);
|
||||
int (*save_context)(struct drm_device *, int channel);
|
||||
} fifo;
|
||||
int (*create_context)(struct nouveau_channel *);
|
||||
void (*destroy_context)(struct nouveau_channel *);
|
||||
int (*load_context)(struct nouveau_channel *);
|
||||
int (*save_context)(struct nouveau_channel *);
|
||||
};
|
||||
|
||||
struct nouveau_engine {
|
||||
struct nouveau_instmem_engine instmem;
|
||||
struct nouveau_mc_engine mc;
|
||||
struct nouveau_timer_engine timer;
|
||||
struct nouveau_fb_engine fb;
|
||||
struct nouveau_pgraph_engine graph;
|
||||
struct nouveau_fifo_engine fifo;
|
||||
};
|
||||
|
||||
struct drm_nouveau_private {
|
||||
|
|
@ -207,9 +235,10 @@ struct drm_nouveau_private {
|
|||
drm_local_map_t *ramin; /* NV40 onwards */
|
||||
|
||||
int fifo_alloc_count;
|
||||
struct nouveau_fifo *fifos[NV_MAX_FIFO_NUMBER];
|
||||
struct nouveau_channel *fifos[NV_MAX_FIFO_NUMBER];
|
||||
|
||||
struct nouveau_engine_func Engine;
|
||||
struct nouveau_engine Engine;
|
||||
struct nouveau_drm_channel channel;
|
||||
|
||||
/* RAMIN configuration, RAMFC, RAMHT and RAMRO offsets */
|
||||
struct nouveau_gpuobj *ramht;
|
||||
|
|
@ -259,96 +288,135 @@ struct drm_nouveau_private {
|
|||
|
||||
struct nouveau_config config;
|
||||
|
||||
struct nouveau_gpuobj *gpuobj_all;
|
||||
struct list_head gpuobj_list;
|
||||
};
|
||||
|
||||
#define NOUVEAU_CHECK_INITIALISED_WITH_RETURN do { \
|
||||
struct drm_nouveau_private *nv = dev->dev_private; \
|
||||
if (nv->init_state != NOUVEAU_CARD_INIT_DONE) { \
|
||||
DRM_ERROR("called without init\n"); \
|
||||
return -EINVAL; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(id,cl,ch) do { \
|
||||
struct drm_nouveau_private *nv = dev->dev_private; \
|
||||
if (!nouveau_fifo_owner(dev, (cl), (id))) { \
|
||||
DRM_ERROR("pid %d doesn't own channel %d\n", \
|
||||
DRM_CURRENTPID, (id)); \
|
||||
return -EPERM; \
|
||||
} \
|
||||
(ch) = nv->fifos[(id)]; \
|
||||
} while(0)
|
||||
|
||||
/* nouveau_state.c */
|
||||
extern void nouveau_preclose(struct drm_device * dev,
|
||||
struct drm_file *file_priv);
|
||||
extern int nouveau_load(struct drm_device *dev, unsigned long flags);
|
||||
extern int nouveau_firstopen(struct drm_device *dev);
|
||||
extern void nouveau_lastclose(struct drm_device *dev);
|
||||
extern int nouveau_unload(struct drm_device *dev);
|
||||
extern int nouveau_ioctl_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv);
|
||||
extern int nouveau_ioctl_setparam(struct drm_device *dev, void *data, struct drm_file *file_priv);
|
||||
extern void nouveau_wait_for_idle(struct drm_device *dev);
|
||||
extern int nouveau_ioctl_card_init(struct drm_device *dev, void *data, struct drm_file *file_priv);
|
||||
extern void nouveau_preclose(struct drm_device *dev, struct drm_file *);
|
||||
extern int nouveau_load(struct drm_device *, unsigned long flags);
|
||||
extern int nouveau_firstopen(struct drm_device *);
|
||||
extern void nouveau_lastclose(struct drm_device *);
|
||||
extern int nouveau_unload(struct drm_device *);
|
||||
extern int nouveau_ioctl_getparam(struct drm_device *, void *data,
|
||||
struct drm_file *);
|
||||
extern int nouveau_ioctl_setparam(struct drm_device *, void *data,
|
||||
struct drm_file *);
|
||||
extern void nouveau_wait_for_idle(struct drm_device *);
|
||||
extern int nouveau_card_init(struct drm_device *);
|
||||
extern int nouveau_ioctl_card_init(struct drm_device *, void *data,
|
||||
struct drm_file *);
|
||||
|
||||
/* nouveau_mem.c */
|
||||
extern int nouveau_mem_init_heap(struct mem_block **,
|
||||
uint64_t start, uint64_t size);
|
||||
extern int nouveau_mem_init_heap(struct mem_block **, uint64_t start,
|
||||
uint64_t size);
|
||||
extern struct mem_block *nouveau_mem_alloc_block(struct mem_block *,
|
||||
uint64_t size, int align2,
|
||||
struct drm_file *file_priv);
|
||||
extern void nouveau_mem_takedown(struct mem_block **heap);
|
||||
extern void nouveau_mem_free_block(struct mem_block *);
|
||||
extern uint64_t nouveau_mem_fb_amount(struct drm_device *dev);
|
||||
extern void nouveau_mem_release(struct drm_file *file_priv,
|
||||
struct mem_block *heap);
|
||||
extern int nouveau_ioctl_mem_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv);
|
||||
extern int nouveau_ioctl_mem_free(struct drm_device *dev, void *data, struct drm_file *file_priv);
|
||||
extern struct mem_block* nouveau_mem_alloc(struct drm_device *dev,
|
||||
struct drm_file *);
|
||||
extern void nouveau_mem_takedown(struct mem_block **heap);
|
||||
extern void nouveau_mem_free_block(struct mem_block *);
|
||||
extern uint64_t nouveau_mem_fb_amount(struct drm_device *);
|
||||
extern void nouveau_mem_release(struct drm_file *, struct mem_block *heap);
|
||||
extern int nouveau_ioctl_mem_alloc(struct drm_device *, void *data,
|
||||
struct drm_file *);
|
||||
extern int nouveau_ioctl_mem_free(struct drm_device *, void *data,
|
||||
struct drm_file *);
|
||||
extern struct mem_block* nouveau_mem_alloc(struct drm_device *,
|
||||
int alignment, uint64_t size,
|
||||
int flags,
|
||||
struct drm_file *file_priv);
|
||||
extern void nouveau_mem_free(struct drm_device* dev, struct mem_block*);
|
||||
extern int nouveau_mem_init(struct drm_device *dev);
|
||||
extern void nouveau_mem_close(struct drm_device *dev);
|
||||
int flags, struct drm_file *);
|
||||
extern void nouveau_mem_free(struct drm_device *dev, struct mem_block*);
|
||||
extern int nouveau_mem_init(struct drm_device *);
|
||||
extern void nouveau_mem_close(struct drm_device *);
|
||||
|
||||
/* nouveau_notifier.c */
|
||||
extern int nouveau_notifier_init_channel(struct drm_device *, int channel,
|
||||
struct drm_file *file_priv);
|
||||
extern void nouveau_notifier_takedown_channel(struct drm_device *, int channel);
|
||||
extern int nouveau_notifier_alloc(struct drm_device *, int channel,
|
||||
uint32_t handle, int cout, uint32_t *offset);
|
||||
extern int nouveau_ioctl_notifier_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv);
|
||||
extern int nouveau_notifier_init_channel(struct nouveau_channel *);
|
||||
extern void nouveau_notifier_takedown_channel(struct nouveau_channel *);
|
||||
extern int nouveau_notifier_alloc(struct nouveau_channel *, uint32_t handle,
|
||||
int cout, uint32_t *offset);
|
||||
extern int nouveau_ioctl_notifier_alloc(struct drm_device *, void *data,
|
||||
struct drm_file *);
|
||||
extern int nouveau_ioctl_notifier_free(struct drm_device *, void *data,
|
||||
struct drm_file *);
|
||||
|
||||
/* nouveau_fifo.c */
|
||||
extern int nouveau_fifo_init(struct drm_device *dev);
|
||||
extern int nouveau_fifo_number(struct drm_device *dev);
|
||||
extern int nouveau_fifo_ctx_size(struct drm_device *dev);
|
||||
extern void nouveau_fifo_cleanup(struct drm_device *dev,
|
||||
struct drm_file *file_priv);
|
||||
extern int nouveau_fifo_owner(struct drm_device *dev,
|
||||
struct drm_file *file_priv, int channel);
|
||||
extern void nouveau_fifo_free(struct drm_device *dev, int channel);
|
||||
extern int nouveau_fifo_init(struct drm_device *);
|
||||
extern int nouveau_fifo_number(struct drm_device *);
|
||||
extern int nouveau_fifo_ctx_size(struct drm_device *);
|
||||
extern void nouveau_fifo_cleanup(struct drm_device *, struct drm_file *);
|
||||
extern int nouveau_fifo_owner(struct drm_device *, struct drm_file *,
|
||||
int channel);
|
||||
extern int nouveau_fifo_alloc(struct drm_device *dev,
|
||||
struct nouveau_channel **chan,
|
||||
struct drm_file *file_priv,
|
||||
struct mem_block *pushbuf,
|
||||
uint32_t fb_ctxdma, uint32_t tt_ctxdma);
|
||||
extern void nouveau_fifo_free(struct nouveau_channel *);
|
||||
|
||||
/* nouveau_object.c */
|
||||
extern void nouveau_gpuobj_takedown(struct drm_device *dev);
|
||||
extern int nouveau_gpuobj_channel_init(struct drm_device *, int channel,
|
||||
extern int nouveau_gpuobj_early_init(struct drm_device *);
|
||||
extern int nouveau_gpuobj_init(struct drm_device *);
|
||||
extern void nouveau_gpuobj_takedown(struct drm_device *);
|
||||
extern void nouveau_gpuobj_late_takedown(struct drm_device *);
|
||||
extern int nouveau_gpuobj_channel_init(struct nouveau_channel *,
|
||||
uint32_t vram_h, uint32_t tt_h);
|
||||
extern void nouveau_gpuobj_channel_takedown(struct drm_device *, int channel);
|
||||
extern int nouveau_gpuobj_new(struct drm_device *, int channel, int size, int align,
|
||||
uint32_t flags, struct nouveau_gpuobj **);
|
||||
extern void nouveau_gpuobj_channel_takedown(struct nouveau_channel *);
|
||||
extern int nouveau_gpuobj_new(struct drm_device *, struct nouveau_channel *,
|
||||
int size, int align, uint32_t flags,
|
||||
struct nouveau_gpuobj **);
|
||||
extern int nouveau_gpuobj_del(struct drm_device *, struct nouveau_gpuobj **);
|
||||
extern int nouveau_gpuobj_ref_add(struct drm_device *, int channel, uint32_t handle,
|
||||
struct nouveau_gpuobj *,
|
||||
extern int nouveau_gpuobj_ref_add(struct drm_device *, struct nouveau_channel *,
|
||||
uint32_t handle, struct nouveau_gpuobj *,
|
||||
struct nouveau_gpuobj_ref **);
|
||||
extern int nouveau_gpuobj_ref_del(struct drm_device *, struct nouveau_gpuobj_ref **);
|
||||
extern int nouveau_gpuobj_new_ref(struct drm_device *, int chan_obj, int chan_ref,
|
||||
extern int nouveau_gpuobj_ref_del(struct drm_device *,
|
||||
struct nouveau_gpuobj_ref **);
|
||||
extern int nouveau_gpuobj_ref_find(struct nouveau_channel *, uint32_t handle,
|
||||
struct nouveau_gpuobj_ref **ref_ret);
|
||||
extern int nouveau_gpuobj_new_ref(struct drm_device *,
|
||||
struct nouveau_channel *alloc_chan,
|
||||
struct nouveau_channel *ref_chan,
|
||||
uint32_t handle, int size, int align,
|
||||
uint32_t flags, struct nouveau_gpuobj_ref **);
|
||||
extern int nouveau_gpuobj_new_fake(struct drm_device *, uint32_t offset,
|
||||
extern int nouveau_gpuobj_new_fake(struct drm_device *,
|
||||
uint32_t p_offset, uint32_t b_offset,
|
||||
uint32_t size, uint32_t flags,
|
||||
struct nouveau_gpuobj**,
|
||||
struct nouveau_gpuobj **,
|
||||
struct nouveau_gpuobj_ref**);
|
||||
extern int nouveau_gpuobj_dma_new(struct drm_device *, int channel, int class,
|
||||
uint64_t offset, uint64_t size,
|
||||
int access, int target,
|
||||
struct nouveau_gpuobj **);
|
||||
extern int nouveau_gpuobj_gart_dma_new(struct drm_device *, int channel,
|
||||
extern int nouveau_gpuobj_dma_new(struct nouveau_channel *, int class,
|
||||
uint64_t offset, uint64_t size, int access,
|
||||
int target, struct nouveau_gpuobj **);
|
||||
extern int nouveau_gpuobj_gart_dma_new(struct nouveau_channel *,
|
||||
uint64_t offset, uint64_t size,
|
||||
int access, struct nouveau_gpuobj **,
|
||||
uint32_t *o_ret);
|
||||
extern int nouveau_gpuobj_gr_new(struct drm_device *, int channel, int class,
|
||||
extern int nouveau_gpuobj_gr_new(struct nouveau_channel *, int class,
|
||||
struct nouveau_gpuobj **);
|
||||
extern int nouveau_ioctl_grobj_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv);
|
||||
extern int nouveau_ioctl_grobj_alloc(struct drm_device *, void *data,
|
||||
struct drm_file *);
|
||||
extern int nouveau_ioctl_gpuobj_free(struct drm_device *, void *data,
|
||||
struct drm_file *);
|
||||
|
||||
/* nouveau_irq.c */
|
||||
extern irqreturn_t nouveau_irq_handler(DRM_IRQ_ARGS);
|
||||
extern void nouveau_irq_preinstall(struct drm_device*);
|
||||
extern void nouveau_irq_postinstall(struct drm_device*);
|
||||
extern void nouveau_irq_uninstall(struct drm_device*);
|
||||
extern void nouveau_irq_preinstall(struct drm_device *);
|
||||
extern void nouveau_irq_postinstall(struct drm_device *);
|
||||
extern void nouveau_irq_uninstall(struct drm_device *);
|
||||
|
||||
/* nouveau_sgdma.c */
|
||||
extern int nouveau_sgdma_init(struct drm_device *);
|
||||
|
|
@ -357,132 +425,138 @@ extern struct drm_ttm_backend *nouveau_sgdma_init_ttm(struct drm_device *);
|
|||
extern int nouveau_sgdma_nottm_hack_init(struct drm_device *);
|
||||
extern void nouveau_sgdma_nottm_hack_takedown(struct drm_device *);
|
||||
|
||||
/* nouveau_dma.c */
|
||||
extern int nouveau_dma_channel_init(struct drm_device *);
|
||||
extern void nouveau_dma_channel_takedown(struct drm_device *);
|
||||
extern int nouveau_dma_wait(struct drm_device *, int size);
|
||||
|
||||
/* nv04_fb.c */
|
||||
extern int nv04_fb_init(struct drm_device *dev);
|
||||
extern void nv04_fb_takedown(struct drm_device *dev);
|
||||
extern int nv04_fb_init(struct drm_device *);
|
||||
extern void nv04_fb_takedown(struct drm_device *);
|
||||
|
||||
/* nv10_fb.c */
|
||||
extern int nv10_fb_init(struct drm_device *dev);
|
||||
extern void nv10_fb_takedown(struct drm_device *dev);
|
||||
extern int nv10_fb_init(struct drm_device *);
|
||||
extern void nv10_fb_takedown(struct drm_device *);
|
||||
|
||||
/* nv40_fb.c */
|
||||
extern int nv40_fb_init(struct drm_device *dev);
|
||||
extern void nv40_fb_takedown(struct drm_device *dev);
|
||||
extern int nv40_fb_init(struct drm_device *);
|
||||
extern void nv40_fb_takedown(struct drm_device *);
|
||||
|
||||
/* nv04_fifo.c */
|
||||
extern int nv04_fifo_create_context(struct drm_device *dev, int channel);
|
||||
extern void nv04_fifo_destroy_context(struct drm_device *dev, int channel);
|
||||
extern int nv04_fifo_load_context(struct drm_device *dev, int channel);
|
||||
extern int nv04_fifo_save_context(struct drm_device *dev, int channel);
|
||||
extern int nv04_fifo_create_context(struct nouveau_channel *);
|
||||
extern void nv04_fifo_destroy_context(struct nouveau_channel *);
|
||||
extern int nv04_fifo_load_context(struct nouveau_channel *);
|
||||
extern int nv04_fifo_save_context(struct nouveau_channel *);
|
||||
|
||||
/* nv10_fifo.c */
|
||||
extern int nv10_fifo_create_context(struct drm_device *dev, int channel);
|
||||
extern void nv10_fifo_destroy_context(struct drm_device *dev, int channel);
|
||||
extern int nv10_fifo_load_context(struct drm_device *dev, int channel);
|
||||
extern int nv10_fifo_save_context(struct drm_device *dev, int channel);
|
||||
extern int nv10_fifo_create_context(struct nouveau_channel *);
|
||||
extern void nv10_fifo_destroy_context(struct nouveau_channel *);
|
||||
extern int nv10_fifo_load_context(struct nouveau_channel *);
|
||||
extern int nv10_fifo_save_context(struct nouveau_channel *);
|
||||
|
||||
/* nv40_fifo.c */
|
||||
extern int nv40_fifo_create_context(struct drm_device *, int channel);
|
||||
extern void nv40_fifo_destroy_context(struct drm_device *, int channel);
|
||||
extern int nv40_fifo_load_context(struct drm_device *, int channel);
|
||||
extern int nv40_fifo_save_context(struct drm_device *, int channel);
|
||||
extern int nv40_fifo_init(struct drm_device *);
|
||||
extern int nv40_fifo_create_context(struct nouveau_channel *);
|
||||
extern void nv40_fifo_destroy_context(struct nouveau_channel *);
|
||||
extern int nv40_fifo_load_context(struct nouveau_channel *);
|
||||
extern int nv40_fifo_save_context(struct nouveau_channel *);
|
||||
|
||||
/* nv50_fifo.c */
|
||||
extern int nv50_fifo_init(struct drm_device *);
|
||||
extern void nv50_fifo_takedown(struct drm_device *);
|
||||
extern int nv50_fifo_create_context(struct drm_device *, int channel);
|
||||
extern void nv50_fifo_destroy_context(struct drm_device *, int channel);
|
||||
extern int nv50_fifo_load_context(struct drm_device *, int channel);
|
||||
extern int nv50_fifo_save_context(struct drm_device *, int channel);
|
||||
extern int nv50_fifo_create_context(struct nouveau_channel *);
|
||||
extern void nv50_fifo_destroy_context(struct nouveau_channel *);
|
||||
extern int nv50_fifo_load_context(struct nouveau_channel *);
|
||||
extern int nv50_fifo_save_context(struct nouveau_channel *);
|
||||
|
||||
/* nv04_graph.c */
|
||||
extern void nouveau_nv04_context_switch(struct drm_device *dev);
|
||||
extern int nv04_graph_init(struct drm_device *dev);
|
||||
extern void nv04_graph_takedown(struct drm_device *dev);
|
||||
extern int nv04_graph_create_context(struct drm_device *dev, int channel);
|
||||
extern void nv04_graph_destroy_context(struct drm_device *dev, int channel);
|
||||
extern int nv04_graph_load_context(struct drm_device *dev, int channel);
|
||||
extern int nv04_graph_save_context(struct drm_device *dev, int channel);
|
||||
extern void nouveau_nv04_context_switch(struct drm_device *);
|
||||
extern int nv04_graph_init(struct drm_device *);
|
||||
extern void nv04_graph_takedown(struct drm_device *);
|
||||
extern int nv04_graph_create_context(struct nouveau_channel *);
|
||||
extern void nv04_graph_destroy_context(struct nouveau_channel *);
|
||||
extern int nv04_graph_load_context(struct nouveau_channel *);
|
||||
extern int nv04_graph_save_context(struct nouveau_channel *);
|
||||
|
||||
/* nv10_graph.c */
|
||||
extern void nouveau_nv10_context_switch(struct drm_device *dev);
|
||||
extern int nv10_graph_init(struct drm_device *dev);
|
||||
extern void nv10_graph_takedown(struct drm_device *dev);
|
||||
extern int nv10_graph_create_context(struct drm_device *dev, int channel);
|
||||
extern void nv10_graph_destroy_context(struct drm_device *dev, int channel);
|
||||
extern int nv10_graph_load_context(struct drm_device *dev, int channel);
|
||||
extern int nv10_graph_save_context(struct drm_device *dev, int channel);
|
||||
extern void nouveau_nv10_context_switch(struct drm_device *);
|
||||
extern int nv10_graph_init(struct drm_device *);
|
||||
extern void nv10_graph_takedown(struct drm_device *);
|
||||
extern int nv10_graph_create_context(struct nouveau_channel *);
|
||||
extern void nv10_graph_destroy_context(struct nouveau_channel *);
|
||||
extern int nv10_graph_load_context(struct nouveau_channel *);
|
||||
extern int nv10_graph_save_context(struct nouveau_channel *);
|
||||
|
||||
/* nv20_graph.c */
|
||||
extern void nouveau_nv20_context_switch(struct drm_device *dev);
|
||||
extern int nv20_graph_init(struct drm_device *dev);
|
||||
extern void nv20_graph_takedown(struct drm_device *dev);
|
||||
extern int nv20_graph_create_context(struct drm_device *dev, int channel);
|
||||
extern void nv20_graph_destroy_context(struct drm_device *dev, int channel);
|
||||
extern int nv20_graph_load_context(struct drm_device *dev, int channel);
|
||||
extern int nv20_graph_save_context(struct drm_device *dev, int channel);
|
||||
extern void nouveau_nv20_context_switch(struct drm_device *);
|
||||
extern int nv20_graph_init(struct drm_device *);
|
||||
extern void nv20_graph_takedown(struct drm_device *);
|
||||
extern int nv20_graph_create_context(struct nouveau_channel *);
|
||||
extern void nv20_graph_destroy_context(struct nouveau_channel *);
|
||||
extern int nv20_graph_load_context(struct nouveau_channel *);
|
||||
extern int nv20_graph_save_context(struct nouveau_channel *);
|
||||
|
||||
/* nv30_graph.c */
|
||||
extern int nv30_graph_init(struct drm_device *dev);
|
||||
extern void nv30_graph_takedown(struct drm_device *dev);
|
||||
extern int nv30_graph_create_context(struct drm_device *, int channel);
|
||||
extern void nv30_graph_destroy_context(struct drm_device *, int channel);
|
||||
extern int nv30_graph_load_context(struct drm_device *, int channel);
|
||||
extern int nv30_graph_save_context(struct drm_device *, int channel);
|
||||
extern int nv30_graph_init(struct drm_device *);
|
||||
extern void nv30_graph_takedown(struct drm_device *);
|
||||
extern int nv30_graph_create_context(struct nouveau_channel *);
|
||||
extern void nv30_graph_destroy_context(struct nouveau_channel *);
|
||||
extern int nv30_graph_load_context(struct nouveau_channel *);
|
||||
extern int nv30_graph_save_context(struct nouveau_channel *);
|
||||
|
||||
/* nv40_graph.c */
|
||||
extern int nv40_graph_init(struct drm_device *);
|
||||
extern void nv40_graph_takedown(struct drm_device *);
|
||||
extern int nv40_graph_create_context(struct drm_device *, int channel);
|
||||
extern void nv40_graph_destroy_context(struct drm_device *, int channel);
|
||||
extern int nv40_graph_load_context(struct drm_device *, int channel);
|
||||
extern int nv40_graph_save_context(struct drm_device *, int channel);
|
||||
extern int nv40_graph_create_context(struct nouveau_channel *);
|
||||
extern void nv40_graph_destroy_context(struct nouveau_channel *);
|
||||
extern int nv40_graph_load_context(struct nouveau_channel *);
|
||||
extern int nv40_graph_save_context(struct nouveau_channel *);
|
||||
|
||||
/* nv50_graph.c */
|
||||
extern int nv50_graph_init(struct drm_device *);
|
||||
extern void nv50_graph_takedown(struct drm_device *);
|
||||
extern int nv50_graph_create_context(struct drm_device *, int channel);
|
||||
extern void nv50_graph_destroy_context(struct drm_device *, int channel);
|
||||
extern int nv50_graph_load_context(struct drm_device *, int channel);
|
||||
extern int nv50_graph_save_context(struct drm_device *, int channel);
|
||||
extern int nv50_graph_create_context(struct nouveau_channel *);
|
||||
extern void nv50_graph_destroy_context(struct nouveau_channel *);
|
||||
extern int nv50_graph_load_context(struct nouveau_channel *);
|
||||
extern int nv50_graph_save_context(struct nouveau_channel *);
|
||||
|
||||
/* nv04_instmem.c */
|
||||
extern int nv04_instmem_init(struct drm_device *dev);
|
||||
extern void nv04_instmem_takedown(struct drm_device *dev);
|
||||
extern int nv04_instmem_populate(struct drm_device*, struct nouveau_gpuobj*,
|
||||
extern int nv04_instmem_init(struct drm_device *);
|
||||
extern void nv04_instmem_takedown(struct drm_device *);
|
||||
extern int nv04_instmem_populate(struct drm_device *, struct nouveau_gpuobj *,
|
||||
uint32_t *size);
|
||||
extern void nv04_instmem_clear(struct drm_device*, struct nouveau_gpuobj*);
|
||||
extern int nv04_instmem_bind(struct drm_device*, struct nouveau_gpuobj*);
|
||||
extern int nv04_instmem_unbind(struct drm_device*, struct nouveau_gpuobj*);
|
||||
extern void nv04_instmem_clear(struct drm_device *, struct nouveau_gpuobj *);
|
||||
extern int nv04_instmem_bind(struct drm_device *, struct nouveau_gpuobj *);
|
||||
extern int nv04_instmem_unbind(struct drm_device *, struct nouveau_gpuobj *);
|
||||
|
||||
/* nv50_instmem.c */
|
||||
extern int nv50_instmem_init(struct drm_device *dev);
|
||||
extern void nv50_instmem_takedown(struct drm_device *dev);
|
||||
extern int nv50_instmem_populate(struct drm_device*, struct nouveau_gpuobj*,
|
||||
extern int nv50_instmem_init(struct drm_device *);
|
||||
extern void nv50_instmem_takedown(struct drm_device *);
|
||||
extern int nv50_instmem_populate(struct drm_device *, struct nouveau_gpuobj *,
|
||||
uint32_t *size);
|
||||
extern void nv50_instmem_clear(struct drm_device*, struct nouveau_gpuobj*);
|
||||
extern int nv50_instmem_bind(struct drm_device*, struct nouveau_gpuobj*);
|
||||
extern int nv50_instmem_unbind(struct drm_device*, struct nouveau_gpuobj*);
|
||||
extern void nv50_instmem_clear(struct drm_device *, struct nouveau_gpuobj *);
|
||||
extern int nv50_instmem_bind(struct drm_device *, struct nouveau_gpuobj *);
|
||||
extern int nv50_instmem_unbind(struct drm_device *, struct nouveau_gpuobj *);
|
||||
|
||||
/* nv04_mc.c */
|
||||
extern int nv04_mc_init(struct drm_device *dev);
|
||||
extern void nv04_mc_takedown(struct drm_device *dev);
|
||||
extern int nv04_mc_init(struct drm_device *);
|
||||
extern void nv04_mc_takedown(struct drm_device *);
|
||||
|
||||
/* nv40_mc.c */
|
||||
extern int nv40_mc_init(struct drm_device *dev);
|
||||
extern void nv40_mc_takedown(struct drm_device *dev);
|
||||
extern int nv40_mc_init(struct drm_device *);
|
||||
extern void nv40_mc_takedown(struct drm_device *);
|
||||
|
||||
/* nv50_mc.c */
|
||||
extern int nv50_mc_init(struct drm_device *dev);
|
||||
extern void nv50_mc_takedown(struct drm_device *dev);
|
||||
extern int nv50_mc_init(struct drm_device *);
|
||||
extern void nv50_mc_takedown(struct drm_device *);
|
||||
|
||||
/* nv04_timer.c */
|
||||
extern int nv04_timer_init(struct drm_device *dev);
|
||||
extern uint64_t nv04_timer_read(struct drm_device *dev);
|
||||
extern void nv04_timer_takedown(struct drm_device *dev);
|
||||
extern int nv04_timer_init(struct drm_device *);
|
||||
extern uint64_t nv04_timer_read(struct drm_device *);
|
||||
extern void nv04_timer_takedown(struct drm_device *);
|
||||
|
||||
extern long nouveau_compat_ioctl(struct file *file, unsigned int cmd,
|
||||
unsigned long arg);
|
||||
unsigned long arg);
|
||||
|
||||
#if defined(__powerpc__)
|
||||
#define NV_READ(reg) in_be32((void __iomem *)(dev_priv->mmio)->handle + (reg) )
|
||||
|
|
|
|||
|
|
@ -120,6 +120,10 @@ int nouveau_fifo_init(struct drm_device *dev)
|
|||
NV_WRITE(NV03_PMC_ENABLE, NV_READ(NV03_PMC_ENABLE) |
|
||||
NV_PMC_ENABLE_PFIFO);
|
||||
|
||||
/* Enable PFIFO error reporting */
|
||||
NV_WRITE(NV03_PFIFO_INTR_0, 0xFFFFFFFF);
|
||||
NV_WRITE(NV03_PFIFO_INTR_EN_0, 0xFFFFFFFF);
|
||||
|
||||
NV_WRITE(NV03_PFIFO_CACHES, 0x00000000);
|
||||
|
||||
ret = nouveau_fifo_instmem_configure(dev);
|
||||
|
|
@ -186,72 +190,47 @@ int nouveau_fifo_init(struct drm_device *dev)
|
|||
}
|
||||
|
||||
static int
|
||||
nouveau_fifo_cmdbuf_alloc(struct drm_device *dev, int channel)
|
||||
nouveau_fifo_pushbuf_ctxdma_init(struct nouveau_channel *chan)
|
||||
{
|
||||
struct drm_device *dev = chan->dev;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_fifo *chan = dev_priv->fifos[channel];
|
||||
struct nouveau_config *config = &dev_priv->config;
|
||||
struct mem_block *cb;
|
||||
int cb_min_size = max(NV03_FIFO_SIZE,PAGE_SIZE);
|
||||
struct mem_block *pb = chan->pushbuf_mem;
|
||||
struct nouveau_gpuobj *pushbuf = NULL;
|
||||
int ret;
|
||||
|
||||
/* Defaults for unconfigured values */
|
||||
if (!config->cmdbuf.location)
|
||||
config->cmdbuf.location = NOUVEAU_MEM_FB;
|
||||
if (!config->cmdbuf.size || config->cmdbuf.size < cb_min_size)
|
||||
config->cmdbuf.size = cb_min_size;
|
||||
|
||||
cb = nouveau_mem_alloc(dev, 0, config->cmdbuf.size,
|
||||
config->cmdbuf.location | NOUVEAU_MEM_MAPPED,
|
||||
(struct drm_file *)-2);
|
||||
if (!cb) {
|
||||
DRM_ERROR("Couldn't allocate DMA command buffer.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (cb->flags & NOUVEAU_MEM_AGP) {
|
||||
ret = nouveau_gpuobj_gart_dma_new(dev, channel,
|
||||
cb->start, cb->size,
|
||||
if (pb->flags & NOUVEAU_MEM_AGP) {
|
||||
ret = nouveau_gpuobj_gart_dma_new(chan, pb->start, pb->size,
|
||||
NV_DMA_ACCESS_RO,
|
||||
&pushbuf,
|
||||
&chan->pushbuf_base);
|
||||
} else
|
||||
if (cb->flags & NOUVEAU_MEM_PCI) {
|
||||
ret = nouveau_gpuobj_dma_new(dev, channel,
|
||||
NV_CLASS_DMA_IN_MEMORY,
|
||||
cb->start, cb->size,
|
||||
if (pb->flags & NOUVEAU_MEM_PCI) {
|
||||
ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY,
|
||||
pb->start, pb->size,
|
||||
NV_DMA_ACCESS_RO,
|
||||
NV_DMA_TARGET_PCI_NONLINEAR,
|
||||
&pushbuf);
|
||||
chan->pushbuf_base = 0;
|
||||
} else if (dev_priv->card_type != NV_04) {
|
||||
ret = nouveau_gpuobj_dma_new
|
||||
(dev, channel, NV_CLASS_DMA_IN_MEMORY,
|
||||
cb->start,
|
||||
cb->size, NV_DMA_ACCESS_RO, NV_DMA_TARGET_VIDMEM,
|
||||
&pushbuf);
|
||||
ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY,
|
||||
pb->start, pb->size,
|
||||
NV_DMA_ACCESS_RO,
|
||||
NV_DMA_TARGET_VIDMEM, &pushbuf);
|
||||
chan->pushbuf_base = 0;
|
||||
} else {
|
||||
/* NV04 cmdbuf hack, from original ddx.. not sure of it's
|
||||
* exact reason for existing :) PCI access to cmdbuf in
|
||||
* VRAM.
|
||||
*/
|
||||
ret = nouveau_gpuobj_dma_new
|
||||
(dev, channel, NV_CLASS_DMA_IN_MEMORY,
|
||||
cb->start + drm_get_resource_start(dev, 1),
|
||||
cb->size, NV_DMA_ACCESS_RO,
|
||||
NV_DMA_TARGET_PCI, &pushbuf);
|
||||
ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY,
|
||||
pb->start +
|
||||
drm_get_resource_start(dev, 1),
|
||||
pb->size, NV_DMA_ACCESS_RO,
|
||||
NV_DMA_TARGET_PCI, &pushbuf);
|
||||
chan->pushbuf_base = 0;
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
nouveau_mem_free(dev, cb);
|
||||
DRM_ERROR("Error creating push buffer ctxdma: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((ret = nouveau_gpuobj_ref_add(dev, channel, 0, pushbuf,
|
||||
if ((ret = nouveau_gpuobj_ref_add(dev, chan, 0, pushbuf,
|
||||
&chan->pushbuf))) {
|
||||
DRM_ERROR("Error referencing push buffer ctxdma: %d\n", ret);
|
||||
if (pushbuf != dev_priv->gart_info.sg_ctxdma)
|
||||
|
|
@ -259,19 +238,42 @@ nouveau_fifo_cmdbuf_alloc(struct drm_device *dev, int channel)
|
|||
return ret;
|
||||
}
|
||||
|
||||
chan->pushbuf_mem = cb;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct mem_block *
|
||||
nouveau_fifo_user_pushbuf_alloc(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_config *config = &dev_priv->config;
|
||||
struct mem_block *pb;
|
||||
int pb_min_size = max(NV03_FIFO_SIZE,PAGE_SIZE);
|
||||
|
||||
/* Defaults for unconfigured values */
|
||||
if (!config->cmdbuf.location)
|
||||
config->cmdbuf.location = NOUVEAU_MEM_FB;
|
||||
if (!config->cmdbuf.size || config->cmdbuf.size < pb_min_size)
|
||||
config->cmdbuf.size = pb_min_size;
|
||||
|
||||
pb = nouveau_mem_alloc(dev, 0, config->cmdbuf.size,
|
||||
config->cmdbuf.location | NOUVEAU_MEM_MAPPED,
|
||||
(struct drm_file *)-2);
|
||||
if (!pb)
|
||||
DRM_ERROR("Couldn't allocate DMA push buffer.\n");
|
||||
|
||||
return pb;
|
||||
}
|
||||
|
||||
/* allocates and initializes a fifo for user space consumption */
|
||||
int nouveau_fifo_alloc(struct drm_device *dev, int *chan_ret,
|
||||
struct drm_file *file_priv,
|
||||
uint32_t vram_handle, uint32_t tt_handle)
|
||||
int
|
||||
nouveau_fifo_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret,
|
||||
struct drm_file *file_priv, struct mem_block *pushbuf,
|
||||
uint32_t vram_handle, uint32_t tt_handle)
|
||||
{
|
||||
int ret;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_engine_func *engine = &dev_priv->Engine;
|
||||
struct nouveau_fifo *chan;
|
||||
struct nouveau_engine *engine = &dev_priv->Engine;
|
||||
struct nouveau_channel *chan;
|
||||
int channel;
|
||||
|
||||
/*
|
||||
|
|
@ -283,44 +285,44 @@ int nouveau_fifo_alloc(struct drm_device *dev, int *chan_ret,
|
|||
* When there are no more contexts, you lost
|
||||
*/
|
||||
for(channel=0; channel<nouveau_fifo_number(dev); channel++) {
|
||||
if ((dev_priv->card_type == NV_50) && (channel == 0))
|
||||
continue;
|
||||
if (dev_priv->fifos[channel] == NULL)
|
||||
break;
|
||||
}
|
||||
/* no more fifos. you lost. */
|
||||
if (channel==nouveau_fifo_number(dev))
|
||||
return -EINVAL;
|
||||
(*chan_ret) = channel;
|
||||
|
||||
dev_priv->fifos[channel] = drm_calloc(1, sizeof(struct nouveau_fifo),
|
||||
dev_priv->fifos[channel] = drm_calloc(1, sizeof(struct nouveau_channel),
|
||||
DRM_MEM_DRIVER);
|
||||
if (!dev_priv->fifos[channel])
|
||||
return -ENOMEM;
|
||||
dev_priv->fifo_alloc_count++;
|
||||
chan = dev_priv->fifos[channel];
|
||||
chan->dev = dev;
|
||||
chan->id = channel;
|
||||
chan->file_priv = file_priv;
|
||||
chan->pushbuf_mem = pushbuf;
|
||||
|
||||
DRM_INFO("Allocating FIFO number %d\n", channel);
|
||||
|
||||
/* Setup channel's default objects */
|
||||
ret = nouveau_gpuobj_channel_init(dev, channel, vram_handle, tt_handle);
|
||||
if (ret) {
|
||||
nouveau_fifo_free(dev, channel);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* allocate a command buffer, and create a dma object for the gpu */
|
||||
ret = nouveau_fifo_cmdbuf_alloc(dev, channel);
|
||||
if (ret) {
|
||||
nouveau_fifo_free(dev, channel);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Allocate space for per-channel fixed notifier memory */
|
||||
ret = nouveau_notifier_init_channel(dev, channel, file_priv);
|
||||
ret = nouveau_notifier_init_channel(chan);
|
||||
if (ret) {
|
||||
nouveau_fifo_free(dev, channel);
|
||||
nouveau_fifo_free(chan);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Setup channel's default objects */
|
||||
ret = nouveau_gpuobj_channel_init(chan, vram_handle, tt_handle);
|
||||
if (ret) {
|
||||
nouveau_fifo_free(chan);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Create a dma object for the push buffer */
|
||||
ret = nouveau_fifo_pushbuf_ctxdma_init(chan);
|
||||
if (ret) {
|
||||
nouveau_fifo_free(chan);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -333,16 +335,16 @@ int nouveau_fifo_alloc(struct drm_device *dev, int *chan_ret,
|
|||
NV_WRITE(NV04_PFIFO_CACHE1_PULL0, 0x00000000);
|
||||
|
||||
/* Create a graphics context for new channel */
|
||||
ret = engine->graph.create_context(dev, channel);
|
||||
ret = engine->graph.create_context(chan);
|
||||
if (ret) {
|
||||
nouveau_fifo_free(dev, channel);
|
||||
nouveau_fifo_free(chan);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Construct inital RAMFC for new channel */
|
||||
ret = engine->fifo.create_context(dev, channel);
|
||||
ret = engine->fifo.create_context(chan);
|
||||
if (ret) {
|
||||
nouveau_fifo_free(dev, channel);
|
||||
nouveau_fifo_free(chan);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -359,30 +361,17 @@ int nouveau_fifo_alloc(struct drm_device *dev, int *chan_ret,
|
|||
* other case, the GPU will handle this when it switches contexts.
|
||||
*/
|
||||
if (dev_priv->fifo_alloc_count == 1) {
|
||||
ret = engine->fifo.load_context(dev, channel);
|
||||
ret = engine->fifo.load_context(chan);
|
||||
if (ret) {
|
||||
nouveau_fifo_free(dev, channel);
|
||||
nouveau_fifo_free(chan);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = engine->graph.load_context(dev, channel);
|
||||
ret = engine->graph.load_context(chan);
|
||||
if (ret) {
|
||||
nouveau_fifo_free(dev, channel);
|
||||
nouveau_fifo_free(chan);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Temporary hack, to avoid breaking Xv on cards where the
|
||||
* initial context value for 0x400710 doesn't have these bits
|
||||
* set. Proper fix would be to find which object+method is
|
||||
* responsible for modifying this state.
|
||||
*/
|
||||
if (dev_priv->chipset >= 0x10 && dev_priv->chipset < 0x50) {
|
||||
uint32_t tmp;
|
||||
tmp = NV_READ(NV10_PGRAPH_SURFACE) & 0x0007ff00;
|
||||
NV_WRITE(NV10_PGRAPH_SURFACE, tmp);
|
||||
tmp = NV_READ(NV10_PGRAPH_SURFACE) | 0x00020100;
|
||||
NV_WRITE(NV10_PGRAPH_SURFACE, tmp);
|
||||
}
|
||||
}
|
||||
|
||||
NV_WRITE(NV04_PFIFO_CACHE1_DMA_PUSH,
|
||||
|
|
@ -395,32 +384,28 @@ int nouveau_fifo_alloc(struct drm_device *dev, int *chan_ret,
|
|||
NV_WRITE(NV03_PFIFO_CACHES, 1);
|
||||
|
||||
DRM_INFO("%s: initialised FIFO %d\n", __func__, channel);
|
||||
*chan_ret = chan;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* stops a fifo */
|
||||
void nouveau_fifo_free(struct drm_device *dev, int channel)
|
||||
void nouveau_fifo_free(struct nouveau_channel *chan)
|
||||
{
|
||||
struct drm_device *dev = chan->dev;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_engine_func *engine = &dev_priv->Engine;
|
||||
struct nouveau_fifo *chan = dev_priv->fifos[channel];
|
||||
struct nouveau_engine *engine = &dev_priv->Engine;
|
||||
|
||||
if (!chan) {
|
||||
DRM_ERROR("Freeing non-existant channel %d\n", channel);
|
||||
return;
|
||||
}
|
||||
|
||||
DRM_INFO("%s: freeing fifo %d\n", __func__, channel);
|
||||
DRM_INFO("%s: freeing fifo %d\n", __func__, chan->id);
|
||||
|
||||
/* disable the fifo caches */
|
||||
NV_WRITE(NV03_PFIFO_CACHES, 0x00000000);
|
||||
|
||||
// FIXME XXX needs more code
|
||||
|
||||
engine->fifo.destroy_context(dev, channel);
|
||||
engine->fifo.destroy_context(chan);
|
||||
|
||||
/* Cleanup PGRAPH state */
|
||||
engine->graph.destroy_context(dev, channel);
|
||||
engine->graph.destroy_context(chan);
|
||||
|
||||
/* reenable the fifo caches */
|
||||
NV_WRITE(NV03_PFIFO_CACHES, 0x00000001);
|
||||
|
|
@ -432,12 +417,12 @@ void nouveau_fifo_free(struct drm_device *dev, int channel)
|
|||
chan->pushbuf_mem = NULL;
|
||||
}
|
||||
|
||||
nouveau_notifier_takedown_channel(dev, channel);
|
||||
|
||||
/* Destroy objects belonging to the channel */
|
||||
nouveau_gpuobj_channel_takedown(dev, channel);
|
||||
nouveau_gpuobj_channel_takedown(chan);
|
||||
|
||||
dev_priv->fifos[channel] = NULL;
|
||||
nouveau_notifier_takedown_channel(chan);
|
||||
|
||||
dev_priv->fifos[chan->id] = NULL;
|
||||
dev_priv->fifo_alloc_count--;
|
||||
drm_free(chan, sizeof(*chan), DRM_MEM_DRIVER);
|
||||
}
|
||||
|
|
@ -445,14 +430,16 @@ void nouveau_fifo_free(struct drm_device *dev, int channel)
|
|||
/* cleanups all the fifos from file_priv */
|
||||
void nouveau_fifo_cleanup(struct drm_device *dev, struct drm_file *file_priv)
|
||||
{
|
||||
int i;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
int i;
|
||||
|
||||
DRM_DEBUG("clearing FIFO enables from file_priv\n");
|
||||
for(i=0;i<nouveau_fifo_number(dev);i++)
|
||||
if (dev_priv->fifos[i] &&
|
||||
dev_priv->fifos[i]->file_priv==file_priv)
|
||||
nouveau_fifo_free(dev,i);
|
||||
for(i = 0; i < nouveau_fifo_number(dev); i++) {
|
||||
struct nouveau_channel *chan = dev_priv->fifos[i];
|
||||
|
||||
if (chan && chan->file_priv == file_priv)
|
||||
nouveau_fifo_free(chan);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
|
|
@ -472,24 +459,31 @@ nouveau_fifo_owner(struct drm_device *dev, struct drm_file *file_priv,
|
|||
* ioctls wrapping the functions
|
||||
***********************************/
|
||||
|
||||
static int nouveau_ioctl_fifo_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
||||
static int nouveau_ioctl_fifo_alloc(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct drm_nouveau_fifo_alloc *init = data;
|
||||
struct drm_nouveau_channel_alloc *init = data;
|
||||
struct drm_map_list *entry;
|
||||
struct nouveau_fifo *chan;
|
||||
struct nouveau_channel *chan;
|
||||
struct mem_block *pushbuf;
|
||||
int res;
|
||||
|
||||
NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
|
||||
|
||||
if (init->fb_ctxdma_handle == ~0 || init->tt_ctxdma_handle == ~0)
|
||||
return -EINVAL;
|
||||
|
||||
res = nouveau_fifo_alloc(dev, &init->channel, file_priv,
|
||||
pushbuf = nouveau_fifo_user_pushbuf_alloc(dev);
|
||||
if (!pushbuf)
|
||||
return -ENOMEM;
|
||||
|
||||
res = nouveau_fifo_alloc(dev, &chan, file_priv, pushbuf,
|
||||
init->fb_ctxdma_handle,
|
||||
init->tt_ctxdma_handle);
|
||||
if (res)
|
||||
return res;
|
||||
chan = dev_priv->fifos[init->channel];
|
||||
|
||||
init->channel = chan->id;
|
||||
init->put_base = chan->pushbuf_base;
|
||||
|
||||
/* make the fifo available to user space */
|
||||
|
|
@ -523,18 +517,34 @@ static int nouveau_ioctl_fifo_alloc(struct drm_device *dev, void *data, struct d
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int nouveau_ioctl_fifo_free(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_nouveau_channel_free *cfree = data;
|
||||
struct nouveau_channel *chan;
|
||||
|
||||
NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
|
||||
NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(cfree->channel, file_priv, chan);
|
||||
|
||||
nouveau_fifo_free(chan);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***********************************
|
||||
* finally, the ioctl table
|
||||
***********************************/
|
||||
|
||||
struct drm_ioctl_desc nouveau_ioctls[] = {
|
||||
DRM_IOCTL_DEF(DRM_NOUVEAU_FIFO_ALLOC, nouveau_ioctl_fifo_alloc, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_NOUVEAU_GROBJ_ALLOC, nouveau_ioctl_grobj_alloc, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_NOUVEAU_NOTIFIER_ALLOC, nouveau_ioctl_notifier_alloc, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_NOUVEAU_MEM_ALLOC, nouveau_ioctl_mem_alloc, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_NOUVEAU_MEM_FREE, nouveau_ioctl_mem_free, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_NOUVEAU_CARD_INIT, nouveau_ioctl_card_init, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_NOUVEAU_GETPARAM, nouveau_ioctl_getparam, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_NOUVEAU_SETPARAM, nouveau_ioctl_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
|
||||
DRM_IOCTL_DEF(DRM_NOUVEAU_CHANNEL_ALLOC, nouveau_ioctl_fifo_alloc, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_NOUVEAU_CHANNEL_FREE, nouveau_ioctl_fifo_free, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_NOUVEAU_GROBJ_ALLOC, nouveau_ioctl_grobj_alloc, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_NOUVEAU_NOTIFIEROBJ_ALLOC, nouveau_ioctl_notifier_alloc, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_NOUVEAU_GPUOBJ_FREE, nouveau_ioctl_gpuobj_free, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_NOUVEAU_MEM_ALLOC, nouveau_ioctl_mem_alloc, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_NOUVEAU_MEM_FREE, nouveau_ioctl_mem_free, DRM_AUTH),
|
||||
};
|
||||
|
||||
int nouveau_max_ioctl = DRM_ARRAY_SIZE(nouveau_ioctls);
|
||||
|
|
|
|||
|
|
@ -40,33 +40,6 @@ void nouveau_irq_preinstall(struct drm_device *dev)
|
|||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
|
||||
DRM_DEBUG("IRQ: preinst\n");
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("AIII, no dev_priv\n");
|
||||
return;
|
||||
}
|
||||
if (!dev_priv->mmio) {
|
||||
DRM_ERROR("AIII, no dev_priv->mmio\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Disable/Clear PFIFO interrupts */
|
||||
NV_WRITE(NV03_PFIFO_INTR_EN_0, 0);
|
||||
NV_WRITE(NV03_PFIFO_INTR_0, 0xFFFFFFFF);
|
||||
/* Disable/Clear PGRAPH interrupts */
|
||||
if (dev_priv->card_type<NV_40)
|
||||
NV_WRITE(NV03_PGRAPH_INTR_EN, 0);
|
||||
else
|
||||
NV_WRITE(NV40_PGRAPH_INTR_EN, 0);
|
||||
NV_WRITE(NV03_PGRAPH_INTR, 0xFFFFFFFF);
|
||||
#if 0
|
||||
/* Disable/Clear CRTC0/1 interrupts */
|
||||
NV_WRITE(NV_CRTC0_INTEN, 0);
|
||||
NV_WRITE(NV_CRTC0_INTSTAT, NV_CRTC_INTR_VBLANK);
|
||||
NV_WRITE(NV_CRTC1_INTEN, 0);
|
||||
NV_WRITE(NV_CRTC1_INTSTAT, NV_CRTC_INTR_VBLANK);
|
||||
#endif
|
||||
/* Master disable */
|
||||
NV_WRITE(NV03_PMC_INTR_EN_0, 0);
|
||||
}
|
||||
|
|
@ -75,34 +48,6 @@ void nouveau_irq_postinstall(struct drm_device *dev)
|
|||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("AIII, no dev_priv\n");
|
||||
return;
|
||||
}
|
||||
if (!dev_priv->mmio) {
|
||||
DRM_ERROR("AIII, no dev_priv->mmio\n");
|
||||
return;
|
||||
}
|
||||
|
||||
DRM_DEBUG("IRQ: postinst\n");
|
||||
|
||||
/* Enable PFIFO error reporting */
|
||||
NV_WRITE(NV03_PFIFO_INTR_EN_0, 0xFFFFFFFF);
|
||||
NV_WRITE(NV03_PFIFO_INTR_0, 0xFFFFFFFF);
|
||||
|
||||
/* Enable PGRAPH interrupts */
|
||||
if (dev_priv->card_type<NV_40)
|
||||
NV_WRITE(NV03_PGRAPH_INTR_EN, 0xFFFFFFFF);
|
||||
else
|
||||
NV_WRITE(NV40_PGRAPH_INTR_EN, 0xFFFFFFFF);
|
||||
NV_WRITE(NV03_PGRAPH_INTR, 0xFFFFFFFF);
|
||||
|
||||
#if 0
|
||||
/* Enable CRTC0/1 interrupts */
|
||||
NV_WRITE(NV_CRTC0_INTEN, NV_CRTC_INTR_VBLANK);
|
||||
NV_WRITE(NV_CRTC1_INTEN, NV_CRTC_INTR_VBLANK);
|
||||
#endif
|
||||
|
||||
/* Master enable */
|
||||
NV_WRITE(NV03_PMC_INTR_EN_0, NV_PMC_INTR_EN_0_MASTER_ENABLE);
|
||||
}
|
||||
|
|
@ -111,29 +56,6 @@ void nouveau_irq_uninstall(struct drm_device *dev)
|
|||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("AIII, no dev_priv\n");
|
||||
return;
|
||||
}
|
||||
if (!dev_priv->mmio) {
|
||||
DRM_ERROR("AIII, no dev_priv->mmio\n");
|
||||
return;
|
||||
}
|
||||
|
||||
DRM_DEBUG("IRQ: uninst\n");
|
||||
|
||||
/* Disable PFIFO interrupts */
|
||||
NV_WRITE(NV03_PFIFO_INTR_EN_0, 0);
|
||||
/* Disable PGRAPH interrupts */
|
||||
if (dev_priv->card_type<NV_40)
|
||||
NV_WRITE(NV03_PGRAPH_INTR_EN, 0);
|
||||
else
|
||||
NV_WRITE(NV40_PGRAPH_INTR_EN, 0);
|
||||
#if 0
|
||||
/* Disable CRTC0/1 interrupts */
|
||||
NV_WRITE(NV_CRTC0_INTEN, 0);
|
||||
NV_WRITE(NV_CRTC1_INTEN, 0);
|
||||
#endif
|
||||
/* Master disable */
|
||||
NV_WRITE(NV03_PMC_INTR_EN_0, 0);
|
||||
}
|
||||
|
|
@ -150,12 +72,10 @@ static void nouveau_fifo_irq_handler(struct drm_device *dev)
|
|||
chstat = NV_READ(NV04_PFIFO_DMA);
|
||||
channel=NV_READ(NV03_PFIFO_CACHE1_PUSH1)&(nouveau_fifo_number(dev)-1);
|
||||
|
||||
DRM_DEBUG("NV: PFIFO interrupt! Channel=%d, INTSTAT=0x%08x/MODE=0x%08x/PEND=0x%08x\n", channel, status, chmode, chstat);
|
||||
|
||||
if (status & NV_PFIFO_INTR_CACHE_ERROR) {
|
||||
uint32_t c1get, c1method, c1data;
|
||||
|
||||
DRM_ERROR("NV: PFIFO error interrupt\n");
|
||||
DRM_ERROR("PFIFO error interrupt\n");
|
||||
|
||||
c1get = NV_READ(NV03_PFIFO_CACHE1_GET) >> 2;
|
||||
if (dev_priv->card_type < NV_40) {
|
||||
|
|
@ -167,17 +87,17 @@ static void nouveau_fifo_irq_handler(struct drm_device *dev)
|
|||
c1data = NV_READ(NV40_PFIFO_CACHE1_DATA(c1get));
|
||||
}
|
||||
|
||||
DRM_ERROR("NV: Channel %d/%d - Method 0x%04x, Data 0x%08x\n",
|
||||
channel, (c1method >> 13) & 7,
|
||||
c1method & 0x1ffc, c1data
|
||||
);
|
||||
DRM_ERROR("Channel %d/%d - Method 0x%04x, Data 0x%08x\n",
|
||||
channel, (c1method >> 13) & 7, c1method & 0x1ffc,
|
||||
c1data);
|
||||
|
||||
status &= ~NV_PFIFO_INTR_CACHE_ERROR;
|
||||
NV_WRITE(NV03_PFIFO_INTR_0, NV_PFIFO_INTR_CACHE_ERROR);
|
||||
}
|
||||
|
||||
if (status & NV_PFIFO_INTR_DMA_PUSHER) {
|
||||
DRM_INFO("NV: PFIFO DMA pusher interrupt\n");
|
||||
DRM_ERROR("PFIFO DMA pusher interrupt: ch%d, 0x%08x\n",
|
||||
channel, NV_READ(NV04_PFIFO_CACHE1_DMA_GET));
|
||||
|
||||
status &= ~NV_PFIFO_INTR_DMA_PUSHER;
|
||||
NV_WRITE(NV03_PFIFO_INTR_0, NV_PFIFO_INTR_DMA_PUSHER);
|
||||
|
|
@ -191,7 +111,7 @@ static void nouveau_fifo_irq_handler(struct drm_device *dev)
|
|||
}
|
||||
|
||||
if (status) {
|
||||
DRM_INFO("NV: unknown PFIFO interrupt. status=0x%08x\n", status);
|
||||
DRM_ERROR("Unhandled PFIFO interrupt: status=0x%08x\n", status);
|
||||
|
||||
NV_WRITE(NV03_PFIFO_INTR_0, status);
|
||||
}
|
||||
|
|
@ -301,6 +221,62 @@ nouveau_print_bitfield_names(uint32_t value,
|
|||
printk(" (unknown bits 0x%08x)", value);
|
||||
}
|
||||
|
||||
static int
|
||||
nouveau_graph_trapped_channel(struct drm_device *dev, int *channel_ret)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
int channel;
|
||||
|
||||
if (dev_priv->card_type < NV_40) {
|
||||
channel = (NV_READ(0x400704) >> 20) & 0x1f;
|
||||
} else
|
||||
if (dev_priv->card_type < NV_50) {
|
||||
uint32_t cur_grctx = (NV_READ(0x40032C) & 0xfffff) << 4;
|
||||
|
||||
/* 0x400704 *sometimes* contains a sensible channel ID, but
|
||||
* mostly not.. for now lookup which channel owns the active
|
||||
* PGRAPH context. Probably a better way, but this'll do
|
||||
* for now.
|
||||
*/
|
||||
for (channel = 0; channel < 32; channel++) {
|
||||
if (dev_priv->fifos[channel] == NULL)
|
||||
continue;
|
||||
if (cur_grctx ==
|
||||
dev_priv->fifos[channel]->ramin_grctx->instance)
|
||||
break;
|
||||
}
|
||||
if (channel == 32) {
|
||||
DRM_ERROR("AIII, unable to determine active channel "
|
||||
"from PGRAPH context 0x%08x\n", cur_grctx);
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
uint32_t cur_grctx = (NV_READ(0x40032C) & 0xfffff) << 12;
|
||||
|
||||
for (channel = 0; channel < 128; channel++) {
|
||||
if (dev_priv->fifos[channel] == NULL)
|
||||
continue;
|
||||
if (cur_grctx ==
|
||||
dev_priv->fifos[channel]->ramin_grctx->instance)
|
||||
break;
|
||||
}
|
||||
if (channel == 128) {
|
||||
DRM_ERROR("AIII, unable to determine active channel "
|
||||
"from PGRAPH context 0x%08x\n", cur_grctx);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (channel > nouveau_fifo_number(dev) ||
|
||||
dev_priv->fifos[channel] == NULL) {
|
||||
DRM_ERROR("AIII, invalid/inactive channel id %d\n", channel);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
*channel_ret = channel;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
nouveau_graph_dump_trap_info(struct drm_device *dev)
|
||||
{
|
||||
|
|
@ -310,8 +286,10 @@ nouveau_graph_dump_trap_info(struct drm_device *dev)
|
|||
uint32_t method, subc, data;
|
||||
uint32_t nsource, nstatus;
|
||||
|
||||
if (nouveau_graph_trapped_channel(dev, &channel))
|
||||
channel = -1;
|
||||
|
||||
address = NV_READ(0x400704);
|
||||
channel = (address >> 20) & 0x1F;
|
||||
subc = (address >> 16) & 0x7;
|
||||
method = address & 0x1FFC;
|
||||
data = NV_READ(0x400708);
|
||||
|
|
@ -331,77 +309,31 @@ nouveau_graph_dump_trap_info(struct drm_device *dev)
|
|||
ARRAY_SIZE(nouveau_nstatus_names));
|
||||
printk("\n");
|
||||
|
||||
DRM_ERROR("NV: Channel %d/%d (class 0x%04x) - "
|
||||
"Method 0x%04x, Data 0x%08x\n",
|
||||
channel, subc, class, method, data
|
||||
);
|
||||
DRM_ERROR("Channel %d/%d (class 0x%04x) - Method 0x%04x, Data 0x%08x\n",
|
||||
channel, subc, class, method, data);
|
||||
}
|
||||
|
||||
static void nouveau_pgraph_irq_handler(struct drm_device *dev)
|
||||
{
|
||||
uint32_t status;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
uint32_t status, nsource;
|
||||
|
||||
status = NV_READ(NV03_PGRAPH_INTR);
|
||||
if (!status)
|
||||
return;
|
||||
nsource = NV_READ(NV03_PGRAPH_NSOURCE);
|
||||
|
||||
if (status & NV_PGRAPH_INTR_NOTIFY) {
|
||||
uint32_t nsource, nstatus, instance, notify;
|
||||
DRM_DEBUG("NV: PGRAPH notify interrupt\n");
|
||||
DRM_DEBUG("PGRAPH notify interrupt\n");
|
||||
|
||||
nstatus = NV_READ(NV03_PGRAPH_NSTATUS);
|
||||
nsource = NV_READ(NV03_PGRAPH_NSOURCE);
|
||||
DRM_DEBUG("nsource:0x%08x\tnstatus:0x%08x\n", nsource, nstatus);
|
||||
|
||||
/* if this wasn't NOTIFICATION_PENDING, dump extra trap info */
|
||||
if (nsource & ~(1<<0)) {
|
||||
nouveau_graph_dump_trap_info(dev);
|
||||
} else {
|
||||
instance = NV_READ(0x00400158);
|
||||
notify = NV_READ(0x00400150) >> 16;
|
||||
DRM_DEBUG("instance:0x%08x\tnotify:0x%08x\n",
|
||||
instance, notify);
|
||||
}
|
||||
nouveau_graph_dump_trap_info(dev);
|
||||
|
||||
status &= ~NV_PGRAPH_INTR_NOTIFY;
|
||||
NV_WRITE(NV03_PGRAPH_INTR, NV_PGRAPH_INTR_NOTIFY);
|
||||
}
|
||||
|
||||
if (status & NV_PGRAPH_INTR_BUFFER_NOTIFY) {
|
||||
uint32_t nsource, nstatus, instance, notify;
|
||||
DRM_DEBUG("NV: PGRAPH buffer notify interrupt\n");
|
||||
|
||||
nstatus = NV_READ(NV03_PGRAPH_NSTATUS);
|
||||
nsource = NV_READ(NV03_PGRAPH_NSOURCE);
|
||||
DRM_DEBUG("nsource:0x%08x\tnstatus:0x%08x\n", nsource, nstatus);
|
||||
|
||||
instance = NV_READ(0x00400158);
|
||||
notify = NV_READ(0x00400150) >> 16;
|
||||
DRM_DEBUG("instance:0x%08x\tnotify:0x%08x\n", instance, notify);
|
||||
|
||||
status &= ~NV_PGRAPH_INTR_BUFFER_NOTIFY;
|
||||
NV_WRITE(NV03_PGRAPH_INTR, NV_PGRAPH_INTR_BUFFER_NOTIFY);
|
||||
}
|
||||
|
||||
if (status & NV_PGRAPH_INTR_MISSING_HW) {
|
||||
DRM_ERROR("NV: PGRAPH missing hw interrupt\n");
|
||||
|
||||
status &= ~NV_PGRAPH_INTR_MISSING_HW;
|
||||
NV_WRITE(NV03_PGRAPH_INTR, NV_PGRAPH_INTR_MISSING_HW);
|
||||
}
|
||||
|
||||
if (status & NV_PGRAPH_INTR_ERROR) {
|
||||
uint32_t nsource, nstatus, instance;
|
||||
|
||||
DRM_ERROR("NV: PGRAPH error interrupt\n");
|
||||
|
||||
nstatus = NV_READ(NV03_PGRAPH_NSTATUS);
|
||||
nsource = NV_READ(NV03_PGRAPH_NSOURCE);
|
||||
DRM_ERROR("nsource:0x%08x\tnstatus:0x%08x\n", nsource, nstatus);
|
||||
|
||||
instance = NV_READ(0x00400158);
|
||||
DRM_ERROR("instance:0x%08x\n", instance);
|
||||
DRM_ERROR("PGRAPH error interrupt\n");
|
||||
|
||||
nouveau_graph_dump_trap_info(dev);
|
||||
|
||||
|
|
@ -411,7 +343,7 @@ static void nouveau_pgraph_irq_handler(struct drm_device *dev)
|
|||
|
||||
if (status & NV_PGRAPH_INTR_CONTEXT_SWITCH) {
|
||||
uint32_t channel=NV_READ(NV03_PFIFO_CACHE1_PUSH1)&(nouveau_fifo_number(dev)-1);
|
||||
DRM_INFO("NV: PGRAPH context switch interrupt channel %x\n",channel);
|
||||
DRM_DEBUG("PGRAPH context switch interrupt channel %x\n",channel);
|
||||
switch(dev_priv->card_type)
|
||||
{
|
||||
case NV_04:
|
||||
|
|
@ -428,7 +360,7 @@ static void nouveau_pgraph_irq_handler(struct drm_device *dev)
|
|||
nouveau_nv20_context_switch(dev);
|
||||
break;
|
||||
default:
|
||||
DRM_INFO("NV: Context switch not implemented\n");
|
||||
DRM_ERROR("Context switch not implemented\n");
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -437,7 +369,7 @@ static void nouveau_pgraph_irq_handler(struct drm_device *dev)
|
|||
}
|
||||
|
||||
if (status) {
|
||||
DRM_INFO("NV: Unknown PGRAPH interrupt! STAT=0x%08x\n", status);
|
||||
DRM_ERROR("Unhandled PGRAPH interrupt: STAT=0x%08x\n", status);
|
||||
NV_WRITE(NV03_PGRAPH_INTR, status);
|
||||
}
|
||||
|
||||
|
|
@ -447,6 +379,7 @@ static void nouveau_pgraph_irq_handler(struct drm_device *dev)
|
|||
static void nouveau_crtc_irq_handler(struct drm_device *dev, int crtc)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
|
||||
if (crtc&1) {
|
||||
NV_WRITE(NV_CRTC0_INTSTAT, NV_CRTC_INTR_VBLANK);
|
||||
}
|
||||
|
|
@ -466,16 +399,16 @@ irqreturn_t nouveau_irq_handler(DRM_IRQ_ARGS)
|
|||
if (!status)
|
||||
return IRQ_NONE;
|
||||
|
||||
DRM_DEBUG("PMC INTSTAT: 0x%08x\n", status);
|
||||
|
||||
if (status & NV_PMC_INTR_0_PFIFO_PENDING) {
|
||||
nouveau_fifo_irq_handler(dev);
|
||||
status &= ~NV_PMC_INTR_0_PFIFO_PENDING;
|
||||
}
|
||||
|
||||
if (status & NV_PMC_INTR_0_PGRAPH_PENDING) {
|
||||
nouveau_pgraph_irq_handler(dev);
|
||||
status &= ~NV_PMC_INTR_0_PGRAPH_PENDING;
|
||||
}
|
||||
|
||||
if (status & NV_PMC_INTR_0_CRTCn_PENDING) {
|
||||
nouveau_crtc_irq_handler(dev, (status>>24)&3);
|
||||
status &= ~NV_PMC_INTR_0_CRTCn_PENDING;
|
||||
|
|
|
|||
|
|
@ -411,7 +411,7 @@ int nouveau_mem_init(struct drm_device *dev)
|
|||
struct drm_scatter_gather sgreq;
|
||||
|
||||
DRM_DEBUG("Allocating sg memory for PCI DMA\n");
|
||||
sgreq.size = 4 << 20; //4MB of PCI scatter-gather zone
|
||||
sgreq.size = 16 << 20; //4MB of PCI scatter-gather zone
|
||||
|
||||
if (drm_sg_alloc(dev, &sgreq)) {
|
||||
DRM_ERROR("Unable to allocate 4MB of scatter-gather"
|
||||
|
|
@ -549,14 +549,10 @@ void nouveau_mem_free(struct drm_device* dev, struct mem_block* block)
|
|||
|
||||
int nouveau_ioctl_mem_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct drm_nouveau_mem_alloc *alloc = data;
|
||||
struct mem_block *block;
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
|
||||
return -EINVAL;
|
||||
}
|
||||
NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
|
||||
|
||||
block=nouveau_mem_alloc(dev, alloc->alignment, alloc->size,
|
||||
alloc->flags, file_priv);
|
||||
|
|
@ -575,6 +571,8 @@ int nouveau_ioctl_mem_free(struct drm_device *dev, void *data, struct drm_file *
|
|||
struct drm_nouveau_mem_free *memfree = data;
|
||||
struct mem_block *block;
|
||||
|
||||
NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
|
||||
|
||||
block=NULL;
|
||||
if (memfree->flags & NOUVEAU_MEM_FB)
|
||||
block = find_block(dev_priv->fb_heap, memfree->offset);
|
||||
|
|
|
|||
|
|
@ -30,23 +30,25 @@
|
|||
#include "nouveau_drv.h"
|
||||
|
||||
int
|
||||
nouveau_notifier_init_channel(struct drm_device *dev, int channel,
|
||||
struct drm_file *file_priv)
|
||||
nouveau_notifier_init_channel(struct nouveau_channel *chan)
|
||||
{
|
||||
struct drm_device *dev = chan->dev;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_fifo *chan = dev_priv->fifos[channel];
|
||||
int flags, ret;
|
||||
|
||||
/*TODO: PCI notifier blocks */
|
||||
if (dev_priv->agp_heap &&
|
||||
dev_priv->gart_info.type != NOUVEAU_GART_SGDMA)
|
||||
flags = NOUVEAU_MEM_AGP | NOUVEAU_MEM_FB_ACCEPTABLE;
|
||||
else if ( dev_priv->pci_heap )
|
||||
flags = NOUVEAU_MEM_PCI;
|
||||
else
|
||||
flags = NOUVEAU_MEM_FB;
|
||||
flags |= NOUVEAU_MEM_MAPPED;
|
||||
|
||||
DRM_DEBUG("Allocating notifier block in %d\n", flags);
|
||||
chan->notifier_block = nouveau_mem_alloc(dev, 0, PAGE_SIZE, flags,
|
||||
file_priv);
|
||||
(struct drm_file *)-2);
|
||||
if (!chan->notifier_block)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
@ -59,25 +61,33 @@ nouveau_notifier_init_channel(struct drm_device *dev, int channel,
|
|||
}
|
||||
|
||||
void
|
||||
nouveau_notifier_takedown_channel(struct drm_device *dev, int channel)
|
||||
nouveau_notifier_takedown_channel(struct nouveau_channel *chan)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_fifo *chan = dev_priv->fifos[channel];
|
||||
struct drm_device *dev = chan->dev;
|
||||
|
||||
if (chan->notifier_block) {
|
||||
nouveau_mem_free(dev, chan->notifier_block);
|
||||
chan->notifier_block = NULL;
|
||||
}
|
||||
|
||||
/*XXX: heap destroy */
|
||||
nouveau_mem_takedown(&chan->notifier_heap);
|
||||
}
|
||||
|
||||
static void
|
||||
nouveau_notifier_gpuobj_dtor(struct drm_device *dev,
|
||||
struct nouveau_gpuobj *gpuobj)
|
||||
{
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
if (gpuobj->priv)
|
||||
nouveau_mem_free_block(gpuobj->priv);
|
||||
}
|
||||
|
||||
int
|
||||
nouveau_notifier_alloc(struct drm_device *dev, int channel, uint32_t handle,
|
||||
nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle,
|
||||
int count, uint32_t *b_offset)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_fifo *chan = dev_priv->fifos[channel];
|
||||
struct drm_device *dev = chan->dev;
|
||||
struct nouveau_gpuobj *nobj = NULL;
|
||||
struct mem_block *mem;
|
||||
uint32_t offset;
|
||||
|
|
@ -85,14 +95,14 @@ nouveau_notifier_alloc(struct drm_device *dev, int channel, uint32_t handle,
|
|||
|
||||
if (!chan->notifier_heap) {
|
||||
DRM_ERROR("Channel %d doesn't have a notifier heap!\n",
|
||||
channel);
|
||||
chan->id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mem = nouveau_mem_alloc_block(chan->notifier_heap, 32, 0,
|
||||
chan->file_priv);
|
||||
(struct drm_file *)-2);
|
||||
if (!mem) {
|
||||
DRM_ERROR("Channel %d notifier block full\n", channel);
|
||||
DRM_ERROR("Channel %d notifier block full\n", chan->id);
|
||||
return -ENOMEM;
|
||||
}
|
||||
mem->flags = NOUVEAU_MEM_NOTIFIER;
|
||||
|
|
@ -102,21 +112,25 @@ nouveau_notifier_alloc(struct drm_device *dev, int channel, uint32_t handle,
|
|||
target = NV_DMA_TARGET_VIDMEM;
|
||||
} else if (chan->notifier_block->flags & NOUVEAU_MEM_AGP) {
|
||||
target = NV_DMA_TARGET_AGP;
|
||||
} else if (chan->notifier_block->flags & NOUVEAU_MEM_PCI) {
|
||||
target = NV_DMA_TARGET_PCI_NONLINEAR;
|
||||
} else {
|
||||
DRM_ERROR("Bad DMA target, flags 0x%08x!\n",
|
||||
chan->notifier_block->flags);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((ret = nouveau_gpuobj_dma_new(dev, channel, NV_CLASS_DMA_IN_MEMORY,
|
||||
if ((ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY,
|
||||
offset, mem->size,
|
||||
NV_DMA_ACCESS_RW, target, &nobj))) {
|
||||
nouveau_mem_free_block(mem);
|
||||
DRM_ERROR("Error creating notifier ctxdma: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
nobj->dtor = nouveau_notifier_gpuobj_dtor;
|
||||
nobj->priv = mem;
|
||||
|
||||
if ((ret = nouveau_gpuobj_ref_add(dev, channel, handle, nobj, NULL))) {
|
||||
if ((ret = nouveau_gpuobj_ref_add(dev, chan, handle, nobj, NULL))) {
|
||||
nouveau_gpuobj_del(dev, &nobj);
|
||||
nouveau_mem_free_block(mem);
|
||||
DRM_ERROR("Error referencing notifier ctxdma: %d\n", ret);
|
||||
|
|
@ -128,19 +142,17 @@ nouveau_notifier_alloc(struct drm_device *dev, int channel, uint32_t handle,
|
|||
}
|
||||
|
||||
int
|
||||
nouveau_ioctl_notifier_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
||||
nouveau_ioctl_notifier_alloc(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_nouveau_notifier_alloc *na = data;
|
||||
struct drm_nouveau_notifierobj_alloc *na = data;
|
||||
struct nouveau_channel *chan;
|
||||
int ret;
|
||||
|
||||
if (!nouveau_fifo_owner(dev, file_priv, na->channel)) {
|
||||
DRM_ERROR("pid %d doesn't own channel %d\n",
|
||||
DRM_CURRENTPID, na->channel);
|
||||
return -EPERM;
|
||||
}
|
||||
NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
|
||||
NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(na->channel, file_priv, chan);
|
||||
|
||||
ret = nouveau_notifier_alloc(dev, na->channel, na->handle,
|
||||
na->count, &na->offset);
|
||||
ret = nouveau_notifier_alloc(chan, na->handle, na->count, &na->offset);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
|
|||
|
|
@ -72,6 +72,8 @@ nouveau_ramht_hash_handle(struct drm_device *dev, int channel, uint32_t handle)
|
|||
uint32_t hash = 0;
|
||||
int i;
|
||||
|
||||
DRM_DEBUG("ch%d handle=0x%08x\n", channel, handle);
|
||||
|
||||
for (i=32;i>0;i-=dev_priv->ramht_bits) {
|
||||
hash ^= (handle & ((1 << dev_priv->ramht_bits) - 1));
|
||||
handle >>= dev_priv->ramht_bits;
|
||||
|
|
@ -80,7 +82,7 @@ nouveau_ramht_hash_handle(struct drm_device *dev, int channel, uint32_t handle)
|
|||
hash ^= channel << (dev_priv->ramht_bits - 4);
|
||||
hash <<= 3;
|
||||
|
||||
DRM_DEBUG("ch%d handle=0x%08x hash=0x%08x\n", channel, handle, hash);
|
||||
DRM_DEBUG("hash=0x%08x\n", hash);
|
||||
return hash;
|
||||
}
|
||||
|
||||
|
|
@ -100,7 +102,7 @@ static int
|
|||
nouveau_ramht_insert(struct drm_device *dev, struct nouveau_gpuobj_ref *ref)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv=dev->dev_private;
|
||||
struct nouveau_fifo *chan = dev_priv->fifos[ref->channel];
|
||||
struct nouveau_channel *chan = dev_priv->fifos[ref->channel];
|
||||
struct nouveau_gpuobj *ramht = chan->ramht ? chan->ramht->gpuobj : NULL;
|
||||
struct nouveau_gpuobj *gpuobj = ref->gpuobj;
|
||||
uint32_t ctx, co, ho;
|
||||
|
|
@ -131,6 +133,8 @@ nouveau_ramht_insert(struct drm_device *dev, struct nouveau_gpuobj_ref *ref)
|
|||
ref->channel, co, ref->handle, ctx);
|
||||
INSTANCE_WR(ramht, (co + 0)/4, ref->handle);
|
||||
INSTANCE_WR(ramht, (co + 4)/4, ctx);
|
||||
|
||||
list_add_tail(&ref->list, &chan->ramht_refs);
|
||||
return 0;
|
||||
}
|
||||
DRM_DEBUG("collision ch%d 0x%08x: h=0x%08x\n",
|
||||
|
|
@ -149,7 +153,7 @@ static void
|
|||
nouveau_ramht_remove(struct drm_device *dev, struct nouveau_gpuobj_ref *ref)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_fifo *chan = dev_priv->fifos[ref->channel];
|
||||
struct nouveau_channel *chan = dev_priv->fifos[ref->channel];
|
||||
struct nouveau_gpuobj *ramht = chan->ramht ? chan->ramht->gpuobj : NULL;
|
||||
uint32_t co, ho;
|
||||
|
||||
|
|
@ -167,6 +171,8 @@ nouveau_ramht_remove(struct drm_device *dev, struct nouveau_gpuobj_ref *ref)
|
|||
INSTANCE_RD(ramht, (co + 4)));
|
||||
INSTANCE_WR(ramht, (co + 0)/4, 0x00000000);
|
||||
INSTANCE_WR(ramht, (co + 4)/4, 0x00000000);
|
||||
|
||||
list_del(&ref->list);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -180,34 +186,30 @@ nouveau_ramht_remove(struct drm_device *dev, struct nouveau_gpuobj_ref *ref)
|
|||
}
|
||||
|
||||
int
|
||||
nouveau_gpuobj_new(struct drm_device *dev, int channel, int size, int align,
|
||||
uint32_t flags, struct nouveau_gpuobj **gpuobj_ret)
|
||||
nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan,
|
||||
int size, int align, uint32_t flags,
|
||||
struct nouveau_gpuobj **gpuobj_ret)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_engine_func *engine = &dev_priv->Engine;
|
||||
struct nouveau_fifo *chan = NULL;
|
||||
struct nouveau_engine *engine = &dev_priv->Engine;
|
||||
struct nouveau_gpuobj *gpuobj;
|
||||
struct mem_block *pramin = NULL;
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG("ch%d size=%d align=%d flags=0x%08x\n",
|
||||
channel, size, align, flags);
|
||||
chan ? chan->id : -1, size, align, flags);
|
||||
|
||||
if (!dev_priv || !gpuobj_ret || *gpuobj_ret != NULL)
|
||||
return -EINVAL;
|
||||
|
||||
if (channel >= 0) {
|
||||
if (channel > nouveau_fifo_number(dev))
|
||||
return -EINVAL;
|
||||
chan = dev_priv->fifos[channel];
|
||||
}
|
||||
|
||||
gpuobj = drm_calloc(1, sizeof(*gpuobj), DRM_MEM_DRIVER);
|
||||
if (!gpuobj)
|
||||
return -ENOMEM;
|
||||
DRM_DEBUG("gpuobj %p\n", gpuobj);
|
||||
gpuobj->flags = flags;
|
||||
gpuobj->im_channel = channel;
|
||||
gpuobj->im_channel = chan ? chan->id : -1;
|
||||
|
||||
list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list);
|
||||
|
||||
/* Choose between global instmem heap, and per-channel private
|
||||
* instmem heap. On <NV50 allow requests for private instmem
|
||||
|
|
@ -260,24 +262,64 @@ nouveau_gpuobj_new(struct drm_device *dev, int channel, int size, int align,
|
|||
INSTANCE_WR(gpuobj, i/4, 0);
|
||||
}
|
||||
|
||||
if (dev_priv->gpuobj_all) {
|
||||
gpuobj->next = dev_priv->gpuobj_all;
|
||||
gpuobj->next->prev = gpuobj;
|
||||
}
|
||||
dev_priv->gpuobj_all = gpuobj;
|
||||
|
||||
*gpuobj_ret = gpuobj;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nouveau_gpuobj_takedown(struct drm_device *dev)
|
||||
int
|
||||
nouveau_gpuobj_early_init(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_gpuobj *gpuobj = NULL;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
while ((gpuobj = dev_priv->gpuobj_all)) {
|
||||
INIT_LIST_HEAD(&dev_priv->gpuobj_list);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
nouveau_gpuobj_init(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
if (dev_priv->card_type < NV_50) {
|
||||
if ((ret = nouveau_gpuobj_new_fake(dev, dev_priv->ramht_offset,
|
||||
~0, dev_priv->ramht_size,
|
||||
NVOBJ_FLAG_ZERO_ALLOC |
|
||||
NVOBJ_FLAG_ALLOW_NO_REFS,
|
||||
&dev_priv->ramht, NULL)))
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
nouveau_gpuobj_takedown(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
nouveau_gpuobj_del(dev, &dev_priv->ramht);
|
||||
}
|
||||
|
||||
void
|
||||
nouveau_gpuobj_late_takedown(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_gpuobj *gpuobj = NULL;
|
||||
struct list_head *entry, *tmp;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
list_for_each_safe(entry, tmp, &dev_priv->gpuobj_list) {
|
||||
gpuobj = list_entry(entry, struct nouveau_gpuobj, list);
|
||||
|
||||
DRM_ERROR("gpuobj %p still exists at takedown, refs=%d\n",
|
||||
gpuobj, gpuobj->refcount);
|
||||
gpuobj->refcount = 0;
|
||||
|
|
@ -285,10 +327,11 @@ void nouveau_gpuobj_takedown(struct drm_device *dev)
|
|||
}
|
||||
}
|
||||
|
||||
int nouveau_gpuobj_del(struct drm_device *dev, struct nouveau_gpuobj **pgpuobj)
|
||||
int
|
||||
nouveau_gpuobj_del(struct drm_device *dev, struct nouveau_gpuobj **pgpuobj)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_engine_func *engine = &dev_priv->Engine;
|
||||
struct nouveau_engine *engine = &dev_priv->Engine;
|
||||
struct nouveau_gpuobj *gpuobj;
|
||||
|
||||
DRM_DEBUG("gpuobj %p\n", pgpuobj ? *pgpuobj : NULL);
|
||||
|
|
@ -302,7 +345,16 @@ int nouveau_gpuobj_del(struct drm_device *dev, struct nouveau_gpuobj **pgpuobj)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
engine->instmem.clear(dev, gpuobj);
|
||||
if (gpuobj->dtor)
|
||||
gpuobj->dtor(dev, gpuobj);
|
||||
|
||||
if (gpuobj->im_backing) {
|
||||
if (gpuobj->flags & NVOBJ_FLAG_FAKE)
|
||||
drm_free(gpuobj->im_backing,
|
||||
sizeof(*gpuobj->im_backing), DRM_MEM_DRIVER);
|
||||
else
|
||||
engine->instmem.clear(dev, gpuobj);
|
||||
}
|
||||
|
||||
if (gpuobj->im_pramin) {
|
||||
if (gpuobj->flags & NVOBJ_FLAG_FAKE)
|
||||
|
|
@ -312,12 +364,7 @@ int nouveau_gpuobj_del(struct drm_device *dev, struct nouveau_gpuobj **pgpuobj)
|
|||
nouveau_mem_free_block(gpuobj->im_pramin);
|
||||
}
|
||||
|
||||
if (gpuobj->next)
|
||||
gpuobj->next->prev = gpuobj->prev;
|
||||
if (gpuobj->prev)
|
||||
gpuobj->prev->next = gpuobj->next;
|
||||
else
|
||||
dev_priv->gpuobj_all = gpuobj->next;
|
||||
list_del(&gpuobj->list);
|
||||
|
||||
*pgpuobj = NULL;
|
||||
drm_free(gpuobj, sizeof(*gpuobj), DRM_MEM_DRIVER);
|
||||
|
|
@ -325,7 +372,8 @@ int nouveau_gpuobj_del(struct drm_device *dev, struct nouveau_gpuobj **pgpuobj)
|
|||
}
|
||||
|
||||
static int
|
||||
nouveau_gpuobj_instance_get(struct drm_device *dev, int channel,
|
||||
nouveau_gpuobj_instance_get(struct drm_device *dev,
|
||||
struct nouveau_channel *chan,
|
||||
struct nouveau_gpuobj *gpuobj, uint32_t *inst)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
|
|
@ -337,15 +385,15 @@ nouveau_gpuobj_instance_get(struct drm_device *dev, int channel,
|
|||
return 0;
|
||||
}
|
||||
|
||||
if ((channel > 0) && gpuobj->im_channel != channel) {
|
||||
if (chan && gpuobj->im_channel != chan->id) {
|
||||
DRM_ERROR("Channel mismatch: obj %d, ref %d\n",
|
||||
gpuobj->im_channel, channel);
|
||||
gpuobj->im_channel, chan->id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* NV50 channel-local instance */
|
||||
if (channel > 0) {
|
||||
cpramin = dev_priv->fifos[channel]->ramin->gpuobj;
|
||||
if (chan > 0) {
|
||||
cpramin = chan->ramin->gpuobj;
|
||||
*inst = gpuobj->im_pramin->start - cpramin->im_pramin->start;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -371,29 +419,25 @@ nouveau_gpuobj_instance_get(struct drm_device *dev, int channel,
|
|||
}
|
||||
|
||||
int
|
||||
nouveau_gpuobj_ref_add(struct drm_device *dev, int channel, uint32_t handle,
|
||||
struct nouveau_gpuobj *gpuobj, struct nouveau_gpuobj_ref **ref_ret)
|
||||
nouveau_gpuobj_ref_add(struct drm_device *dev, struct nouveau_channel *chan,
|
||||
uint32_t handle, struct nouveau_gpuobj *gpuobj,
|
||||
struct nouveau_gpuobj_ref **ref_ret)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_fifo *chan = NULL;
|
||||
struct nouveau_gpuobj_ref *ref;
|
||||
uint32_t instance;
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG("ch%d h=0x%08x gpuobj=%p\n", channel, handle, gpuobj);
|
||||
DRM_DEBUG("ch%d h=0x%08x gpuobj=%p\n",
|
||||
chan ? chan->id : -1, handle, gpuobj);
|
||||
|
||||
if (!dev_priv || !gpuobj || (ref_ret && *ref_ret != NULL))
|
||||
return -EINVAL;
|
||||
|
||||
if (channel >= 0) {
|
||||
if (channel > nouveau_fifo_number(dev))
|
||||
return -EINVAL;
|
||||
chan = dev_priv->fifos[channel];
|
||||
} else
|
||||
if (!ref_ret)
|
||||
if (!chan && !ref_ret)
|
||||
return -EINVAL;
|
||||
|
||||
ret = nouveau_gpuobj_instance_get(dev, channel, gpuobj, &instance);
|
||||
ret = nouveau_gpuobj_instance_get(dev, chan, gpuobj, &instance);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
@ -401,7 +445,7 @@ nouveau_gpuobj_ref_add(struct drm_device *dev, int channel, uint32_t handle,
|
|||
if (!ref)
|
||||
return -ENOMEM;
|
||||
ref->gpuobj = gpuobj;
|
||||
ref->channel = channel;
|
||||
ref->channel = chan ? chan->id : -1;
|
||||
ref->instance = instance;
|
||||
|
||||
if (!ref_ret) {
|
||||
|
|
@ -412,9 +456,6 @@ nouveau_gpuobj_ref_add(struct drm_device *dev, int channel, uint32_t handle,
|
|||
drm_free(ref, sizeof(*ref), DRM_MEM_DRIVER);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ref->next = chan->ramht_refs;
|
||||
chan->ramht_refs = ref;
|
||||
} else {
|
||||
ref->handle = ~0;
|
||||
*ref_ret = ref;
|
||||
|
|
@ -452,8 +493,9 @@ int nouveau_gpuobj_ref_del(struct drm_device *dev, struct nouveau_gpuobj_ref **p
|
|||
}
|
||||
|
||||
int
|
||||
nouveau_gpuobj_new_ref(struct drm_device *dev, int oc, int rc, uint32_t handle,
|
||||
int size, int align, uint32_t flags,
|
||||
nouveau_gpuobj_new_ref(struct drm_device *dev,
|
||||
struct nouveau_channel *oc, struct nouveau_channel *rc,
|
||||
uint32_t handle, int size, int align, uint32_t flags,
|
||||
struct nouveau_gpuobj_ref **ref)
|
||||
{
|
||||
struct nouveau_gpuobj *gpuobj = NULL;
|
||||
|
|
@ -470,28 +512,29 @@ nouveau_gpuobj_new_ref(struct drm_device *dev, int oc, int rc, uint32_t handle,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
nouveau_gpuobj_ref_find(struct drm_device *dev, int channel, uint32_t handle,
|
||||
int
|
||||
nouveau_gpuobj_ref_find(struct nouveau_channel *chan, uint32_t handle,
|
||||
struct nouveau_gpuobj_ref **ref_ret)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_fifo *chan = dev_priv->fifos[channel];
|
||||
struct nouveau_gpuobj_ref *ref = chan->ramht_refs;
|
||||
struct nouveau_gpuobj_ref *ref;
|
||||
struct list_head *entry, *tmp;
|
||||
|
||||
list_for_each_safe(entry, tmp, &chan->ramht_refs) {
|
||||
ref = list_entry(entry, struct nouveau_gpuobj_ref, list);
|
||||
|
||||
while (ref) {
|
||||
if (ref->handle == handle) {
|
||||
if (ref_ret)
|
||||
*ref_ret = ref;
|
||||
return 0;
|
||||
}
|
||||
ref = ref->next;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int
|
||||
nouveau_gpuobj_new_fake(struct drm_device *dev, uint32_t offset, uint32_t size,
|
||||
nouveau_gpuobj_new_fake(struct drm_device *dev, uint32_t p_offset,
|
||||
uint32_t b_offset, uint32_t size,
|
||||
uint32_t flags, struct nouveau_gpuobj **pgpuobj,
|
||||
struct nouveau_gpuobj_ref **pref)
|
||||
{
|
||||
|
|
@ -499,8 +542,8 @@ nouveau_gpuobj_new_fake(struct drm_device *dev, uint32_t offset, uint32_t size,
|
|||
struct nouveau_gpuobj *gpuobj = NULL;
|
||||
int i;
|
||||
|
||||
DRM_DEBUG("offset=0x%08x size=0x%08x flags=0x%08x\n",
|
||||
offset, size, flags);
|
||||
DRM_DEBUG("p_offset=0x%08x b_offset=0x%08x size=0x%08x flags=0x%08x\n",
|
||||
p_offset, b_offset, size, flags);
|
||||
|
||||
gpuobj = drm_calloc(1, sizeof(*gpuobj), DRM_MEM_DRIVER);
|
||||
if (!gpuobj)
|
||||
|
|
@ -509,14 +552,29 @@ nouveau_gpuobj_new_fake(struct drm_device *dev, uint32_t offset, uint32_t size,
|
|||
gpuobj->im_channel = -1;
|
||||
gpuobj->flags = flags | NVOBJ_FLAG_FAKE;
|
||||
|
||||
gpuobj->im_pramin = drm_calloc(1, sizeof(struct mem_block),
|
||||
DRM_MEM_DRIVER);
|
||||
if (!gpuobj->im_pramin) {
|
||||
nouveau_gpuobj_del(dev, &gpuobj);
|
||||
return -ENOMEM;
|
||||
list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list);
|
||||
|
||||
if (p_offset != ~0) {
|
||||
gpuobj->im_pramin = drm_calloc(1, sizeof(struct mem_block),
|
||||
DRM_MEM_DRIVER);
|
||||
if (!gpuobj->im_pramin) {
|
||||
nouveau_gpuobj_del(dev, &gpuobj);
|
||||
return -ENOMEM;
|
||||
}
|
||||
gpuobj->im_pramin->start = p_offset;
|
||||
gpuobj->im_pramin->size = size;
|
||||
}
|
||||
|
||||
if (b_offset != ~0) {
|
||||
gpuobj->im_backing = drm_calloc(1, sizeof(struct mem_block),
|
||||
DRM_MEM_DRIVER);
|
||||
if (!gpuobj->im_backing) {
|
||||
nouveau_gpuobj_del(dev, &gpuobj);
|
||||
return -ENOMEM;
|
||||
}
|
||||
gpuobj->im_backing->start = b_offset;
|
||||
gpuobj->im_backing->size = size;
|
||||
}
|
||||
gpuobj->im_pramin->start = offset;
|
||||
gpuobj->im_pramin->size = size;
|
||||
|
||||
if (gpuobj->flags & NVOBJ_FLAG_ZERO_ALLOC) {
|
||||
for (i = 0; i < gpuobj->im_pramin->size; i += 4)
|
||||
|
|
@ -524,7 +582,7 @@ nouveau_gpuobj_new_fake(struct drm_device *dev, uint32_t offset, uint32_t size,
|
|||
}
|
||||
|
||||
if (pref) {
|
||||
if ((i = nouveau_gpuobj_ref_add(dev, -1, 0, gpuobj, pref))) {
|
||||
if ((i = nouveau_gpuobj_ref_add(dev, NULL, 0, gpuobj, pref))) {
|
||||
nouveau_gpuobj_del(dev, &gpuobj);
|
||||
return i;
|
||||
}
|
||||
|
|
@ -577,10 +635,11 @@ nouveau_gpuobj_class_instmem_size(struct drm_device *dev, int class)
|
|||
to it that can be used to set up context objects.
|
||||
*/
|
||||
int
|
||||
nouveau_gpuobj_dma_new(struct drm_device *dev, int channel, int class,
|
||||
uint64_t offset, uint64_t size, int access, int target,
|
||||
struct nouveau_gpuobj **gpuobj)
|
||||
nouveau_gpuobj_dma_new(struct nouveau_channel *chan, int class,
|
||||
uint64_t offset, uint64_t size, int access,
|
||||
int target, struct nouveau_gpuobj **gpuobj)
|
||||
{
|
||||
struct drm_device *dev = chan->dev;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
int ret;
|
||||
uint32_t is_scatter_gather = 0;
|
||||
|
|
@ -591,7 +650,7 @@ nouveau_gpuobj_dma_new(struct drm_device *dev, int channel, int class,
|
|||
|
||||
|
||||
DRM_DEBUG("ch%d class=0x%04x offset=0x%llx size=0x%llx\n",
|
||||
channel, class, offset, size);
|
||||
chan->id, class, offset, size);
|
||||
DRM_DEBUG("access=%d target=%d\n", access, target);
|
||||
|
||||
switch (target) {
|
||||
|
|
@ -608,7 +667,7 @@ nouveau_gpuobj_dma_new(struct drm_device *dev, int channel, int class,
|
|||
break;
|
||||
}
|
||||
|
||||
ret = nouveau_gpuobj_new(dev, channel,
|
||||
ret = nouveau_gpuobj_new(dev, chan,
|
||||
is_scatter_gather ? ((page_count << 2) + 12) : nouveau_gpuobj_class_instmem_size(dev, class),
|
||||
16,
|
||||
NVOBJ_FLAG_ZERO_ALLOC | NVOBJ_FLAG_ZERO_FREE,
|
||||
|
|
@ -711,19 +770,19 @@ nouveau_gpuobj_dma_new(struct drm_device *dev, int channel, int class,
|
|||
}
|
||||
|
||||
int
|
||||
nouveau_gpuobj_gart_dma_new(struct drm_device *dev, int channel,
|
||||
nouveau_gpuobj_gart_dma_new(struct nouveau_channel *chan,
|
||||
uint64_t offset, uint64_t size, int access,
|
||||
struct nouveau_gpuobj **gpuobj,
|
||||
uint32_t *o_ret)
|
||||
{
|
||||
struct drm_device *dev = chan->dev;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
int ret;
|
||||
|
||||
if (dev_priv->gart_info.type == NOUVEAU_GART_AGP ||
|
||||
(dev_priv->card_type >= NV_50 &&
|
||||
dev_priv->gart_info.type == NOUVEAU_GART_SGDMA)) {
|
||||
ret = nouveau_gpuobj_dma_new(dev, channel,
|
||||
NV_CLASS_DMA_IN_MEMORY,
|
||||
ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY,
|
||||
offset, size, access,
|
||||
NV_DMA_TARGET_AGP, gpuobj);
|
||||
if (o_ret)
|
||||
|
|
@ -798,15 +857,16 @@ nouveau_gpuobj_gart_dma_new(struct drm_device *dev, int channel,
|
|||
set to 0?
|
||||
*/
|
||||
int
|
||||
nouveau_gpuobj_gr_new(struct drm_device *dev, int channel, int class,
|
||||
nouveau_gpuobj_gr_new(struct nouveau_channel *chan, int class,
|
||||
struct nouveau_gpuobj **gpuobj)
|
||||
{
|
||||
struct drm_device *dev = chan->dev;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG("ch%d class=0x%04x\n", channel, class);
|
||||
DRM_DEBUG("ch%d class=0x%04x\n", chan->id, class);
|
||||
|
||||
ret = nouveau_gpuobj_new(dev, channel,
|
||||
ret = nouveau_gpuobj_new(dev, chan,
|
||||
nouveau_gpuobj_class_instmem_size(dev, class),
|
||||
16,
|
||||
NVOBJ_FLAG_ZERO_ALLOC | NVOBJ_FLAG_ZERO_FREE,
|
||||
|
|
@ -847,14 +907,14 @@ nouveau_gpuobj_gr_new(struct drm_device *dev, int channel, int class,
|
|||
}
|
||||
|
||||
static int
|
||||
nouveau_gpuobj_channel_init_pramin(struct drm_device *dev, int channel)
|
||||
nouveau_gpuobj_channel_init_pramin(struct nouveau_channel *chan)
|
||||
{
|
||||
struct drm_device *dev = chan->dev;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_fifo *chan = dev_priv->fifos[channel];
|
||||
struct nouveau_gpuobj *pramin = NULL;
|
||||
int size, base, ret;
|
||||
|
||||
DRM_DEBUG("ch%d\n", channel);
|
||||
DRM_DEBUG("ch%d\n", chan->id);
|
||||
|
||||
/* Base amount for object storage (4KiB enough?) */
|
||||
size = 0x1000;
|
||||
|
|
@ -876,8 +936,8 @@ nouveau_gpuobj_channel_init_pramin(struct drm_device *dev, int channel)
|
|||
}
|
||||
|
||||
DRM_DEBUG("ch%d PRAMIN size: 0x%08x bytes, base alloc=0x%08x\n",
|
||||
channel, size, base);
|
||||
ret = nouveau_gpuobj_new_ref(dev, -1, -1, 0, size, 0x1000, 0,
|
||||
chan->id, size, base);
|
||||
ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, size, 0x1000, 0,
|
||||
&chan->ramin);
|
||||
if (ret) {
|
||||
DRM_ERROR("Error allocating channel PRAMIN: %d\n", ret);
|
||||
|
|
@ -897,21 +957,23 @@ nouveau_gpuobj_channel_init_pramin(struct drm_device *dev, int channel)
|
|||
}
|
||||
|
||||
int
|
||||
nouveau_gpuobj_channel_init(struct drm_device *dev, int channel,
|
||||
nouveau_gpuobj_channel_init(struct nouveau_channel *chan,
|
||||
uint32_t vram_h, uint32_t tt_h)
|
||||
{
|
||||
struct drm_device *dev = chan->dev;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_fifo *chan = dev_priv->fifos[channel];
|
||||
struct nouveau_gpuobj *vram = NULL, *tt = NULL;
|
||||
int ret, i;
|
||||
|
||||
DRM_DEBUG("ch%d vram=0x%08x tt=0x%08x\n", channel, vram_h, tt_h);
|
||||
INIT_LIST_HEAD(&chan->ramht_refs);
|
||||
|
||||
DRM_DEBUG("ch%d vram=0x%08x tt=0x%08x\n", chan->id, vram_h, tt_h);
|
||||
|
||||
/* Reserve a block of PRAMIN for the channel
|
||||
*XXX: maybe on <NV50 too at some point
|
||||
*/
|
||||
if (0 || dev_priv->card_type == NV_50) {
|
||||
ret = nouveau_gpuobj_channel_init_pramin(dev, channel);
|
||||
ret = nouveau_gpuobj_channel_init_pramin(chan);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -922,7 +984,7 @@ nouveau_gpuobj_channel_init(struct drm_device *dev, int channel,
|
|||
|
||||
vm_offset = (dev_priv->chipset & 0xf0) == 0x50 ? 0x1400 : 0x200;
|
||||
vm_offset += chan->ramin->gpuobj->im_pramin->start;
|
||||
if ((ret = nouveau_gpuobj_new_fake(dev, vm_offset, 0x4000,
|
||||
if ((ret = nouveau_gpuobj_new_fake(dev, vm_offset, ~0, 0x4000,
|
||||
0, &chan->vm_pd, NULL)))
|
||||
return ret;
|
||||
for (i=0; i<0x4000; i+=8) {
|
||||
|
|
@ -930,7 +992,7 @@ nouveau_gpuobj_channel_init(struct drm_device *dev, int channel,
|
|||
INSTANCE_WR(chan->vm_pd, (i+4)/4, 0xdeadcafe);
|
||||
}
|
||||
|
||||
if ((ret = nouveau_gpuobj_ref_add(dev, -1, 0,
|
||||
if ((ret = nouveau_gpuobj_ref_add(dev, NULL, 0,
|
||||
dev_priv->gart_info.sg_ctxdma,
|
||||
&chan->vm_gart_pt)))
|
||||
return ret;
|
||||
|
|
@ -941,12 +1003,12 @@ nouveau_gpuobj_channel_init(struct drm_device *dev, int channel,
|
|||
|
||||
/* RAMHT */
|
||||
if (dev_priv->card_type < NV_50) {
|
||||
ret = nouveau_gpuobj_ref_add(dev, -1, 0, dev_priv->ramht,
|
||||
ret = nouveau_gpuobj_ref_add(dev, NULL, 0, dev_priv->ramht,
|
||||
&chan->ramht);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else {
|
||||
ret = nouveau_gpuobj_new_ref(dev, channel, channel, 0,
|
||||
ret = nouveau_gpuobj_new_ref(dev, chan, chan, 0,
|
||||
0x8000, 16,
|
||||
NVOBJ_FLAG_ZERO_ALLOC,
|
||||
&chan->ramht);
|
||||
|
|
@ -955,7 +1017,7 @@ nouveau_gpuobj_channel_init(struct drm_device *dev, int channel,
|
|||
}
|
||||
|
||||
/* VRAM ctxdma */
|
||||
if ((ret = nouveau_gpuobj_dma_new(dev, channel, NV_CLASS_DMA_IN_MEMORY,
|
||||
if ((ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY,
|
||||
0, dev_priv->fb_available_size,
|
||||
NV_DMA_ACCESS_RW,
|
||||
NV_DMA_TARGET_VIDMEM, &vram))) {
|
||||
|
|
@ -963,20 +1025,19 @@ nouveau_gpuobj_channel_init(struct drm_device *dev, int channel,
|
|||
return ret;
|
||||
}
|
||||
|
||||
if ((ret = nouveau_gpuobj_ref_add(dev, channel, vram_h, vram, NULL))) {
|
||||
if ((ret = nouveau_gpuobj_ref_add(dev, chan, vram_h, vram, NULL))) {
|
||||
DRM_ERROR("Error referencing VRAM ctxdma: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* TT memory ctxdma */
|
||||
if (dev_priv->gart_info.type != NOUVEAU_GART_NONE) {
|
||||
ret = nouveau_gpuobj_gart_dma_new(dev, channel, 0,
|
||||
ret = nouveau_gpuobj_gart_dma_new(chan, 0,
|
||||
dev_priv->gart_info.aper_size,
|
||||
NV_DMA_ACCESS_RW, &tt, NULL);
|
||||
} else
|
||||
if (dev_priv->pci_heap) {
|
||||
ret = nouveau_gpuobj_dma_new(dev, channel,
|
||||
NV_CLASS_DMA_IN_MEMORY,
|
||||
ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY,
|
||||
0, dev->sg->pages * PAGE_SIZE,
|
||||
NV_DMA_ACCESS_RW,
|
||||
NV_DMA_TARGET_PCI_NONLINEAR, &tt);
|
||||
|
|
@ -990,7 +1051,7 @@ nouveau_gpuobj_channel_init(struct drm_device *dev, int channel,
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = nouveau_gpuobj_ref_add(dev, channel, tt_h, tt, NULL);
|
||||
ret = nouveau_gpuobj_ref_add(dev, chan, tt_h, tt, NULL);
|
||||
if (ret) {
|
||||
DRM_ERROR("Error referencing TT ctxdma: %d\n", ret);
|
||||
return ret;
|
||||
|
|
@ -1000,18 +1061,20 @@ nouveau_gpuobj_channel_init(struct drm_device *dev, int channel,
|
|||
}
|
||||
|
||||
void
|
||||
nouveau_gpuobj_channel_takedown(struct drm_device *dev, int channel)
|
||||
nouveau_gpuobj_channel_takedown(struct nouveau_channel *chan)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_fifo *chan = dev_priv->fifos[channel];
|
||||
struct drm_device *dev = chan->dev;
|
||||
struct list_head *entry, *tmp;
|
||||
struct nouveau_gpuobj_ref *ref;
|
||||
|
||||
DRM_DEBUG("ch%d\n", channel);
|
||||
DRM_DEBUG("ch%d\n", chan->id);
|
||||
|
||||
list_for_each_safe(entry, tmp, &chan->ramht_refs) {
|
||||
ref = list_entry(entry, struct nouveau_gpuobj_ref, list);
|
||||
|
||||
while ((ref = chan->ramht_refs)) {
|
||||
chan->ramht_refs = ref->next;
|
||||
nouveau_gpuobj_ref_del(dev, &ref);
|
||||
}
|
||||
|
||||
nouveau_gpuobj_ref_del(dev, &chan->ramht);
|
||||
|
||||
nouveau_gpuobj_del(dev, &chan->vm_pd);
|
||||
|
|
@ -1024,35 +1087,33 @@ nouveau_gpuobj_channel_takedown(struct drm_device *dev, int channel)
|
|||
|
||||
}
|
||||
|
||||
int nouveau_ioctl_grobj_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
||||
int nouveau_ioctl_grobj_alloc(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct nouveau_channel *chan;
|
||||
struct drm_nouveau_grobj_alloc *init = data;
|
||||
struct nouveau_gpuobj *gr = NULL;
|
||||
int ret;
|
||||
|
||||
if (!nouveau_fifo_owner(dev, file_priv, init->channel)) {
|
||||
DRM_ERROR("pid %d doesn't own channel %d\n",
|
||||
DRM_CURRENTPID, init->channel);
|
||||
return -EINVAL;
|
||||
}
|
||||
NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
|
||||
NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(init->channel, file_priv, chan);
|
||||
|
||||
//FIXME: check args, only allow trusted objects to be created
|
||||
|
||||
if (init->handle == ~0)
|
||||
return -EINVAL;
|
||||
if (nouveau_gpuobj_ref_find(dev, init->channel, init->handle, NULL) ==
|
||||
0)
|
||||
|
||||
if (nouveau_gpuobj_ref_find(chan, init->handle, NULL) == 0)
|
||||
return -EEXIST;
|
||||
|
||||
ret = nouveau_gpuobj_gr_new(dev, init->channel, init->class, &gr);
|
||||
ret = nouveau_gpuobj_gr_new(chan, init->class, &gr);
|
||||
if (ret) {
|
||||
DRM_ERROR("Error creating gr object: %d (%d/0x%08x)\n",
|
||||
ret, init->channel, init->handle);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((ret = nouveau_gpuobj_ref_add(dev, init->channel, init->handle,
|
||||
gr, NULL))) {
|
||||
if ((ret = nouveau_gpuobj_ref_add(dev, chan, init->handle, gr, NULL))) {
|
||||
DRM_ERROR("Error referencing gr object: %d (%d/0x%08x\n)",
|
||||
ret, init->channel, init->handle);
|
||||
nouveau_gpuobj_del(dev, &gr);
|
||||
|
|
@ -1062,3 +1123,21 @@ int nouveau_ioctl_grobj_alloc(struct drm_device *dev, void *data, struct drm_fil
|
|||
return 0;
|
||||
}
|
||||
|
||||
int nouveau_ioctl_gpuobj_free(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_nouveau_gpuobj_free *objfree = data;
|
||||
struct nouveau_gpuobj_ref *ref;
|
||||
struct nouveau_channel *chan;
|
||||
int ret;
|
||||
|
||||
NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
|
||||
NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(objfree->channel, file_priv, chan);
|
||||
|
||||
if ((ret = nouveau_gpuobj_ref_find(chan, objfree->handle, &ref)))
|
||||
return ret;
|
||||
nouveau_gpuobj_ref_del(dev, &ref);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -80,6 +80,16 @@
|
|||
#define NV40_PMC_1708 0x00001708
|
||||
#define NV40_PMC_170C 0x0000170C
|
||||
|
||||
/* probably PMC ? */
|
||||
#define NV50_PUNK_BAR0_PRAMIN 0x00001700
|
||||
#define NV50_PUNK_BAR_CFG_BASE 0x00001704
|
||||
#define NV50_PUNK_BAR_CFG_BASE_VALID (1<<30)
|
||||
#define NV50_PUNK_BAR1_CTXDMA 0x00001708
|
||||
#define NV50_PUNK_BAR1_CTXDMA_VALID (1<<31)
|
||||
#define NV50_PUNK_BAR3_CTXDMA 0x0000170C
|
||||
#define NV50_PUNK_BAR3_CTXDMA_VALID (1<<31)
|
||||
#define NV50_PUNK_UNK1710 0x00001710
|
||||
|
||||
#define NV04_PTIMER_INTR_0 0x00009100
|
||||
#define NV04_PTIMER_INTR_EN_0 0x00009140
|
||||
#define NV04_PTIMER_NUMERATOR 0x00009200
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ static uint64_t nouveau_stub_timer_read(struct drm_device *dev) { return 0; }
|
|||
static int nouveau_init_engine_ptrs(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_engine_func *engine = &dev_priv->Engine;
|
||||
struct nouveau_engine *engine = &dev_priv->Engine;
|
||||
|
||||
switch (dev_priv->chipset & 0xf0) {
|
||||
case 0x00:
|
||||
|
|
@ -224,7 +224,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
|
|||
engine->graph.destroy_context = nv40_graph_destroy_context;
|
||||
engine->graph.load_context = nv40_graph_load_context;
|
||||
engine->graph.save_context = nv40_graph_save_context;
|
||||
engine->fifo.init = nouveau_fifo_init;
|
||||
engine->fifo.init = nv40_fifo_init;
|
||||
engine->fifo.takedown = nouveau_stub_takedown;
|
||||
engine->fifo.create_context = nv40_fifo_create_context;
|
||||
engine->fifo.destroy_context = nv40_fifo_destroy_context;
|
||||
|
|
@ -267,12 +267,18 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int nouveau_card_init(struct drm_device *dev)
|
||||
int
|
||||
nouveau_card_init(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_engine_func *engine;
|
||||
struct nouveau_engine *engine;
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG("prev state = %d\n", dev_priv->init_state);
|
||||
|
||||
if (dev_priv->init_state == NOUVEAU_CARD_INIT_DONE)
|
||||
return 0;
|
||||
|
||||
/* Map any PCI resources we need on the card */
|
||||
ret = nouveau_init_card_mappings(dev);
|
||||
if (ret) return ret;
|
||||
|
|
@ -290,6 +296,9 @@ static int nouveau_card_init(struct drm_device *dev)
|
|||
engine = &dev_priv->Engine;
|
||||
dev_priv->init_state = NOUVEAU_CARD_INIT_FAILED;
|
||||
|
||||
ret = nouveau_gpuobj_early_init(dev);
|
||||
if (ret) return ret;
|
||||
|
||||
/* Initialise instance memory, must happen before mem_init so we
|
||||
* know exactly how much VRAM we're able to use for "normal"
|
||||
* purposes.
|
||||
|
|
@ -301,6 +310,9 @@ static int nouveau_card_init(struct drm_device *dev)
|
|||
ret = nouveau_mem_init(dev);
|
||||
if (ret) return ret;
|
||||
|
||||
ret = nouveau_gpuobj_init(dev);
|
||||
if (ret) return ret;
|
||||
|
||||
/* Parse BIOS tables / Run init tables? */
|
||||
|
||||
/* PMC */
|
||||
|
|
@ -323,8 +335,17 @@ static int nouveau_card_init(struct drm_device *dev)
|
|||
ret = engine->fifo.init(dev);
|
||||
if (ret) return ret;
|
||||
|
||||
/* this call irq_preinstall, register irq handler and
|
||||
* call irq_postinstall
|
||||
*/
|
||||
ret = drm_irq_install(dev);
|
||||
if (ret) return ret;
|
||||
|
||||
/* what about PVIDEO/PCRTC/PRAMDAC etc? */
|
||||
|
||||
ret = nouveau_dma_channel_init(dev);
|
||||
if (ret) return ret;
|
||||
|
||||
dev_priv->init_state = NOUVEAU_CARD_INIT_DONE;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -332,9 +353,13 @@ static int nouveau_card_init(struct drm_device *dev)
|
|||
static void nouveau_card_takedown(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_engine_func *engine = &dev_priv->Engine;
|
||||
struct nouveau_engine *engine = &dev_priv->Engine;
|
||||
|
||||
DRM_DEBUG("prev state = %d\n", dev_priv->init_state);
|
||||
|
||||
if (dev_priv->init_state != NOUVEAU_CARD_INIT_DOWN) {
|
||||
nouveau_dma_channel_takedown(dev);
|
||||
|
||||
engine->fifo.takedown(dev);
|
||||
engine->graph.takedown(dev);
|
||||
engine->fb.takedown(dev);
|
||||
|
|
@ -349,6 +374,10 @@ static void nouveau_card_takedown(struct drm_device *dev)
|
|||
nouveau_mem_close(dev);
|
||||
engine->instmem.takedown(dev);
|
||||
|
||||
drm_irq_uninstall(dev);
|
||||
|
||||
nouveau_gpuobj_late_takedown(dev);
|
||||
|
||||
dev_priv->init_state = NOUVEAU_CARD_INIT_DOWN;
|
||||
}
|
||||
}
|
||||
|
|
@ -368,14 +397,6 @@ void nouveau_preclose(struct drm_device *dev, struct drm_file *file_priv)
|
|||
/* first module load, setup the mmio/fb mapping */
|
||||
int nouveau_firstopen(struct drm_device *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = nouveau_card_init(dev);
|
||||
if (ret) {
|
||||
DRM_ERROR("nouveau_card_init() failed! (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -395,15 +416,6 @@ int nouveau_load(struct drm_device *dev, unsigned long flags)
|
|||
dev_priv->init_state = NOUVEAU_CARD_INIT_DOWN;
|
||||
|
||||
dev->dev_private = (void *)dev_priv;
|
||||
|
||||
#if 0
|
||||
ret = nouveau_card_init(dev);
|
||||
if (ret) {
|
||||
DRM_ERROR("nouveau_card_init() failed! (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -427,12 +439,24 @@ int nouveau_unload(struct drm_device *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
nouveau_ioctl_card_init(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
return nouveau_card_init(dev);
|
||||
}
|
||||
|
||||
int nouveau_ioctl_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct drm_nouveau_getparam *getparam = data;
|
||||
|
||||
NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
|
||||
|
||||
switch (getparam->param) {
|
||||
case NOUVEAU_GETPARAM_CHIPSET_ID:
|
||||
getparam->value = dev_priv->chipset;
|
||||
break;
|
||||
case NOUVEAU_GETPARAM_PCI_VENDOR:
|
||||
getparam->value=dev->pci_vendor;
|
||||
break;
|
||||
|
|
@ -481,6 +505,8 @@ int nouveau_ioctl_setparam(struct drm_device *dev, void *data, struct drm_file *
|
|||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct drm_nouveau_setparam *setparam = data;
|
||||
|
||||
NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
|
||||
|
||||
switch (setparam->param) {
|
||||
case NOUVEAU_SETPARAM_CMDBUF_LOCATION:
|
||||
switch (setparam->value) {
|
||||
|
|
@ -526,6 +552,7 @@ void nouveau_wait_for_idle(struct drm_device *dev)
|
|||
uint32_t status;
|
||||
do {
|
||||
uint32_t pmc_e = NV_READ(NV03_PMC_ENABLE);
|
||||
(void)pmc_e;
|
||||
status = NV_READ(NV04_PGRAPH_STATUS);
|
||||
if (!status)
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -36,13 +36,13 @@
|
|||
#define NV04_RAMFC__SIZE 32
|
||||
|
||||
int
|
||||
nv04_fifo_create_context(struct drm_device *dev, int channel)
|
||||
nv04_fifo_create_context(struct nouveau_channel *chan)
|
||||
{
|
||||
struct drm_device *dev = chan->dev;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_fifo *chan = dev_priv->fifos[channel];
|
||||
int ret;
|
||||
|
||||
if ((ret = nouveau_gpuobj_new_fake(dev, NV04_RAMFC(channel),
|
||||
if ((ret = nouveau_gpuobj_new_fake(dev, NV04_RAMFC(chan->id), ~0,
|
||||
NV04_RAMFC__SIZE,
|
||||
NVOBJ_FLAG_ZERO_ALLOC |
|
||||
NVOBJ_FLAG_ZERO_FREE,
|
||||
|
|
@ -62,30 +62,29 @@ nv04_fifo_create_context(struct drm_device *dev, int channel)
|
|||
0));
|
||||
|
||||
/* enable the fifo dma operation */
|
||||
NV_WRITE(NV04_PFIFO_MODE,NV_READ(NV04_PFIFO_MODE)|(1<<channel));
|
||||
NV_WRITE(NV04_PFIFO_MODE,NV_READ(NV04_PFIFO_MODE) | (1<<chan->id));
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
nv04_fifo_destroy_context(struct drm_device *dev, int channel)
|
||||
nv04_fifo_destroy_context(struct nouveau_channel *chan)
|
||||
{
|
||||
struct drm_device *dev = chan->dev;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_fifo *chan = dev_priv->fifos[channel];
|
||||
|
||||
NV_WRITE(NV04_PFIFO_MODE, NV_READ(NV04_PFIFO_MODE)&~(1<<chan->id));
|
||||
|
||||
NV_WRITE(NV04_PFIFO_MODE, NV_READ(NV04_PFIFO_MODE)&~(1<<channel));
|
||||
|
||||
if (chan->ramfc)
|
||||
nouveau_gpuobj_ref_del(dev, &chan->ramfc);
|
||||
nouveau_gpuobj_ref_del(dev, &chan->ramfc);
|
||||
}
|
||||
|
||||
int
|
||||
nv04_fifo_load_context(struct drm_device *dev, int channel)
|
||||
nv04_fifo_load_context(struct nouveau_channel *chan)
|
||||
{
|
||||
struct drm_device *dev = chan->dev;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_fifo *chan = dev_priv->fifos[channel];
|
||||
uint32_t tmp;
|
||||
|
||||
NV_WRITE(NV03_PFIFO_CACHE1_PUSH1, (1<<8) | channel);
|
||||
NV_WRITE(NV03_PFIFO_CACHE1_PUSH1, (1<<8) | chan->id);
|
||||
|
||||
NV_WRITE(NV04_PFIFO_CACHE1_DMA_GET, RAMFC_RD(DMA_GET));
|
||||
NV_WRITE(NV04_PFIFO_CACHE1_DMA_PUT, RAMFC_RD(DMA_PUT));
|
||||
|
|
@ -107,10 +106,10 @@ nv04_fifo_load_context(struct drm_device *dev, int channel)
|
|||
}
|
||||
|
||||
int
|
||||
nv04_fifo_save_context(struct drm_device *dev, int channel)
|
||||
nv04_fifo_save_context(struct nouveau_channel *chan)
|
||||
{
|
||||
struct drm_device *dev = chan->dev;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_fifo *chan = dev_priv->fifos[channel];
|
||||
uint32_t tmp;
|
||||
|
||||
RAMFC_WR(DMA_PUT, NV04_PFIFO_CACHE1_DMA_PUT);
|
||||
|
|
|
|||
|
|
@ -336,14 +336,13 @@ void nouveau_nv04_context_switch(struct drm_device *dev)
|
|||
NV_WRITE(NV04_PGRAPH_FIFO,0x1);
|
||||
}
|
||||
|
||||
int nv04_graph_create_context(struct drm_device *dev, int channel) {
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
DRM_DEBUG("nv04_graph_context_create %d\n", channel);
|
||||
int nv04_graph_create_context(struct nouveau_channel *chan) {
|
||||
DRM_DEBUG("nv04_graph_context_create %d\n", chan->id);
|
||||
|
||||
memset(dev_priv->fifos[channel]->pgraph_ctx, 0, sizeof(dev_priv->fifos[channel]->pgraph_ctx));
|
||||
memset(chan->pgraph_ctx, 0, sizeof(chan->pgraph_ctx));
|
||||
|
||||
//dev_priv->fifos[channel].pgraph_ctx_user = channel << 24;
|
||||
dev_priv->fifos[channel]->pgraph_ctx[0] = 0x0001ffff;
|
||||
chan->pgraph_ctx[0] = 0x0001ffff;
|
||||
/* is it really needed ??? */
|
||||
//dev_priv->fifos[channel].pgraph_ctx[1] = NV_READ(NV_PGRAPH_DEBUG_4);
|
||||
//dev_priv->fifos[channel].pgraph_ctx[2] = NV_READ(0x004006b0);
|
||||
|
|
@ -351,17 +350,17 @@ int nv04_graph_create_context(struct drm_device *dev, int channel) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
void nv04_graph_destroy_context(struct drm_device *dev, int channel)
|
||||
void nv04_graph_destroy_context(struct nouveau_channel *chan)
|
||||
{
|
||||
}
|
||||
|
||||
int nv04_graph_load_context(struct drm_device *dev, int channel)
|
||||
int nv04_graph_load_context(struct nouveau_channel *chan)
|
||||
{
|
||||
DRM_ERROR("stub!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nv04_graph_save_context(struct drm_device *dev, int channel)
|
||||
int nv04_graph_save_context(struct nouveau_channel *chan)
|
||||
{
|
||||
DRM_ERROR("stub!\n");
|
||||
return 0;
|
||||
|
|
@ -376,6 +375,10 @@ int nv04_graph_init(struct drm_device *dev) {
|
|||
NV_WRITE(NV03_PMC_ENABLE, NV_READ(NV03_PMC_ENABLE) |
|
||||
NV_PMC_ENABLE_PGRAPH);
|
||||
|
||||
/* Enable PGRAPH interrupts */
|
||||
NV_WRITE(NV03_PGRAPH_INTR, 0xFFFFFFFF);
|
||||
NV_WRITE(NV03_PGRAPH_INTR_EN, 0xFFFFFFFF);
|
||||
|
||||
// check the context is big enough
|
||||
for ( i = 0 ; i<sizeof(nv04_graph_ctx_regs)/sizeof(nv04_graph_ctx_regs[0]); i++)
|
||||
sum+=nv04_graph_ctx_regs[i].number;
|
||||
|
|
|
|||
|
|
@ -93,13 +93,6 @@ int nv04_instmem_init(struct drm_device *dev)
|
|||
nv04_instmem_determine_amount(dev);
|
||||
nv04_instmem_configure_fixed_tables(dev);
|
||||
|
||||
if ((ret = nouveau_gpuobj_new_fake(dev, dev_priv->ramht_offset,
|
||||
dev_priv->ramht_size,
|
||||
NVOBJ_FLAG_ZERO_ALLOC |
|
||||
NVOBJ_FLAG_ALLOW_NO_REFS,
|
||||
&dev_priv->ramht, NULL)))
|
||||
return ret;
|
||||
|
||||
/* Create a heap to manage RAMIN allocations, we don't allocate
|
||||
* the space that was reserved for RAMHT/FC/RO.
|
||||
*/
|
||||
|
|
@ -117,9 +110,6 @@ int nv04_instmem_init(struct drm_device *dev)
|
|||
void
|
||||
nv04_instmem_takedown(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
|
||||
nouveau_gpuobj_del(dev, &dev_priv->ramht);
|
||||
}
|
||||
|
||||
int
|
||||
|
|
@ -139,7 +129,6 @@ nv04_instmem_clear(struct drm_device *dev, struct nouveau_gpuobj *gpuobj)
|
|||
if (gpuobj && gpuobj->im_backing) {
|
||||
if (gpuobj->im_bound)
|
||||
dev_priv->Engine.instmem.unbind(dev, gpuobj);
|
||||
nouveau_mem_free(dev, gpuobj->im_backing);
|
||||
gpuobj->im_backing = NULL;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,8 +13,6 @@ nv04_mc_init(struct drm_device *dev)
|
|||
*/
|
||||
NV_WRITE(NV03_PMC_ENABLE, 0xFFFFFFFF);
|
||||
|
||||
NV_WRITE(NV03_PMC_INTR_EN_0, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,17 +33,17 @@
|
|||
NV10_RAMFC_##offset/4, (val))
|
||||
#define RAMFC_RD(offset) INSTANCE_RD(chan->ramfc->gpuobj, \
|
||||
NV10_RAMFC_##offset/4)
|
||||
#define NV10_RAMFC(c) (dev_priv->ramfc_offset + NV10_RAMFC__SIZE)
|
||||
#define NV10_RAMFC(c) (dev_priv->ramfc_offset + ((c) * NV10_RAMFC__SIZE))
|
||||
#define NV10_RAMFC__SIZE ((dev_priv->chipset) >= 0x17 ? 64 : 32)
|
||||
|
||||
int
|
||||
nv10_fifo_create_context(struct drm_device *dev, int channel)
|
||||
nv10_fifo_create_context(struct nouveau_channel *chan)
|
||||
{
|
||||
struct drm_device *dev = chan->dev;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_fifo *chan = dev_priv->fifos[channel];
|
||||
int ret;
|
||||
|
||||
if ((ret = nouveau_gpuobj_new_fake(dev, NV10_RAMFC(channel),
|
||||
if ((ret = nouveau_gpuobj_new_fake(dev, NV10_RAMFC(chan->id), ~0,
|
||||
NV10_RAMFC__SIZE,
|
||||
NVOBJ_FLAG_ZERO_ALLOC |
|
||||
NVOBJ_FLAG_ZERO_FREE,
|
||||
|
|
@ -65,30 +65,29 @@ nv10_fifo_create_context(struct drm_device *dev, int channel)
|
|||
0);
|
||||
|
||||
/* enable the fifo dma operation */
|
||||
NV_WRITE(NV04_PFIFO_MODE,NV_READ(NV04_PFIFO_MODE)|(1<<channel));
|
||||
NV_WRITE(NV04_PFIFO_MODE,NV_READ(NV04_PFIFO_MODE)|(1<<chan->id));
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
nv10_fifo_destroy_context(struct drm_device *dev, int channel)
|
||||
nv10_fifo_destroy_context(struct nouveau_channel *chan)
|
||||
{
|
||||
struct drm_device *dev = chan->dev;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_fifo *chan = dev_priv->fifos[channel];
|
||||
|
||||
NV_WRITE(NV04_PFIFO_MODE, NV_READ(NV04_PFIFO_MODE)&~(1<<channel));
|
||||
NV_WRITE(NV04_PFIFO_MODE, NV_READ(NV04_PFIFO_MODE)&~(1<<chan->id));
|
||||
|
||||
if (chan->ramfc)
|
||||
nouveau_gpuobj_ref_del(dev, &chan->ramfc);
|
||||
nouveau_gpuobj_ref_del(dev, &chan->ramfc);
|
||||
}
|
||||
|
||||
int
|
||||
nv10_fifo_load_context(struct drm_device *dev, int channel)
|
||||
nv10_fifo_load_context(struct nouveau_channel *chan)
|
||||
{
|
||||
struct drm_device *dev = chan->dev;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_fifo *chan = dev_priv->fifos[channel];
|
||||
uint32_t tmp;
|
||||
|
||||
NV_WRITE(NV03_PFIFO_CACHE1_PUSH1 , 0x00000100 | channel);
|
||||
NV_WRITE(NV03_PFIFO_CACHE1_PUSH1 , 0x00000100 | chan->id);
|
||||
|
||||
NV_WRITE(NV04_PFIFO_CACHE1_DMA_GET , RAMFC_RD(DMA_GET));
|
||||
NV_WRITE(NV04_PFIFO_CACHE1_DMA_PUT , RAMFC_RD(DMA_PUT));
|
||||
|
|
@ -124,10 +123,10 @@ nv10_fifo_load_context(struct drm_device *dev, int channel)
|
|||
}
|
||||
|
||||
int
|
||||
nv10_fifo_save_context(struct drm_device *dev, int channel)
|
||||
nv10_fifo_save_context(struct nouveau_channel *chan)
|
||||
{
|
||||
struct drm_device *dev = chan->dev;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_fifo *chan = dev_priv->fifos[channel];
|
||||
uint32_t tmp;
|
||||
|
||||
RAMFC_WR(DMA_PUT , NV_READ(NV04_PFIFO_CACHE1_DMA_PUT));
|
||||
|
|
|
|||
|
|
@ -544,29 +544,52 @@ static int nv10_graph_ctx_regs_find_offset(struct drm_device *dev, int reg)
|
|||
return -1;
|
||||
}
|
||||
|
||||
static void restore_ctx_regs(struct drm_device *dev, int channel)
|
||||
int nv10_graph_load_context(struct nouveau_channel *chan)
|
||||
{
|
||||
struct drm_device *dev = chan->dev;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_fifo *fifo = dev_priv->fifos[channel];
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < sizeof(nv10_graph_ctx_regs)/sizeof(nv10_graph_ctx_regs[0]); i++)
|
||||
NV_WRITE(nv10_graph_ctx_regs[i], fifo->pgraph_ctx[i]);
|
||||
NV_WRITE(nv10_graph_ctx_regs[i], chan->pgraph_ctx[i]);
|
||||
if (dev_priv->chipset>=0x17) {
|
||||
for (j = 0; j < sizeof(nv17_graph_ctx_regs)/sizeof(nv17_graph_ctx_regs[0]); i++,j++)
|
||||
NV_WRITE(nv17_graph_ctx_regs[j], fifo->pgraph_ctx[i]);
|
||||
NV_WRITE(nv17_graph_ctx_regs[j], chan->pgraph_ctx[i]);
|
||||
}
|
||||
nouveau_wait_for_idle(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nv10_graph_save_context(struct nouveau_channel *chan)
|
||||
{
|
||||
struct drm_device *dev = chan->dev;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < sizeof(nv10_graph_ctx_regs)/sizeof(nv10_graph_ctx_regs[0]); i++)
|
||||
chan->pgraph_ctx[i] = NV_READ(nv10_graph_ctx_regs[i]);
|
||||
if (dev_priv->chipset>=0x17) {
|
||||
for (j = 0; j < sizeof(nv17_graph_ctx_regs)/sizeof(nv17_graph_ctx_regs[0]); i++,j++)
|
||||
chan->pgraph_ctx[i] = NV_READ(nv17_graph_ctx_regs[j]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nouveau_nv10_context_switch(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
int channel, channel_old, i, j;
|
||||
struct nouveau_channel *next, *last;
|
||||
int chid;
|
||||
|
||||
channel=NV_READ(NV03_PFIFO_CACHE1_PUSH1)&(nouveau_fifo_number(dev)-1);
|
||||
channel_old = (NV_READ(NV10_PGRAPH_CTX_USER) >> 24) & (nouveau_fifo_number(dev)-1);
|
||||
chid = NV_READ(NV03_PFIFO_CACHE1_PUSH1)&(nouveau_fifo_number(dev)-1);
|
||||
next = dev_priv->fifos[chid];
|
||||
|
||||
DRM_INFO("NV: PGRAPH context switch interrupt channel %x -> %x\n",channel_old, channel);
|
||||
chid = (NV_READ(NV10_PGRAPH_CTX_USER) >> 24) & (nouveau_fifo_number(dev)-1);
|
||||
last = dev_priv->fifos[chid];
|
||||
|
||||
DRM_INFO("NV: PGRAPH context switch interrupt channel %x -> %x\n",
|
||||
last->id, next->id);
|
||||
|
||||
NV_WRITE(NV04_PGRAPH_FIFO,0x0);
|
||||
#if 0
|
||||
|
|
@ -574,14 +597,7 @@ void nouveau_nv10_context_switch(struct drm_device *dev)
|
|||
NV_WRITE(NV_PFIFO_CACH1_PUL1, 0x00000000);
|
||||
NV_WRITE(NV_PFIFO_CACHES, 0x00000000);
|
||||
#endif
|
||||
|
||||
// save PGRAPH context
|
||||
for (i = 0; i < sizeof(nv10_graph_ctx_regs)/sizeof(nv10_graph_ctx_regs[0]); i++)
|
||||
dev_priv->fifos[channel_old]->pgraph_ctx[i] = NV_READ(nv10_graph_ctx_regs[i]);
|
||||
if (dev_priv->chipset>=0x17) {
|
||||
for (j = 0; j < sizeof(nv17_graph_ctx_regs)/sizeof(nv17_graph_ctx_regs[0]); i++,j++)
|
||||
dev_priv->fifos[channel_old]->pgraph_ctx[i] = NV_READ(nv17_graph_ctx_regs[j]);
|
||||
}
|
||||
nv10_graph_save_context(last);
|
||||
|
||||
nouveau_wait_for_idle(dev);
|
||||
|
||||
|
|
@ -589,15 +605,12 @@ void nouveau_nv10_context_switch(struct drm_device *dev)
|
|||
NV_WRITE(NV10_PGRAPH_CTX_USER, (NV_READ(NV10_PGRAPH_CTX_USER) & 0xffffff) | (0x1f << 24));
|
||||
|
||||
nouveau_wait_for_idle(dev);
|
||||
// restore PGRAPH context
|
||||
#if 1
|
||||
restore_ctx_regs(dev, channel);
|
||||
#endif
|
||||
|
||||
nv10_graph_load_context(next);
|
||||
|
||||
NV_WRITE(NV10_PGRAPH_CTX_CONTROL, 0x10010100);
|
||||
NV_WRITE(NV10_PGRAPH_CTX_USER, channel << 24);
|
||||
NV_WRITE(NV10_PGRAPH_CTX_USER, next->id << 24);
|
||||
NV_WRITE(NV10_PGRAPH_FFINTFC_ST2, NV_READ(NV10_PGRAPH_FFINTFC_ST2)&0xCFFFFFFF);
|
||||
|
||||
#if 0
|
||||
NV_WRITE(NV_PFIFO_CACH1_PUL0, 0x00000001);
|
||||
NV_WRITE(NV_PFIFO_CACH1_PUL1, 0x00000001);
|
||||
|
|
@ -609,16 +622,17 @@ void nouveau_nv10_context_switch(struct drm_device *dev)
|
|||
#define NV_WRITE_CTX(reg, val) do { \
|
||||
int offset = nv10_graph_ctx_regs_find_offset(dev, reg); \
|
||||
if (offset > 0) \
|
||||
fifo->pgraph_ctx[offset] = val; \
|
||||
chan->pgraph_ctx[offset] = val; \
|
||||
} while (0)
|
||||
int nv10_graph_create_context(struct drm_device *dev, int channel) {
|
||||
|
||||
int nv10_graph_create_context(struct nouveau_channel *chan) {
|
||||
struct drm_device *dev = chan->dev;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_fifo *fifo = dev_priv->fifos[channel];
|
||||
uint32_t tmp, vramsz;
|
||||
|
||||
DRM_DEBUG("nv10_graph_context_create %d\n", channel);
|
||||
DRM_DEBUG("nv10_graph_context_create %d\n", chan->id);
|
||||
|
||||
memset(fifo->pgraph_ctx, 0, sizeof(fifo->pgraph_ctx));
|
||||
memset(chan->pgraph_ctx, 0, sizeof(chan->pgraph_ctx));
|
||||
|
||||
/* per channel init from ddx */
|
||||
tmp = NV_READ(NV10_PGRAPH_SURFACE) & 0x0007ff00;
|
||||
|
|
@ -654,7 +668,7 @@ int nv10_graph_create_context(struct drm_device *dev, int channel) {
|
|||
|
||||
/* for the first channel init the regs */
|
||||
if (dev_priv->fifo_alloc_count == 0)
|
||||
restore_ctx_regs(dev, channel);
|
||||
nv10_graph_load_context(chan);
|
||||
|
||||
|
||||
//XXX should be saved/restored for each fifo
|
||||
|
|
@ -663,22 +677,10 @@ int nv10_graph_create_context(struct drm_device *dev, int channel) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
void nv10_graph_destroy_context(struct drm_device *dev, int channel)
|
||||
void nv10_graph_destroy_context(struct nouveau_channel *chan)
|
||||
{
|
||||
}
|
||||
|
||||
int nv10_graph_load_context(struct drm_device *dev, int channel)
|
||||
{
|
||||
DRM_ERROR("stub!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nv10_graph_save_context(struct drm_device *dev, int channel)
|
||||
{
|
||||
DRM_ERROR("stub!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nv10_graph_init(struct drm_device *dev) {
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
int i;
|
||||
|
|
@ -688,8 +690,8 @@ int nv10_graph_init(struct drm_device *dev) {
|
|||
NV_WRITE(NV03_PMC_ENABLE, NV_READ(NV03_PMC_ENABLE) |
|
||||
NV_PMC_ENABLE_PGRAPH);
|
||||
|
||||
NV_WRITE(NV03_PGRAPH_INTR_EN, 0x00000000);
|
||||
NV_WRITE(NV03_PGRAPH_INTR , 0xFFFFFFFF);
|
||||
NV_WRITE(NV03_PGRAPH_INTR_EN, 0xFFFFFFFF);
|
||||
|
||||
NV_WRITE(NV04_PGRAPH_DEBUG_0, 0xFFFFFFFF);
|
||||
NV_WRITE(NV04_PGRAPH_DEBUG_0, 0x00000000);
|
||||
|
|
|
|||
|
|
@ -29,39 +29,36 @@
|
|||
|
||||
#define NV20_GRCTX_SIZE (3529*4)
|
||||
|
||||
int nv20_graph_create_context(struct drm_device *dev, int channel) {
|
||||
struct drm_nouveau_private *dev_priv =
|
||||
(struct drm_nouveau_private *)dev->dev_private;
|
||||
struct nouveau_fifo *chan = dev_priv->fifos[channel];
|
||||
int nv20_graph_create_context(struct nouveau_channel *chan) {
|
||||
struct drm_device *dev = chan->dev;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
unsigned int ctx_size = NV20_GRCTX_SIZE;
|
||||
int ret;
|
||||
|
||||
if ((ret = nouveau_gpuobj_new_ref(dev, channel, -1, 0, ctx_size, 16,
|
||||
if ((ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, ctx_size, 16,
|
||||
NVOBJ_FLAG_ZERO_ALLOC,
|
||||
&chan->ramin_grctx)))
|
||||
return ret;
|
||||
|
||||
/* Initialise default context values */
|
||||
INSTANCE_WR(chan->ramin_grctx->gpuobj, 10, channel<<24); /* CTX_USER */
|
||||
INSTANCE_WR(chan->ramin_grctx->gpuobj, 10, chan->id<<24); /* CTX_USER */
|
||||
|
||||
INSTANCE_WR(dev_priv->ctx_table->gpuobj, channel,
|
||||
INSTANCE_WR(dev_priv->ctx_table->gpuobj, chan->id,
|
||||
chan->ramin_grctx->instance >> 4);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nv20_graph_destroy_context(struct drm_device *dev, int channel) {
|
||||
void nv20_graph_destroy_context(struct nouveau_channel *chan) {
|
||||
struct drm_device *dev = chan->dev;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_fifo *chan = dev_priv->fifos[channel];
|
||||
|
||||
if (chan->ramin_grctx)
|
||||
nouveau_gpuobj_ref_del(dev, &chan->ramin_grctx);
|
||||
nouveau_gpuobj_ref_del(dev, &chan->ramin_grctx);
|
||||
|
||||
INSTANCE_WR(dev_priv->ctx_table->gpuobj, channel, 0);
|
||||
INSTANCE_WR(dev_priv->ctx_table->gpuobj, chan->id, 0);
|
||||
}
|
||||
|
||||
static void nv20_graph_rdi(struct drm_device *dev) {
|
||||
struct drm_nouveau_private *dev_priv =
|
||||
(struct drm_nouveau_private *)dev->dev_private;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
int i;
|
||||
|
||||
NV_WRITE(NV10_PGRAPH_RDI_INDEX, 0x2c80000);
|
||||
|
|
@ -73,13 +70,12 @@ static void nv20_graph_rdi(struct drm_device *dev) {
|
|||
|
||||
/* Save current context (from PGRAPH) into the channel's context
|
||||
*/
|
||||
int nv20_graph_save_context(struct drm_device *dev, int channel) {
|
||||
struct drm_nouveau_private *dev_priv =
|
||||
(struct drm_nouveau_private *)dev->dev_private;
|
||||
struct nouveau_fifo *chan = dev_priv->fifos[channel];
|
||||
int nv20_graph_save_context(struct nouveau_channel *chan) {
|
||||
struct drm_device *dev = chan->dev;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
uint32_t instance;
|
||||
|
||||
instance = INSTANCE_RD(dev_priv->ctx_table->gpuobj, channel);
|
||||
instance = INSTANCE_RD(dev_priv->ctx_table->gpuobj, chan->id);
|
||||
if (!instance) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
@ -94,20 +90,19 @@ int nv20_graph_save_context(struct drm_device *dev, int channel) {
|
|||
|
||||
/* Restore the context for a specific channel into PGRAPH
|
||||
*/
|
||||
int nv20_graph_load_context(struct drm_device *dev, int channel) {
|
||||
struct drm_nouveau_private *dev_priv =
|
||||
(struct drm_nouveau_private *)dev->dev_private;
|
||||
struct nouveau_fifo *chan = dev_priv->fifos[channel];
|
||||
int nv20_graph_load_context(struct nouveau_channel *chan) {
|
||||
struct drm_device *dev = chan->dev;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
uint32_t instance;
|
||||
|
||||
instance = INSTANCE_RD(dev_priv->ctx_table->gpuobj, channel);
|
||||
instance = INSTANCE_RD(dev_priv->ctx_table->gpuobj, chan->id);
|
||||
if (!instance) {
|
||||
return -EINVAL;
|
||||
}
|
||||
if (instance != (chan->ramin_grctx->instance >> 4))
|
||||
DRM_ERROR("nv20_graph_load_context_current : bad instance\n");
|
||||
|
||||
NV_WRITE(NV10_PGRAPH_CTX_USER, channel << 24);
|
||||
NV_WRITE(NV10_PGRAPH_CTX_USER, chan->id << 24);
|
||||
NV_WRITE(NV10_PGRAPH_CHANNEL_CTX_SIZE, instance);
|
||||
NV_WRITE(NV10_PGRAPH_CHANNEL_CTX_POINTER, 1 /* restore ctx */);
|
||||
return 0;
|
||||
|
|
@ -116,27 +111,32 @@ int nv20_graph_load_context(struct drm_device *dev, int channel) {
|
|||
void nouveau_nv20_context_switch(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
int channel, channel_old;
|
||||
struct nouveau_channel *next, *last;
|
||||
int chid;
|
||||
|
||||
channel=NV_READ(NV03_PFIFO_CACHE1_PUSH1)&(nouveau_fifo_number(dev)-1);
|
||||
channel_old = (NV_READ(NV10_PGRAPH_CTX_USER) >> 24) & (nouveau_fifo_number(dev)-1);
|
||||
chid = NV_READ(NV03_PFIFO_CACHE1_PUSH1)&(nouveau_fifo_number(dev)-1);
|
||||
next = dev_priv->fifos[chid];
|
||||
|
||||
DRM_DEBUG("NV: PGRAPH context switch interrupt channel %x -> %x\n",channel_old, channel);
|
||||
chid = (NV_READ(NV10_PGRAPH_CTX_USER) >> 24) & (nouveau_fifo_number(dev)-1);
|
||||
last = dev_priv->fifos[chid];
|
||||
|
||||
DRM_DEBUG("NV: PGRAPH context switch interrupt channel %x -> %x\n",
|
||||
last->id, next->id);
|
||||
|
||||
NV_WRITE(NV04_PGRAPH_FIFO,0x0);
|
||||
|
||||
nv20_graph_save_context(dev, channel_old);
|
||||
nv20_graph_save_context(last);
|
||||
|
||||
nouveau_wait_for_idle(dev);
|
||||
|
||||
NV_WRITE(NV10_PGRAPH_CTX_CONTROL, 0x10000000);
|
||||
|
||||
nv20_graph_load_context(dev, channel);
|
||||
nv20_graph_load_context(next);
|
||||
|
||||
nouveau_wait_for_idle(dev);
|
||||
|
||||
if ((NV_READ(NV10_PGRAPH_CTX_USER) >> 24) != channel)
|
||||
DRM_ERROR("nouveau_nv20_context_switch : wrong channel restored %x %x!!!\n", channel, NV_READ(NV10_PGRAPH_CTX_USER) >> 24);
|
||||
if ((NV_READ(NV10_PGRAPH_CTX_USER) >> 24) != next->id)
|
||||
DRM_ERROR("nouveau_nv20_context_switch : wrong channel restored %x %x!!!\n", next->id, NV_READ(NV10_PGRAPH_CTX_USER) >> 24);
|
||||
|
||||
NV_WRITE(NV10_PGRAPH_CTX_CONTROL, 0x10010100);
|
||||
NV_WRITE(NV10_PGRAPH_FFINTFC_ST2, NV_READ(NV10_PGRAPH_FFINTFC_ST2)&0xCFFFFFFF);
|
||||
|
|
@ -157,7 +157,7 @@ int nv20_graph_init(struct drm_device *dev) {
|
|||
|
||||
/* Create Context Pointer Table */
|
||||
dev_priv->ctx_table_size = 32 * 4;
|
||||
if ((ret = nouveau_gpuobj_new_ref(dev, -1, -1, 0,
|
||||
if ((ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0,
|
||||
dev_priv->ctx_table_size, 16,
|
||||
NVOBJ_FLAG_ZERO_ALLOC,
|
||||
&dev_priv->ctx_table)))
|
||||
|
|
@ -169,8 +169,8 @@ int nv20_graph_init(struct drm_device *dev) {
|
|||
//XXX need to be done and save/restore for each fifo ???
|
||||
nv20_graph_rdi(dev);
|
||||
|
||||
NV_WRITE(NV03_PGRAPH_INTR_EN, 0x00000000);
|
||||
NV_WRITE(NV03_PGRAPH_INTR , 0xFFFFFFFF);
|
||||
NV_WRITE(NV03_PGRAPH_INTR_EN, 0xFFFFFFFF);
|
||||
|
||||
NV_WRITE(NV04_PGRAPH_DEBUG_0, 0xFFFFFFFF);
|
||||
NV_WRITE(NV04_PGRAPH_DEBUG_0, 0x00000000);
|
||||
|
|
|
|||
|
|
@ -100,11 +100,10 @@ static void nv30_graph_context_init(struct drm_device *dev, struct nouveau_gpuob
|
|||
}
|
||||
|
||||
|
||||
int nv30_graph_create_context(struct drm_device *dev, int channel)
|
||||
int nv30_graph_create_context(struct nouveau_channel *chan)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv =
|
||||
(struct drm_nouveau_private *)dev->dev_private;
|
||||
struct nouveau_fifo *chan = dev_priv->fifos[channel];
|
||||
struct drm_device *dev = chan->dev;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
void (*ctx_init)(struct drm_device *, struct nouveau_gpuobj *);
|
||||
unsigned int ctx_size;
|
||||
int ret;
|
||||
|
|
@ -116,7 +115,7 @@ int nv30_graph_create_context(struct drm_device *dev, int channel)
|
|||
break;
|
||||
}
|
||||
|
||||
if ((ret = nouveau_gpuobj_new_ref(dev, channel, -1, 0, ctx_size, 16,
|
||||
if ((ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, ctx_size, 16,
|
||||
NVOBJ_FLAG_ZERO_ALLOC,
|
||||
&chan->ramin_grctx)))
|
||||
return ret;
|
||||
|
|
@ -124,23 +123,22 @@ int nv30_graph_create_context(struct drm_device *dev, int channel)
|
|||
/* Initialise default context values */
|
||||
ctx_init(dev, chan->ramin_grctx->gpuobj);
|
||||
|
||||
INSTANCE_WR(chan->ramin_grctx->gpuobj, 10, channel<<24); /* CTX_USER */
|
||||
INSTANCE_WR(dev_priv->ctx_table->gpuobj, channel,
|
||||
INSTANCE_WR(chan->ramin_grctx->gpuobj, 10, chan->id<<24); /* CTX_USER */
|
||||
INSTANCE_WR(dev_priv->ctx_table->gpuobj, chan->id,
|
||||
chan->ramin_grctx->instance >> 4);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nv30_graph_destroy_context(struct drm_device *dev, int channel)
|
||||
void nv30_graph_destroy_context(struct nouveau_channel *chan)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv =
|
||||
(struct drm_nouveau_private *)dev->dev_private;
|
||||
struct nouveau_fifo *chan = dev_priv->fifos[channel];
|
||||
struct drm_device *dev = chan->dev;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
|
||||
if (chan->ramin_grctx)
|
||||
nouveau_gpuobj_ref_del(dev, &chan->ramin_grctx);
|
||||
|
||||
INSTANCE_WR(dev_priv->ctx_table->gpuobj, channel, 0);
|
||||
INSTANCE_WR(dev_priv->ctx_table->gpuobj, chan->id, 0);
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
@ -161,10 +159,10 @@ nouveau_graph_wait_idle(struct drm_device *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int nv30_graph_load_context(struct drm_device *dev, int channel)
|
||||
int nv30_graph_load_context(struct nouveau_channel *chan)
|
||||
{
|
||||
struct drm_device *dev = chan->dev;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_fifo *chan = dev_priv->fifos[channel];
|
||||
uint32_t inst;
|
||||
|
||||
if (!chan->ramin_grctx)
|
||||
|
|
@ -178,10 +176,10 @@ int nv30_graph_load_context(struct drm_device *dev, int channel)
|
|||
return nouveau_graph_wait_idle(dev);
|
||||
}
|
||||
|
||||
int nv30_graph_save_context(struct drm_device *dev, int channel)
|
||||
int nv30_graph_save_context(struct nouveau_channel *chan)
|
||||
{
|
||||
struct drm_device *dev = chan->dev;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_fifo *chan = dev_priv->fifos[channel];
|
||||
uint32_t inst;
|
||||
|
||||
if (!chan->ramin_grctx)
|
||||
|
|
@ -197,8 +195,7 @@ int nv30_graph_save_context(struct drm_device *dev, int channel)
|
|||
|
||||
int nv30_graph_init(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv =
|
||||
(struct drm_nouveau_private *)dev->dev_private;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
uint32_t vramsz, tmp;
|
||||
int ret, i;
|
||||
|
||||
|
|
@ -209,7 +206,7 @@ int nv30_graph_init(struct drm_device *dev)
|
|||
|
||||
/* Create Context Pointer Table */
|
||||
dev_priv->ctx_table_size = 32 * 4;
|
||||
if ((ret = nouveau_gpuobj_new_ref(dev, -1, -1, 0,
|
||||
if ((ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0,
|
||||
dev_priv->ctx_table_size, 16,
|
||||
NVOBJ_FLAG_ZERO_ALLOC,
|
||||
&dev_priv->ctx_table)))
|
||||
|
|
@ -218,8 +215,8 @@ int nv30_graph_init(struct drm_device *dev)
|
|||
NV_WRITE(NV10_PGRAPH_CHANNEL_CTX_TABLE,
|
||||
dev_priv->ctx_table->instance >> 4);
|
||||
|
||||
NV_WRITE(NV03_PGRAPH_INTR_EN, 0x00000000);
|
||||
NV_WRITE(NV03_PGRAPH_INTR , 0xFFFFFFFF);
|
||||
NV_WRITE(NV03_PGRAPH_INTR_EN, 0xFFFFFFFF);
|
||||
|
||||
NV_WRITE(NV04_PGRAPH_DEBUG_0, 0xFFFFFFFF);
|
||||
NV_WRITE(NV04_PGRAPH_DEBUG_0, 0x00000000);
|
||||
|
|
|
|||
|
|
@ -37,13 +37,13 @@
|
|||
#define NV40_RAMFC__SIZE 128
|
||||
|
||||
int
|
||||
nv40_fifo_create_context(struct drm_device *dev, int channel)
|
||||
nv40_fifo_create_context(struct nouveau_channel *chan)
|
||||
{
|
||||
struct drm_device *dev = chan->dev;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_fifo *chan = dev_priv->fifos[channel];
|
||||
int ret;
|
||||
|
||||
if ((ret = nouveau_gpuobj_new_fake(dev, NV40_RAMFC(channel),
|
||||
if ((ret = nouveau_gpuobj_new_fake(dev, NV40_RAMFC(chan->id), ~0,
|
||||
NV40_RAMFC__SIZE,
|
||||
NVOBJ_FLAG_ZERO_ALLOC |
|
||||
NVOBJ_FLAG_ZERO_FREE,
|
||||
|
|
@ -68,27 +68,27 @@ nv40_fifo_create_context(struct drm_device *dev, int channel)
|
|||
RAMFC_WR(DMA_TIMESLICE , 0x0001FFFF);
|
||||
|
||||
/* enable the fifo dma operation */
|
||||
NV_WRITE(NV04_PFIFO_MODE,NV_READ(NV04_PFIFO_MODE)|(1<<channel));
|
||||
NV_WRITE(NV04_PFIFO_MODE,NV_READ(NV04_PFIFO_MODE)|(1<<chan->id));
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
nv40_fifo_destroy_context(struct drm_device *dev, int channel)
|
||||
nv40_fifo_destroy_context(struct nouveau_channel *chan)
|
||||
{
|
||||
struct drm_device *dev = chan->dev;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_fifo *chan = dev_priv->fifos[channel];
|
||||
|
||||
NV_WRITE(NV04_PFIFO_MODE, NV_READ(NV04_PFIFO_MODE)&~(1<<channel));
|
||||
NV_WRITE(NV04_PFIFO_MODE, NV_READ(NV04_PFIFO_MODE)&~(1<<chan->id));
|
||||
|
||||
if (chan->ramfc)
|
||||
nouveau_gpuobj_ref_del(dev, &chan->ramfc);
|
||||
}
|
||||
|
||||
int
|
||||
nv40_fifo_load_context(struct drm_device *dev, int channel)
|
||||
nv40_fifo_load_context(struct nouveau_channel *chan)
|
||||
{
|
||||
struct drm_device *dev = chan->dev;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_fifo *chan = dev_priv->fifos[channel];
|
||||
uint32_t tmp, tmp2;
|
||||
|
||||
NV_WRITE(NV04_PFIFO_CACHE1_DMA_GET , RAMFC_RD(DMA_GET));
|
||||
|
|
@ -135,7 +135,7 @@ nv40_fifo_load_context(struct drm_device *dev, int channel)
|
|||
NV_WRITE(NV04_PFIFO_DMA_TIMESLICE, tmp);
|
||||
|
||||
/* Set channel active, and in DMA mode */
|
||||
NV_WRITE(NV03_PFIFO_CACHE1_PUSH1 , 0x00010000 | channel);
|
||||
NV_WRITE(NV03_PFIFO_CACHE1_PUSH1 , 0x00010000 | chan->id);
|
||||
/* Reset DMA_CTL_AT_INFO to INVALID */
|
||||
tmp = NV_READ(NV04_PFIFO_CACHE1_DMA_CTL) & ~(1<<31);
|
||||
NV_WRITE(NV04_PFIFO_CACHE1_DMA_CTL, tmp);
|
||||
|
|
@ -144,10 +144,10 @@ nv40_fifo_load_context(struct drm_device *dev, int channel)
|
|||
}
|
||||
|
||||
int
|
||||
nv40_fifo_save_context(struct drm_device *dev, int channel)
|
||||
nv40_fifo_save_context(struct nouveau_channel *chan)
|
||||
{
|
||||
struct drm_device *dev = chan->dev;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_fifo *chan = dev_priv->fifos[channel];
|
||||
uint32_t tmp;
|
||||
|
||||
RAMFC_WR(DMA_PUT , NV_READ(NV04_PFIFO_CACHE1_DMA_PUT));
|
||||
|
|
@ -193,3 +193,16 @@ nv40_fifo_save_context(struct drm_device *dev, int channel)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
nv40_fifo_init(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
int ret;
|
||||
|
||||
if ((ret = nouveau_fifo_init(dev)))
|
||||
return ret;
|
||||
|
||||
NV_WRITE(NV04_PFIFO_DMA_TIMESLICE, 0x2101ffff);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1224,11 +1224,10 @@ nv4e_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx)
|
|||
}
|
||||
|
||||
int
|
||||
nv40_graph_create_context(struct drm_device *dev, int channel)
|
||||
nv40_graph_create_context(struct nouveau_channel *chan)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv =
|
||||
(struct drm_nouveau_private *)dev->dev_private;
|
||||
struct nouveau_fifo *chan = dev_priv->fifos[channel];
|
||||
struct drm_device *dev = chan->dev;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
void (*ctx_init)(struct drm_device *, struct nouveau_gpuobj *);
|
||||
unsigned int ctx_size;
|
||||
int ret;
|
||||
|
|
@ -1272,7 +1271,7 @@ nv40_graph_create_context(struct drm_device *dev, int channel)
|
|||
break;
|
||||
}
|
||||
|
||||
if ((ret = nouveau_gpuobj_new_ref(dev, channel, -1, 0, ctx_size, 16,
|
||||
if ((ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, ctx_size, 16,
|
||||
NVOBJ_FLAG_ZERO_ALLOC,
|
||||
&chan->ramin_grctx)))
|
||||
return ret;
|
||||
|
|
@ -1284,13 +1283,9 @@ nv40_graph_create_context(struct drm_device *dev, int channel)
|
|||
}
|
||||
|
||||
void
|
||||
nv40_graph_destroy_context(struct drm_device *dev, int channel)
|
||||
nv40_graph_destroy_context(struct nouveau_channel *chan)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_fifo *chan = dev_priv->fifos[channel];
|
||||
|
||||
if (chan->ramin_grctx)
|
||||
nouveau_gpuobj_ref_del(dev, &chan->ramin_grctx);
|
||||
nouveau_gpuobj_ref_del(chan->dev, &chan->ramin_grctx);
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
@ -1327,10 +1322,9 @@ nv40_graph_transfer_context(struct drm_device *dev, uint32_t inst, int save)
|
|||
*XXX: fails sometimes, not sure why..
|
||||
*/
|
||||
int
|
||||
nv40_graph_save_context(struct drm_device *dev, int channel)
|
||||
nv40_graph_save_context(struct nouveau_channel *chan)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_fifo *chan = dev_priv->fifos[channel];
|
||||
struct drm_device *dev = chan->dev;
|
||||
uint32_t inst;
|
||||
|
||||
if (!chan->ramin_grctx)
|
||||
|
|
@ -1344,10 +1338,10 @@ nv40_graph_save_context(struct drm_device *dev, int channel)
|
|||
* XXX: fails sometimes.. not sure why
|
||||
*/
|
||||
int
|
||||
nv40_graph_load_context(struct drm_device *dev, int channel)
|
||||
nv40_graph_load_context(struct nouveau_channel *chan)
|
||||
{
|
||||
struct drm_device *dev = chan->dev;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_fifo *chan = dev_priv->fifos[channel];
|
||||
uint32_t inst;
|
||||
int ret;
|
||||
|
||||
|
|
@ -1642,8 +1636,8 @@ nv40_graph_init(struct drm_device *dev)
|
|||
/* No context present currently */
|
||||
NV_WRITE(NV40_PGRAPH_CTXCTL_CUR, 0x00000000);
|
||||
|
||||
NV_WRITE(NV03_PGRAPH_INTR_EN, 0x00000000);
|
||||
NV_WRITE(NV03_PGRAPH_INTR , 0xFFFFFFFF);
|
||||
NV_WRITE(NV40_PGRAPH_INTR_EN, 0xFFFFFFFF);
|
||||
|
||||
NV_WRITE(NV04_PGRAPH_DEBUG_0, 0xFFFFFFFF);
|
||||
NV_WRITE(NV04_PGRAPH_DEBUG_0, 0x00000000);
|
||||
|
|
|
|||
|
|
@ -14,8 +14,6 @@ nv40_mc_init(struct drm_device *dev)
|
|||
*/
|
||||
NV_WRITE(NV03_PMC_ENABLE, 0xFFFFFFFF);
|
||||
|
||||
NV_WRITE(NV03_PMC_INTR_EN_0, 0);
|
||||
|
||||
switch (dev_priv->chipset) {
|
||||
case 0x44:
|
||||
case 0x46: /* G72 */
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@
|
|||
|
||||
typedef struct {
|
||||
struct nouveau_gpuobj_ref *thingo;
|
||||
struct nouveau_gpuobj_ref *dummyctx;
|
||||
} nv50_fifo_priv;
|
||||
|
||||
#define IS_G80 ((dev_priv->chipset & 0xf0) == 0x50)
|
||||
|
|
@ -47,7 +46,7 @@ nv50_fifo_init_thingo(struct drm_device *dev)
|
|||
|
||||
INSTANCE_WR(thingo->gpuobj, 0, 0x7e);
|
||||
INSTANCE_WR(thingo->gpuobj, 1, 0x7e);
|
||||
for (i = 0; i <NV_MAX_FIFO_NUMBER; i++, fi) {
|
||||
for (i = 1; i < 127; i++, fi) {
|
||||
if (dev_priv->fifos[i]) {
|
||||
INSTANCE_WR(thingo->gpuobj, fi, i);
|
||||
fi++;
|
||||
|
|
@ -60,10 +59,10 @@ nv50_fifo_init_thingo(struct drm_device *dev)
|
|||
}
|
||||
|
||||
static int
|
||||
nv50_fifo_channel_enable(struct drm_device *dev, int channel)
|
||||
nv50_fifo_channel_enable(struct drm_device *dev, int channel, int nt)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_fifo *chan = dev_priv->fifos[channel];
|
||||
struct nouveau_channel *chan = dev_priv->fifos[channel];
|
||||
|
||||
DRM_DEBUG("ch%d\n", channel);
|
||||
|
||||
|
|
@ -83,7 +82,7 @@ nv50_fifo_channel_enable(struct drm_device *dev, int channel)
|
|||
NV50_PFIFO_CTX_TABLE_CHANNEL_ENABLED);
|
||||
}
|
||||
|
||||
nv50_fifo_init_thingo(dev);
|
||||
if (!nt) nv50_fifo_init_thingo(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -119,6 +118,17 @@ nv50_fifo_init_reset(struct drm_device *dev)
|
|||
NV_WRITE(NV03_PMC_ENABLE, pmc_e | NV_PMC_ENABLE_PFIFO);
|
||||
}
|
||||
|
||||
static void
|
||||
nv50_fifo_init_intr(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
NV_WRITE(NV03_PFIFO_INTR_0, 0xFFFFFFFF);
|
||||
NV_WRITE(NV03_PFIFO_INTR_EN_0, 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
static void
|
||||
nv50_fifo_init_context_table(struct drm_device *dev)
|
||||
{
|
||||
|
|
@ -145,18 +155,9 @@ static int
|
|||
nv50_fifo_init_regs(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
nv50_fifo_priv *priv = dev_priv->Engine.fifo.priv;
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
if ((ret = nouveau_gpuobj_new_ref(dev, -1, -1, 0, 0x1000,
|
||||
0x1000,
|
||||
NVOBJ_FLAG_ZERO_ALLOC |
|
||||
NVOBJ_FLAG_ZERO_FREE,
|
||||
&priv->dummyctx)))
|
||||
return ret;
|
||||
|
||||
NV_WRITE(0x2500, 0);
|
||||
NV_WRITE(0x3250, 0);
|
||||
NV_WRITE(0x3220, 0);
|
||||
|
|
@ -164,13 +165,9 @@ nv50_fifo_init_regs(struct drm_device *dev)
|
|||
NV_WRITE(0x3210, 0);
|
||||
NV_WRITE(0x3270, 0);
|
||||
|
||||
if (IS_G80) {
|
||||
NV_WRITE(0x2600, (priv->dummyctx->instance>>8) | (1<<31));
|
||||
NV_WRITE(0x27fc, (priv->dummyctx->instance>>8) | (1<<31));
|
||||
} else {
|
||||
NV_WRITE(0x2600, (priv->dummyctx->instance>>12) | (1<<31));
|
||||
NV_WRITE(0x27fc, (priv->dummyctx->instance>>12) | (1<<31));
|
||||
}
|
||||
/* Enable dummy channels setup by nv50_instmem.c */
|
||||
nv50_fifo_channel_enable(dev, 0, 1);
|
||||
nv50_fifo_channel_enable(dev, 127, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -190,13 +187,15 @@ nv50_fifo_init(struct drm_device *dev)
|
|||
dev_priv->Engine.fifo.priv = priv;
|
||||
|
||||
nv50_fifo_init_reset(dev);
|
||||
nv50_fifo_init_intr(dev);
|
||||
|
||||
if ((ret = nouveau_gpuobj_new_ref(dev, -1, -1, 0, (128+2)*4, 0x1000,
|
||||
if ((ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, (128+2)*4, 0x1000,
|
||||
NVOBJ_FLAG_ZERO_ALLOC,
|
||||
&priv->thingo))) {
|
||||
DRM_ERROR("error creating thingo: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
nv50_fifo_init_context_table(dev);
|
||||
|
||||
nv50_fifo_init_regs__nv(dev);
|
||||
|
|
@ -218,31 +217,30 @@ nv50_fifo_takedown(struct drm_device *dev)
|
|||
return;
|
||||
|
||||
nouveau_gpuobj_ref_del(dev, &priv->thingo);
|
||||
nouveau_gpuobj_ref_del(dev, &priv->dummyctx);
|
||||
|
||||
dev_priv->Engine.fifo.priv = NULL;
|
||||
drm_free(priv, sizeof(*priv), DRM_MEM_DRIVER);
|
||||
}
|
||||
|
||||
int
|
||||
nv50_fifo_create_context(struct drm_device *dev, int channel)
|
||||
nv50_fifo_create_context(struct nouveau_channel *chan)
|
||||
{
|
||||
struct drm_device *dev = chan->dev;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_fifo *chan = dev_priv->fifos[channel];
|
||||
struct nouveau_gpuobj *ramfc = NULL;
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG("ch%d\n", channel);
|
||||
DRM_DEBUG("ch%d\n", chan->id);
|
||||
|
||||
if (IS_G80) {
|
||||
uint32_t ramfc_offset = chan->ramin->gpuobj->im_pramin->start;
|
||||
if ((ret = nouveau_gpuobj_new_fake(dev, ramfc_offset, 0x100,
|
||||
if ((ret = nouveau_gpuobj_new_fake(dev, ramfc_offset, ~0, 0x100,
|
||||
NVOBJ_FLAG_ZERO_ALLOC |
|
||||
NVOBJ_FLAG_ZERO_FREE,
|
||||
&ramfc, &chan->ramfc)))
|
||||
return ret;
|
||||
} else {
|
||||
if ((ret = nouveau_gpuobj_new_ref(dev, channel, -1, 0, 0x100,
|
||||
if ((ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, 0x100,
|
||||
256,
|
||||
NVOBJ_FLAG_ZERO_ALLOC |
|
||||
NVOBJ_FLAG_ZERO_FREE,
|
||||
|
|
@ -266,15 +264,15 @@ nv50_fifo_create_context(struct drm_device *dev, int channel)
|
|||
INSTANCE_WR(ramfc, 0x4c/4, chan->pushbuf_mem->size - 1);
|
||||
|
||||
if (!IS_G80) {
|
||||
INSTANCE_WR(chan->ramin->gpuobj, 0, channel);
|
||||
INSTANCE_WR(chan->ramin->gpuobj, 0, chan->id);
|
||||
INSTANCE_WR(chan->ramin->gpuobj, 1, chan->ramfc->instance);
|
||||
|
||||
INSTANCE_WR(ramfc, 0x88/4, 0x3d520); /* some vram addy >> 10 */
|
||||
INSTANCE_WR(ramfc, 0x98/4, chan->ramin->instance >> 12);
|
||||
}
|
||||
|
||||
if ((ret = nv50_fifo_channel_enable(dev, channel))) {
|
||||
DRM_ERROR("error enabling ch%d: %d\n", channel, ret);
|
||||
if ((ret = nv50_fifo_channel_enable(dev, chan->id, 0))) {
|
||||
DRM_ERROR("error enabling ch%d: %d\n", chan->id, ret);
|
||||
nouveau_gpuobj_ref_del(dev, &chan->ramfc);
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -283,25 +281,29 @@ nv50_fifo_create_context(struct drm_device *dev, int channel)
|
|||
}
|
||||
|
||||
void
|
||||
nv50_fifo_destroy_context(struct drm_device *dev, int channel)
|
||||
nv50_fifo_destroy_context(struct nouveau_channel *chan)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_fifo *chan = dev_priv->fifos[channel];
|
||||
struct drm_device *dev = chan->dev;
|
||||
|
||||
DRM_DEBUG("ch%d\n", channel);
|
||||
DRM_DEBUG("ch%d\n", chan->id);
|
||||
|
||||
nv50_fifo_channel_disable(dev, chan->id, 0);
|
||||
|
||||
/* Dummy channel, also used on ch 127 */
|
||||
if (chan->id == 0)
|
||||
nv50_fifo_channel_disable(dev, 127, 0);
|
||||
|
||||
nv50_fifo_channel_disable(dev, channel, 0);
|
||||
nouveau_gpuobj_ref_del(dev, &chan->ramfc);
|
||||
}
|
||||
|
||||
int
|
||||
nv50_fifo_load_context(struct drm_device *dev, int channel)
|
||||
nv50_fifo_load_context(struct nouveau_channel *chan)
|
||||
{
|
||||
struct drm_device *dev = chan->dev;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_fifo *chan = dev_priv->fifos[channel];
|
||||
struct nouveau_gpuobj *ramfc = chan->ramfc->gpuobj;
|
||||
|
||||
DRM_DEBUG("ch%d\n", channel);
|
||||
DRM_DEBUG("ch%d\n", chan->id);
|
||||
|
||||
/*XXX: incomplete, only touches the regs that NV does */
|
||||
|
||||
|
|
@ -319,14 +321,14 @@ nv50_fifo_load_context(struct drm_device *dev, int channel)
|
|||
NV_WRITE(0x3410, INSTANCE_RD(ramfc, 0x98/4));
|
||||
}
|
||||
|
||||
NV_WRITE(NV03_PFIFO_CACHE1_PUSH1, channel | (1<<16));
|
||||
NV_WRITE(NV03_PFIFO_CACHE1_PUSH1, chan->id | (1<<16));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
nv50_fifo_save_context(struct drm_device *dev, int channel)
|
||||
nv50_fifo_save_context(struct nouveau_channel *chan)
|
||||
{
|
||||
DRM_DEBUG("ch%d\n", channel);
|
||||
DRM_DEBUG("ch%d\n", chan->id);
|
||||
DRM_ERROR("stub!\n");
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,6 +44,16 @@ nv50_graph_init_reset(struct drm_device *dev)
|
|||
NV_WRITE(NV03_PMC_ENABLE, pmc_e | NV_PMC_ENABLE_PGRAPH);
|
||||
}
|
||||
|
||||
static void
|
||||
nv50_graph_init_intr(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
NV_WRITE(NV03_PGRAPH_INTR, 0xffffffff);
|
||||
NV_WRITE(NV40_PGRAPH_INTR_EN, 0xffffffff);
|
||||
}
|
||||
|
||||
static void
|
||||
nv50_graph_init_regs__nv(struct drm_device *dev)
|
||||
{
|
||||
|
|
@ -59,7 +69,6 @@ nv50_graph_init_regs__nv(struct drm_device *dev)
|
|||
NV_WRITE(0x402000, 0xc0000000);
|
||||
|
||||
NV_WRITE(0x400108, 0xffffffff);
|
||||
NV_WRITE(0x400100, 0xffffffff);
|
||||
|
||||
NV_WRITE(0x400824, 0x00004000);
|
||||
NV_WRITE(0x400500, 0x00010001);
|
||||
|
|
@ -174,6 +183,7 @@ nv50_graph_init(struct drm_device *dev)
|
|||
DRM_DEBUG("\n");
|
||||
|
||||
nv50_graph_init_reset(dev);
|
||||
nv50_graph_init_intr(dev);
|
||||
nv50_graph_init_regs__nv(dev);
|
||||
nv50_graph_init_regs(dev);
|
||||
nv50_graph_init_ctxctl(dev);
|
||||
|
|
@ -188,17 +198,18 @@ nv50_graph_takedown(struct drm_device *dev)
|
|||
}
|
||||
|
||||
int
|
||||
nv50_graph_create_context(struct drm_device *dev, int channel)
|
||||
nv50_graph_create_context(struct nouveau_channel *chan)
|
||||
{
|
||||
struct drm_device *dev = chan->dev;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_fifo *chan = dev_priv->fifos[channel];
|
||||
struct nouveau_engine *engine = &dev_priv->Engine;
|
||||
struct nouveau_gpuobj *ramin = chan->ramin->gpuobj;
|
||||
int grctx_size = 0x60000, hdr;
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG("ch%d\n", channel);
|
||||
DRM_DEBUG("ch%d\n", chan->id);
|
||||
|
||||
if ((ret = nouveau_gpuobj_new_ref(dev, channel, -1, 0,
|
||||
if ((ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0,
|
||||
grctx_size, 0x1000,
|
||||
NVOBJ_FLAG_ZERO_ALLOC |
|
||||
NVOBJ_FLAG_ZERO_FREE,
|
||||
|
|
@ -214,17 +225,22 @@ nv50_graph_create_context(struct drm_device *dev, int channel)
|
|||
INSTANCE_WR(ramin, (hdr + 0x10)/4, 0);
|
||||
INSTANCE_WR(ramin, (hdr + 0x14)/4, 0x00010000);
|
||||
|
||||
if ((ret = engine->graph.load_context(chan))) {
|
||||
DRM_ERROR("Error hacking up initial context: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
nv50_graph_destroy_context(struct drm_device *dev, int channel)
|
||||
nv50_graph_destroy_context(struct nouveau_channel *chan)
|
||||
{
|
||||
struct drm_device *dev = chan->dev;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_fifo *chan = dev_priv->fifos[channel];
|
||||
int i, hdr;
|
||||
|
||||
DRM_DEBUG("ch%d\n", channel);
|
||||
DRM_DEBUG("ch%d\n", chan->id);
|
||||
|
||||
hdr = IS_G80 ? 0x200 : 0x20;
|
||||
for (i=hdr; i<hdr+24; i+=4)
|
||||
|
|
@ -266,14 +282,14 @@ nv50_graph_transfer_context(struct drm_device *dev, uint32_t inst, int save)
|
|||
}
|
||||
|
||||
int
|
||||
nv50_graph_load_context(struct drm_device *dev, int channel)
|
||||
nv50_graph_load_context(struct nouveau_channel *chan)
|
||||
{
|
||||
struct drm_device *dev = chan->dev;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_fifo *chan = dev_priv->fifos[channel];
|
||||
uint32_t inst = ((chan->ramin->instance >> 12) | (1<<31));
|
||||
int ret; (void)ret;
|
||||
|
||||
DRM_DEBUG("ch%d\n", channel);
|
||||
DRM_DEBUG("ch%d\n", chan->id);
|
||||
|
||||
#if 0
|
||||
if ((ret = nv50_graph_transfer_context(dev, inst, 0)))
|
||||
|
|
@ -288,13 +304,12 @@ nv50_graph_load_context(struct drm_device *dev, int channel)
|
|||
}
|
||||
|
||||
int
|
||||
nv50_graph_save_context(struct drm_device *dev, int channel)
|
||||
nv50_graph_save_context(struct nouveau_channel *chan)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_fifo *chan = dev_priv->fifos[channel];
|
||||
struct drm_device *dev = chan->dev;
|
||||
uint32_t inst = ((chan->ramin->instance >> 12) | (1<<31));
|
||||
|
||||
DRM_DEBUG("ch%d\n", channel);
|
||||
DRM_DEBUG("ch%d\n", chan->id);
|
||||
|
||||
return nv50_graph_transfer_context(dev, inst, 1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,118 +31,162 @@
|
|||
|
||||
typedef struct {
|
||||
uint32_t save1700[5]; /* 0x1700->0x1710 */
|
||||
|
||||
struct nouveau_gpuobj_ref *pramin_pt;
|
||||
struct nouveau_gpuobj_ref *pramin_bar;
|
||||
} nv50_instmem_priv;
|
||||
|
||||
#define NV50_INSTMEM_PAGE_SHIFT 12
|
||||
#define NV50_INSTMEM_PAGE_SIZE (1 << NV50_INSTMEM_PAGE_SHIFT)
|
||||
#define NV50_INSTMEM_RSVD_SIZE (64 * 1024)
|
||||
#define NV50_INSTMEM_PT_SIZE(a) (((a) >> 12) << 3)
|
||||
|
||||
/*NOTE: - Assumes 0x1700 already covers the correct MiB of PRAMIN
|
||||
*/
|
||||
#define BAR0_WI32(g,o,v) do { \
|
||||
uint32_t offset; \
|
||||
if ((g)->im_backing) { \
|
||||
offset = (g)->im_backing->start; \
|
||||
} else { \
|
||||
offset = chan->ramin->gpuobj->im_backing->start; \
|
||||
offset += (g)->im_pramin->start; \
|
||||
} \
|
||||
offset += (o); \
|
||||
NV_WRITE(NV_RAMIN + (offset & 0xfffff), (v)); \
|
||||
} while(0)
|
||||
|
||||
int
|
||||
nv50_instmem_init(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_channel *chan;
|
||||
uint32_t c_offset, c_size, c_ramfc, c_vmpd, c_base, pt_size;
|
||||
nv50_instmem_priv *priv;
|
||||
uint32_t rv, pt, pts, cb, cb0, cb1, unk, as;
|
||||
uint32_t i, v;
|
||||
int ret;
|
||||
int ret, i;
|
||||
uint32_t v;
|
||||
|
||||
priv = drm_calloc(1, sizeof(*priv), DRM_MEM_DRIVER);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
dev_priv->Engine.instmem.priv = priv;
|
||||
|
||||
/* Save current state */
|
||||
for (i = 0x1700; i <= 0x1710; i+=4)
|
||||
priv->save1700[(i-0x1700)/4] = NV_READ(i);
|
||||
|
||||
as = dev_priv->ramin->size;
|
||||
rv = nouveau_mem_fb_amount(dev) - (1*1024*1024);
|
||||
pt = rv + 0xd0000;
|
||||
pts = NV50_INSTMEM_PT_SIZE(as);
|
||||
cb = rv + 0xc8000;
|
||||
if ((dev_priv->chipset & 0xf0) != 0x50) {
|
||||
unk = cb + 0x4200;
|
||||
cb0 = cb + 0x4240;
|
||||
cb1 = cb + 0x278;
|
||||
} else {
|
||||
unk = cb + 0x5400;
|
||||
cb0 = cb + 0x5440;
|
||||
cb1 = cb + 0x1478;
|
||||
}
|
||||
|
||||
DRM_DEBUG("PRAMIN config:\n");
|
||||
DRM_DEBUG(" Rsvd VRAM base: 0x%08x\n", rv);
|
||||
DRM_DEBUG(" Aperture size: %i MiB\n", as >> 20);
|
||||
DRM_DEBUG(" PT base: 0x%08x\n", pt);
|
||||
DRM_DEBUG(" PT size: %d KiB\n", pts >> 10);
|
||||
DRM_DEBUG(" BIOS image: 0x%08x\n", (NV_READ(0x619f04)&~0xff)<<8);
|
||||
DRM_DEBUG(" Config base: 0x%08x\n", cb);
|
||||
DRM_DEBUG(" ctxdma Config0: 0x%08x\n", cb0);
|
||||
DRM_DEBUG(" Config1: 0x%08x\n", cb1);
|
||||
|
||||
/* Map first MiB of reserved vram into BAR0 PRAMIN aperture */
|
||||
NV_WRITE(0x1700, (rv>>16));
|
||||
/* Poke some regs.. */
|
||||
NV_WRITE(0x1704, (cb>>12));
|
||||
NV_WRITE(0x1710, (((unk-cb)>>4))|(1<<31));
|
||||
NV_WRITE(0x1704, (cb>>12)|(1<<30));
|
||||
|
||||
/* CB0, some DMA object, NFI what it points at... Needed however,
|
||||
* or the PRAMIN aperture doesn't operate as expected.
|
||||
/* Reserve the last MiB of VRAM, we should probably try to avoid
|
||||
* setting up the below tables over the top of the VBIOS image at
|
||||
* some point.
|
||||
*/
|
||||
NV_WRITE(NV_RAMIN + (cb0 - rv) + 0x00, 0x7fc00000);
|
||||
NV_WRITE(NV_RAMIN + (cb0 - rv) + 0x04, 0xe1ffffff);
|
||||
NV_WRITE(NV_RAMIN + (cb0 - rv) + 0x08, 0xe0000000);
|
||||
NV_WRITE(NV_RAMIN + (cb0 - rv) + 0x0c, 0x01000001);
|
||||
NV_WRITE(NV_RAMIN + (cb0 - rv) + 0x10, 0x00000000);
|
||||
NV_WRITE(NV_RAMIN + (cb0 - rv) + 0x14, 0x00000000);
|
||||
dev_priv->ramin_rsvd_vram = 1 << 20;
|
||||
c_offset = nouveau_mem_fb_amount(dev) - dev_priv->ramin_rsvd_vram;
|
||||
c_size = 128 << 10;
|
||||
c_vmpd = ((dev_priv->chipset & 0xf0) == 0x50) ? 0x1400 : 0x200;
|
||||
c_ramfc = ((dev_priv->chipset & 0xf0) == 0x50) ? 0x0 : 0x20;
|
||||
c_base = c_vmpd + 0x4000;
|
||||
pt_size = NV50_INSTMEM_PT_SIZE(dev_priv->ramin->size);
|
||||
|
||||
/* CB1, points at PRAMIN PT */
|
||||
NV_WRITE(NV_RAMIN + (cb1 - rv) + 0, pt | 0x63);
|
||||
NV_WRITE(NV_RAMIN + (cb1 - rv) + 4, 0x00000000);
|
||||
DRM_DEBUG(" Rsvd VRAM base: 0x%08x\n", c_offset);
|
||||
DRM_DEBUG(" VBIOS image: 0x%08x\n", (NV_READ(0x619f04)&~0xff)<<8);
|
||||
DRM_DEBUG(" Aperture size: %d MiB\n",
|
||||
(uint32_t)dev_priv->ramin->size >> 20);
|
||||
DRM_DEBUG(" PT size: %d KiB\n", pt_size >> 10);
|
||||
|
||||
/* Zero PRAMIN page table */
|
||||
v = NV_RAMIN + (pt - rv);
|
||||
for (i = v; i < v + pts; i += 8) {
|
||||
NV_WRITE(i + 0x00, 0x00000009);
|
||||
NV_WRITE(i + 0x04, 0x00000000);
|
||||
}
|
||||
NV_WRITE(NV50_PUNK_BAR0_PRAMIN, (c_offset >> 16));
|
||||
|
||||
/* Map page table into PRAMIN aperture */
|
||||
for (i = pt; i < pt + pts; i += 0x1000) {
|
||||
uint32_t pte = NV_RAMIN + (pt-rv) + (((i-pt) >> 12) << 3);
|
||||
DRM_DEBUG("PRAMIN PTE = 0x%08x @ 0x%08x\n", i, pte);
|
||||
NV_WRITE(pte + 0x00, i | 1);
|
||||
NV_WRITE(pte + 0x04, 0x00000000);
|
||||
}
|
||||
|
||||
/* Points at CB0 */
|
||||
NV_WRITE(0x170c, (((cb0 - cb)>>4)|(1<<31)));
|
||||
|
||||
/* Confirm it all worked, should be able to read back the page table's
|
||||
* PTEs from the PRAMIN BAR
|
||||
/* Create a fake channel, and use it as our "dummy" channels 0/127.
|
||||
* The main reason for creating a channel is so we can use the gpuobj
|
||||
* code. However, it's probably worth noting that NVIDIA also setup
|
||||
* their channels 0/127 with the same values they configure here.
|
||||
* So, there may be some other reason for doing this.
|
||||
*
|
||||
* Have to create the entire channel manually, as the real channel
|
||||
* creation code assumes we have PRAMIN access, and we don't until
|
||||
* we're done here.
|
||||
*/
|
||||
NV_WRITE(0x1700, pt >> 16);
|
||||
if (NV_READ(0x700000) != NV_RI32(0)) {
|
||||
DRM_ERROR("Failed to init PRAMIN page table\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Create a heap to manage PRAMIN aperture allocations */
|
||||
ret = nouveau_mem_init_heap(&dev_priv->ramin_heap, pts, as-pts);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to init PRAMIN heap\n");
|
||||
chan = drm_calloc(1, sizeof(*chan), DRM_MEM_DRIVER);
|
||||
if (!chan)
|
||||
return -ENOMEM;
|
||||
chan->id = 0;
|
||||
chan->dev = dev;
|
||||
chan->file_priv = (struct drm_file *)-2;
|
||||
dev_priv->fifos[0] = dev_priv->fifos[127] = chan;
|
||||
|
||||
/* Channel's PRAMIN object + heap */
|
||||
if ((ret = nouveau_gpuobj_new_fake(dev, 0, c_offset, 128<<10, 0,
|
||||
NULL, &chan->ramin)))
|
||||
return ret;
|
||||
|
||||
if (nouveau_mem_init_heap(&chan->ramin_heap, c_base, c_size - c_base))
|
||||
return -ENOMEM;
|
||||
|
||||
/* RAMFC + zero channel's PRAMIN up to start of VM pagedir */
|
||||
if ((ret = nouveau_gpuobj_new_fake(dev, c_ramfc, c_offset + c_ramfc,
|
||||
0x4000, 0, NULL, &chan->ramfc)))
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < c_vmpd; i += 4)
|
||||
BAR0_WI32(chan->ramin->gpuobj, i, 0);
|
||||
|
||||
/* VM page directory */
|
||||
if ((ret = nouveau_gpuobj_new_fake(dev, c_vmpd, c_offset + c_vmpd,
|
||||
0x4000, 0, &chan->vm_pd, NULL)))
|
||||
return ret;
|
||||
for (i = 0; i < 0x4000; i += 8) {
|
||||
BAR0_WI32(chan->vm_pd, i + 0x00, 0x00000000);
|
||||
BAR0_WI32(chan->vm_pd, i + 0x04, 0x00000000);
|
||||
}
|
||||
DRM_DEBUG("NV50: PRAMIN setup ok\n");
|
||||
|
||||
/* Don't alloc the last MiB of VRAM, probably too much, but be safe
|
||||
* at least for now.
|
||||
/* PRAMIN page table, cheat and map into VM at 0x0000000000.
|
||||
* We map the entire fake channel into the start of the PRAMIN BAR
|
||||
*/
|
||||
dev_priv->ramin_rsvd_vram = 1*1024*1024;
|
||||
if ((ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, pt_size, 0x1000,
|
||||
0, &priv->pramin_pt)))
|
||||
return ret;
|
||||
|
||||
/*XXX: probably incorrect, but needed to make hash func "work" */
|
||||
for (i = 0, v = c_offset; i < pt_size; i+=8, v+=0x1000) {
|
||||
if (v < (c_offset + c_size))
|
||||
BAR0_WI32(priv->pramin_pt->gpuobj, i + 0, v | 1);
|
||||
else
|
||||
BAR0_WI32(priv->pramin_pt->gpuobj, i + 0, 0x00000009);
|
||||
BAR0_WI32(priv->pramin_pt->gpuobj, i + 4, 0x00000000);
|
||||
}
|
||||
|
||||
BAR0_WI32(chan->vm_pd, 0x00, priv->pramin_pt->instance | 0x63);
|
||||
BAR0_WI32(chan->vm_pd, 0x04, 0x00000000);
|
||||
|
||||
/* DMA object for PRAMIN BAR */
|
||||
if ((ret = nouveau_gpuobj_new_ref(dev, chan, chan, 0, 6*4, 16, 0,
|
||||
&priv->pramin_bar)))
|
||||
return ret;
|
||||
BAR0_WI32(priv->pramin_bar->gpuobj, 0x00, 0x7fc00000);
|
||||
BAR0_WI32(priv->pramin_bar->gpuobj, 0x04, dev_priv->ramin->size - 1);
|
||||
BAR0_WI32(priv->pramin_bar->gpuobj, 0x08, 0x00000000);
|
||||
BAR0_WI32(priv->pramin_bar->gpuobj, 0x0c, 0x00000000);
|
||||
BAR0_WI32(priv->pramin_bar->gpuobj, 0x10, 0x00000000);
|
||||
BAR0_WI32(priv->pramin_bar->gpuobj, 0x14, 0x00000000);
|
||||
|
||||
/* Poke the relevant regs, and pray it works :) */
|
||||
NV_WRITE(NV50_PUNK_BAR_CFG_BASE, (chan->ramin->instance >> 12));
|
||||
NV_WRITE(NV50_PUNK_UNK1710, 0);
|
||||
NV_WRITE(NV50_PUNK_BAR_CFG_BASE, (chan->ramin->instance >> 12) |
|
||||
NV50_PUNK_BAR_CFG_BASE_VALID);
|
||||
NV_WRITE(NV50_PUNK_BAR1_CTXDMA, 0);
|
||||
NV_WRITE(NV50_PUNK_BAR3_CTXDMA, (priv->pramin_bar->instance >> 4) |
|
||||
NV50_PUNK_BAR3_CTXDMA_VALID);
|
||||
|
||||
/* Assume that praying isn't enough, check that we can re-read the
|
||||
* entire fake channel back from the PRAMIN BAR */
|
||||
for (i = 0; i < c_size; i+=4) {
|
||||
if (NV_READ(NV_RAMIN + i) != NV_RI32(i)) {
|
||||
DRM_ERROR("Error reading back PRAMIN at 0x%08x\n", i);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Global PRAMIN heap */
|
||||
if (nouveau_mem_init_heap(&dev_priv->ramin_heap,
|
||||
c_size, dev_priv->ramin->size - c_size)) {
|
||||
dev_priv->ramin_heap = NULL;
|
||||
DRM_ERROR("Failed to init RAMIN heap\n");
|
||||
}
|
||||
|
||||
/*XXX: incorrect, but needed to make hash func "work" */
|
||||
dev_priv->ramht_offset = 0x10000;
|
||||
dev_priv->ramht_bits = 9;
|
||||
dev_priv->ramht_size = (1 << dev_priv->ramht_bits);
|
||||
|
|
@ -154,8 +198,11 @@ nv50_instmem_takedown(struct drm_device *dev)
|
|||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
nv50_instmem_priv *priv = dev_priv->Engine.instmem.priv;
|
||||
struct nouveau_channel *chan = dev_priv->fifos[0];
|
||||
int i;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
if (!priv)
|
||||
return;
|
||||
|
||||
|
|
@ -163,6 +210,20 @@ nv50_instmem_takedown(struct drm_device *dev)
|
|||
for (i = 0x1700; i <= 0x1710; i+=4)
|
||||
NV_WRITE(i, priv->save1700[(i-0x1700)/4]);
|
||||
|
||||
nouveau_gpuobj_ref_del(dev, &priv->pramin_bar);
|
||||
nouveau_gpuobj_ref_del(dev, &priv->pramin_pt);
|
||||
|
||||
/* Destroy dummy channel */
|
||||
if (chan) {
|
||||
nouveau_gpuobj_del(dev, &chan->vm_pd);
|
||||
nouveau_gpuobj_ref_del(dev, &chan->ramfc);
|
||||
nouveau_gpuobj_ref_del(dev, &chan->ramin);
|
||||
nouveau_mem_takedown(&chan->ramin_heap);
|
||||
|
||||
dev_priv->fifos[0] = dev_priv->fifos[127] = NULL;
|
||||
drm_free(chan, sizeof(*chan), DRM_MEM_DRIVER);
|
||||
}
|
||||
|
||||
dev_priv->Engine.instmem.priv = NULL;
|
||||
drm_free(priv, sizeof(*priv), DRM_MEM_DRIVER);
|
||||
}
|
||||
|
|
@ -205,6 +266,7 @@ int
|
|||
nv50_instmem_bind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
nv50_instmem_priv *priv = dev_priv->Engine.instmem.priv;
|
||||
uint32_t pte, pte_end, vram;
|
||||
|
||||
if (!gpuobj->im_backing || !gpuobj->im_pramin || gpuobj->im_bound)
|
||||
|
|
@ -217,19 +279,14 @@ nv50_instmem_bind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj)
|
|||
pte_end = ((gpuobj->im_pramin->size >> 12) << 3) + pte;
|
||||
vram = gpuobj->im_backing->start;
|
||||
|
||||
if (pte == pte_end) {
|
||||
DRM_ERROR("WARNING: badness in bind() pte calc\n");
|
||||
pte_end++;
|
||||
}
|
||||
|
||||
DRM_DEBUG("pramin=0x%llx, pte=%d, pte_end=%d\n",
|
||||
gpuobj->im_pramin->start, pte, pte_end);
|
||||
DRM_DEBUG("first vram page: 0x%llx\n",
|
||||
gpuobj->im_backing->start);
|
||||
|
||||
while (pte < pte_end) {
|
||||
NV_WI32(pte + 0, vram | 1);
|
||||
NV_WI32(pte + 4, 0x00000000);
|
||||
INSTANCE_WR(priv->pramin_pt->gpuobj, (pte + 0)/4, vram | 1);
|
||||
INSTANCE_WR(priv->pramin_pt->gpuobj, (pte + 4)/4, 0x00000000);
|
||||
|
||||
pte += 8;
|
||||
vram += NV50_INSTMEM_PAGE_SIZE;
|
||||
|
|
@ -243,6 +300,7 @@ int
|
|||
nv50_instmem_unbind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
nv50_instmem_priv *priv = dev_priv->Engine.instmem.priv;
|
||||
uint32_t pte, pte_end;
|
||||
|
||||
if (gpuobj->im_bound == 0)
|
||||
|
|
@ -251,8 +309,8 @@ nv50_instmem_unbind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj)
|
|||
pte = (gpuobj->im_pramin->start >> 12) << 3;
|
||||
pte_end = ((gpuobj->im_pramin->size >> 12) << 3) + pte;
|
||||
while (pte < pte_end) {
|
||||
NV_WI32(pte + 0, 0x00000000);
|
||||
NV_WI32(pte + 4, 0x00000000);
|
||||
INSTANCE_WR(priv->pramin_pt->gpuobj, (pte + 0)/4, 0x00000009);
|
||||
INSTANCE_WR(priv->pramin_pt->gpuobj, (pte + 4)/4, 0x00000000);
|
||||
pte += 8;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ nv50_mc_init(struct drm_device *dev)
|
|||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
|
||||
NV_WRITE(NV03_PMC_ENABLE, 0xFFFFFFFF);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
AM_CFLAGS = \
|
||||
-I $(top_srcdir)/shared-core
|
||||
-I $(top_srcdir)/shared-core \
|
||||
-I $(top_srcdir)/libdrm
|
||||
|
||||
noinst_PROGRAMS = \
|
||||
dristat \
|
||||
|
|
@ -14,10 +15,12 @@ libdrmtest_la_LIBADD = \
|
|||
|
||||
LDADD = libdrmtest.la
|
||||
|
||||
TESTS = openclose \
|
||||
TESTS = auth \
|
||||
openclose \
|
||||
getversion \
|
||||
getclient \
|
||||
updatedraw
|
||||
|
||||
EXTRA_PROGRAMS = $(TESTS)
|
||||
CLEANFILES = $(EXTRA_PROGRAMS) $(EXTRA_LTLIBRARIES)
|
||||
CLEANFILES = $(EXTRA_PROGRAMS) $(EXTRA_LTLIBRARIES)
|
||||
|
||||
|
|
|
|||
137
tests/auth.c
Normal file
137
tests/auth.c
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
* Copyright © 2007 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Eric Anholt <eric@anholt.net>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
#include "drmtest.h"
|
||||
|
||||
enum auth_event {
|
||||
SERVER_READY,
|
||||
CLIENT_MAGIC,
|
||||
CLIENT_DONE,
|
||||
};
|
||||
|
||||
int commfd[2];
|
||||
|
||||
static void wait_event(int pipe, enum auth_event expected_event)
|
||||
{
|
||||
int ret;
|
||||
enum auth_event event;
|
||||
unsigned char in;
|
||||
|
||||
ret = read(commfd[pipe], &in, 1);
|
||||
if (ret == -1)
|
||||
err(1, "read error");
|
||||
event = in;
|
||||
|
||||
if (event != expected_event)
|
||||
errx(1, "unexpected event: %d\n", event);
|
||||
}
|
||||
|
||||
static void
|
||||
send_event(int pipe, enum auth_event send_event)
|
||||
{
|
||||
int ret;
|
||||
unsigned char event;
|
||||
|
||||
event = send_event;
|
||||
ret = write(commfd[pipe], &event, 1);
|
||||
if (ret == -1)
|
||||
err(1, "failed to send event %d", event);
|
||||
}
|
||||
|
||||
static void client()
|
||||
{
|
||||
struct drm_auth auth;
|
||||
int drmfd, ret;
|
||||
|
||||
/* XXX: Should make sure we open the same DRM as the master */
|
||||
drmfd = drm_open_any();
|
||||
|
||||
wait_event(0, SERVER_READY);
|
||||
|
||||
/* Get a client magic number and pass it to the master for auth. */
|
||||
auth.magic = 0; /* Quiet valgrind */
|
||||
ret = ioctl(drmfd, DRM_IOCTL_GET_MAGIC, &auth);
|
||||
if (ret == -1)
|
||||
err(1, "Couldn't get client magic");
|
||||
send_event(0, CLIENT_MAGIC);
|
||||
ret = write(commfd[0], &auth.magic, sizeof(auth.magic));
|
||||
if (ret == -1)
|
||||
err(1, "Couldn't write auth data");
|
||||
|
||||
/* Signal that the client is completely done. */
|
||||
send_event(0, CLIENT_DONE);
|
||||
}
|
||||
|
||||
static void server()
|
||||
{
|
||||
int drmfd, ret;
|
||||
struct drm_auth auth;
|
||||
|
||||
drmfd = drm_open_any_master();
|
||||
|
||||
auth.magic = 0xd0d0d0d0;
|
||||
ret = ioctl(drmfd, DRM_IOCTL_AUTH_MAGIC, &auth);
|
||||
if (ret != -1 || errno != EINVAL)
|
||||
errx(1, "Authenticating bad magic succeeded\n");
|
||||
|
||||
send_event(1, SERVER_READY);
|
||||
|
||||
wait_event(1, CLIENT_MAGIC);
|
||||
ret = read(commfd[1], &auth.magic, sizeof(auth.magic));
|
||||
if (ret == -1)
|
||||
err(1, "Failure to read client magic");
|
||||
|
||||
ret = ioctl(drmfd, DRM_IOCTL_AUTH_MAGIC, &auth);
|
||||
if (ret == -1)
|
||||
err(1, "Authenticating bad magic succeeded\n");
|
||||
|
||||
wait_event(1, CLIENT_DONE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks DRM authentication mechanisms.
|
||||
*/
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = pipe(commfd);
|
||||
if (ret == -1)
|
||||
err(1, "Couldn't create pipe");
|
||||
|
||||
ret = fork();
|
||||
if (ret == -1)
|
||||
err(1, "failure to fork client");
|
||||
if (ret == 0)
|
||||
client();
|
||||
else
|
||||
server();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -83,16 +83,10 @@ set_draw_cliprects_2(int fd, int drawable)
|
|||
assert(ret == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests drawable management: adding, removing, and updating the cliprects of
|
||||
* drawables.
|
||||
*/
|
||||
int main(int argc, char **argv)
|
||||
static int add_drawable(int fd)
|
||||
{
|
||||
drm_draw_t drawarg;
|
||||
int fd, ret, drawable;
|
||||
|
||||
fd = drm_open_any_master();
|
||||
int ret;
|
||||
|
||||
/* Create a drawable.
|
||||
* IOCTL_ADD_DRAW is RDWR, though it should really just be RD
|
||||
|
|
@ -100,27 +94,54 @@ int main(int argc, char **argv)
|
|||
drawarg.handle = 0;
|
||||
ret = ioctl(fd, DRM_IOCTL_ADD_DRAW, &drawarg);
|
||||
assert(ret == 0);
|
||||
drawable = drawarg.handle;
|
||||
return drawarg.handle;
|
||||
}
|
||||
|
||||
/* Do a series of cliprect updates */
|
||||
set_draw_cliprects_empty(fd, drawable);
|
||||
set_draw_cliprects_2(fd, drawable);
|
||||
set_draw_cliprects_empty(fd, drawable);
|
||||
static int rm_drawable(int fd, int drawable, int fail)
|
||||
{
|
||||
drm_draw_t drawarg;
|
||||
int ret;
|
||||
|
||||
/* Remove our drawable */
|
||||
/* Create a drawable.
|
||||
* IOCTL_ADD_DRAW is RDWR, though it should really just be RD
|
||||
*/
|
||||
drawarg.handle = drawable;
|
||||
ret = ioctl(fd, DRM_IOCTL_RM_DRAW, &drawarg);
|
||||
assert(ret == 0);
|
||||
drawable = drawarg.handle;
|
||||
if (!fail)
|
||||
assert(ret == 0);
|
||||
else
|
||||
assert(ret == -1 && errno == EINVAL);
|
||||
|
||||
return drawarg.handle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests drawable management: adding, removing, and updating the cliprects of
|
||||
* drawables.
|
||||
*/
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int fd, ret, d1, d2;
|
||||
|
||||
fd = drm_open_any_master();
|
||||
|
||||
d1 = add_drawable(fd);
|
||||
d2 = add_drawable(fd);
|
||||
/* Do a series of cliprect updates */
|
||||
set_draw_cliprects_empty(fd, d1);
|
||||
set_draw_cliprects_empty(fd, d2);
|
||||
set_draw_cliprects_2(fd, d1);
|
||||
set_draw_cliprects_empty(fd, d1);
|
||||
|
||||
/* Remove our drawables */
|
||||
rm_drawable(fd, d1, 0);
|
||||
rm_drawable(fd, d2, 0);
|
||||
|
||||
/* Check that removing an unknown drawable returns error */
|
||||
drawarg.handle = 0x7fffffff;
|
||||
ret = ioctl(fd, DRM_IOCTL_RM_DRAW, &drawarg);
|
||||
assert(ret == -1 && errno == EINVAL);
|
||||
drawable = drawarg.handle;
|
||||
rm_drawable(fd, 0x7fffffff, 1);
|
||||
|
||||
/* Attempt to set cliprects on a nonexistent drawable */
|
||||
set_draw_cliprects_empty_fail(fd, drawable);
|
||||
set_draw_cliprects_empty_fail(fd, d1);
|
||||
|
||||
close(fd);
|
||||
return 0;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue