aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Hourihane <alanh@fairlite.demon.co.uk>2007-06-29 20:09:44 +0100
committerAlan Hourihane <alanh@fairlite.demon.co.uk>2007-06-29 20:09:44 +0100
commit8a78dead291ffdb5a8774419cdca369a1e27cad9 (patch)
tree399b8378e32036bdc7dadc10c639465a8fb21681
parente79e2a58161d44754fd55507e155b7e12a09c4d2 (diff)
parenta27af4c4a665864df09123f177ca7269e48f6171 (diff)
Merge branch 'master' of git+ssh://git.freedesktop.org/git/mesa/drm into modesetting-101
Conflicts: linux-core/drm_drv.c linux-core/drm_fops.c linux-core/drm_objects.h linux-core/drm_stub.c shared-core/i915_dma.c
-rw-r--r--bsd-core/Makefile1
-rw-r--r--bsd-core/ati_pcigart.c21
-rw-r--r--bsd-core/drmP.h28
-rw-r--r--bsd-core/drm_agpsupport.c2
-rw-r--r--bsd-core/drm_drv.c12
-rw-r--r--libdrm/xf86drm.c648
-rw-r--r--libdrm/xf86mm.h58
-rw-r--r--linux-core/Makefile.kernel7
-rw-r--r--linux-core/ati_pcigart.c6
-rw-r--r--linux-core/drmP.h54
-rw-r--r--linux-core/drm_agpsupport.c28
-rw-r--r--linux-core/drm_bo.c137
-rw-r--r--linux-core/drm_bo_move.c6
-rw-r--r--linux-core/drm_bufs.c43
-rw-r--r--linux-core/drm_compat.c123
-rw-r--r--linux-core/drm_compat.h9
-rw-r--r--linux-core/drm_context.c162
-rw-r--r--linux-core/drm_drawable.c226
-rw-r--r--linux-core/drm_drv.c93
-rw-r--r--linux-core/drm_fence.c151
-rw-r--r--linux-core/drm_fops.c47
-rw-r--r--linux-core/drm_ioc32.c1
-rw-r--r--linux-core/drm_ioctl.c14
-rw-r--r--linux-core/drm_irq.c20
-rw-r--r--linux-core/drm_memory.c2
-rw-r--r--linux-core/drm_object.c9
-rw-r--r--linux-core/drm_objects.h28
-rw-r--r--linux-core/drm_pci.c2
-rw-r--r--linux-core/drm_proc.c19
-rw-r--r--linux-core/drm_stub.c16
-rw-r--r--linux-core/drm_vm.c36
-rw-r--r--linux-core/i810_dma.c6
-rw-r--r--linux-core/i915_drv.c6
-rw-r--r--linux-core/i915_fence.c2
-rw-r--r--linux-core/i915_ioc32.c1
-rw-r--r--linux-core/mga_ioc32.c1
-rw-r--r--linux-core/nouveau_ioc32.c1
l---------linux-core/nouveau_notifier.c1
l---------linux-core/nv04_fifo.c1
l---------linux-core/nv10_fifo.c1
l---------linux-core/nv40_fifo.c1
l---------linux-core/nv50_fifo.c1
l---------linux-core/nv50_graph.c1
l---------linux-core/nv50_mc.c1
-rw-r--r--linux-core/r128_ioc32.c1
-rw-r--r--linux-core/radeon_drv.c3
-rw-r--r--linux-core/radeon_ioc32.c32
-rw-r--r--linux-core/sis_mm.c2
-rw-r--r--shared-core/drm_pciids.txt22
-rw-r--r--shared-core/i915_dma.c103
-rw-r--r--shared-core/i915_drm.h5
-rw-r--r--shared-core/i915_drv.h13
-rw-r--r--shared-core/i915_init.c31
-rw-r--r--shared-core/i915_irq.c17
-rw-r--r--shared-core/mga_dma.c2
-rw-r--r--shared-core/nouveau_drm.h28
-rw-r--r--shared-core/nouveau_drv.h169
-rw-r--r--shared-core/nouveau_fifo.c392
-rw-r--r--shared-core/nouveau_mem.c92
-rw-r--r--shared-core/nouveau_notifier.c154
-rw-r--r--shared-core/nouveau_object.c268
-rw-r--r--shared-core/nouveau_reg.h24
-rw-r--r--shared-core/nouveau_state.c192
-rw-r--r--shared-core/nv04_fifo.c126
-rw-r--r--shared-core/nv04_graph.c17
-rw-r--r--shared-core/nv10_fifo.c154
-rw-r--r--shared-core/nv10_graph.c17
-rw-r--r--shared-core/nv20_graph.c33
-rw-r--r--shared-core/nv30_graph.c68
-rw-r--r--shared-core/nv40_fifo.c189
-rw-r--r--shared-core/nv40_graph.c652
-rw-r--r--shared-core/nv50_fifo.c83
-rw-r--r--shared-core/nv50_graph.c84
-rw-r--r--shared-core/nv50_mc.c42
-rw-r--r--shared-core/r300_cmdbuf.c3
-rw-r--r--shared-core/r300_reg.h25
-rw-r--r--shared-core/radeon_cp.c23
-rw-r--r--shared-core/radeon_drm.h5
-rw-r--r--shared-core/radeon_drv.h67
-rw-r--r--shared-core/radeon_irq.c106
-rw-r--r--shared-core/radeon_state.c6
-rw-r--r--shared-core/sis_drv.h8
-rw-r--r--shared-core/via_dma.c49
-rw-r--r--shared-core/via_verifier.c4
84 files changed, 3501 insertions, 1843 deletions
diff --git a/bsd-core/Makefile b/bsd-core/Makefile
index db563a65..00889dae 100644
--- a/bsd-core/Makefile
+++ b/bsd-core/Makefile
@@ -69,4 +69,3 @@ drm_pciids.h: ${SHARED}/drm_pciids.txt
${SHAREDFILES}:
ln -sf ${SHARED}/$@ $@
-
diff --git a/bsd-core/ati_pcigart.c b/bsd-core/ati_pcigart.c
index d48d0a80..682eace6 100644
--- a/bsd-core/ati_pcigart.c
+++ b/bsd-core/ati_pcigart.c
@@ -32,8 +32,6 @@
#include "drmP.h"
#define ATI_PCIGART_PAGE_SIZE 4096 /* PCI GART page size */
-#define ATI_MAX_PCIGART_PAGES 8192 /* 32 MB aperture, 4K pages */
-#define ATI_PCIGART_TABLE_SIZE 32768
int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info)
{
@@ -48,7 +46,7 @@ int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info)
if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) {
/* GART table in system memory */
- dev->sg->dmah = drm_pci_alloc(dev, ATI_PCIGART_TABLE_SIZE, 0,
+ dev->sg->dmah = drm_pci_alloc(dev, gart_info->table_size, 0,
0xfffffffful);
if (dev->sg->dmah == NULL) {
DRM_ERROR("cannot allocate PCI GART table!\n");
@@ -63,9 +61,9 @@ int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info)
pci_gart = gart_info->addr;
}
- pages = DRM_MIN(dev->sg->pages, ATI_MAX_PCIGART_PAGES);
+ pages = DRM_MIN(dev->sg->pages, gart_info->table_size / sizeof(u32));
- bzero(pci_gart, ATI_PCIGART_TABLE_SIZE);
+ bzero(pci_gart, gart_info->table_size);
KASSERT(PAGE_SIZE >= ATI_PCIGART_PAGE_SIZE, ("page size too small"));
@@ -73,10 +71,17 @@ int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info)
page_base = (u32) dev->sg->busaddr[i];
for (j = 0; j < (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); j++) {
- if (gart_info->is_pcie)
- *pci_gart = (cpu_to_le32(page_base) >> 8) | 0xc;
- else
+ switch(gart_info->gart_reg_if) {
+ case DRM_ATI_GART_IGP:
+ *pci_gart = cpu_to_le32(page_base | 0xc);
+ break;
+ case DRM_ATI_GART_PCIE:
+ *pci_gart = cpu_to_le32((page_base >> 8) | 0xc);
+ break;
+ default:
*pci_gart = cpu_to_le32(page_base);
+ break;
+ }
pci_gart++;
page_base += ATI_PCIGART_PAGE_SIZE;
}
diff --git a/bsd-core/drmP.h b/bsd-core/drmP.h
index 9ebb12ae..9ba3d502 100644
--- a/bsd-core/drmP.h
+++ b/bsd-core/drmP.h
@@ -47,6 +47,9 @@ typedef struct drm_file drm_file_t;
#include <sys/systm.h>
#include <sys/conf.h>
#include <sys/stat.h>
+#if __FreeBSD_version >= 700000
+#include <sys/priv.h>
+#endif
#include <sys/proc.h>
#include <sys/lock.h>
#include <sys/fcntl.h>
@@ -230,7 +233,11 @@ enum {
#define PAGE_ALIGN(addr) round_page(addr)
/* DRM_SUSER returns true if the user is superuser */
+#if __FreeBSD_version >= 700000
+#define DRM_SUSER(p) (priv_check(p, PRIV_DRIVER) == 0)
+#else
#define DRM_SUSER(p) (suser(p) == 0)
+#endif
#define DRM_AGP_FIND_DEVICE() agp_find_device()
#define DRM_MTRR_WC MDF_WRITECOMBINE
#define jiffies ticks
@@ -394,19 +401,6 @@ do { \
} \
} while (0)
-#define DRM_GETSAREA() \
-do { \
- drm_local_map_t *map; \
- DRM_SPINLOCK_ASSERT(&dev->dev_lock); \
- TAILQ_FOREACH(map, &dev->maplist, link) { \
- if (map->type == _DRM_SHM && \
- map->flags & _DRM_CONTAINS_LOCK) { \
- dev_priv->sarea = map; \
- break; \
- } \
- } \
-} while (0)
-
#if defined(__FreeBSD__) && __FreeBSD_version > 500000
#define DRM_WAIT_ON( ret, queue, timeout, condition ) \
for ( ret = 0 ; !ret && !(condition) ; ) { \
@@ -627,12 +621,17 @@ typedef struct drm_vbl_sig {
#define DRM_ATI_GART_MAIN 1
#define DRM_ATI_GART_FB 2
+#define DRM_ATI_GART_PCI 1
+#define DRM_ATI_GART_PCIE 2
+#define DRM_ATI_GART_IGP 3
+
typedef struct ati_pcigart_info {
int gart_table_location;
- int is_pcie;
+ int gart_reg_if;
void *addr;
dma_addr_t bus_addr;
drm_local_map_t mapping;
+ int table_size;
} drm_ati_pcigart_info;
struct drm_driver_info {
@@ -822,6 +821,7 @@ dev_type_read(drm_read);
dev_type_poll(drm_poll);
dev_type_mmap(drm_mmap);
#endif
+extern drm_local_map_t *drm_getsarea(drm_device_t *dev);
/* File operations helpers (drm_fops.c) */
#ifdef __FreeBSD__
diff --git a/bsd-core/drm_agpsupport.c b/bsd-core/drm_agpsupport.c
index 0406f50e..28239d1b 100644
--- a/bsd-core/drm_agpsupport.c
+++ b/bsd-core/drm_agpsupport.c
@@ -43,7 +43,7 @@ static int
drm_device_find_capability(drm_device_t *dev, int cap)
{
#ifdef __FreeBSD__
-#if __FreeBSD_version >= 700010
+#if __FreeBSD_version >= 602102
return (pci_find_extcap(dev->device, cap, NULL) == 0);
#else
diff --git a/bsd-core/drm_drv.c b/bsd-core/drm_drv.c
index 9fb10c53..baaeb43c 100644
--- a/bsd-core/drm_drv.c
+++ b/bsd-core/drm_drv.c
@@ -912,6 +912,18 @@ int drm_ioctl(struct cdev *kdev, u_long cmd, caddr_t data, int flags,
return DRM_ERR(retcode);
}
+drm_local_map_t *drm_getsarea(drm_device_t *dev)
+{
+ drm_local_map_t *map;
+
+ DRM_SPINLOCK_ASSERT(&dev->dev_lock);
+ TAILQ_FOREACH(map, &dev->maplist, link) {
+ if (map->type == _DRM_SHM && (map->flags & _DRM_CONTAINS_LOCK))
+ return map;
+ }
+
+ return NULL;
+}
#if DRM_LINUX
diff --git a/libdrm/xf86drm.c b/libdrm/xf86drm.c
index 78efcf2a..93185512 100644
--- a/libdrm/xf86drm.c
+++ b/libdrm/xf86drm.c
@@ -92,7 +92,7 @@ static drmServerInfoPtr drm_server_info;
void drmSetServerInfo(drmServerInfoPtr info)
{
- drm_server_info = info;
+ drm_server_info = info;
}
/**
@@ -106,7 +106,7 @@ void drmSetServerInfo(drmServerInfoPtr info)
static int drmDebugPrint(const char *format, va_list ap)
{
- return vfprintf(stderr, format, ap);
+ return vfprintf(stderr, format, ap);
}
static int (*drm_debug_print)(const char *format, va_list ap) = drmDebugPrint;
@@ -131,26 +131,28 @@ drmMsg(const char *format, ...)
void
drmSetDebugMsgFunction(int (*debug_msg_ptr)(const char *format, va_list ap))
{
- drm_debug_print = debug_msg_ptr;
+ drm_debug_print = debug_msg_ptr;
}
static void *drmHashTable = NULL; /* Context switch callbacks */
void *drmGetHashTable(void)
{
- return drmHashTable;
+ return drmHashTable;
}
void *drmMalloc(int size)
{
void *pt;
- if ((pt = malloc(size))) memset(pt, 0, size);
+ if ((pt = malloc(size)))
+ memset(pt, 0, size);
return pt;
}
void drmFree(void *pt)
{
- if (pt) free(pt);
+ if (pt)
+ free(pt);
}
/* drmStrdup can't use strdup(3), since it doesn't call _DRM_MALLOC... */
@@ -186,7 +188,8 @@ drmHashEntry *drmGetEntry(int fd)
void *value;
drmHashEntry *entry;
- if (!drmHashTable) drmHashTable = drmHashCreate();
+ if (!drmHashTable)
+ drmHashTable = drmHashCreate();
if (drmHashLookup(drmHashTable, key, &value)) {
entry = drmMalloc(sizeof(*entry));
@@ -276,14 +279,15 @@ static int drmOpenDevice(long dev, int minor)
drmMsg("drmOpenDevice: node name is %s\n", buf);
if (drm_server_info) {
- drm_server_info->get_perms(&serv_group, &serv_mode);
- devmode = serv_mode ? serv_mode : DRM_DEV_MODE;
- devmode &= ~(S_IXUSR|S_IXGRP|S_IXOTH);
- group = (serv_group >= 0) ? serv_group : DRM_DEV_GID;
+ drm_server_info->get_perms(&serv_group, &serv_mode);
+ devmode = serv_mode ? serv_mode : DRM_DEV_MODE;
+ devmode &= ~(S_IXUSR|S_IXGRP|S_IXOTH);
+ group = (serv_group >= 0) ? serv_group : DRM_DEV_GID;
}
if (stat(DRM_DIR_NAME, &st)) {
- if (!isroot) return DRM_ERR_NOT_ROOT;
+ if (!isroot)
+ return DRM_ERR_NOT_ROOT;
mkdir(DRM_DIR_NAME, DRM_DEV_DIRMODE);
chown(DRM_DIR_NAME, 0, 0); /* root:root */
chmod(DRM_DIR_NAME, DRM_DEV_DIRMODE);
@@ -291,37 +295,41 @@ static int drmOpenDevice(long dev, int minor)
/* Check if the device node exists and create it if necessary. */
if (stat(buf, &st)) {
- if (!isroot) return DRM_ERR_NOT_ROOT;
+ if (!isroot)
+ return DRM_ERR_NOT_ROOT;
remove(buf);
mknod(buf, S_IFCHR | devmode, dev);
}
if (drm_server_info) {
- chown(buf, user, group);
- chmod(buf, devmode);
+ chown(buf, user, group);
+ chmod(buf, devmode);
}
fd = open(buf, O_RDWR, 0);
drmMsg("drmOpenDevice: open result is %d, (%s)\n",
fd, fd < 0 ? strerror(errno) : "OK");
- if (fd >= 0) return fd;
+ if (fd >= 0)
+ return fd;
/* Check if the device node is not what we expect it to be, and recreate it
* and try again if so.
*/
if (st.st_rdev != dev) {
- if (!isroot) return DRM_ERR_NOT_ROOT;
+ if (!isroot)
+ return DRM_ERR_NOT_ROOT;
remove(buf);
mknod(buf, S_IFCHR | devmode, dev);
if (drm_server_info) {
- chown(buf, user, group);
- chmod(buf, devmode);
+ chown(buf, user, group);
+ chmod(buf, devmode);
}
}
fd = open(buf, O_RDWR, 0);
drmMsg("drmOpenDevice: open result is %d, (%s)\n",
fd, fd < 0 ? strerror(errno) : "OK");
- if (fd >= 0) return fd;
+ if (fd >= 0)
+ return fd;
drmMsg("drmOpenDevice: Open failed\n");
remove(buf);
@@ -346,10 +354,12 @@ static int drmOpenMinor(int minor, int create)
int fd;
char buf[64];
- if (create) return drmOpenDevice(makedev(DRM_MAJOR, minor), minor);
+ if (create)
+ return drmOpenDevice(makedev(DRM_MAJOR, minor), minor);
sprintf(buf, DRM_DEV_NAME, DRM_DIR_NAME, minor);
- if ((fd = open(buf, O_RDWR, 0)) >= 0) return fd;
+ if ((fd = open(buf, O_RDWR, 0)) >= 0)
+ return fd;
return -errno;
}
@@ -373,7 +383,8 @@ int drmAvailable(void)
if ((fd = drmOpenMinor(0, 1)) < 0) {
#ifdef __linux__
/* Try proc for backward Linux compatibility */
- if (!access("/proc/dri/0", R_OK)) return 1;
+ if (!access("/proc/dri/0", R_OK))
+ return 1;
#endif
return 0;
}
@@ -424,7 +435,8 @@ static int drmOpenByBusid(const char *busid)
drmFreeBusid(buf);
return fd;
}
- if (buf) drmFreeBusid(buf);
+ if (buf)
+ drmFreeBusid(buf);
close(fd);
}
}
@@ -454,16 +466,16 @@ static int drmOpenByName(const char *name)
char * id;
if (!drmAvailable()) {
- if (!drm_server_info)
- return -1;
- else {
- /* try to load the kernel module now */
- if (!drm_server_info->load_module(name)) {
- drmMsg("[drm] failed to load kernel module \"%s\"\n",
- name);
- return -1;
- }
- }
+ if (!drm_server_info) {
+ return -1;
+ }
+ else {
+ /* try to load the kernel module now */
+ if (!drm_server_info->load_module(name)) {
+ drmMsg("[drm] failed to load kernel module \"%s\"\n", name);
+ return -1;
+ }
+ }
}
/*
@@ -548,16 +560,13 @@ int drmOpen(const char *name, const char *busid)
if (!drmAvailable() && name != NULL && drm_server_info) {
/* try to load the kernel */
if (!drm_server_info->load_module(name)) {
- drmMsg("[drm] failed to load kernel module \"%s\"\n",
- name);
+ drmMsg("[drm] failed to load kernel module \"%s\"\n", name);
return -1;
}
}
if (busid) {
- int fd;
-
- fd = drmOpenByBusid(busid);
+ int fd = drmOpenByBusid(busid);
if (fd >= 0)
return fd;
}
@@ -580,7 +589,8 @@ int drmOpen(const char *name, const char *busid)
*/
void drmFreeVersion(drmVersionPtr v)
{
- if (!v) return;
+ if (!v)
+ return;
drmFree(v->name);
drmFree(v->date);
drmFree(v->desc);
@@ -599,7 +609,8 @@ void drmFreeVersion(drmVersionPtr v)
*/
static void drmFreeKernelVersion(drm_version_t *v)
{
- if (!v) return;
+ if (!v)
+ return;
drmFree(v->name);
drmFree(v->date);
drmFree(v->desc);
@@ -756,9 +767,11 @@ char *drmGetBusid(int fd)
u.unique_len = 0;
u.unique = NULL;
- if (ioctl(fd, DRM_IOCTL_GET_UNIQUE, &u)) return NULL;
+ if (ioctl(fd, DRM_IOCTL_GET_UNIQUE, &u))
+ return NULL;
u.unique = drmMalloc(u.unique_len + 1);
- if (ioctl(fd, DRM_IOCTL_GET_UNIQUE, &u)) return NULL;
+ if (ioctl(fd, DRM_IOCTL_GET_UNIQUE, &u))
+ return NULL;
u.unique[u.unique_len] = '\0';
return u.unique;
@@ -795,7 +808,8 @@ int drmGetMagic(int fd, drm_magic_t * magic)
drm_auth_t auth;
*magic = 0;
- if (ioctl(fd, DRM_IOCTL_GET_MAGIC, &auth)) return -errno;
+ if (ioctl(fd, DRM_IOCTL_GET_MAGIC, &auth))
+ return -errno;
*magic = auth.magic;
return 0;
}
@@ -805,7 +819,8 @@ int drmAuthMagic(int fd, drm_magic_t magic)
drm_auth_t auth;
auth.magic = magic;
- if (ioctl(fd, DRM_IOCTL_AUTH_MAGIC, &auth)) return -errno;
+ if (ioctl(fd, DRM_IOCTL_AUTH_MAGIC, &auth))
+ return -errno;
return 0;
}
@@ -869,8 +884,10 @@ int drmAddMap(int fd, drm_handle_t offset, drmSize size, drmMapType type,
map.handle = 0;
map.type = type;
map.flags = flags;
- if (ioctl(fd, DRM_IOCTL_ADD_MAP, &map)) return -errno;
- if (handle) *handle = (drm_handle_t)map.handle;
+ if (ioctl(fd, DRM_IOCTL_ADD_MAP, &map))
+ return -errno;
+ if (handle)
+ *handle = (drm_handle_t)map.handle;
return 0;
}
@@ -880,7 +897,8 @@ int drmRmMap(int fd, drm_handle_t handle)
map.handle = (void *)handle;
- if(ioctl(fd, DRM_IOCTL_RM_MAP, &map)) return -errno;
+ if(ioctl(fd, DRM_IOCTL_RM_MAP, &map))
+ return -errno;
return 0;
}
@@ -912,7 +930,8 @@ int drmAddBufs(int fd, int count, int size, drmBufDescFlags flags,
request.flags = flags;
request.agp_start = agp_offset;
- if (ioctl(fd, DRM_IOCTL_ADD_BUFS, &request)) return -errno;
+ if (ioctl(fd, DRM_IOCTL_ADD_BUFS, &request))
+ return -errno;
return request.count;
}
@@ -924,9 +943,11 @@ int drmMarkBufs(int fd, double low, double high)
info.count = 0;
info.list = NULL;
- if (ioctl(fd, DRM_IOCTL_INFO_BUFS, &info)) return -EINVAL;
+ if (ioctl(fd, DRM_IOCTL_INFO_BUFS, &info))
+ return -EINVAL;
- if (!info.count) return -EINVAL;
+ if (!info.count)
+ return -EINVAL;
if (!(info.list = drmMalloc(info.count * sizeof(*info.list))))
return -ENOMEM;
@@ -972,7 +993,8 @@ int drmFreeBufs(int fd, int count, int *list)
request.count = count;
request.list = list;
- if (ioctl(fd, DRM_IOCTL_FREE_BUFS, &request)) return -errno;
+ if (ioctl(fd, DRM_IOCTL_FREE_BUFS, &request))
+ return -errno;
return 0;
}
@@ -1020,7 +1042,8 @@ int drmMap(int fd, drm_handle_t handle, drmSize size, drmAddressPtr address)
{
static unsigned long pagesize_mask = 0;
- if (fd < 0) return -EINVAL;
+ if (fd < 0)
+ return -EINVAL;
if (!pagesize_mask)
pagesize_mask = getpagesize() - 1;
@@ -1028,7 +1051,8 @@ int drmMap(int fd, drm_handle_t handle, drmSize size, drmAddressPtr address)
size = (size + pagesize_mask) & ~pagesize_mask;
*address = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, handle);
- if (*address == MAP_FAILED) return -errno;
+ if (*address == MAP_FAILED)
+ return -errno;
return 0;
}
@@ -1058,7 +1082,8 @@ drmBufInfoPtr drmGetBufInfo(int fd)
info.count = 0;
info.list = NULL;
- if (ioctl(fd, DRM_IOCTL_INFO_BUFS, &info)) return NULL;
+ if (ioctl(fd, DRM_IOCTL_INFO_BUFS, &info))
+ return NULL;
if (info.count) {
if (!(info.list = drmMalloc(info.count * sizeof(*info.list))))
@@ -1108,9 +1133,11 @@ drmBufMapPtr drmMapBufs(int fd)
bufs.count = 0;
bufs.list = NULL;
bufs.virtual = NULL;
- if (ioctl(fd, DRM_IOCTL_MAP_BUFS, &bufs)) return NULL;
+ if (ioctl(fd, DRM_IOCTL_MAP_BUFS, &bufs))
+ return NULL;
- if (!bufs.count) return NULL;
+ if (!bufs.count)
+ return NULL;
if (!(bufs.list = drmMalloc(bufs.count * sizeof(*bufs.list))))
return NULL;
@@ -1265,20 +1292,25 @@ drm_context_t *drmGetReservedContextList(int fd, int *count)
res.count = 0;
res.contexts = NULL;
- if (ioctl(fd, DRM_IOCTL_RES_CTX, &res)) return NULL;
+ if (ioctl(fd, DRM_IOCTL_RES_CTX, &res))
+ return NULL;
- if (!res.count) return NULL;
+ if (!res.count)
+ return NULL;
- if (!(list = drmMalloc(res.count * sizeof(*list)))) return NULL;
+ if (!(list = drmMalloc(res.count * sizeof(*list))))
+ return NULL;
if (!(retval = drmMalloc(res.count * sizeof(*retval)))) {
drmFree(list);
return NULL;
}
res.contexts = list;
- if (ioctl(fd, DRM_IOCTL_RES_CTX, &res)) return NULL;
+ if (ioctl(fd, DRM_IOCTL_RES_CTX, &res))
+ return NULL;
- for (i = 0; i < res.count; i++) retval[i] = list[i].handle;
+ for (i = 0; i < res.count; i++)
+ retval[i] = list[i].handle;
drmFree(list);
*count = res.count;
@@ -1313,7 +1345,8 @@ int drmCreateContext(int fd, drm_context_t *handle)
drm_ctx_t ctx;
ctx.flags = 0; /* Modified with functions below */
- if (ioctl(fd, DRM_IOCTL_ADD_CTX, &ctx)) return -errno;
+ if (ioctl(fd, DRM_IOCTL_ADD_CTX, &ctx))
+ return -errno;
*handle = ctx.handle;
return 0;
}
@@ -1323,7 +1356,8 @@ int drmSwitchToContext(int fd, drm_context_t context)
drm_ctx_t ctx;
ctx.handle = context;
- if (ioctl(fd, DRM_IOCTL_SWITCH_CTX, &ctx)) return -errno;
+ if (ioctl(fd, DRM_IOCTL_SWITCH_CTX, &ctx))
+ return -errno;
return 0;
}
@@ -1339,9 +1373,12 @@ int drmSetContextFlags(int fd, drm_context_t context, drm_context_tFlags flags)
*/
ctx.handle = context;
ctx.flags = 0;
- if (flags & DRM_CONTEXT_PRESERVED) ctx.flags |= _DRM_CONTEXT_PRESERVED;
- if (flags & DRM_CONTEXT_2DONLY) ctx.flags |= _DRM_CONTEXT_2DONLY;
- if (ioctl(fd, DRM_IOCTL_MOD_CTX, &ctx)) return -errno;
+ if (flags & DRM_CONTEXT_PRESERVED)
+ ctx.flags |= _DRM_CONTEXT_PRESERVED;
+ if (flags & DRM_CONTEXT_2DONLY)
+ ctx.flags |= _DRM_CONTEXT_2DONLY;
+ if (ioctl(fd, DRM_IOCTL_MOD_CTX, &ctx))
+ return -errno;
return 0;
}
@@ -1351,10 +1388,13 @@ int drmGetContextFlags(int fd, drm_context_t context,
drm_ctx_t ctx;
ctx.handle = context;
- if (ioctl(fd, DRM_IOCTL_GET_CTX, &ctx)) return -errno;
+ if (ioctl(fd, DRM_IOCTL_GET_CTX, &ctx))
+ return -errno;
*flags = 0;
- if (ctx.flags & _DRM_CONTEXT_PRESERVED) *flags |= DRM_CONTEXT_PRESERVED;
- if (ctx.flags & _DRM_CONTEXT_2DONLY) *flags |= DRM_CONTEXT_2DONLY;
+ if (ctx.flags & _DRM_CONTEXT_PRESERVED)
+ *flags |= DRM_CONTEXT_PRESERVED;
+ if (ctx.flags & _DRM_CONTEXT_2DONLY)
+ *flags |= DRM_CONTEXT_2DONLY;
return 0;
}
@@ -1379,14 +1419,16 @@ int drmDestroyContext(int fd, drm_context_t handle)
{
drm_ctx_t ctx;
ctx.handle = handle;
- if (ioctl(fd, DRM_IOCTL_RM_CTX, &ctx)) return -errno;
+ if (ioctl(fd, DRM_IOCTL_RM_CTX, &ctx))
+ return -errno;
return 0;
}
int drmCreateDrawable(int fd, drm_drawable_t *handle)
{
drm_draw_t draw;
- if (ioctl(fd, DRM_IOCTL_ADD_DRAW, &draw)) return -errno;
+ if (ioctl(fd, DRM_IOCTL_ADD_DRAW, &draw))
+ return -errno;
*handle = draw.handle;
return 0;
}
@@ -1395,7 +1437,8 @@ int drmDestroyDrawable(int fd, drm_drawable_t handle)
{
drm_draw_t draw;
draw.handle = handle;
- if (ioctl(fd, DRM_IOCTL_RM_DRAW, &draw)) return -errno;
+ if (ioctl(fd, DRM_IOCTL_RM_DRAW, &draw))
+ return -errno;
return 0;
}
@@ -1410,7 +1453,8 @@ int drmUpdateDrawableInfo(int fd, drm_drawable_t handle,
update.num = num;
update.data = (unsigned long long)(unsigned long)data;
- if (ioctl(fd, DRM_IOCTL_UPDATE_DRAW, &update)) return -errno;
+ if (ioctl(fd, DRM_IOCTL_UPDATE_DRAW, &update))
+ return -errno;
return 0;
}
@@ -1429,7 +1473,8 @@ int drmUpdateDrawableInfo(int fd, drm_drawable_t handle,
*/
int drmAgpAcquire(int fd)
{
- if (ioctl(fd, DRM_IOCTL_AGP_ACQUIRE, NULL)) return -errno;
+ if (ioctl(fd, DRM_IOCTL_AGP_ACQUIRE, NULL))
+ return -errno;
return 0;
}
@@ -1446,7 +1491,8 @@ int drmAgpAcquire(int fd)
*/
int drmAgpRelease(int fd)
{
- if (ioctl(fd, DRM_IOCTL_AGP_RELEASE, NULL)) return -errno;
+ if (ioctl(fd, DRM_IOCTL_AGP_RELEASE, NULL))
+ return -errno;
return 0;
}
@@ -1468,7 +1514,8 @@ int drmAgpEnable(int fd, unsigned long mode)
drm_agp_mode_t m;
m.mode = mode;
- if (ioctl(fd, DRM_IOCTL_AGP_ENABLE, &m)) return -errno;
+ if (ioctl(fd, DRM_IOCTL_AGP_ENABLE, &m))
+ return -errno;
return 0;
}
@@ -1498,8 +1545,10 @@ int drmAgpAlloc(int fd, unsigned long size, unsigned long type,
b.size = size;
b.handle = 0;
b.type = type;
- if (ioctl(fd, DRM_IOCTL_AGP_ALLOC, &b)) return -errno;
- if (address != 0UL) *address = b.physical;
+ if (ioctl(fd, DRM_IOCTL_AGP_ALLOC, &b))
+ return -errno;
+ if (address != 0UL)
+ *address = b.physical;
*handle = b.handle;
return 0;
}
@@ -1523,7 +1572,8 @@ int drmAgpFree(int fd, drm_handle_t handle)
b.size = 0;
b.handle = handle;
- if (ioctl(fd, DRM_IOCTL_AGP_FREE, &b)) return -errno;
+ if (ioctl(fd, DRM_IOCTL_AGP_FREE, &b))
+ return -errno;
return 0;
}
@@ -1547,7 +1597,8 @@ int drmAgpBind(int fd, drm_handle_t handle, unsigned long offset)
b.handle = handle;
b.offset = offset;
- if (ioctl(fd, DRM_IOCTL_AGP_BIND, &b)) return -errno;
+ if (ioctl(fd, DRM_IOCTL_AGP_BIND, &b))
+ return -errno;
return 0;
}
@@ -1570,7 +1621,8 @@ int drmAgpUnbind(int fd, drm_handle_t handle)
b.handle = handle;
b.offset = 0;
- if (ioctl(fd, DRM_IOCTL_AGP_UNBIND, &b)) return -errno;
+ if (ioctl(fd, DRM_IOCTL_AGP_UNBIND, &b))
+ return -errno;
return 0;
}
@@ -1590,7 +1642,8 @@ int drmAgpVersionMajor(int fd)
{
drm_agp_info_t i;
- if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return -errno;
+ if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i))
+ return -errno;
return i.agp_version_major;
}
@@ -1610,7 +1663,8 @@ int drmAgpVersionMinor(int fd)
{
drm_agp_info_t i;
- if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return -errno;
+ if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i))
+ return -errno;
return i.agp_version_minor;
}
@@ -1630,7 +1684,8 @@ unsigned long drmAgpGetMode(int fd)
{
drm_agp_info_t i;
- if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0;
+ if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i))
+ return 0;
return i.mode;
}
@@ -1650,7 +1705,8 @@ unsigned long drmAgpBase(int fd)
{
drm_agp_info_t i;
- if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0;
+ if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i))
+ return 0;
return i.aperture_base;
}
@@ -1670,7 +1726,8 @@ unsigned long drmAgpSize(int fd)
{
drm_agp_info_t i;
- if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0;
+ if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i))
+ return 0;
return i.aperture_size;
}
@@ -1690,7 +1747,8 @@ unsigned long drmAgpMemoryUsed(int fd)
{
drm_agp_info_t i;
- if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0;
+ if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i))
+ return 0;
return i.memory_used;
}
@@ -1710,7 +1768,8 @@ unsigned long drmAgpMemoryAvail(int fd)
{
drm_agp_info_t i;
- if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0;
+ if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i))
+ return 0;
return i.memory_allowed;
}
@@ -1730,7 +1789,8 @@ unsigned int drmAgpVendorId(int fd)
{
drm_agp_info_t i;
- if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0;
+ if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i))
+ return 0;
return i.id_vendor;
}
@@ -1750,7 +1810,8 @@ unsigned int drmAgpDeviceId(int fd)
{
drm_agp_info_t i;
- if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0;
+ if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i))
+ return 0;
return i.id_device;
}
@@ -1761,7 +1822,8 @@ int drmScatterGatherAlloc(int fd, unsigned long size, drm_handle_t *handle)
*handle = 0;
sg.size = size;
sg.handle = 0;
- if (ioctl(fd, DRM_IOCTL_SG_ALLOC, &sg)) return -errno;
+ if (ioctl(fd, DRM_IOCTL_SG_ALLOC, &sg))
+ return -errno;
*handle = sg.handle;
return 0;
}
@@ -1772,7 +1834,8 @@ int drmScatterGatherFree(int fd, drm_handle_t handle)
sg.size = 0;
sg.handle = handle;
- if (ioctl(fd, DRM_IOCTL_SG_FREE, &sg)) return -errno;
+ if (ioctl(fd, DRM_IOCTL_SG_FREE, &sg))
+ return -errno;
return 0;
}
@@ -1802,12 +1865,21 @@ int drmWaitVBlank(int fd, drmVBlankPtr vbl)
int drmError(int err, const char *label)
{
switch (err) {
- case DRM_ERR_NO_DEVICE: fprintf(stderr, "%s: no device\n", label); break;
- case DRM_ERR_NO_ACCESS: fprintf(stderr, "%s: no access\n", label); break;
- case DRM_ERR_NOT_ROOT: fprintf(stderr, "%s: not root\n", label); break;
- case DRM_ERR_INVALID: fprintf(stderr, "%s: invalid args\n", label);break;
+ case DRM_ERR_NO_DEVICE:
+ fprintf(stderr, "%s: no device\n", label);
+ break;
+ case DRM_ERR_NO_ACCESS:
+ fprintf(stderr, "%s: no access\n", label);
+ break;
+ case DRM_ERR_NOT_ROOT:
+ fprintf(stderr, "%s: not root\n", label);
+ break;
+ case DRM_ERR_INVALID:
+ fprintf(stderr, "%s: invalid args\n", label);
+ break;
default:
- if (err < 0) err = -err;
+ if (err < 0)
+ err = -err;
fprintf( stderr, "%s: error %d (%s)\n", label, err, strerror(err) );
break;
}
@@ -1833,7 +1905,8 @@ int drmCtlInstHandler(int fd, int irq)
ctl.func = DRM_INST_HANDLER;
ctl.irq = irq;
- if (ioctl(fd, DRM_IOCTL_CONTROL, &ctl)) return -errno;
+ if (ioctl(fd, DRM_IOCTL_CONTROL, &ctl))
+ return -errno;
return 0;
}
@@ -1855,7 +1928,8 @@ int drmCtlUninstHandler(int fd)
ctl.func = DRM_UNINST_HANDLER;
ctl.irq = 0;
- if (ioctl(fd, DRM_IOCTL_CONTROL, &ctl)) return -errno;
+ if (ioctl(fd, DRM_IOCTL_CONTROL, &ctl))
+ return -errno;
return 0;
}
@@ -1871,7 +1945,8 @@ int drmFinish(int fd, int context, drmLockFlags flags)
if (flags & DRM_LOCK_FLUSH_ALL) lock.flags |= _DRM_LOCK_FLUSH_ALL;
if (flags & DRM_HALT_ALL_QUEUES) lock.flags |= _DRM_HALT_ALL_QUEUES;
if (flags & DRM_HALT_CUR_QUEUES) lock.flags |= _DRM_HALT_CUR_QUEUES;
- if (ioctl(fd, DRM_IOCTL_FINISH, &lock)) return -errno;
+ if (ioctl(fd, DRM_IOCTL_FINISH, &lock))
+ return -errno;
return 0;
}
@@ -1896,7 +1971,8 @@ int drmGetInterruptFromBusID(int fd, int busnum, int devnum, int funcnum)
p.busnum = busnum;
p.devnum = devnum;
p.funcnum = funcnum;
- if (ioctl(fd, DRM_IOCTL_IRQ_BUSID, &p)) return -errno;
+ if (ioctl(fd, DRM_IOCTL_IRQ_BUSID, &p))
+ return -errno;
return p.irq;
}
@@ -1923,7 +1999,8 @@ void *drmGetContextTag(int fd, drm_context_t context)
drmHashEntry *entry = drmGetEntry(fd);
void *value;
- if (drmHashLookup(entry->tagTable, context, &value)) return NULL;
+ if (drmHashLookup(entry->tagTable, context, &value))
+ return NULL;
return value;
}
@@ -1936,7 +2013,8 @@ int drmAddContextPrivateMapping(int fd, drm_context_t ctx_id,
map.ctx_id = ctx_id;
map.handle = (void *)handle;
- if (ioctl(fd, DRM_IOCTL_SET_SAREA_CTX, &map)) return -errno;
+ if (ioctl(fd, DRM_IOCTL_SET_SAREA_CTX, &map))
+ return -errno;
return 0;
}
@@ -1947,8 +2025,10 @@ int drmGetContextPrivateMapping(int fd, drm_context_t ctx_id,
map.ctx_id = ctx_id;
- if (ioctl(fd, DRM_IOCTL_GET_SAREA_CTX, &map)) return -errno;
- if (handle) *handle = (drm_handle_t)map.handle;
+ if (ioctl(fd, DRM_IOCTL_GET_SAREA_CTX, &map))
+ return -errno;
+ if (handle)
+ *handle = (drm_handle_t)map.handle;
return 0;
}
@@ -1960,7 +2040,8 @@ int drmGetMap(int fd, int idx, drm_handle_t *offset, drmSize *size,
drm_map_t map;
map.offset = idx;
- if (ioctl(fd, DRM_IOCTL_GET_MAP, &map)) return -errno;
+ if (ioctl(fd, DRM_IOCTL_GET_MAP, &map))
+ return -errno;
*offset = map.offset;
*size = map.size;
*type = map.type;
@@ -1976,7 +2057,8 @@ int drmGetClient(int fd, int idx, int *auth, int *pid, int *uid,
drm_client_t client;
client.idx = idx;
- if (ioctl(fd, DRM_IOCTL_GET_CLIENT, &client)) return -errno;
+ if (ioctl(fd, DRM_IOCTL_GET_CLIENT, &client))
+ return -errno;
*auth = client.auth;
*pid = client.pid;
*uid = client.uid;
@@ -1990,7 +2072,8 @@ int drmGetStats(int fd, drmStatsT *stats)
drm_stats_t s;
int i;
- if (ioctl(fd, DRM_IOCTL_GET_STATS, &s)) return -errno;
+ if (ioctl(fd, DRM_IOCTL_GET_STATS, &s))
+ return -errno;
stats->count = 0;
memset(stats, 0, sizeof(*stats));
@@ -2292,7 +2375,7 @@ int drmFenceCreate(int fd, unsigned flags, int class, unsigned type,
int drmFenceBuffers(int fd, unsigned flags, drmFence *fence)
{
drm_fence_arg_t arg;
-
+
memset(&arg, 0, sizeof(arg));
arg.flags = flags;
arg.op = drm_fence_buffers;
@@ -2309,7 +2392,7 @@ int drmFenceBuffers(int fd, unsigned flags, drmFence *fence)
int drmFenceDestroy(int fd, const drmFence *fence)
{
drm_fence_arg_t arg;
-
+
memset(&arg, 0, sizeof(arg));
arg.handle = fence->handle;
arg.op = drm_fence_destroy;
@@ -2321,7 +2404,7 @@ int drmFenceDestroy(int fd, const drmFence *fence)
int drmFenceReference(int fd, unsigned handle, drmFence *fence)
{
drm_fence_arg_t arg;
-
+
memset(&arg, 0, sizeof(arg));
arg.handle = handle;
arg.op = drm_fence_reference;
@@ -2338,7 +2421,7 @@ int drmFenceReference(int fd, unsigned handle, drmFence *fence)
int drmFenceUnreference(int fd, const drmFence *fence)
{
drm_fence_arg_t arg;
-
+
memset(&arg, 0, sizeof(arg));
arg.handle = fence->handle;
arg.op = drm_fence_unreference;
@@ -2350,7 +2433,7 @@ int drmFenceUnreference(int fd, const drmFence *fence)
int drmFenceFlush(int fd, drmFence *fence, unsigned flush_type)
{
drm_fence_arg_t arg;
-
+
memset(&arg, 0, sizeof(arg));
arg.handle = fence->handle;
arg.type = flush_type;
@@ -2365,8 +2448,8 @@ int drmFenceFlush(int fd, drmFence *fence, unsigned flush_type)
int drmFenceUpdate(int fd, drmFence *fence)
{
- drm_fence_arg_t arg;
-
+ drm_fence_arg_t arg;
+
memset(&arg, 0, sizeof(arg));
arg.handle = fence->handle;
arg.op = drm_fence_signaled;
@@ -2381,13 +2464,9 @@ int drmFenceUpdate(int fd, drmFence *fence)
int drmFenceSignaled(int fd, drmFence *fence, unsigned fenceType,
int *signaled)
{
- int
- ret;
-
if ((fence->flags & DRM_FENCE_FLAG_SHAREABLE) ||
((fenceType & fence->signaled) != fenceType)) {
-
- ret = drmFenceFlush(fd, fence, fenceType);
+ int ret = drmFenceFlush(fd, fence, fenceType);
if (ret)
return ret;
}
@@ -2514,8 +2593,8 @@ void drmBOFreeList(drmBOList *list)
}
}
-int drmBOResetList(drmBOList *list) {
-
+int drmBOResetList(drmBOList *list)
+{
drmMMListHead *l;
int ret;
@@ -2524,7 +2603,7 @@ int drmBOResetList(drmBOList *list) {
return ret;
l = list->list.next;
- while(l != &list->list) {
+ while (l != &list->list) {
DRMLISTDEL(l);
DRMLISTADD(l, &list->free);
list->numOnList--;
@@ -2547,7 +2626,8 @@ static drmBONode *drmAddListItem(drmBOList *list, drmBO *item,
return NULL;
}
list->numCurrent++;
- } else {
+ }
+ else {
DRMLISTDEL(l);
node = DRMLISTENTRY(drmBONode, l, head);
}
@@ -2584,7 +2664,6 @@ drmBO *drmBOListBuf(void *iterator)
drmBONode *node;
drmMMListHead *l = (drmMMListHead *) iterator;
node = DRMLISTENTRY(drmBONode, l, head);
-
return node->buf;
}
@@ -2599,8 +2678,7 @@ int drmBOCreateList(int numTarget, drmBOList *list)
return drmAdjustListNodes(list);
}
-static void drmBOCopyReply(const drm_bo_arg_reply_t *rep,
- drmBO *buf)
+static void drmBOCopyReply(const drm_bo_arg_reply_t *rep, drmBO *buf)
{
buf->handle = rep->handle;
buf->flags = rep->flags;
@@ -2613,8 +2691,6 @@ static void drmBOCopyReply(const drm_bo_arg_reply_t *rep,
buf->replyFlags = rep->rep_flags;
buf->pageAlignment = rep->page_alignment;
}
-
-
int drmBOCreate(int fd, unsigned long start, unsigned long size,
unsigned pageAlignment, void *user_buffer, drm_bo_type_t type,
@@ -2704,7 +2780,6 @@ int drmBODestroy(int fd, drmBO *buf)
int drmBOReference(int fd, unsigned handle, drmBO *buf)
{
-
drm_bo_arg_t arg;
drm_bo_arg_request_t *req = &arg.d.req;
drm_bo_arg_reply_t *rep = &arg.d.rep;
@@ -2736,7 +2811,6 @@ int drmBOUnReference(int fd, drmBO *buf)
drm_bo_arg_t arg;
drm_bo_arg_request_t *req = &arg.d.req;
drm_bo_arg_reply_t *rep = &arg.d.rep;
-
if (buf->mapVirtual && (buf->type != drm_bo_type_fake)) {
(void) munmap(buf->mapVirtual, buf->start + buf->size);
@@ -2770,7 +2844,6 @@ int drmBOUnReference(int fd, drmBO *buf)
int drmBOMap(int fd, drmBO *buf, unsigned mapFlags, unsigned mapHint,
void **address)
{
-
drm_bo_arg_t arg;
drm_bo_arg_request_t *req = &arg.d.req;
drm_bo_arg_reply_t *rep = &arg.d.rep;
@@ -2830,7 +2903,6 @@ int drmBOUnmap(int fd, drmBO *buf)
drm_bo_arg_request_t *req = &arg.d.req;
drm_bo_arg_reply_t *rep = &arg.d.rep;
-
memset(&arg, 0, sizeof(arg));
req->handle = buf->handle;
req->op = drm_bo_unmap;
@@ -2864,7 +2936,7 @@ int drmBOValidate(int fd, drmBO *buf, unsigned flags, unsigned mask,
do{
ret = ioctl(fd, DRM_IOCTL_BUFOBJ, &arg);
} while (ret && errno == EAGAIN);
-
+
if (ret)
return -errno;
if (!arg.handled)
@@ -2891,7 +2963,7 @@ int drmBOFence(int fd, drmBO *buf, unsigned flags, unsigned fenceHandle)
req->op = drm_bo_fence;
ret = ioctl(fd, DRM_IOCTL_BUFOBJ, &arg);
-
+
if (ret)
return -errno;
if (!arg.handled)
@@ -2913,7 +2985,7 @@ int drmBOInfo(int fd, drmBO *buf)
req->op = drm_bo_info;
ret = ioctl(fd, DRM_IOCTL_BUFOBJ, &arg);
-
+
if (ret)
return -errno;
if (!arg.handled)
@@ -2959,7 +3031,8 @@ int drmBOBusy(int fd, drmBO *buf, int *busy)
!(buf->replyFlags & DRM_BO_REP_BUSY)) {
*busy = 0;
return 0;
- } else {
+ }
+ else {
int ret = drmBOInfo(fd, buf);
if (ret)
return ret;
@@ -2995,7 +3068,8 @@ int drmAddValidateItem(drmBOList *list, drmBO *buf, unsigned flags,
*newItem = 1;
cur->arg0 = flags;
cur->arg1 = mask;
- } else {
+ }
+ else {
unsigned memMask = (cur->arg1 | mask) & DRM_BO_MASK_MEM;
unsigned memFlags = cur->arg0 & flags & memMask;
@@ -3027,134 +3101,129 @@ int drmAddValidateItem(drmBOList *list, drmBO *buf, unsigned flags,
int drmBOValidateList(int fd, drmBOList *list)
{
-
- drmBONode *node;
- drmMMListHead *l;
- drm_bo_arg_t *arg, *first;
- drm_bo_arg_request_t *req;
- drm_bo_arg_reply_t *rep;
- drm_u64_t *prevNext = NULL;
- drmBO *buf;
- int ret;
-
- first = NULL;
-
- for (l = list->list.next; l != &list->list; l = l->next) {
- node = DRMLISTENTRY(drmBONode, l, head);
-
- arg = &node->bo_arg;
- req = &arg->d.req;
-
- if (!first)
- first = arg;
-
- if (prevNext)
- *prevNext = (unsigned long) arg;
-
- memset(arg, 0, sizeof(*arg));
- prevNext = &arg->next;
- req->handle = node->buf->handle;
- req->op = drm_bo_validate;
- req->mask = node->arg0;
- req->hint = 0;
- req->arg_handle = node->arg1;
- }
-
- if (!first)
- return 0;
+ drmBONode *node;
+ drmMMListHead *l;
+ drm_bo_arg_t *arg, *first;
+ drm_bo_arg_request_t *req;
+ drm_bo_arg_reply_t *rep;
+ drm_u64_t *prevNext = NULL;
+ drmBO *buf;
+ int ret;
+
+ first = NULL;
- do{
- ret = ioctl(fd, DRM_IOCTL_BUFOBJ, first);
- } while (ret && errno == EAGAIN);
+ for (l = list->list.next; l != &list->list; l = l->next) {
+ node = DRMLISTENTRY(drmBONode, l, head);
+
+ arg = &node->bo_arg;
+ req = &arg->d.req;
+ if (!first)
+ first = arg;
+
+ if (prevNext)
+ *prevNext = (unsigned long) arg;
+
+ memset(arg, 0, sizeof(*arg));
+ prevNext = &arg->next;
+ req->handle = node->buf->handle;
+ req->op = drm_bo_validate;
+ req->mask = node->arg0;
+ req->hint = 0;
+ req->arg_handle = node->arg1;
+ }
+
+ if (!first)
+ return 0;
+
+ do {
+ ret = ioctl(fd, DRM_IOCTL_BUFOBJ, first);
+ } while (ret && errno == EAGAIN);
- if (ret)
- return -errno;
+ if (ret)
+ return -errno;
- for (l = list->list.next; l != &list->list; l = l->next) {
- node = DRMLISTENTRY(drmBONode, l, head);
- arg = &node->bo_arg;
- rep = &arg->d.rep;
-
- if (!arg->handled) {
- drmMsg("Unhandled request\n");
- return -EFAULT;
- }
- if (rep->ret)
- return rep->ret;
-
- buf = node->buf;
- drmBOCopyReply(rep, buf);
- }
-
- return 0;
+ for (l = list->list.next; l != &list->list; l = l->next) {
+ node = DRMLISTENTRY(drmBONode, l, head);
+ arg = &node->bo_arg;
+ rep = &arg->d.rep;
+
+ if (!arg->handled) {
+ drmMsg("Unhandled request\n");
+ return -EFAULT;
+ }
+ if (rep->ret)
+ return rep->ret;
+
+ buf = node->buf;
+ drmBOCopyReply(rep, buf);
+ }
+
+ return 0;
}
int drmBOFenceList(int fd, drmBOList *list, unsigned fenceHandle)
{
-
- drmBONode *node;
- drmMMListHead *l;
- drm_bo_arg_t *arg, *first;
- drm_bo_arg_request_t *req;
- drm_bo_arg_reply_t *rep;
- drm_u64_t *prevNext = NULL;
- drmBO *buf;
- unsigned fence_flags;
- int ret;
-
- first = NULL;
-
- for (l = list->list.next; l != &list->list; l = l->next) {
- node = DRMLISTENTRY(drmBONode, l, head);
-
- arg = &node->bo_arg;
- req = &arg->d.req;
-
- if (!first)
- first = arg;
-
- if (prevNext)
- *prevNext = (unsigned long) arg;
-
- memset(arg, 0, sizeof(*arg));
- prevNext = &arg->next;
- req->handle = node->buf->handle;
- req->op = drm_bo_fence;
- req->mask = node->arg0;
- req->arg_handle = fenceHandle;
- }
-
- if (!first)
- return 0;
+ drmBONode *node;
+ drmMMListHead *l;
+ drm_bo_arg_t *arg, *first;
+ drm_bo_arg_request_t *req;
+ drm_bo_arg_reply_t *rep;
+ drm_u64_t *prevNext = NULL;
+ drmBO *buf;
+ unsigned fence_flags;
+ int ret;
+
+ first = NULL;
+
+ for (l = list->list.next; l != &list->list; l = l->next) {
+ node = DRMLISTENTRY(drmBONode, l, head);
+
+ arg = &node->bo_arg;
+ req = &arg->d.req;
+
+ if (!first)
+ first = arg;
- ret = ioctl(fd, DRM_IOCTL_BUFOBJ, first);
+ if (prevNext)
+ *prevNext = (unsigned long) arg;
- if (ret)
- return -errno;
+ memset(arg, 0, sizeof(*arg));
+ prevNext = &arg->next;
+ req->handle = node->buf->handle;
+ req->op = drm_bo_fence;
+ req->mask = node->arg0;
+ req->arg_handle = fenceHandle;
+ }
- for (l = list->list.next; l != &list->list; l = l->next) {
- node = DRMLISTENTRY(drmBONode, l, head);
+ if (!first)
+ return 0;
- arg = &node->bo_arg;
- rep = &arg->d.rep;
-
- if (!arg->handled)
- return -EFAULT;
- if (rep->ret)
- return rep->ret;
- drmBOCopyReply(rep, node->buf);
- }
+ ret = ioctl(fd, DRM_IOCTL_BUFOBJ, first);
- return 0;
+ if (ret)
+ return -errno;
+
+ for (l = list->list.next; l != &list->list; l = l->next) {
+ node = DRMLISTENTRY(drmBONode, l, head);
+ arg = &node->bo_arg;
+ rep = &arg->d.rep;
+ if (!arg->handled)
+ return -EFAULT;
+ if (rep->ret)
+ return rep->ret;
+ drmBOCopyReply(rep, node->buf);
+ }
+
+ return 0;
}
int drmMMInit(int fd, unsigned long pOffset, unsigned long pSize,
unsigned memType)
{
drm_mm_init_arg_t arg;
-
+
memset(&arg, 0, sizeof(arg));
arg.req.op = mm_init;
arg.req.p_offset = pOffset;
@@ -3163,7 +3232,6 @@ int drmMMInit(int fd, unsigned long pOffset, unsigned long pSize,
if (ioctl(fd, DRM_IOCTL_MM_INIT, &arg))
return -errno;
-
return 0;
}
@@ -3171,14 +3239,12 @@ int drmMMTakedown(int fd, unsigned memType)
{
drm_mm_init_arg_t arg;
-
memset(&arg, 0, sizeof(arg));
arg.req.op = mm_takedown;
arg.req.mem_type = memType;
if (ioctl(fd, DRM_IOCTL_MM_INIT, &arg))
return -errno;
-
return 0;
}
@@ -3194,8 +3260,8 @@ int drmMMLock(int fd, unsigned memType)
do{
ret = ioctl(fd, DRM_IOCTL_MM_INIT, &arg);
} while (ret && errno == EAGAIN);
-
- return -errno;
+
+ return (ret) ? -errno : 0;
}
int drmMMUnlock(int fd, unsigned memType)
@@ -3210,15 +3276,15 @@ int drmMMUnlock(int fd, unsigned memType)
do{
ret = ioctl(fd, DRM_IOCTL_MM_INIT, &arg);
} while (ret && errno == EAGAIN);
-
- return -errno;
+
+ return (ret) ? -errno : 0;
}
#define DRM_MAX_FDS 16
static struct {
- char *BusID;
- int fd;
- int refcount;
+ char *BusID;
+ int fd;
+ int refcount;
} connection[DRM_MAX_FDS];
static int nr_fds = 0;
@@ -3227,50 +3293,50 @@ int drmOpenOnce(void *unused,
const char *BusID,
int *newlyopened)
{
- int i;
- int fd;
+ int i;
+ int fd;
- for (i = 0; i < nr_fds; i++)
- if (strcmp(BusID, connection[i].BusID) == 0) {
- connection[i].refcount++;
- *newlyopened = 0;
- return connection[i].fd;
- }
-
- fd = drmOpen(unused, BusID);
- if (fd <= 0 || nr_fds == DRM_MAX_FDS)
- return fd;
+ for (i = 0; i < nr_fds; i++)
+ if (strcmp(BusID, connection[i].BusID) == 0) {
+ connection[i].refcount++;
+ *newlyopened = 0;
+ return connection[i].fd;
+ }
+
+ fd = drmOpen(unused, BusID);
+ if (fd <= 0 || nr_fds == DRM_MAX_FDS)
+ return fd;
- connection[nr_fds].BusID = strdup(BusID);
- connection[nr_fds].fd = fd;
- connection[nr_fds].refcount = 1;
- *newlyopened = 1;
+ connection[nr_fds].BusID = strdup(BusID);
+ connection[nr_fds].fd = fd;
+ connection[nr_fds].refcount = 1;
+ *newlyopened = 1;
- if (0)
- fprintf(stderr, "saved connection %d for %s %d\n",
- nr_fds, connection[nr_fds].BusID,
- strcmp(BusID, connection[nr_fds].BusID));
+ if (0)
+ fprintf(stderr, "saved connection %d for %s %d\n",
+ nr_fds, connection[nr_fds].BusID,
+ strcmp(BusID, connection[nr_fds].BusID));
- nr_fds++;
+ nr_fds++;
- return fd;
+ return fd;
}
void drmCloseOnce(int fd)
{
- int i;
+ int i;
- for (i = 0; i < nr_fds; i++) {
- if (fd == connection[i].fd) {
- if (--connection[i].refcount == 0) {
- drmClose(connection[i].fd);
- free(connection[i].BusID);
+ for (i = 0; i < nr_fds; i++) {
+ if (fd == connection[i].fd) {
+ if (--connection[i].refcount == 0) {
+ drmClose(connection[i].fd);
+ free(connection[i].BusID);
- if (i < --nr_fds)
- connection[i] = connection[nr_fds];
+ if (i < --nr_fds)
+ connection[i] = connection[nr_fds];
- return;
- }
- }
- }
+ return;
+ }
+ }
+ }
}
diff --git a/libdrm/xf86mm.h b/libdrm/xf86mm.h
index bd0d2812..b3822d4d 100644
--- a/libdrm/xf86mm.h
+++ b/libdrm/xf86mm.h
@@ -60,7 +60,7 @@ typedef struct _drmMMListHead
(__item)->next = (__item); \
} while (0)
-#define DRMLISTADD(__item, __list) \
+#define DRMLISTADD(__item, __list) \
do { \
(__item)->prev = (__list); \
(__item)->next = (__list)->next; \
@@ -93,16 +93,18 @@ typedef struct _drmMMListHead
#define DRMLISTENTRY(__type, __item, __field) \
((__type *)(((char *) (__item)) - offsetof(__type, __field)))
-typedef struct _drmFence{
- unsigned handle;
- int class;
- unsigned type;
- unsigned flags;
- unsigned signaled;
- unsigned pad[4]; /* for future expansion */
+typedef struct _drmFence
+{
+ unsigned handle;
+ int class;
+ unsigned type;
+ unsigned flags;
+ unsigned signaled;
+ unsigned pad[4]; /* for future expansion */
} drmFence;
-typedef struct _drmBO{
+typedef struct _drmBO
+{
drm_bo_type_t type;
unsigned handle;
drm_u64_t mapHandle;
@@ -121,8 +123,8 @@ typedef struct _drmBO{
unsigned pad[8]; /* for future expansion */
} drmBO;
-
-typedef struct _drmBONode {
+typedef struct _drmBONode
+{
drmMMListHead head;
drmBO *buf;
drm_bo_arg_t bo_arg;
@@ -138,22 +140,24 @@ typedef struct _drmBOList {
drmMMListHead free;
} drmBOList;
-/* Fencing */
-
-extern int drmFenceCreate(int fd, unsigned flags, int class,
- unsigned type,
- drmFence *fence);
-extern int drmFenceDestroy(int fd, const drmFence *fence);
-extern int drmFenceReference(int fd, unsigned handle, drmFence *fence);
-extern int drmFenceUnreference(int fd, const drmFence *fence);
-extern int drmFenceFlush(int fd, drmFence *fence, unsigned flush_type);
-extern int drmFenceSignaled(int fd, drmFence *fence,
- unsigned fenceType, int *signaled);
-extern int drmFenceWait(int fd, unsigned flags, drmFence *fence,
- unsigned flush_type);
-extern int drmFenceEmit(int fd, unsigned flags, drmFence *fence,
- unsigned emit_type);
-extern int drmFenceBuffers(int fd, unsigned flags, drmFence *fence);
+
+/*
+ * Fence functions.
+ */
+
+extern int drmFenceCreate(int fd, unsigned flags, int class,
+ unsigned type, drmFence *fence);
+extern int drmFenceDestroy(int fd, const drmFence *fence);
+extern int drmFenceReference(int fd, unsigned handle, drmFence *fence);
+extern int drmFenceUnreference(int fd, const drmFence *fence);
+extern int drmFenceFlush(int fd, drmFence *fence, unsigned flush_type);
+extern int drmFenceSignaled(int fd, drmFence *fence,
+ unsigned fenceType, int *signaled);
+extern int drmFenceWait(int fd, unsigned flags, drmFence *fence,
+ unsigned flush_type);
+extern int drmFenceEmit(int fd, unsigned flags, drmFence *fence,
+ unsigned emit_type);
+extern int drmFenceBuffers(int fd, unsigned flags, drmFence *fence);
/*
diff --git a/linux-core/Makefile.kernel b/linux-core/Makefile.kernel
index b4fe7fa8..ac613d2e 100644
--- a/linux-core/Makefile.kernel
+++ b/linux-core/Makefile.kernel
@@ -23,12 +23,13 @@ i915-objs := i915_drv.o i915_dma.o i915_irq.o i915_mem.o i915_fence.o \
i915_buffer.o intel_display.o intel_crt.o intel_lvds.o \
intel_sdvo.o intel_modes.o intel_i2c.o i915_init.o intel_fb.o
nouveau-objs := nouveau_drv.o nouveau_state.o nouveau_fifo.o nouveau_mem.o \
- nouveau_object.o nouveau_irq.o \
+ nouveau_object.o nouveau_irq.o nouveau_notifier.o \
nv04_timer.o \
- nv04_mc.o nv40_mc.o \
+ nv04_mc.o nv40_mc.o nv50_mc.o \
nv04_fb.o nv10_fb.o nv40_fb.o \
+ nv04_fifo.o nv10_fifo.o nv40_fifo.o nv50_fifo.o \
nv04_graph.o nv10_graph.o nv20_graph.o nv30_graph.o \
- nv40_graph.o
+ nv40_graph.o nv50_graph.o
radeon-objs := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o radeon_irq.o r300_cmdbuf.o
sis-objs := sis_drv.o sis_mm.o
ffb-objs := ffb_drv.o ffb_context.o
diff --git a/linux-core/ati_pcigart.c b/linux-core/ati_pcigart.c
index 52bf8922..524618a8 100644
--- a/linux-core/ati_pcigart.c
+++ b/linux-core/ati_pcigart.c
@@ -151,7 +151,8 @@ int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info)
if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) {
DRM_DEBUG("PCI: no table in VRAM: using normal RAM\n");
- order = drm_order((gart_info->table_size + (PAGE_SIZE-1)) / PAGE_SIZE);
+ order = drm_order((gart_info->table_size +
+ (PAGE_SIZE-1)) / PAGE_SIZE);
num_pages = 1 << order;
address = drm_ati_alloc_pcigart_table(order);
if (!address) {
@@ -169,7 +170,8 @@ int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info)
PCI_DMA_TODEVICE);
if (bus_address == 0) {
DRM_ERROR("unable to map PCIGART pages!\n");
- order = drm_order((gart_info->table_size + (PAGE_SIZE-1)) / PAGE_SIZE);
+ order = drm_order((gart_info->table_size +
+ (PAGE_SIZE-1)) / PAGE_SIZE);
drm_ati_free_pcigart_table(address, order);
address = NULL;
goto done;
diff --git a/linux-core/drmP.h b/linux-core/drmP.h
index 4e36dab1..510de608 100644
--- a/linux-core/drmP.h
+++ b/linux-core/drmP.h
@@ -76,6 +76,7 @@
#include <asm/pgalloc.h>
#include "drm.h"
#include <linux/slab.h>
+#include <linux/idr.h>
#define __OS_HAS_AGP (defined(CONFIG_AGP) || (defined(CONFIG_AGP_MODULE) && defined(MODULE)))
#define __OS_HAS_MTRR (defined(CONFIG_MTRR))
@@ -302,19 +303,14 @@ typedef struct drm_devstate {
} drm_devstate_t;
typedef struct drm_magic_entry {
- drm_hash_item_t hash_item;
struct list_head head;
+ drm_hash_item_t hash_item;
struct drm_file *priv;
} drm_magic_entry_t;
-typedef struct drm_magic_head {
- struct drm_magic_entry *head;
- struct drm_magic_entry *tail;
-} drm_magic_head_t;
-
typedef struct drm_vma_entry {
+ struct list_head head;
struct vm_area_struct *vma;
- struct drm_vma_entry *next;
pid_t pid;
} drm_vma_entry_t;
@@ -413,8 +409,7 @@ typedef struct drm_file {
uid_t uid;
drm_magic_t magic;
unsigned long ioctl_count;
- struct drm_file *next;
- struct drm_file *prev;
+ struct list_head lhead;
struct drm_head *head;
int remove_auth_on_close;
unsigned long lock_count;
@@ -497,8 +492,7 @@ typedef struct drm_agp_mem {
DRM_AGP_MEM *memory;
unsigned long bound; /**< address */
int pages;
- struct drm_agp_mem *prev; /**< previous entry */
- struct drm_agp_mem *next; /**< next entry */
+ struct list_head head;
} drm_agp_mem_t;
/**
@@ -508,7 +502,7 @@ typedef struct drm_agp_mem {
*/
typedef struct drm_agp_head {
DRM_AGP_KERN agp_info; /**< AGP device information */
- drm_agp_mem_t *memory; /**< memory entries */
+ struct list_head memory;
unsigned long mode; /**< AGP mode */
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,11)
struct agp_bridge_data *bridge;
@@ -580,6 +574,10 @@ typedef struct drm_ctx_list {
drm_file_t *tag; /**< associated fd private data */
} drm_ctx_list_t;
+struct drm_ctx_sarea_list {
+ drm_map_t *map;
+};
+
typedef struct drm_vbl_sig {
struct list_head head;
unsigned int sequence;
@@ -604,6 +602,9 @@ typedef struct ati_pcigart_info {
int table_size;
} drm_ati_pcigart_info;
+struct drm_drawable_list {
+ drm_drawable_info_t info;
+};
#include "drm_objects.h"
@@ -734,15 +735,14 @@ typedef struct drm_device {
/** \name Authentication */
/*@{ */
- drm_file_t *file_first; /**< file list head */
- drm_file_t *file_last; /**< file list tail */
+ struct list_head filelist;
drm_open_hash_t magiclist;
struct list_head magicfree;
/*@} */
/** \name Memory management */
/*@{ */
- drm_map_list_t *maplist; /**< Linked list of regions */
+ struct list_head maplist; /**< Linked list of regions */
int map_count; /**< Number of mappable regions */
drm_open_hash_t map_hash; /**< User token hash table for maps */
drm_mm_t offset_manager; /**< User token manager */
@@ -752,14 +752,13 @@ typedef struct drm_device {
/** \name Context handle management */
/*@{ */
- drm_ctx_list_t *ctxlist; /**< Linked list of context handles */
+ struct list_head ctxlist; /**< Linked list of context handles */
int ctx_count; /**< Number of context handles */
struct mutex ctxlist_mutex; /**< For ctxlist */
- drm_map_t **context_sareas; /**< per-context SAREA's */
- int max_context;
+ struct idr ctx_idr;
- drm_vma_entry_t *vmalist; /**< List of vmas (for debugging) */
+ struct list_head vmalist; /**< List of vmas (for debugging) */
drm_lock_data_t lock; /**< Information on hardware lock */
/*@} */
@@ -795,8 +794,8 @@ typedef struct drm_device {
atomic_t vbl_received;
atomic_t vbl_received2; /**< number of secondary VBLANK interrupts */
spinlock_t vbl_lock;
- drm_vbl_sig_t vbl_sigs; /**< signal list to send on VBLANK */
- drm_vbl_sig_t vbl_sigs2; /**< signals to send on secondary VBLANK */
+ struct list_head vbl_sigs; /**< signal list to send on VBLANK */
+ struct list_head vbl_sigs2; /**< signals to send on secondary VBLANK */
unsigned int vbl_pending;
spinlock_t tasklet_lock; /**< For drm_locked_tasklet */
void (*locked_tasklet_func)(struct drm_device *dev);
@@ -818,7 +817,6 @@ typedef struct drm_device {
struct pci_controller *hose;
#endif
drm_sg_mem_t *sg; /**< Scatter gather memory */
- unsigned long *ctx_bitmap; /**< context bitmap */
void *dev_private; /**< device private data */
drm_sigdata_t sigdata; /**< For block_all_signals */
sigset_t sigmask;
@@ -834,10 +832,7 @@ typedef struct drm_device {
/** \name Drawable information */
/*@{ */
spinlock_t drw_lock;
- unsigned int drw_bitfield_length;
- u32 *drw_bitfield;
- unsigned int drw_info_length;
- drm_drawable_info_t **drw_info;
+ struct idr drw_idr;
/*@} */
/* DRM mode setting */
@@ -1018,6 +1013,7 @@ extern int drm_update_drawable_info(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern drm_drawable_info_t *drm_get_drawable_info(drm_device_t *dev,
drm_drawable_t id);
+extern void drm_drawable_free_all(drm_device_t *dev);
/* Authentication IOCTL support (drm_auth.h) */
extern int drm_getmagic(struct inode *inode, struct file *filp,
@@ -1140,9 +1136,7 @@ extern struct drm_sysfs_class *drm_class;
extern struct proc_dir_entry *drm_proc_root;
extern drm_local_map_t *drm_getsarea(struct drm_device *dev);
-extern int drm_wait_on(drm_device_t *dev, wait_queue_head_t *queue,
- int timeout, int (*fn)(drm_device_t *dev, void *priv),
- void *priv);
+
/* Proc support (drm_proc.h) */
extern int drm_proc_init(drm_device_t * dev,
int minor,
@@ -1205,7 +1199,7 @@ static __inline__ struct drm_map *drm_core_findmap(struct drm_device *dev,
unsigned int token)
{
drm_map_list_t *_entry;
- list_for_each_entry(_entry, &dev->maplist->head, head)
+ list_for_each_entry(_entry, &dev->maplist, head)
if (_entry->user_token == token)
return _entry->map;
return NULL;
diff --git a/linux-core/drm_agpsupport.c b/linux-core/drm_agpsupport.c
index 7d8f0737..f134563a 100644
--- a/linux-core/drm_agpsupport.c
+++ b/linux-core/drm_agpsupport.c
@@ -249,11 +249,7 @@ int drm_agp_alloc(drm_device_t *dev, drm_agp_buffer_t *request)
entry->memory = memory;
entry->bound = 0;
entry->pages = pages;
- entry->prev = NULL;
- entry->next = dev->agp->memory;
- if (dev->agp->memory)
- dev->agp->memory->prev = entry;
- dev->agp->memory = entry;
+ list_add(&entry->head, &dev->agp->memory);
request->handle = entry->handle;
request->physical = memory->physical;
@@ -280,10 +276,12 @@ int drm_agp_alloc_ioctl(struct inode *inode, struct file *filp,
return err;
if (copy_to_user(argp, &request, sizeof(request))) {
- drm_agp_mem_t *entry = dev->agp->memory;
-
- dev->agp->memory = entry->next;
- dev->agp->memory->prev = NULL;
+ drm_agp_mem_t *entry;
+ list_for_each_entry(entry, &dev->agp->memory, head) {
+ if (entry->handle == request.handle)
+ break;
+ }
+ list_del(&entry->head);
drm_free_agp(entry->memory, entry->pages);
drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
return -EFAULT;
@@ -306,7 +304,7 @@ static drm_agp_mem_t *drm_agp_lookup_entry(drm_device_t * dev,
{
drm_agp_mem_t *entry;
- for (entry = dev->agp->memory; entry; entry = entry->next) {
+ list_for_each_entry(entry, &dev->agp->memory, head) {
if (entry->handle == handle)
return entry;
}
@@ -435,13 +433,7 @@ int drm_agp_free(drm_device_t *dev, drm_agp_buffer_t *request)
if (entry->bound)
drm_unbind_agp(entry->memory);
- if (entry->prev)
- entry->prev->next = entry->next;
- else
- dev->agp->memory = entry->next;
-
- if (entry->next)
- entry->next->prev = entry->prev;
+ list_del(&entry->head);
drm_free_agp(entry->memory, entry->pages);
drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
@@ -502,7 +494,7 @@ drm_agp_head_t *drm_agp_init(drm_device_t *dev)
drm_free(head, sizeof(*head), DRM_MEM_AGPLISTS);
return NULL;
}
- head->memory = NULL;
+ INIT_LIST_HEAD(&head->memory);
head->cant_use_aperture = head->agp_info.cant_use_aperture;
head->page_mask = head->agp_info.page_mask;
return head;
diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c
index 50f62dce..fd097968 100644
--- a/linux-core/drm_bo.c
+++ b/linux-core/drm_bo.c
@@ -67,6 +67,9 @@ void drm_bo_add_to_pinned_lru(drm_buffer_object_t * bo)
{
drm_mem_type_manager_t *man;
+ DRM_ASSERT_LOCKED(&bo->dev->struct_mutex);
+ DRM_ASSERT_LOCKED(&bo->mutex);
+
man = &bo->dev->bm.man[bo->pinned_mem_type];
list_add_tail(&bo->pinned_lru, &man->pinned);
}
@@ -75,6 +78,8 @@ void drm_bo_add_to_lru(drm_buffer_object_t * bo)
{
drm_mem_type_manager_t *man;
+ DRM_ASSERT_LOCKED(&bo->dev->struct_mutex);
+
if (!(bo->mem.mask & (DRM_BO_FLAG_NO_MOVE | DRM_BO_FLAG_NO_EVICT))
|| bo->mem.mem_type != bo->pinned_mem_type) {
man = &bo->dev->bm.man[bo->mem.mem_type];
@@ -134,6 +139,8 @@ static int drm_bo_add_ttm(drm_buffer_object_t * bo)
int ret = 0;
bo->ttm = NULL;
+ DRM_ASSERT_LOCKED(&bo->mutex);
+
switch (bo->type) {
case drm_bo_type_dc:
bo->ttm = drm_ttm_init(dev, bo->mem.num_pages << PAGE_SHIFT);
@@ -262,29 +269,25 @@ static int drm_bo_handle_move_mem(drm_buffer_object_t * bo,
int drm_bo_wait(drm_buffer_object_t * bo, int lazy, int ignore_signals,
int no_wait)
{
-
- drm_fence_object_t *fence = bo->fence;
int ret;
- if (fence) {
- drm_device_t *dev = bo->dev;
- if (drm_fence_object_signaled(fence, bo->fence_type)) {
- drm_fence_usage_deref_unlocked(dev, fence);
- bo->fence = NULL;
+ DRM_ASSERT_LOCKED(&bo->mutex);
+
+ if (bo->fence) {
+ if (drm_fence_object_signaled(bo->fence, bo->fence_type, 0)) {
+ drm_fence_usage_deref_unlocked(&bo->fence);
return 0;
}
if (no_wait) {
return -EBUSY;
}
ret =
- drm_fence_object_wait(dev, fence, lazy, ignore_signals,
+ drm_fence_object_wait(bo->fence, lazy, ignore_signals,
bo->fence_type);
if (ret)
return ret;
- drm_fence_usage_deref_unlocked(dev, fence);
- bo->fence = NULL;
-
+ drm_fence_usage_deref_unlocked(&bo->fence);
}
return 0;
}
@@ -312,10 +315,8 @@ static int drm_bo_expire_fence(drm_buffer_object_t * bo, int allow_errors)
"Evicting buffer.\n");
}
}
- if (bo->fence) {
- drm_fence_usage_deref_unlocked(dev, bo->fence);
- bo->fence = NULL;
- }
+ if (bo->fence)
+ drm_fence_usage_deref_unlocked(&bo->fence);
}
return 0;
}
@@ -331,16 +332,17 @@ static void drm_bo_cleanup_refs(drm_buffer_object_t * bo, int remove_all)
drm_device_t *dev = bo->dev;
drm_buffer_manager_t *bm = &dev->bm;
+ DRM_ASSERT_LOCKED(&dev->struct_mutex);
+
atomic_inc(&bo->usage);
mutex_unlock(&dev->struct_mutex);
mutex_lock(&bo->mutex);
DRM_FLAG_MASKED(bo->priv_flags, 0, _DRM_BO_FLAG_UNFENCED);
- if (bo->fence && drm_fence_object_signaled(bo->fence, bo->fence_type)) {
- drm_fence_usage_deref_locked(dev, bo->fence);
- bo->fence = NULL;
- }
+ if (bo->fence && drm_fence_object_signaled(bo->fence,
+ bo->fence_type, 0))
+ drm_fence_usage_deref_unlocked(&bo->fence);
if (bo->fence && remove_all)
(void)drm_bo_expire_fence(bo, 0);
@@ -371,7 +373,7 @@ static void drm_bo_cleanup_refs(drm_buffer_object_t * bo, int remove_all)
}
if (list_empty(&bo->ddestroy)) {
- drm_fence_object_flush(dev, bo->fence, bo->fence_type);
+ drm_fence_object_flush(bo->fence, bo->fence_type);
list_add_tail(&bo->ddestroy, &bm->ddestroy);
schedule_delayed_work(&bm->wq,
((DRM_HZ / 100) < 1) ? 1 : DRM_HZ / 100);
@@ -392,6 +394,8 @@ static void drm_bo_destroy_locked(drm_buffer_object_t * bo)
drm_device_t *dev = bo->dev;
drm_buffer_manager_t *bm = &dev->bm;
+ DRM_ASSERT_LOCKED(&dev->struct_mutex);
+
if (list_empty(&bo->lru) && bo->mem.mm_node == NULL &&
list_empty(&bo->pinned_lru) && bo->pinned_node == NULL &&
list_empty(&bo->ddestroy) && atomic_read(&bo->usage) == 0) {
@@ -414,6 +418,7 @@ static void drm_bo_destroy_locked(drm_buffer_object_t * bo)
atomic_dec(&bm->count);
+ BUG_ON(!list_empty(&bo->base.list));
drm_ctl_free(bo, sizeof(*bo), DRM_MEM_BUFOBJ);
return;
@@ -488,10 +493,15 @@ static void drm_bo_delayed_workqueue(struct work_struct *work)
mutex_unlock(&dev->struct_mutex);
}
-void drm_bo_usage_deref_locked(drm_buffer_object_t * bo)
+void drm_bo_usage_deref_locked(drm_buffer_object_t ** bo)
{
- if (atomic_dec_and_test(&bo->usage)) {
- drm_bo_destroy_locked(bo);
+ struct drm_buffer_object *tmp_bo = *bo;
+ bo = NULL;
+
+ DRM_ASSERT_LOCKED(&tmp_bo->dev->struct_mutex);
+
+ if (atomic_dec_and_test(&tmp_bo->usage)) {
+ drm_bo_destroy_locked(tmp_bo);
}
}
EXPORT_SYMBOL(drm_bo_usage_deref_locked);
@@ -501,18 +511,22 @@ static void drm_bo_base_deref_locked(drm_file_t * priv, drm_user_object_t * uo)
drm_buffer_object_t *bo =
drm_user_object_entry(uo, drm_buffer_object_t, base);
+ DRM_ASSERT_LOCKED(&bo->dev->struct_mutex);
+
drm_bo_takedown_vm_locked(bo);
- drm_bo_usage_deref_locked(bo);
+ drm_bo_usage_deref_locked(&bo);
}
-static void drm_bo_usage_deref_unlocked(drm_buffer_object_t * bo)
+static void drm_bo_usage_deref_unlocked(drm_buffer_object_t ** bo)
{
- drm_device_t *dev = bo->dev;
+ struct drm_buffer_object *tmp_bo = *bo;
+ drm_device_t *dev = tmp_bo->dev;
- if (atomic_dec_and_test(&bo->usage)) {
+ *bo = NULL;
+ if (atomic_dec_and_test(&tmp_bo->usage)) {
mutex_lock(&dev->struct_mutex);
- if (atomic_read(&bo->usage) == 0)
- drm_bo_destroy_locked(bo);
+ if (atomic_read(&tmp_bo->usage) == 0)
+ drm_bo_destroy_locked(tmp_bo);
mutex_unlock(&dev->struct_mutex);
}
}
@@ -598,18 +612,17 @@ int drm_fence_buffer_objects(drm_file_t * priv,
if (entry->priv_flags & _DRM_BO_FLAG_UNFENCED) {
count++;
if (entry->fence)
- drm_fence_usage_deref_locked(dev, entry->fence);
- entry->fence = fence;
+ drm_fence_usage_deref_locked(&entry->fence);
+ entry->fence = drm_fence_reference_locked(fence);
DRM_FLAG_MASKED(entry->priv_flags, 0,
_DRM_BO_FLAG_UNFENCED);
DRM_WAKEUP(&entry->event_queue);
drm_bo_add_to_lru(entry);
}
mutex_unlock(&entry->mutex);
- drm_bo_usage_deref_locked(entry);
+ drm_bo_usage_deref_locked(&entry);
l = f_list.next;
}
- atomic_add(count, &fence->usage);
DRM_DEBUG("Fenced %d buffers\n", count);
out:
mutex_unlock(&dev->struct_mutex);
@@ -724,7 +737,7 @@ static int drm_bo_mem_force_space(drm_device_t * dev,
ret = drm_bo_evict(entry, mem_type, no_wait);
mutex_unlock(&entry->mutex);
- drm_bo_usage_deref_unlocked(entry);
+ drm_bo_usage_deref_unlocked(&entry);
if (ret)
return ret;
mutex_lock(&dev->struct_mutex);
@@ -944,10 +957,8 @@ static int drm_bo_quick_busy(drm_buffer_object_t * bo)
BUG_ON(bo->priv_flags & _DRM_BO_FLAG_UNFENCED);
if (fence) {
- drm_device_t *dev = bo->dev;
- if (drm_fence_object_signaled(fence, bo->fence_type)) {
- drm_fence_usage_deref_unlocked(dev, fence);
- bo->fence = NULL;
+ if (drm_fence_object_signaled(fence, bo->fence_type, 0)) {
+ drm_fence_usage_deref_unlocked(&bo->fence);
return 0;
}
return 1;
@@ -966,16 +977,13 @@ static int drm_bo_busy(drm_buffer_object_t * bo)
BUG_ON(bo->priv_flags & _DRM_BO_FLAG_UNFENCED);
if (fence) {
- drm_device_t *dev = bo->dev;
- if (drm_fence_object_signaled(fence, bo->fence_type)) {
- drm_fence_usage_deref_unlocked(dev, fence);
- bo->fence = NULL;
+ if (drm_fence_object_signaled(fence, bo->fence_type, 0)) {
+ drm_fence_usage_deref_unlocked(&bo->fence);
return 0;
}
- drm_fence_object_flush(dev, fence, DRM_FENCE_TYPE_EXE);
- if (drm_fence_object_signaled(fence, bo->fence_type)) {
- drm_fence_usage_deref_unlocked(dev, fence);
- bo->fence = NULL;
+ drm_fence_object_flush(fence, DRM_FENCE_TYPE_EXE);
+ if (drm_fence_object_signaled(fence, bo->fence_type, 0)) {
+ drm_fence_usage_deref_unlocked(&bo->fence);
return 0;
}
return 1;
@@ -1172,7 +1180,7 @@ static int drm_buffer_object_map(drm_file_t * priv, uint32_t handle,
drm_bo_fill_rep_arg(bo, rep);
out:
mutex_unlock(&bo->mutex);
- drm_bo_usage_deref_unlocked(bo);
+ drm_bo_usage_deref_unlocked(&bo);
return ret;
}
@@ -1198,7 +1206,7 @@ static int drm_buffer_object_unmap(drm_file_t * priv, uint32_t handle)
}
drm_remove_ref_object(priv, ro);
- drm_bo_usage_deref_locked(bo);
+ drm_bo_usage_deref_locked(&bo);
out:
mutex_unlock(&dev->struct_mutex);
return ret;
@@ -1462,11 +1470,14 @@ static int drm_bo_handle_validate(drm_file_t * priv, uint32_t handle,
uint32_t flags, uint32_t mask, uint32_t hint,
drm_bo_arg_reply_t * rep)
{
+ struct drm_device *dev = priv->head->dev;
drm_buffer_object_t *bo;
int ret;
int no_wait = hint & DRM_BO_HINT_DONT_BLOCK;
+ mutex_lock(&dev->struct_mutex);
bo = drm_lookup_buffer_object(priv, handle, 1);
+ mutex_unlock(&dev->struct_mutex);
if (!bo) {
return -EINVAL;
}
@@ -1491,16 +1502,20 @@ static int drm_bo_handle_validate(drm_file_t * priv, uint32_t handle,
mutex_unlock(&bo->mutex);
- drm_bo_usage_deref_unlocked(bo);
+ drm_bo_usage_deref_unlocked(&bo);
return ret;
}
static int drm_bo_handle_info(drm_file_t * priv, uint32_t handle,
drm_bo_arg_reply_t * rep)
{
+ struct drm_device *dev = priv->head->dev;
drm_buffer_object_t *bo;
+ mutex_lock(&dev->struct_mutex);
bo = drm_lookup_buffer_object(priv, handle, 1);
+ mutex_unlock(&dev->struct_mutex);
+
if (!bo) {
return -EINVAL;
}
@@ -1509,18 +1524,22 @@ static int drm_bo_handle_info(drm_file_t * priv, uint32_t handle,
(void)drm_bo_busy(bo);
drm_bo_fill_rep_arg(bo, rep);
mutex_unlock(&bo->mutex);
- drm_bo_usage_deref_unlocked(bo);
+ drm_bo_usage_deref_unlocked(&bo);
return 0;
}
static int drm_bo_handle_wait(drm_file_t * priv, uint32_t handle,
uint32_t hint, drm_bo_arg_reply_t * rep)
{
+ struct drm_device *dev = priv->head->dev;
drm_buffer_object_t *bo;
int no_wait = hint & DRM_BO_HINT_DONT_BLOCK;
int ret;
+ mutex_lock(&dev->struct_mutex);
bo = drm_lookup_buffer_object(priv, handle, 1);
+ mutex_unlock(&dev->struct_mutex);
+
if (!bo) {
return -EINVAL;
}
@@ -1537,7 +1556,7 @@ static int drm_bo_handle_wait(drm_file_t * priv, uint32_t handle,
out:
mutex_unlock(&bo->mutex);
- drm_bo_usage_deref_unlocked(bo);
+ drm_bo_usage_deref_unlocked(&bo);
return ret;
}
@@ -1622,7 +1641,7 @@ int drm_buffer_object_create(drm_device_t *dev,
out_err:
mutex_unlock(&bo->mutex);
- drm_bo_usage_deref_unlocked(bo);
+ drm_bo_usage_deref_unlocked(&bo);
return ret;
}
EXPORT_SYMBOL(drm_buffer_object_create);
@@ -1700,7 +1719,7 @@ int drm_bo_ioctl(DRM_IOCTL_ARGS)
mask &
DRM_BO_FLAG_SHAREABLE);
if (rep.ret)
- drm_bo_usage_deref_unlocked(entry);
+ drm_bo_usage_deref_unlocked(&entry);
if (rep.ret)
break;
@@ -1928,7 +1947,7 @@ restart:
allow_errors);
mutex_lock(&dev->struct_mutex);
- drm_bo_usage_deref_locked(entry);
+ drm_bo_usage_deref_locked(&entry);
if (ret)
return ret;
@@ -1938,10 +1957,8 @@ restart:
do_restart = ((next->prev != list) && (next->prev != prev));
- if (nentry != NULL && do_restart) {
- drm_bo_usage_deref_locked(nentry);
- nentry = NULL;
- }
+ if (nentry != NULL && do_restart)
+ drm_bo_usage_deref_locked(&nentry);
if (do_restart)
goto restart;
@@ -2321,6 +2338,7 @@ static void drm_bo_takedown_vm_locked(drm_buffer_object_t * bo)
drm_local_map_t *map;
drm_device_t *dev = bo->dev;
+ DRM_ASSERT_LOCKED(&dev->struct_mutex);
if (list->user_token) {
drm_ht_remove_item(&dev->map_hash, &list->hash);
list->user_token = 0;
@@ -2337,7 +2355,7 @@ static void drm_bo_takedown_vm_locked(drm_buffer_object_t * bo)
drm_ctl_free(map, sizeof(*map), DRM_MEM_BUFOBJ);
list->map = NULL;
list->user_token = 0ULL;
- drm_bo_usage_deref_locked(bo);
+ drm_bo_usage_deref_locked(&bo);
}
static int drm_bo_setup_vm_locked(drm_buffer_object_t * bo)
@@ -2346,6 +2364,7 @@ static int drm_bo_setup_vm_locked(drm_buffer_object_t * bo)
drm_local_map_t *map;
drm_device_t *dev = bo->dev;
+ DRM_ASSERT_LOCKED(&dev->struct_mutex);
list->map = drm_ctl_calloc(1, sizeof(*map), DRM_MEM_BUFOBJ);
if (!list->map)
return -ENOMEM;
diff --git a/linux-core/drm_bo_move.c b/linux-core/drm_bo_move.c
index eaeef1b0..28c1509e 100644
--- a/linux-core/drm_bo_move.c
+++ b/linux-core/drm_bo_move.c
@@ -308,7 +308,7 @@ int drm_buffer_object_transfer(drm_buffer_object_t * bo,
INIT_LIST_HEAD(&fbo->p_mm_list);
#endif
- atomic_inc(&bo->fence->usage);
+ drm_fence_reference_unlocked(&fbo->fence, bo->fence);
fbo->pinned_node = NULL;
fbo->mem.mm_node->private = (void *)fbo;
atomic_set(&fbo->usage, 1);
@@ -341,7 +341,7 @@ int drm_bo_move_accel_cleanup(drm_buffer_object_t * bo,
drm_buffer_object_t *old_obj;
if (bo->fence)
- drm_fence_usage_deref_unlocked(dev, bo->fence);
+ drm_fence_usage_deref_unlocked(&bo->fence);
ret = drm_fence_object_create(dev, fence_class, fence_type,
fence_flags | DRM_FENCE_FLAG_EMIT,
&bo->fence);
@@ -398,7 +398,7 @@ int drm_bo_move_accel_cleanup(drm_buffer_object_t * bo,
DRM_FLAG_MASKED(bo->priv_flags, 0, _DRM_BO_FLAG_UNFENCED);
drm_bo_add_to_lru(old_obj);
- drm_bo_usage_deref_locked(old_obj);
+ drm_bo_usage_deref_locked(&old_obj);
mutex_unlock(&dev->struct_mutex);
}
diff --git a/linux-core/drm_bufs.c b/linux-core/drm_bufs.c
index 1ba53c8f..38f0dd3a 100644
--- a/linux-core/drm_bufs.c
+++ b/linux-core/drm_bufs.c
@@ -51,10 +51,8 @@ EXPORT_SYMBOL(drm_get_resource_len);
static drm_map_list_t *drm_find_matching_map(drm_device_t *dev,
drm_local_map_t *map)
{
- struct list_head *list;
-
- list_for_each(list, &dev->maplist->head) {
- drm_map_list_t *entry = list_entry(list, drm_map_list_t, head);
+ drm_map_list_t *entry;
+ list_for_each_entry(entry, &dev->maplist, head) {
if (entry->map && map->type == entry->map->type &&
((entry->map->offset == map->offset) ||
((map->type == _DRM_SHM) && (map->flags&_DRM_CONTAINS_LOCK)))) {
@@ -237,14 +235,14 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset,
* skipped and we double check that dev->agp->memory is
* actually set as well as being invalid before EPERM'ing
*/
- for (entry = dev->agp->memory; entry; entry = entry->next) {
+ list_for_each_entry(entry, &dev->agp->memory, head) {
if ((map->offset >= entry->bound) &&
(map->offset + map->size <= entry->bound + entry->pages * PAGE_SIZE)) {
valid = 1;
break;
}
}
- if (dev->agp->memory && !valid) {
+ if (!list_empty(&dev->agp->memory) && !valid) {
drm_free(map, sizeof(*map), DRM_MEM_MAPS);
return -EPERM;
}
@@ -288,7 +286,7 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset,
list->map = map;
mutex_lock(&dev->struct_mutex);
- list_add(&list->head, &dev->maplist->head);
+ list_add(&list->head, &dev->maplist);
/* Assign a 32-bit handle */
@@ -380,29 +378,28 @@ int drm_addmap_ioctl(struct inode *inode, struct file *filp,
*/
int drm_rmmap_locked(drm_device_t *dev, drm_local_map_t *map)
{
- struct list_head *list;
- drm_map_list_t *r_list = NULL;
+ drm_map_list_t *r_list = NULL, *list_t;
drm_dma_handle_t dmah;
+ int found = 0;
/* Find the list entry for the map and remove it */
- list_for_each(list, &dev->maplist->head) {
- r_list = list_entry(list, drm_map_list_t, head);
-
+ list_for_each_entry_safe(r_list, list_t, &dev->maplist, head) {
if (r_list->map == map) {
- list_del(list);
+ list_del(&r_list->head);
drm_ht_remove_key(&dev->map_hash,
r_list->user_token >> PAGE_SHIFT);
- drm_free(list, sizeof(*list), DRM_MEM_MAPS);
+ drm_free(r_list, sizeof(*r_list), DRM_MEM_MAPS);
+ found = 1;
break;
}
}
+ if (!found) {
+ return -EINVAL;
+ }
/* List has wrapped around to the head pointer, or it's empty and we
* didn't find anything.
*/
- if (list == (&dev->maplist->head)) {
- return -EINVAL;
- }
switch (map->type) {
case _DRM_REGISTERS:
@@ -465,7 +462,7 @@ int drm_rmmap_ioctl(struct inode *inode, struct file *filp,
drm_device_t *dev = priv->head->dev;
drm_map_t request;
drm_local_map_t *map = NULL;
- struct list_head *list;
+ drm_map_list_t *r_list;
int ret;
if (copy_from_user(&request, (drm_map_t __user *) arg, sizeof(request))) {
@@ -473,9 +470,7 @@ int drm_rmmap_ioctl(struct inode *inode, struct file *filp,
}
mutex_lock(&dev->struct_mutex);
- list_for_each(list, &dev->maplist->head) {
- drm_map_list_t *r_list = list_entry(list, drm_map_list_t, head);
-
+ list_for_each_entry(r_list, &dev->maplist, head) {
if (r_list->map &&
r_list->user_token == (unsigned long)request.handle &&
r_list->map->flags & _DRM_REMOVABLE) {
@@ -487,7 +482,7 @@ int drm_rmmap_ioctl(struct inode *inode, struct file *filp,
/* List has wrapped around to the head pointer, or its empty we didn't
* find anything.
*/
- if (list == (&dev->maplist->head)) {
+ if (list_empty(&dev->maplist) || !map) {
mutex_unlock(&dev->struct_mutex);
return -EINVAL;
}
@@ -611,14 +606,14 @@ int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request)
/* Make sure buffers are located in AGP memory that we own */
valid = 0;
- for (agp_entry = dev->agp->memory; agp_entry; agp_entry = agp_entry->next) {
+ list_for_each_entry(agp_entry, &dev->agp->memory, head) {
if ((agp_offset >= agp_entry->bound) &&
(agp_offset + total * count <= agp_entry->bound + agp_entry->pages * PAGE_SIZE)) {
valid = 1;
break;
}
}
- if (dev->agp->memory && !valid) {
+ if (!list_empty(&dev->agp->memory) && !valid) {
DRM_DEBUG("zone invalid\n");
return -EINVAL;
}
diff --git a/linux-core/drm_compat.c b/linux-core/drm_compat.c
index 9ac5658c..08d20d06 100644
--- a/linux-core/drm_compat.c
+++ b/linux-core/drm_compat.c
@@ -555,3 +555,126 @@ void drm_bo_finish_unmap(drm_buffer_object_t *bo)
#endif
+#ifdef DRM_IDR_COMPAT_FN
+/* only called when idp->lock is held */
+static void __free_layer(struct idr *idp, struct idr_layer *p)
+{
+ p->ary[0] = idp->id_free;
+ idp->id_free = p;
+ idp->id_free_cnt++;
+}
+
+static void free_layer(struct idr *idp, struct idr_layer *p)
+{
+ unsigned long flags;
+
+ /*
+ * Depends on the return element being zeroed.
+ */
+ spin_lock_irqsave(&idp->lock, flags);
+ __free_layer(idp, p);
+ spin_unlock_irqrestore(&idp->lock, flags);
+}
+
+/**
+ * idr_for_each - iterate through all stored pointers
+ * @idp: idr handle
+ * @fn: function to be called for each pointer
+ * @data: data passed back to callback function
+ *
+ * Iterate over the pointers registered with the given idr. The
+ * callback function will be called for each pointer currently
+ * registered, passing the id, the pointer and the data pointer passed
+ * to this function. It is not safe to modify the idr tree while in
+ * the callback, so functions such as idr_get_new and idr_remove are
+ * not allowed.
+ *
+ * We check the return of @fn each time. If it returns anything other
+ * than 0, we break out and return that value.
+ *
+* The caller must serialize idr_find() vs idr_get_new() and idr_remove().
+ */
+int idr_for_each(struct idr *idp,
+ int (*fn)(int id, void *p, void *data), void *data)
+{
+ int n, id, max, error = 0;
+ struct idr_layer *p;
+ struct idr_layer *pa[MAX_LEVEL];
+ struct idr_layer **paa = &pa[0];
+
+ n = idp->layers * IDR_BITS;
+ p = idp->top;
+ max = 1 << n;
+
+ id = 0;
+ while (id < max) {
+ while (n > 0 && p) {
+ n -= IDR_BITS;
+ *paa++ = p;
+ p = p->ary[(id >> n) & IDR_MASK];
+ }
+
+ if (p) {
+ error = fn(id, (void *)p, data);
+ if (error)
+ break;
+ }
+
+ id += 1 << n;
+ while (n < fls(id)) {
+ n += IDR_BITS;
+ p = *--paa;
+ }
+ }
+
+ return error;
+}
+EXPORT_SYMBOL(idr_for_each);
+
+/**
+ * idr_remove_all - remove all ids from the given idr tree
+ * @idp: idr handle
+ *
+ * idr_destroy() only frees up unused, cached idp_layers, but this
+ * function will remove all id mappings and leave all idp_layers
+ * unused.
+ *
+ * A typical clean-up sequence for objects stored in an idr tree, will
+ * use idr_for_each() to free all objects, if necessay, then
+ * idr_remove_all() to remove all ids, and idr_destroy() to free
+ * up the cached idr_layers.
+ */
+void idr_remove_all(struct idr *idp)
+{
+ int n, id, max, error = 0;
+ struct idr_layer *p;
+ struct idr_layer *pa[MAX_LEVEL];
+ struct idr_layer **paa = &pa[0];
+
+ n = idp->layers * IDR_BITS;
+ p = idp->top;
+ max = 1 << n;
+
+ id = 0;
+ while (id < max && !error) {
+ while (n > IDR_BITS && p) {
+ n -= IDR_BITS;
+ *paa++ = p;
+ p = p->ary[(id >> n) & IDR_MASK];
+ }
+
+ id += 1 << n;
+ while (n < fls(id)) {
+ if (p) {
+ memset(p, 0, sizeof *p);
+ free_layer(idp, p);
+ }
+ n += IDR_BITS;
+ p = *--paa;
+ }
+ }
+ idp->top = NULL;
+ idp->layers = 0;
+}
+EXPORT_SYMBOL(idr_remove_all);
+#endif
diff --git a/linux-core/drm_compat.h b/linux-core/drm_compat.h
index bada1fdf..1cf7f165 100644
--- a/linux-core/drm_compat.h
+++ b/linux-core/drm_compat.h
@@ -312,4 +312,13 @@ extern int drm_bo_remap_bound(struct drm_buffer_object *bo);
extern int drm_bo_map_bound(struct vm_area_struct *vma);
#endif
+
+/* fixme when functions are upstreamed */
+#define DRM_IDR_COMPAT_FN
+#ifdef DRM_IDR_COMPAT_FN
+int idr_for_each(struct idr *idp,
+ int (*fn)(int id, void *p, void *data), void *data);
+void idr_remove_all(struct idr *idp);
+#endif
+
#endif
diff --git a/linux-core/drm_context.c b/linux-core/drm_context.c
index 49042272..101a298c 100644
--- a/linux-core/drm_context.c
+++ b/linux-core/drm_context.c
@@ -53,25 +53,21 @@
* \param ctx_handle context handle.
*
* Clears the bit specified by \p ctx_handle in drm_device::ctx_bitmap and the entry
- * in drm_device::context_sareas, while holding the drm_device::struct_mutex
+ * in drm_device::ctx_idr, while holding the drm_device::struct_mutex
* lock.
*/
void drm_ctxbitmap_free(drm_device_t * dev, int ctx_handle)
{
- if (ctx_handle < 0)
- goto failed;
- if (!dev->ctx_bitmap)
- goto failed;
-
- if (ctx_handle < DRM_MAX_CTXBITMAP) {
- mutex_lock(&dev->struct_mutex);
- clear_bit(ctx_handle, dev->ctx_bitmap);
- dev->context_sareas[ctx_handle] = NULL;
- mutex_unlock(&dev->struct_mutex);
- return;
- }
- failed:
- DRM_ERROR("Attempt to free invalid context handle: %d\n", ctx_handle);
+ struct drm_ctx_sarea_list *ctx;
+
+ mutex_lock(&dev->struct_mutex);
+ ctx = idr_find(&dev->ctx_idr, ctx_handle);
+ if (ctx) {
+ idr_remove(&dev->ctx_idr, ctx_handle);
+ drm_free(ctx, sizeof(struct drm_ctx_sarea_list), DRM_MEM_CTXLIST);
+ } else
+ DRM_ERROR("Attempt to free invalid context handle: %d\n", ctx_handle);
+ mutex_unlock(&dev->struct_mutex);
return;
}
@@ -81,62 +77,34 @@ void drm_ctxbitmap_free(drm_device_t * dev, int ctx_handle)
* \param dev DRM device.
* \return (non-negative) context handle on success or a negative number on failure.
*
- * Find the first zero bit in drm_device::ctx_bitmap and (re)allocates
- * drm_device::context_sareas to accommodate the new entry while holding the
+ * Allocate a new idr from drm_device::ctx_idr while holding the
* drm_device::struct_mutex lock.
*/
static int drm_ctxbitmap_next(drm_device_t * dev)
{
- int bit;
+ int new_id;
+ int ret;
+ struct drm_ctx_sarea_list *new_ctx;
- if (!dev->ctx_bitmap)
+ new_ctx = drm_calloc(1, sizeof(struct drm_ctx_sarea_list), DRM_MEM_CTXLIST);
+ if (!new_ctx)
return -1;
+again:
+ if (idr_pre_get(&dev->ctx_idr, GFP_KERNEL) == 0) {
+ DRM_ERROR("Out of memory expanding drawable idr\n");
+ drm_free(new_ctx, sizeof(struct drm_ctx_sarea_list), DRM_MEM_CTXLIST);
+ return -ENOMEM;
+ }
mutex_lock(&dev->struct_mutex);
- bit = find_first_zero_bit(dev->ctx_bitmap, DRM_MAX_CTXBITMAP);
- if (bit < DRM_MAX_CTXBITMAP) {
- set_bit(bit, dev->ctx_bitmap);
- DRM_DEBUG("drm_ctxbitmap_next bit : %d\n", bit);
- if ((bit + 1) > dev->max_context) {
- dev->max_context = (bit + 1);
- if (dev->context_sareas) {
- drm_map_t **ctx_sareas;
-
- ctx_sareas = drm_realloc(dev->context_sareas,
- (dev->max_context -
- 1) *
- sizeof(*dev->
- context_sareas),
- dev->max_context *
- sizeof(*dev->
- context_sareas),
- DRM_MEM_MAPS);
- if (!ctx_sareas) {
- clear_bit(bit, dev->ctx_bitmap);
- mutex_unlock(&dev->struct_mutex);
- return -1;
- }
- dev->context_sareas = ctx_sareas;
- dev->context_sareas[bit] = NULL;
- } else {
- /* max_context == 1 at this point */
- dev->context_sareas =
- drm_alloc(dev->max_context *
- sizeof(*dev->context_sareas),
- DRM_MEM_MAPS);
- if (!dev->context_sareas) {
- clear_bit(bit, dev->ctx_bitmap);
- mutex_unlock(&dev->struct_mutex);
- return -1;
- }
- dev->context_sareas[bit] = NULL;
- }
- }
+ ret = idr_get_new_above(&dev->ctx_idr, new_ctx, DRM_RESERVED_CONTEXTS, &new_id);
+ if (ret == -EAGAIN) {
mutex_unlock(&dev->struct_mutex);
- return bit;
+ goto again;
}
+
mutex_unlock(&dev->struct_mutex);
- return -1;
+ return new_id;
}
/**
@@ -144,31 +112,20 @@ static int drm_ctxbitmap_next(drm_device_t * dev)
*
* \param dev DRM device.
*
- * Allocates and initialize drm_device::ctx_bitmap and drm_device::context_sareas, while holding
- * the drm_device::struct_mutex lock.
+ * Initialise the drm_device::ctx_idr
*/
int drm_ctxbitmap_init(drm_device_t * dev)
{
- int i;
- int temp;
+ idr_init(&dev->ctx_idr);
+ return 0;
+}
- mutex_lock(&dev->struct_mutex);
- dev->ctx_bitmap = (unsigned long *)drm_alloc(PAGE_SIZE,
- DRM_MEM_CTXBITMAP);
- if (dev->ctx_bitmap == NULL) {
- mutex_unlock(&dev->struct_mutex);
- return -ENOMEM;
- }
- memset((void *)dev->ctx_bitmap, 0, PAGE_SIZE);
- dev->context_sareas = NULL;
- dev->max_context = -1;
- mutex_unlock(&dev->struct_mutex);
- for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
- temp = drm_ctxbitmap_next(dev);
- DRM_DEBUG("drm_ctxbitmap_init : %d\n", temp);
- }
+static int drm_ctx_sarea_free(int id, void *p, void *data)
+{
+ struct drm_ctx_sarea_list *ctx_entry = p;
+ drm_free(ctx_entry, sizeof(struct drm_ctx_sarea_list), DRM_MEM_CTXLIST);
return 0;
}
@@ -177,17 +134,14 @@ int drm_ctxbitmap_init(drm_device_t * dev)
*
* \param dev DRM device.
*
- * Frees drm_device::ctx_bitmap and drm_device::context_sareas, while holding
- * the drm_device::struct_mutex lock.
+ * Free all idr members using drm_ctx_sarea_free helper function
+ * while holding the drm_device::struct_mutex lock.
*/
void drm_ctxbitmap_cleanup(drm_device_t * dev)
{
mutex_lock(&dev->struct_mutex);
- if (dev->context_sareas)
- drm_free(dev->context_sareas,
- sizeof(*dev->context_sareas) *
- dev->max_context, DRM_MEM_MAPS);
- drm_free((void *)dev->ctx_bitmap, PAGE_SIZE, DRM_MEM_CTXBITMAP);
+ idr_for_each(&dev->ctx_idr, drm_ctx_sarea_free, NULL);
+ idr_remove_all(&dev->ctx_idr);
mutex_unlock(&dev->struct_mutex);
}
@@ -206,7 +160,7 @@ void drm_ctxbitmap_cleanup(drm_device_t * dev)
* \param arg user argument pointing to a drm_ctx_priv_map structure.
* \return zero on success or a negative number on failure.
*
- * Gets the map from drm_device::context_sareas with the handle specified and
+ * Gets the map from drm_device::ctx_idr with the handle specified and
* returns its handle.
*/
int drm_getsareactx(struct inode *inode, struct file *filp,
@@ -218,22 +172,24 @@ int drm_getsareactx(struct inode *inode, struct file *filp,
drm_ctx_priv_map_t request;
drm_map_t *map;
drm_map_list_t *_entry;
+ struct drm_ctx_sarea_list *ctx_sarea;
if (copy_from_user(&request, argp, sizeof(request)))
return -EFAULT;
mutex_lock(&dev->struct_mutex);
- if (dev->max_context < 0
- || request.ctx_id >= (unsigned)dev->max_context) {
+
+ ctx_sarea = idr_find(&dev->ctx_idr, request.ctx_id);
+ if (!ctx_sarea) {
mutex_unlock(&dev->struct_mutex);
return -EINVAL;
}
+ map = ctx_sarea->map;
- map = dev->context_sareas[request.ctx_id];
mutex_unlock(&dev->struct_mutex);
request.handle = NULL;
- list_for_each_entry(_entry, &dev->maplist->head,head) {
+ list_for_each_entry(_entry, &dev->maplist, head) {
if (_entry->map == map) {
request.handle =
(void *)(unsigned long)_entry->user_token;
@@ -258,7 +214,7 @@ int drm_getsareactx(struct inode *inode, struct file *filp,
* \return zero on success or a negative number on failure.
*
* Searches the mapping specified in \p arg and update the entry in
- * drm_device::context_sareas with it.
+ * drm_device::ctx_idr with it.
*/
int drm_setsareactx(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
@@ -268,15 +224,14 @@ int drm_setsareactx(struct inode *inode, struct file *filp,
drm_ctx_priv_map_t request;
drm_map_t *map = NULL;
drm_map_list_t *r_list = NULL;
- struct list_head *list;
+ struct drm_ctx_sarea_list *ctx_sarea;
if (copy_from_user(&request,
(drm_ctx_priv_map_t __user *) arg, sizeof(request)))
return -EFAULT;
mutex_lock(&dev->struct_mutex);
- list_for_each(list, &dev->maplist->head) {
- r_list = list_entry(list, drm_map_list_t, head);
+ list_for_each_entry(r_list, &dev->maplist, head) {
if (r_list->map
&& r_list->user_token == (unsigned long) request.handle)
goto found;
@@ -289,11 +244,14 @@ int drm_setsareactx(struct inode *inode, struct file *filp,
map = r_list->map;
if (!map)
goto bad;
- if (dev->max_context < 0)
- goto bad;
- if (request.ctx_id >= (unsigned)dev->max_context)
+
+ mutex_lock(&dev->struct_mutex);
+
+ ctx_sarea = idr_find(&dev->ctx_idr, request.ctx_id);
+ if (!ctx_sarea)
goto bad;
- dev->context_sareas[request.ctx_id] = map;
+
+ ctx_sarea->map = map;
mutex_unlock(&dev->struct_mutex);
return 0;
}
@@ -449,7 +407,7 @@ int drm_addctx(struct inode *inode, struct file *filp,
ctx_entry->tag = priv;
mutex_lock(&dev->ctxlist_mutex);
- list_add(&ctx_entry->head, &dev->ctxlist->head);
+ list_add(&ctx_entry->head, &dev->ctxlist);
++dev->ctx_count;
mutex_unlock(&dev->ctxlist_mutex);
@@ -575,10 +533,10 @@ int drm_rmctx(struct inode *inode, struct file *filp,
}
mutex_lock(&dev->ctxlist_mutex);
- if (!list_empty(&dev->ctxlist->head)) {
+ if (!list_empty(&dev->ctxlist)) {
drm_ctx_list_t *pos, *n;
- list_for_each_entry_safe(pos, n, &dev->ctxlist->head, head) {
+ list_for_each_entry_safe(pos, n, &dev->ctxlist, head) {
if (pos->handle == ctx.handle) {
list_del(&pos->head);
drm_free(pos, sizeof(*pos), DRM_MEM_CTXLIST);
diff --git a/linux-core/drm_drawable.c b/linux-core/drm_drawable.c
index 0817e321..eb44a189 100644
--- a/linux-core/drm_drawable.c
+++ b/linux-core/drm_drawable.c
@@ -44,82 +44,35 @@ int drm_adddraw(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
unsigned long irqflags;
- int i, j;
- u32 *bitfield = dev->drw_bitfield;
- unsigned int bitfield_length = dev->drw_bitfield_length;
- drm_drawable_info_t **info = dev->drw_info;
- unsigned int info_length = dev->drw_info_length;
+ struct drm_drawable_list *draw_info;
drm_draw_t draw;
-
- for (i = 0, j = 0; i < bitfield_length; i++) {
- if (bitfield[i] == ~0)
- continue;
-
- for (; j < 8 * sizeof(*bitfield); j++)
- if (!(bitfield[i] & (1 << j)))
- goto done;
- }
-done:
-
- if (i == bitfield_length) {
- bitfield_length++;
-
- bitfield = drm_alloc(bitfield_length * sizeof(*bitfield),
- DRM_MEM_BUFS);
-
- if (!bitfield) {
- DRM_ERROR("Failed to allocate new drawable bitfield\n");
- return DRM_ERR(ENOMEM);
- }
-
- if (8 * sizeof(*bitfield) * bitfield_length > info_length) {
- info_length += 8 * sizeof(*bitfield);
-
- info = drm_alloc(info_length * sizeof(*info),
- DRM_MEM_BUFS);
-
- if (!info) {
- DRM_ERROR("Failed to allocate new drawable info"
- " array\n");
-
- drm_free(bitfield,
- bitfield_length * sizeof(*bitfield),
- DRM_MEM_BUFS);
- return DRM_ERR(ENOMEM);
- }
- }
-
- bitfield[i] = 0;
+ int new_id = 0;
+ int ret;
+
+ draw_info = drm_calloc(1, sizeof(struct drm_drawable_list), DRM_MEM_BUFS);
+ if (!draw_info)
+ return -ENOMEM;
+
+again:
+ if (idr_pre_get(&dev->drw_idr, GFP_KERNEL) == 0) {
+ DRM_ERROR("Out of memory expanding drawable idr\n");
+ drm_free(draw_info, sizeof(struct drm_drawable_list), DRM_MEM_BUFS);
+ return -ENOMEM;
}
- draw.handle = i * 8 * sizeof(*bitfield) + j + 1;
- DRM_DEBUG("%d\n", draw.handle);
-
spin_lock_irqsave(&dev->drw_lock, irqflags);
-
- bitfield[i] |= 1 << j;
- info[draw.handle - 1] = NULL;
-
- if (bitfield != dev->drw_bitfield) {
- memcpy(bitfield, dev->drw_bitfield, dev->drw_bitfield_length *
- sizeof(*bitfield));
- drm_free(dev->drw_bitfield, sizeof(*bitfield) *
- dev->drw_bitfield_length, DRM_MEM_BUFS);
- dev->drw_bitfield = bitfield;
- dev->drw_bitfield_length = bitfield_length;
- }
-
- if (info != dev->drw_info) {
- memcpy(info, dev->drw_info, dev->drw_info_length *
- sizeof(*info));
- drm_free(dev->drw_info, sizeof(*info) * dev->drw_info_length,
- DRM_MEM_BUFS);
- dev->drw_info = info;
- dev->drw_info_length = info_length;
+ ret = idr_get_new_above(&dev->drw_idr, draw_info, 1, &new_id);
+ if (ret == -EAGAIN) {
+ spin_unlock_irqrestore(&dev->drw_lock, irqflags);
+ goto again;
}
spin_unlock_irqrestore(&dev->drw_lock, irqflags);
+ draw.handle = new_id;
+
+ DRM_DEBUG("%d\n", draw.handle);
+
DRM_COPY_TO_USER_IOCTL((drm_draw_t __user *)data, draw, sizeof(draw));
return 0;
@@ -132,87 +85,24 @@ int drm_rmdraw(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_draw_t draw;
- int id, idx;
- unsigned int shift;
unsigned long irqflags;
- u32 *bitfield = dev->drw_bitfield;
- unsigned int bitfield_length = dev->drw_bitfield_length;
- drm_drawable_info_t **info = dev->drw_info;
- unsigned int info_length = dev->drw_info_length;
+ struct drm_drawable_list *draw_info;
DRM_COPY_FROM_USER_IOCTL(draw, (drm_draw_t __user *) data,
sizeof(draw));
- id = draw.handle - 1;
- idx = id / (8 * sizeof(*bitfield));
- shift = id % (8 * sizeof(*bitfield));
-
- if (idx < 0 || idx >= bitfield_length ||
- !(bitfield[idx] & (1 << shift))) {
+ draw_info = idr_find(&dev->drw_idr, draw.handle);
+ if (!draw_info) {
DRM_DEBUG("No such drawable %d\n", draw.handle);
- return 0;
+ return -EINVAL;
}
spin_lock_irqsave(&dev->drw_lock, irqflags);
- bitfield[idx] &= ~(1 << shift);
+ idr_remove(&dev->drw_idr, draw.handle);
+ drm_free(draw_info, sizeof(struct drm_drawable_list), DRM_MEM_BUFS);
spin_unlock_irqrestore(&dev->drw_lock, irqflags);
-
- if (info[id]) {
- drm_free(info[id]->rects, info[id]->num_rects *
- sizeof(drm_clip_rect_t), DRM_MEM_BUFS);
- drm_free(info[id], sizeof(**info), DRM_MEM_BUFS);
- }
-
- /* Can we shrink the arrays? */
- if (idx == bitfield_length - 1) {
- while (idx >= 0 && !bitfield[idx])
- --idx;
-
- bitfield_length = idx + 1;
-
- if (idx != id / (8 * sizeof(*bitfield)))
- bitfield = drm_alloc(bitfield_length *
- sizeof(*bitfield), DRM_MEM_BUFS);
-
- if (!bitfield && bitfield_length) {
- bitfield = dev->drw_bitfield;
- bitfield_length = dev->drw_bitfield_length;
- }
- }
-
- if (bitfield != dev->drw_bitfield) {
- info_length = 8 * sizeof(*bitfield) * bitfield_length;
-
- info = drm_alloc(info_length * sizeof(*info), DRM_MEM_BUFS);
-
- if (!info && info_length) {
- info = dev->drw_info;
- info_length = dev->drw_info_length;
- }
-
- spin_lock_irqsave(&dev->drw_lock, irqflags);
-
- memcpy(bitfield, dev->drw_bitfield, bitfield_length *
- sizeof(*bitfield));
- drm_free(dev->drw_bitfield, sizeof(*bitfield) *
- dev->drw_bitfield_length, DRM_MEM_BUFS);
- dev->drw_bitfield = bitfield;
- dev->drw_bitfield_length = bitfield_length;
-
- if (info != dev->drw_info) {
- memcpy(info, dev->drw_info, info_length *
- sizeof(*info));
- drm_free(dev->drw_info, sizeof(*info) *
- dev->drw_info_length, DRM_MEM_BUFS);
- dev->drw_info = info;
- dev->drw_info_length = info_length;
- }
-
- spin_unlock_irqrestore(&dev->drw_lock, irqflags);
- }
-
DRM_DEBUG("%d\n", draw.handle);
return 0;
}
@@ -220,36 +110,22 @@ int drm_rmdraw(DRM_IOCTL_ARGS)
int drm_update_drawable_info(DRM_IOCTL_ARGS) {
DRM_DEVICE;
drm_update_draw_t update;
- unsigned int id, idx, shift, bitfield_length = dev->drw_bitfield_length;
- u32 *bitfield = dev->drw_bitfield;
unsigned long irqflags;
drm_drawable_info_t *info;
drm_clip_rect_t *rects;
+ struct drm_drawable_list *draw_info;
int err;
DRM_COPY_FROM_USER_IOCTL(update, (drm_update_draw_t __user *) data,
sizeof(update));
- id = update.handle - 1;
- idx = id / (8 * sizeof(*bitfield));
- shift = id % (8 * sizeof(*bitfield));
-
- if (idx < 0 || idx >= bitfield_length ||
- !(bitfield[idx] & (1 << shift))) {
+ draw_info = idr_find(&dev->drw_idr, update.handle);
+ if (!draw_info) {
DRM_ERROR("No such drawable %d\n", update.handle);
return DRM_ERR(EINVAL);
}
- info = dev->drw_info[id];
-
- if (!info) {
- info = drm_calloc(1, sizeof(drm_drawable_info_t), DRM_MEM_BUFS);
-
- if (!info) {
- DRM_ERROR("Failed to allocate drawable info memory\n");
- return DRM_ERR(ENOMEM);
- }
- }
+ info = &draw_info->info;
switch (update.type) {
case DRM_DRAWABLE_CLIPRECTS:
@@ -284,12 +160,11 @@ int drm_update_drawable_info(DRM_IOCTL_ARGS) {
info->rects = rects;
info->num_rects = update.num;
- dev->drw_info[id] = info;
spin_unlock_irqrestore(&dev->drw_lock, irqflags);
DRM_DEBUG("Updated %d cliprects for drawable %d\n",
- info->num_rects, id);
+ info->num_rects, update.handle);
break;
default:
DRM_ERROR("Invalid update type %d\n", update.type);
@@ -299,11 +174,9 @@ int drm_update_drawable_info(DRM_IOCTL_ARGS) {
return 0;
error:
- if (!dev->drw_info[id])
- drm_free(info, sizeof(*info), DRM_MEM_BUFS);
- else if (rects != dev->drw_info[id]->rects)
- drm_free(rects, update.num *
- sizeof(drm_clip_rect_t), DRM_MEM_BUFS);
+ if (rects != info->rects)
+ drm_free(rects, update.num * sizeof(drm_clip_rect_t),
+ DRM_MEM_BUFS);
return err;
}
@@ -312,19 +185,28 @@ error:
* Caller must hold the drawable spinlock!
*/
drm_drawable_info_t *drm_get_drawable_info(drm_device_t *dev, drm_drawable_t id) {
- u32 *bitfield = dev->drw_bitfield;
- unsigned int idx, shift;
-
- id--;
- idx = id / (8 * sizeof(*bitfield));
- shift = id % (8 * sizeof(*bitfield));
-
- if (idx < 0 || idx >= dev->drw_bitfield_length ||
- !(bitfield[idx] & (1 << shift))) {
+ struct drm_drawable_list *draw_info;
+ draw_info = idr_find(&dev->drw_idr, id);
+ if (!draw_info) {
DRM_DEBUG("No such drawable %d\n", id);
return NULL;
}
- return dev->drw_info[id];
+ return &draw_info->info;
}
EXPORT_SYMBOL(drm_get_drawable_info);
+
+static int drm_drawable_free(int idr, void *p, void *data)
+{
+ struct drm_drawable_list *drw_entry = p;
+ drm_free(drw_entry->info.rects, drw_entry->info.num_rects *
+ sizeof(drm_clip_rect_t), DRM_MEM_BUFS);
+ drm_free(drw_entry, sizeof(struct drm_drawable_list), DRM_MEM_BUFS);
+ return 0;
+}
+
+void drm_drawable_free_all(drm_device_t *dev)
+{
+ idr_for_each(&dev->drw_idr, drm_drawable_free, NULL);
+ idr_remove_all(&dev->drw_idr);
+}
diff --git a/linux-core/drm_drv.c b/linux-core/drm_drv.c
index 76fb90c9..0b4f8095 100644
--- a/linux-core/drm_drv.c
+++ b/linux-core/drm_drv.c
@@ -151,8 +151,8 @@ static drm_ioctl_desc_t drm_ioctls[] = {
int drm_lastclose(drm_device_t * dev)
{
drm_magic_entry_t *pt, *next;
- drm_map_list_t *r_list, *r_list_tmp;
- drm_vma_entry_t *vma, *vma_next;
+ drm_map_list_t *r_list, *list_t;
+ drm_vma_entry_t *vma, *vma_temp;
int i;
DRM_DEBUG("\n");
@@ -175,18 +175,9 @@ int drm_lastclose(drm_device_t * dev)
drm_irq_uninstall(dev);
/* Free drawable information memory */
- for (i = 0; i < dev->drw_bitfield_length / sizeof(*dev->drw_bitfield);
- i++) {
- drm_drawable_info_t *info = drm_get_drawable_info(dev, i);
-
- if (info) {
- drm_free(info->rects, info->num_rects *
- sizeof(drm_clip_rect_t), DRM_MEM_BUFS);
- drm_free(info, sizeof(*info), DRM_MEM_BUFS);
- }
- }
-
mutex_lock(&dev->struct_mutex);
+
+ drm_drawable_free_all(dev);
del_timer(&dev->timer);
if (dev->unique) {
@@ -207,19 +198,17 @@ int drm_lastclose(drm_device_t * dev)
/* Clear AGP information */
if (drm_core_has_AGP(dev) && dev->agp) {
- drm_agp_mem_t *entry;
- drm_agp_mem_t *nexte;
+ drm_agp_mem_t *entry, *tempe;
/* Remove AGP resources, but leave dev->agp
intact until drv_cleanup is called. */
- for (entry = dev->agp->memory; entry; entry = nexte) {
- nexte = entry->next;
+ list_for_each_entry_safe(entry, tempe, &dev->agp->memory, head) {
if (entry->bound)
drm_unbind_agp(entry->memory);
drm_free_agp(entry->memory, entry->pages);
drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
}
- dev->agp->memory = NULL;
+ INIT_LIST_HEAD(&dev->agp->memory);
if (dev->agp->acquired)
drm_agp_release(dev);
@@ -233,19 +222,14 @@ int drm_lastclose(drm_device_t * dev)
}
/* Clear vma list (only built for debugging) */
- if (dev->vmalist) {
- for (vma = dev->vmalist; vma; vma = vma_next) {
- vma_next = vma->next;
- drm_ctl_free(vma, sizeof(*vma), DRM_MEM_VMAS);
- }
- dev->vmalist = NULL;
+ list_for_each_entry_safe(vma, vma_temp, &dev->vmalist, head) {
+ list_del(&vma->head);
+ drm_ctl_free(vma, sizeof(*vma), DRM_MEM_VMAS);
}
-
- if (dev->maplist) {
- list_for_each_entry_safe(r_list, r_list_tmp, &dev->maplist->head, head) {
- if (!(r_list->map->flags & _DRM_DRIVER))
- drm_rmmap_locked(dev, r_list->map);
- }
+
+ list_for_each_entry_safe(r_list, list_t, &dev->maplist, head) {
+ drm_rmmap_locked(dev, r_list->map);
+ r_list = NULL;
}
if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE) && dev->queuelist) {
@@ -379,6 +363,13 @@ static void drm_cleanup(drm_device_t * dev)
drm_lastclose(dev);
drm_fence_manager_takedown(dev);
+ drm_ht_remove(&dev->map_hash);
+ drm_mm_takedown(&dev->offset_manager);
+ drm_ht_remove(&dev->object_hash);
+
+ if (!drm_fb_loaded)
+ pci_disable_device(dev->pdev);
+
drm_ctxbitmap_cleanup(dev);
if (drm_core_has_MTRR(dev) && drm_core_has_AGP(dev) && dev->agp
@@ -398,16 +389,6 @@ static void drm_cleanup(drm_device_t * dev)
dev->agp = NULL;
}
-
- // drm_bo_driver_finish(dev);
- if (dev->maplist) {
- drm_free(dev->maplist, sizeof(*dev->maplist), DRM_MEM_MAPS);
- dev->maplist = NULL;
- drm_ht_remove(&dev->map_hash);
- drm_mm_takedown(&dev->offset_manager);
- drm_ht_remove(&dev->object_hash);
- }
-
if (!drm_fb_loaded)
pci_disable_device(dev->pdev);
@@ -604,7 +585,7 @@ int drm_ioctl(struct inode *inode, struct file *filp,
goto err_i1;
if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_END)
&& (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls))
- ioctl = &dev->driver->ioctls[nr - DRM_COMMAND_BASE];
+ ioctl = &dev->driver->ioctls[nr - DRM_COMMAND_BASE];
else if ((nr >= DRM_COMMAND_END) || (nr < DRM_COMMAND_BASE))
ioctl = &drm_ioctls[nr];
else
@@ -633,39 +614,11 @@ err_i1:
}
EXPORT_SYMBOL(drm_ioctl);
-int drm_wait_on(drm_device_t *dev, wait_queue_head_t *queue, int timeout,
- int (*fn)(drm_device_t *dev, void *priv), void *priv)
-{
- DECLARE_WAITQUEUE(entry, current);
- unsigned long end = jiffies + (timeout);
- int ret = 0;
- add_wait_queue(queue, &entry);
-
- for (;;) {
- __set_current_state(TASK_INTERRUPTIBLE);
- if ((*fn)(dev, priv))
- break;
- if (time_after_eq(jiffies, end)) {
- ret = -EBUSY;
- break;
- }
- schedule_timeout((HZ/100 > 1) ? HZ/100 : 1);
- if (signal_pending(current)) {
- ret = -EINTR;
- break;
- }
- }
- __set_current_state(TASK_RUNNING);
- remove_wait_queue(queue, &entry);
- return ret;
-}
-EXPORT_SYMBOL(drm_wait_on);
-
drm_local_map_t *drm_getsarea(struct drm_device *dev)
{
drm_map_list_t *entry;
- list_for_each_entry(entry, &dev->maplist->head, head) {
+ list_for_each_entry(entry, &dev->maplist, head) {
if (entry->map && entry->map->type == _DRM_SHM &&
(entry->map->flags & _DRM_CONTAINS_LOCK)) {
return entry->map;
diff --git a/linux-core/drm_fence.c b/linux-core/drm_fence.c
index ce161dc3..5215feb6 100644
--- a/linux-core/drm_fence.c
+++ b/linux-core/drm_fence.c
@@ -124,52 +124,76 @@ static void drm_fence_unring(drm_device_t * dev, struct list_head *ring)
write_unlock_irqrestore(&fm->lock, flags);
}
-void drm_fence_usage_deref_locked(drm_device_t * dev,
- drm_fence_object_t * fence)
+void drm_fence_usage_deref_locked(drm_fence_object_t ** fence)
{
+ struct drm_fence_object *tmp_fence = *fence;
+ struct drm_device *dev = tmp_fence->dev;
drm_fence_manager_t *fm = &dev->fm;
- if (atomic_dec_and_test(&fence->usage)) {
- drm_fence_unring(dev, &fence->ring);
+ DRM_ASSERT_LOCKED(&dev->struct_mutex);
+ *fence = NULL;
+ if (atomic_dec_and_test(&tmp_fence->usage)) {
+ drm_fence_unring(dev, &tmp_fence->ring);
DRM_DEBUG("Destroyed a fence object 0x%08lx\n",
- fence->base.hash.key);
+ tmp_fence->base.hash.key);
atomic_dec(&fm->count);
- drm_ctl_free(fence, sizeof(*fence), DRM_MEM_FENCE);
+ BUG_ON(!list_empty(&tmp_fence->base.list));
+ drm_ctl_free(tmp_fence, sizeof(*tmp_fence), DRM_MEM_FENCE);
}
}
-void drm_fence_usage_deref_unlocked(drm_device_t * dev,
- drm_fence_object_t * fence)
+void drm_fence_usage_deref_unlocked(drm_fence_object_t ** fence)
{
+ struct drm_fence_object *tmp_fence = *fence;
+ struct drm_device *dev = tmp_fence->dev;
drm_fence_manager_t *fm = &dev->fm;
- if (atomic_dec_and_test(&fence->usage)) {
+ *fence = NULL;
+ if (atomic_dec_and_test(&tmp_fence->usage)) {
mutex_lock(&dev->struct_mutex);
- if (atomic_read(&fence->usage) == 0) {
- drm_fence_unring(dev, &fence->ring);
+ if (atomic_read(&tmp_fence->usage) == 0) {
+ drm_fence_unring(dev, &tmp_fence->ring);
atomic_dec(&fm->count);
- drm_ctl_free(fence, sizeof(*fence), DRM_MEM_FENCE);
+ BUG_ON(!list_empty(&tmp_fence->base.list));
+ drm_ctl_free(tmp_fence, sizeof(*tmp_fence), DRM_MEM_FENCE);
}
mutex_unlock(&dev->struct_mutex);
}
}
-static void drm_fence_object_destroy(drm_file_t * priv,
- drm_user_object_t * base)
+struct drm_fence_object
+*drm_fence_reference_locked(struct drm_fence_object *src)
+{
+ DRM_ASSERT_LOCKED(&src->dev->struct_mutex);
+
+ atomic_inc(&src->usage);
+ return src;
+}
+
+void drm_fence_reference_unlocked(struct drm_fence_object **dst,
+ struct drm_fence_object *src)
+{
+ mutex_lock(&src->dev->struct_mutex);
+ *dst = src;
+ atomic_inc(&src->usage);
+ mutex_unlock(&src->dev->struct_mutex);
+}
+
+
+static void drm_fence_object_destroy(drm_file_t *priv, drm_user_object_t * base)
{
- drm_device_t *dev = priv->head->dev;
drm_fence_object_t *fence =
drm_user_object_entry(base, drm_fence_object_t, base);
- drm_fence_usage_deref_locked(dev, fence);
+ drm_fence_usage_deref_locked(&fence);
}
-static int fence_signaled(drm_device_t * dev,
- drm_fence_object_t * fence,
- uint32_t mask, int poke_flush)
+int drm_fence_object_signaled(drm_fence_object_t * fence,
+ uint32_t mask, int poke_flush)
{
unsigned long flags;
int signaled;
+ struct drm_device *dev = fence->dev;
drm_fence_manager_t *fm = &dev->fm;
drm_fence_driver_t *driver = dev->driver->fence_driver;
@@ -200,16 +224,10 @@ static void drm_fence_flush_exe(drm_fence_class_manager_t * fc,
}
}
-int drm_fence_object_signaled(drm_fence_object_t * fence,
- uint32_t type)
-{
- return ((fence->signaled & type) == type);
-}
-
-int drm_fence_object_flush(drm_device_t * dev,
- drm_fence_object_t * fence,
+int drm_fence_object_flush(drm_fence_object_t * fence,
uint32_t type)
{
+ struct drm_device *dev = fence->dev;
drm_fence_manager_t *fm = &dev->fm;
drm_fence_class_manager_t *fc = &fm->class[fence->class];
drm_fence_driver_t *driver = dev->driver->fence_driver;
@@ -272,24 +290,23 @@ void drm_fence_flush_old(drm_device_t * dev, uint32_t class, uint32_t sequence)
mutex_unlock(&dev->struct_mutex);
return;
}
- fence = list_entry(fc->ring.next, drm_fence_object_t, ring);
- atomic_inc(&fence->usage);
+ fence = drm_fence_reference_locked(list_entry(fc->ring.next, drm_fence_object_t, ring));
mutex_unlock(&dev->struct_mutex);
diff = (old_sequence - fence->sequence) & driver->sequence_mask;
read_unlock_irqrestore(&fm->lock, flags);
if (diff < driver->wrap_diff) {
- drm_fence_object_flush(dev, fence, fence->type);
+ drm_fence_object_flush(fence, fence->type);
}
- drm_fence_usage_deref_unlocked(dev, fence);
+ drm_fence_usage_deref_unlocked(&fence);
}
EXPORT_SYMBOL(drm_fence_flush_old);
-static int drm_fence_lazy_wait(drm_device_t *dev,
- drm_fence_object_t *fence,
+static int drm_fence_lazy_wait(drm_fence_object_t *fence,
int ignore_signals,
uint32_t mask)
{
+ struct drm_device *dev = fence->dev;
drm_fence_manager_t *fm = &dev->fm;
drm_fence_class_manager_t *fc = &fm->class[fence->class];
int signaled;
@@ -298,13 +315,13 @@ static int drm_fence_lazy_wait(drm_device_t *dev,
do {
DRM_WAIT_ON(ret, fc->fence_queue, 3 * DRM_HZ,
- (signaled = fence_signaled(dev, fence, mask, 1)));
+ (signaled = drm_fence_object_signaled(fence, mask, 1)));
if (signaled)
return 0;
if (time_after_eq(jiffies, _end))
break;
} while (ret == -EINTR && ignore_signals);
- if (fence_signaled(dev, fence, mask, 0))
+ if (drm_fence_object_signaled(fence, mask, 0))
return 0;
if (time_after_eq(jiffies, _end))
ret = -EBUSY;
@@ -319,10 +336,10 @@ static int drm_fence_lazy_wait(drm_device_t *dev,
return 0;
}
-int drm_fence_object_wait(drm_device_t * dev,
- drm_fence_object_t * fence,
+int drm_fence_object_wait(drm_fence_object_t * fence,
int lazy, int ignore_signals, uint32_t mask)
{
+ struct drm_device *dev = fence->dev;
drm_fence_driver_t *driver = dev->driver->fence_driver;
int ret = 0;
unsigned long _end;
@@ -334,16 +351,16 @@ int drm_fence_object_wait(drm_device_t * dev,
return -EINVAL;
}
- if (fence_signaled(dev, fence, mask, 0))
+ if (drm_fence_object_signaled(fence, mask, 0))
return 0;
_end = jiffies + 3 * DRM_HZ;
- drm_fence_object_flush(dev, fence, mask);
+ drm_fence_object_flush(fence, mask);
if (lazy && driver->lazy_capable) {
- ret = drm_fence_lazy_wait(dev, fence, ignore_signals, mask);
+ ret = drm_fence_lazy_wait(fence, ignore_signals, mask);
if (ret)
return ret;
@@ -351,7 +368,7 @@ int drm_fence_object_wait(drm_device_t * dev,
if (driver->has_irq(dev, fence->class,
DRM_FENCE_TYPE_EXE)) {
- ret = drm_fence_lazy_wait(dev, fence, ignore_signals,
+ ret = drm_fence_lazy_wait(fence, ignore_signals,
DRM_FENCE_TYPE_EXE);
if (ret)
return ret;
@@ -359,13 +376,13 @@ int drm_fence_object_wait(drm_device_t * dev,
if (driver->has_irq(dev, fence->class,
mask & ~DRM_FENCE_TYPE_EXE)) {
- ret = drm_fence_lazy_wait(dev, fence, ignore_signals,
+ ret = drm_fence_lazy_wait(fence, ignore_signals,
mask);
if (ret)
return ret;
}
}
- if (drm_fence_object_signaled(fence, mask))
+ if (drm_fence_object_signaled(fence, mask, 0))
return 0;
/*
@@ -377,7 +394,7 @@ int drm_fence_object_wait(drm_device_t * dev,
#endif
do {
schedule();
- signaled = fence_signaled(dev, fence, mask, 1);
+ signaled = drm_fence_object_signaled(fence, mask, 1);
} while (!signaled && !time_after_eq(jiffies, _end));
if (!signaled)
@@ -386,9 +403,10 @@ int drm_fence_object_wait(drm_device_t * dev,
return 0;
}
-int drm_fence_object_emit(drm_device_t * dev, drm_fence_object_t * fence,
+int drm_fence_object_emit(drm_fence_object_t * fence,
uint32_t fence_flags, uint32_t class, uint32_t type)
{
+ struct drm_device *dev = fence->dev;
drm_fence_manager_t *fm = &dev->fm;
drm_fence_driver_t *driver = dev->driver->fence_driver;
drm_fence_class_manager_t *fc = &fm->class[fence->class];
@@ -432,15 +450,22 @@ static int drm_fence_object_init(drm_device_t * dev, uint32_t class,
write_lock_irqsave(&fm->lock, flags);
INIT_LIST_HEAD(&fence->ring);
+
+ /*
+ * Avoid hitting BUG() for kernel-only fence objects.
+ */
+
+ INIT_LIST_HEAD(&fence->base.list);
fence->class = class;
fence->type = type;
fence->flush_mask = 0;
fence->submitted_flush = 0;
fence->signaled = 0;
fence->sequence = 0;
+ fence->dev = dev;
write_unlock_irqrestore(&fm->lock, flags);
if (fence_flags & DRM_FENCE_FLAG_EMIT) {
- ret = drm_fence_object_emit(dev, fence, fence_flags,
+ ret = drm_fence_object_emit(fence, fence_flags,
fence->class, type);
}
return ret;
@@ -454,15 +479,16 @@ int drm_fence_add_user_object(drm_file_t * priv, drm_fence_object_t * fence,
mutex_lock(&dev->struct_mutex);
ret = drm_add_user_object(priv, &fence->base, shareable);
- mutex_unlock(&dev->struct_mutex);
if (ret)
- return ret;
+ goto out;
+ atomic_inc(&fence->usage);
fence->base.type = drm_fence_type;
fence->base.remove = &drm_fence_object_destroy;
DRM_DEBUG("Fence 0x%08lx created\n", fence->base.hash.key);
- return 0;
+out:
+ mutex_unlock(&dev->struct_mutex);
+ return ret;
}
-
EXPORT_SYMBOL(drm_fence_add_user_object);
int drm_fence_object_create(drm_device_t * dev, uint32_t class, uint32_t type,
@@ -472,12 +498,12 @@ int drm_fence_object_create(drm_device_t * dev, uint32_t class, uint32_t type,
int ret;
drm_fence_manager_t *fm = &dev->fm;
- fence = drm_ctl_alloc(sizeof(*fence), DRM_MEM_FENCE);
+ fence = drm_ctl_calloc(1, sizeof(*fence), DRM_MEM_FENCE);
if (!fence)
return -ENOMEM;
ret = drm_fence_object_init(dev, class, type, flags, fence);
if (ret) {
- drm_fence_usage_deref_unlocked(dev, fence);
+ drm_fence_usage_deref_unlocked(&fence);
return ret;
}
*c_fence = fence;
@@ -534,8 +560,7 @@ drm_fence_object_t *drm_lookup_fence_object(drm_file_t * priv, uint32_t handle)
mutex_unlock(&dev->struct_mutex);
return NULL;
}
- fence = drm_user_object_entry(uo, drm_fence_object_t, base);
- atomic_inc(&fence->usage);
+ fence = drm_fence_reference_locked(drm_user_object_entry(uo, drm_fence_object_t, base));
mutex_unlock(&dev->struct_mutex);
return fence;
}
@@ -569,16 +594,11 @@ int drm_fence_ioctl(DRM_IOCTL_ARGS)
arg.flags &
DRM_FENCE_FLAG_SHAREABLE);
if (ret) {
- drm_fence_usage_deref_unlocked(dev, fence);
+ drm_fence_usage_deref_unlocked(&fence);
return ret;
}
-
- /*
- * usage > 0. No need to lock dev->struct_mutex;
- */
-
- atomic_inc(&fence->usage);
arg.handle = fence->base.hash.key;
+
break;
case drm_fence_destroy:
mutex_lock(&dev->struct_mutex);
@@ -609,14 +629,14 @@ int drm_fence_ioctl(DRM_IOCTL_ARGS)
fence = drm_lookup_fence_object(priv, arg.handle);
if (!fence)
return -EINVAL;
- ret = drm_fence_object_flush(dev, fence, arg.type);
+ ret = drm_fence_object_flush(fence, arg.type);
break;
case drm_fence_wait:
fence = drm_lookup_fence_object(priv, arg.handle);
if (!fence)
return -EINVAL;
ret =
- drm_fence_object_wait(dev, fence,
+ drm_fence_object_wait(fence,
arg.flags & DRM_FENCE_FLAG_WAIT_LAZY,
0, arg.type);
break;
@@ -625,7 +645,7 @@ int drm_fence_ioctl(DRM_IOCTL_ARGS)
fence = drm_lookup_fence_object(priv, arg.handle);
if (!fence)
return -EINVAL;
- ret = drm_fence_object_emit(dev, fence, arg.flags, arg.class,
+ ret = drm_fence_object_emit(fence, arg.flags, arg.class,
arg.type);
break;
case drm_fence_buffers:
@@ -643,7 +663,6 @@ int drm_fence_ioctl(DRM_IOCTL_ARGS)
DRM_FENCE_FLAG_SHAREABLE);
if (ret)
return ret;
- atomic_inc(&fence->usage);
arg.handle = fence->base.hash.key;
break;
default:
@@ -654,7 +673,7 @@ int drm_fence_ioctl(DRM_IOCTL_ARGS)
arg.type = fence->type;
arg.signaled = fence->signaled;
read_unlock_irqrestore(&fm->lock, flags);
- drm_fence_usage_deref_unlocked(dev, fence);
+ drm_fence_usage_deref_unlocked(&fence);
DRM_COPY_TO_USER_IOCTL((void __user *)data, arg, sizeof(arg));
return ret;
diff --git a/linux-core/drm_fops.c b/linux-core/drm_fops.c
index e4748978..9116685c 100644
--- a/linux-core/drm_fops.c
+++ b/linux-core/drm_fops.c
@@ -79,14 +79,7 @@ static int drm_setup(drm_device_t * dev)
drm_ht_create(&dev->magiclist, DRM_MAGIC_HASH_ORDER);
INIT_LIST_HEAD(&dev->magicfree);
- dev->ctxlist = drm_alloc(sizeof(*dev->ctxlist), DRM_MEM_CTXLIST);
- if (dev->ctxlist == NULL)
- return -ENOMEM;
- memset(dev->ctxlist, 0, sizeof(*dev->ctxlist));
- INIT_LIST_HEAD(&dev->ctxlist->head);
-
- dev->vmalist = NULL;
- // dev->sigdata.lock = NULL;
+ dev->sigdata.lock = NULL;
init_waitqueue_head(&dev->lock.lock_queue);
dev->queue_count = 0;
dev->queue_reserved = 0;
@@ -268,6 +261,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
priv->authenticated = capable(CAP_SYS_ADMIN);
priv->lock_count = 0;
+ INIT_LIST_HEAD(&priv->lhead);
INIT_LIST_HEAD(&priv->user_objects);
INIT_LIST_HEAD(&priv->refd_objects);
INIT_LIST_HEAD(&priv->fbs);
@@ -292,19 +286,10 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
}
mutex_lock(&dev->struct_mutex);
- if (!dev->file_last) {
- priv->next = NULL;
- priv->prev = NULL;
- dev->file_first = priv;
- dev->file_last = priv;
- /* first opener automatically becomes master */
+ if (list_empty(&dev->filelist))
priv->master = 1;
- } else {
- priv->next = NULL;
- priv->prev = dev->file_last;
- dev->file_last->next = priv;
- dev->file_last = priv;
- }
+
+ list_add(&priv->lhead, &dev->filelist);
mutex_unlock(&dev->struct_mutex);
#ifdef __alpha__
@@ -481,10 +466,10 @@ int drm_release(struct inode *inode, struct file *filp)
mutex_lock(&dev->ctxlist_mutex);
- if (dev->ctxlist && (!list_empty(&dev->ctxlist->head))) {
+ if (!list_empty(&dev->ctxlist)) {
drm_ctx_list_t *pos, *n;
- list_for_each_entry_safe(pos, n, &dev->ctxlist->head, head) {
+ list_for_each_entry_safe(pos, n, &dev->ctxlist, head) {
if (pos->tag == priv &&
pos->handle != DRM_KERNEL_CONTEXT) {
if (dev->driver->context_dtor)
@@ -505,22 +490,12 @@ int drm_release(struct inode *inode, struct file *filp)
drm_fb_release(filp);
drm_object_release(filp);
if (priv->remove_auth_on_close == 1) {
- drm_file_t *temp = dev->file_first;
- while (temp) {
+ drm_file_t *temp;
+
+ list_for_each_entry(temp, &dev->filelist, lhead)
temp->authenticated = 0;
- temp = temp->next;
- }
- }
- if (priv->prev) {
- priv->prev->next = priv->next;
- } else {
- dev->file_first = priv->next;
- }
- if (priv->next) {
- priv->next->prev = priv->prev;
- } else {
- dev->file_last = priv->prev;
}
+ list_del(&priv->lhead);
mutex_unlock(&dev->struct_mutex);
if (dev->driver->postclose)
diff --git a/linux-core/drm_ioc32.c b/linux-core/drm_ioc32.c
index c112e81f..bbab3ea2 100644
--- a/linux-core/drm_ioc32.c
+++ b/linux-core/drm_ioc32.c
@@ -28,7 +28,6 @@
* IN THE SOFTWARE.
*/
#include <linux/compat.h>
-#include <linux/ioctl32.h>
#include "drmP.h"
#include "drm_core.h"
diff --git a/linux-core/drm_ioctl.c b/linux-core/drm_ioctl.c
index f790a4b3..97df972f 100644
--- a/linux-core/drm_ioctl.c
+++ b/linux-core/drm_ioctl.c
@@ -199,7 +199,7 @@ int drm_getmap(struct inode *inode, struct file *filp,
}
i = 0;
- list_for_each(list, &dev->maplist->head) {
+ list_for_each(list, &dev->maplist) {
if (i == idx) {
r_list = list_entry(list, drm_map_list_t, head);
break;
@@ -252,12 +252,18 @@ int drm_getclient(struct inode *inode, struct file *filp,
return -EFAULT;
idx = client.idx;
mutex_lock(&dev->struct_mutex);
- for (i = 0, pt = dev->file_first; i < idx && pt; i++, pt = pt->next) ;
-
- if (!pt) {
+
+ if (list_empty(&dev->filelist)) {
mutex_unlock(&dev->struct_mutex);
return -EINVAL;
}
+
+ i = 0;
+ list_for_each_entry(pt, &dev->filelist, lhead) {
+ if (i++ >= idx)
+ break;
+ }
+
client.auth = pt->authenticated;
client.pid = pt->pid;
client.uid = pt->uid;
diff --git a/linux-core/drm_irq.c b/linux-core/drm_irq.c
index b0f6e3e1..88716712 100644
--- a/linux-core/drm_irq.c
+++ b/linux-core/drm_irq.c
@@ -119,8 +119,8 @@ static int drm_irq_install(drm_device_t * dev)
spin_lock_init(&dev->vbl_lock);
- INIT_LIST_HEAD(&dev->vbl_sigs.head);
- INIT_LIST_HEAD(&dev->vbl_sigs2.head);
+ INIT_LIST_HEAD(&dev->vbl_sigs);
+ INIT_LIST_HEAD(&dev->vbl_sigs2);
dev->vbl_pending = 0;
}
@@ -290,7 +290,7 @@ int drm_wait_vblank(DRM_IOCTL_ARGS)
if (flags & _DRM_VBLANK_SIGNAL) {
unsigned long irqflags;
- drm_vbl_sig_t *vbl_sigs = (flags & _DRM_VBLANK_SECONDARY)
+ struct list_head *vbl_sigs = (flags & _DRM_VBLANK_SECONDARY)
? &dev->vbl_sigs2 : &dev->vbl_sigs;
drm_vbl_sig_t *vbl_sig;
@@ -300,7 +300,7 @@ int drm_wait_vblank(DRM_IOCTL_ARGS)
* for the same vblank sequence number; nothing to be done in
* that case
*/
- list_for_each_entry(vbl_sig, &vbl_sigs->head, head) {
+ list_for_each_entry(vbl_sig, vbl_sigs, head) {
if (vbl_sig->sequence == vblwait.request.sequence
&& vbl_sig->info.si_signo == vblwait.request.signal
&& vbl_sig->task == current) {
@@ -334,7 +334,7 @@ int drm_wait_vblank(DRM_IOCTL_ARGS)
spin_lock_irqsave(&dev->vbl_lock, irqflags);
- list_add_tail((struct list_head *)vbl_sig, &vbl_sigs->head);
+ list_add_tail(&vbl_sig->head, vbl_sigs);
spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
@@ -377,20 +377,18 @@ void drm_vbl_send_signals(drm_device_t * dev)
spin_lock_irqsave(&dev->vbl_lock, flags);
for (i = 0; i < 2; i++) {
- struct list_head *list, *tmp;
- drm_vbl_sig_t *vbl_sig;
- drm_vbl_sig_t *vbl_sigs = i ? &dev->vbl_sigs2 : &dev->vbl_sigs;
+ drm_vbl_sig_t *vbl_sig, *tmp;
+ struct list_head *vbl_sigs = i ? &dev->vbl_sigs2 : &dev->vbl_sigs;
unsigned int vbl_seq = atomic_read(i ? &dev->vbl_received2 :
&dev->vbl_received);
- list_for_each_safe(list, tmp, &vbl_sigs->head) {
- vbl_sig = list_entry(list, drm_vbl_sig_t, head);
+ list_for_each_entry_safe(vbl_sig, tmp, vbl_sigs, head) {
if ((vbl_seq - vbl_sig->sequence) <= (1 << 23)) {
vbl_sig->info.si_code = vbl_seq;
send_sig_info(vbl_sig->info.si_signo,
&vbl_sig->info, vbl_sig->task);
- list_del(list);
+ list_del(&vbl_sig->head);
drm_free(vbl_sig, sizeof(*vbl_sig),
DRM_MEM_DRIVER);
diff --git a/linux-core/drm_memory.c b/linux-core/drm_memory.c
index 759e1f15..b1423c12 100644
--- a/linux-core/drm_memory.c
+++ b/linux-core/drm_memory.c
@@ -228,7 +228,7 @@ static void *agp_remap(unsigned long offset, unsigned long size,
offset -= dev->hose->mem_space->start;
#endif
- for (agpmem = dev->agp->memory; agpmem; agpmem = agpmem->next)
+ list_for_each_entry(agpmem, &dev->agp->memory, head)
if (agpmem->bound <= offset
&& (agpmem->bound + (agpmem->pages << PAGE_SHIFT)) >=
(offset + size))
diff --git a/linux-core/drm_object.c b/linux-core/drm_object.c
index 03906034..567a7d2b 100644
--- a/linux-core/drm_object.c
+++ b/linux-core/drm_object.c
@@ -36,6 +36,8 @@ int drm_add_user_object(drm_file_t * priv, drm_user_object_t * item,
drm_device_t *dev = priv->head->dev;
int ret;
+ DRM_ASSERT_LOCKED(&dev->struct_mutex);
+
atomic_set(&item->refcount, 1);
item->shareable = shareable;
item->owner = priv;
@@ -56,6 +58,8 @@ drm_user_object_t *drm_lookup_user_object(drm_file_t * priv, uint32_t key)
int ret;
drm_user_object_t *item;
+ DRM_ASSERT_LOCKED(&dev->struct_mutex);
+
ret = drm_ht_find_item(&dev->object_hash, key, &hash);
if (ret) {
return NULL;
@@ -88,6 +92,8 @@ static void drm_deref_user_object(drm_file_t * priv, drm_user_object_t * item)
int drm_remove_user_object(drm_file_t * priv, drm_user_object_t * item)
{
+ DRM_ASSERT_LOCKED(&priv->head->dev->struct_mutex);
+
if (item->owner != priv) {
DRM_ERROR("Cannot destroy object not owned by you.\n");
return -EINVAL;
@@ -125,6 +131,7 @@ int drm_add_ref_object(drm_file_t * priv, drm_user_object_t * referenced_object,
drm_ref_object_t *item;
drm_open_hash_t *ht = &priv->refd_object_hash[ref_action];
+ DRM_ASSERT_LOCKED(&priv->head->dev->struct_mutex);
if (!referenced_object->shareable && priv != referenced_object->owner) {
DRM_ERROR("Not allowed to reference this object\n");
return -EINVAL;
@@ -181,6 +188,7 @@ drm_ref_object_t *drm_lookup_ref_object(drm_file_t * priv,
drm_hash_item_t *hash;
int ret;
+ DRM_ASSERT_LOCKED(&priv->head->dev->struct_mutex);
ret = drm_ht_find_item(&priv->refd_object_hash[ref_action],
(unsigned long)referenced_object, &hash);
if (ret)
@@ -213,6 +221,7 @@ void drm_remove_ref_object(drm_file_t * priv, drm_ref_object_t * item)
drm_open_hash_t *ht = &priv->refd_object_hash[item->unref_action];
drm_ref_t unref_action;
+ DRM_ASSERT_LOCKED(&priv->head->dev->struct_mutex);
unref_action = item->unref_action;
if (atomic_dec_and_test(&item->refcount)) {
ret = drm_ht_remove_item(ht, &item->hash);
diff --git a/linux-core/drm_objects.h b/linux-core/drm_objects.h
index b6754453..e0716aa4 100644
--- a/linux-core/drm_objects.h
+++ b/linux-core/drm_objects.h
@@ -141,6 +141,7 @@ extern int drm_user_object_unref(drm_file_t * priv, uint32_t user_token,
typedef struct drm_fence_object {
drm_user_object_t base;
+ struct drm_device *dev;
atomic_t usage;
/*
@@ -196,15 +197,15 @@ extern void drm_fence_manager_init(struct drm_device *dev);
extern void drm_fence_manager_takedown(struct drm_device *dev);
extern void drm_fence_flush_old(struct drm_device *dev, uint32_t class,
uint32_t sequence);
-extern int drm_fence_object_flush(struct drm_device *dev,
- drm_fence_object_t * fence, uint32_t type);
-extern int drm_fence_object_signaled(drm_fence_object_t * fence, uint32_t type);
-extern void drm_fence_usage_deref_locked(struct drm_device *dev,
- drm_fence_object_t * fence);
-extern void drm_fence_usage_deref_unlocked(struct drm_device *dev,
- drm_fence_object_t * fence);
-extern int drm_fence_object_wait(struct drm_device *dev,
- drm_fence_object_t * fence,
+extern int drm_fence_object_flush(drm_fence_object_t * fence, uint32_t type);
+extern int drm_fence_object_signaled(drm_fence_object_t * fence,
+ uint32_t type, int flush);
+extern void drm_fence_usage_deref_locked(drm_fence_object_t ** fence);
+extern void drm_fence_usage_deref_unlocked(drm_fence_object_t ** fence);
+extern struct drm_fence_object *drm_fence_reference_locked(struct drm_fence_object *src);
+extern void drm_fence_reference_unlocked(struct drm_fence_object **dst,
+ struct drm_fence_object *src);
+extern int drm_fence_object_wait(drm_fence_object_t * fence,
int lazy, int ignore_signals, uint32_t mask);
extern int drm_fence_object_create(struct drm_device *dev, uint32_t type,
uint32_t fence_flags, uint32_t class,
@@ -445,7 +446,7 @@ extern int drm_bo_pci_offset(struct drm_device *dev,
unsigned long *bus_size);
extern int drm_mem_reg_is_pci(struct drm_device *dev, drm_bo_mem_reg_t * mem);
-extern void drm_bo_usage_deref_locked(drm_buffer_object_t * bo);
+extern void drm_bo_usage_deref_locked(drm_buffer_object_t ** bo);
extern int drm_fence_buffer_objects(drm_file_t * priv,
struct list_head *list,
uint32_t fence_flags,
@@ -482,5 +483,12 @@ extern int drm_mem_reg_ioremap(struct drm_device *dev, drm_bo_mem_reg_t * mem,
void **virtual);
extern void drm_mem_reg_iounmap(struct drm_device *dev, drm_bo_mem_reg_t * mem,
void *virtual);
+#ifdef CONFIG_DEBUG_MUTEXES
+#define DRM_ASSERT_LOCKED(_mutex) \
+ BUG_ON(!mutex_is_locked(_mutex) || \
+ ((_mutex)->owner != current_thread_info()))
+#else
+#define DRM_ASSERT_LOCKED(_mutex)
+#endif
#endif
diff --git a/linux-core/drm_pci.c b/linux-core/drm_pci.c
index 40a65f3e..76252204 100644
--- a/linux-core/drm_pci.c
+++ b/linux-core/drm_pci.c
@@ -51,10 +51,8 @@ drm_dma_handle_t *drm_pci_alloc(drm_device_t * dev, size_t size, size_t align,
dma_addr_t maxaddr)
{
drm_dma_handle_t *dmah;
-#if 1
unsigned long addr;
size_t sz;
-#endif
#ifdef DRM_DEBUG_MEMORY
int area = DRM_MEM_DMA;
diff --git a/linux-core/drm_proc.c b/linux-core/drm_proc.c
index af62c62a..e93a0406 100644
--- a/linux-core/drm_proc.c
+++ b/linux-core/drm_proc.c
@@ -211,7 +211,6 @@ static int drm__vm_info(char *buf, char **start, off_t offset, int request,
int len = 0;
drm_map_t *map;
drm_map_list_t *r_list;
- struct list_head *list;
/* Hardcoded from _DRM_FRAME_BUFFER,
_DRM_REGISTERS, _DRM_SHM, _DRM_AGP,
@@ -231,9 +230,7 @@ static int drm__vm_info(char *buf, char **start, off_t offset, int request,
DRM_PROC_PRINT("slot offset size type flags "
"address mtrr\n\n");
i = 0;
- if (dev->maplist != NULL)
- list_for_each(list, &dev->maplist->head) {
- r_list = list_entry(list, drm_map_list_t, head);
+ list_for_each_entry(r_list, &dev->maplist, head) {
map = r_list->map;
if (!map)
continue;
@@ -242,10 +239,10 @@ static int drm__vm_info(char *buf, char **start, off_t offset, int request,
else
type = types[map->type];
DRM_PROC_PRINT("%4d 0x%08lx 0x%08lx %4.4s 0x%02x 0x%08lx ",
- i,
- map->offset,
- map->size, type, map->flags,
- (unsigned long) r_list->user_token);
+ i,
+ map->offset,
+ map->size, type, map->flags,
+ (unsigned long) r_list->user_token);
if (map->mtrr < 0) {
DRM_PROC_PRINT("none\n");
@@ -253,7 +250,7 @@ static int drm__vm_info(char *buf, char **start, off_t offset, int request,
DRM_PROC_PRINT("%4d\n", map->mtrr);
}
i++;
- }
+ }
if (len > request + offset)
return request;
@@ -535,7 +532,7 @@ static int drm__clients_info(char *buf, char **start, off_t offset,
*eof = 0;
DRM_PROC_PRINT("a dev pid uid magic ioctls\n\n");
- for (priv = dev->file_first; priv; priv = priv->next) {
+ list_for_each_entry(priv, &dev->filelist, lhead) {
DRM_PROC_PRINT("%c %3d %5d %5d %10u %10lu\n",
priv->authenticated ? 'y' : 'n',
priv->minor,
@@ -588,7 +585,7 @@ static int drm__vma_info(char *buf, char **start, off_t offset, int request,
DRM_PROC_PRINT("vma use count: %d, high_memory = %p, 0x%08lx\n",
atomic_read(&dev->vma_count),
high_memory, virt_to_phys(high_memory));
- for (pt = dev->vmalist; pt; pt = pt->next) {
+ list_for_each_entry(pt, &dev->vmalist, head) {
if (!(vma = pt->vma))
continue;
DRM_PROC_PRINT("\n%5d 0x%08lx-0x%08lx %c%c%c%c%c%c 0x%08lx000",
diff --git a/linux-core/drm_stub.c b/linux-core/drm_stub.c
index 01ffe679..0cc8a105 100644
--- a/linux-core/drm_stub.c
+++ b/linux-core/drm_stub.c
@@ -60,6 +60,11 @@ static int drm_fill_in_dev(drm_device_t * dev, struct pci_dev *pdev,
{
int retcode;
+ INIT_LIST_HEAD(&dev->filelist);
+ INIT_LIST_HEAD(&dev->ctxlist);
+ INIT_LIST_HEAD(&dev->vmalist);
+ INIT_LIST_HEAD(&dev->maplist);
+
spin_lock_init(&dev->count_lock);
spin_lock_init(&dev->drw_lock);
spin_lock_init(&dev->tasklet_lock);
@@ -70,6 +75,8 @@ static int drm_fill_in_dev(drm_device_t * dev, struct pci_dev *pdev,
mutex_init(&dev->bm.init_mutex);
mutex_init(&dev->bm.evict_mutex);
+ idr_init(&dev->drw_idr);
+
dev->pdev = pdev;
dev->pci_device = pdev->device;
dev->pci_vendor = pdev->vendor;
@@ -94,15 +101,6 @@ static int drm_fill_in_dev(drm_device_t * dev, struct pci_dev *pdev,
return -ENOMEM;
}
- dev->maplist = drm_calloc(1, sizeof(*dev->maplist), DRM_MEM_MAPS);
- if (dev->maplist == NULL) {
- drm_ht_remove(&dev->object_hash);
- drm_ht_remove(&dev->map_hash);
- drm_mm_takedown(&dev->offset_manager);
- return -ENOMEM;
- }
- INIT_LIST_HEAD(&dev->maplist->head);
-
/* the DRM has 6 counters */
dev->counters = 6;
dev->types[0] = _DRM_STAT_LOCK;
diff --git a/linux-core/drm_vm.c b/linux-core/drm_vm.c
index b8871539..72d63c10 100644
--- a/linux-core/drm_vm.c
+++ b/linux-core/drm_vm.c
@@ -122,7 +122,7 @@ static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma,
/*
* It's AGP memory - find the real physical page to map
*/
- for (agpmem = dev->agp->memory; agpmem; agpmem = agpmem->next) {
+ list_for_each_entry(agpmem, &dev->agp->memory, head) {
if (agpmem->bound <= baddr &&
agpmem->bound + agpmem->pages * PAGE_SIZE > baddr)
break;
@@ -205,10 +205,9 @@ static void drm_vm_shm_close(struct vm_area_struct *vma)
{
drm_file_t *priv = vma->vm_file->private_data;
drm_device_t *dev = priv->head->dev;
- drm_vma_entry_t *pt, *prev, *next;
+ drm_vma_entry_t *pt, *temp;
drm_map_t *map;
drm_map_list_t *r_list;
- struct list_head *list;
int found_maps = 0;
DRM_DEBUG("0x%08lx,0x%08lx\n",
@@ -218,19 +217,12 @@ static void drm_vm_shm_close(struct vm_area_struct *vma)
map = vma->vm_private_data;
mutex_lock(&dev->struct_mutex);
- for (pt = dev->vmalist, prev = NULL; pt; pt = next) {
- next = pt->next;
+ list_for_each_entry_safe(pt, temp, &dev->vmalist, head) {
if (pt->vma->vm_private_data == map)
found_maps++;
if (pt->vma == vma) {
- if (prev) {
- prev->next = pt->next;
- } else {
- dev->vmalist = pt->next;
- }
+ list_del(&pt->head);
drm_ctl_free(pt, sizeof(*pt), DRM_MEM_VMAS);
- } else {
- prev = pt;
}
}
/* We were the only map that was found */
@@ -239,9 +231,7 @@ static void drm_vm_shm_close(struct vm_area_struct *vma)
* we delete this mappings information.
*/
found_maps = 0;
- list = &dev->maplist->head;
- list_for_each(list, &dev->maplist->head) {
- r_list = list_entry(list, drm_map_list_t, head);
+ list_for_each_entry(r_list, &dev->maplist, head) {
if (r_list->map == map)
found_maps++;
}
@@ -439,9 +429,8 @@ static void drm_vm_open_locked(struct vm_area_struct *vma)
vma_entry = drm_ctl_alloc(sizeof(*vma_entry), DRM_MEM_VMAS);
if (vma_entry) {
vma_entry->vma = vma;
- vma_entry->next = dev->vmalist;
vma_entry->pid = current->pid;
- dev->vmalist = vma_entry;
+ list_add(&vma_entry->head, &dev->vmalist);
}
}
@@ -467,20 +456,16 @@ static void drm_vm_close(struct vm_area_struct *vma)
{
drm_file_t *priv = vma->vm_file->private_data;
drm_device_t *dev = priv->head->dev;
- drm_vma_entry_t *pt, *prev;
+ drm_vma_entry_t *pt, *temp;
DRM_DEBUG("0x%08lx,0x%08lx\n",
vma->vm_start, vma->vm_end - vma->vm_start);
atomic_dec(&dev->vma_count);
mutex_lock(&dev->struct_mutex);
- for (pt = dev->vmalist, prev = NULL; pt; prev = pt, pt = pt->next) {
+ list_for_each_entry_safe(pt, temp, &dev->vmalist, head) {
if (pt->vma == vma) {
- if (prev) {
- prev->next = pt->next;
- } else {
- dev->vmalist = pt->next;
- }
+ list_del(&pt->head);
drm_ctl_free(pt, sizeof(*pt), DRM_MEM_VMAS);
break;
}
@@ -855,7 +840,8 @@ static void drm_bo_vm_close(struct vm_area_struct *vma)
#ifdef DRM_ODD_MM_COMPAT
drm_bo_delete_vma(bo, vma);
#endif
- drm_bo_usage_deref_locked(bo);
+ drm_bo_usage_deref_locked((struct drm_buffer_object **)
+ &vma->vm_private_data);
mutex_unlock(&dev->struct_mutex);
}
return;
diff --git a/linux-core/i810_dma.c b/linux-core/i810_dma.c
index 3f2dad38..49379434 100644
--- a/linux-core/i810_dma.c
+++ b/linux-core/i810_dma.c
@@ -346,12 +346,10 @@ static int i810_dma_initialize(drm_device_t * dev,
drm_i810_private_t * dev_priv,
drm_i810_init_t * init)
{
- struct list_head *list;
-
+ drm_map_list_t *r_list;
memset(dev_priv, 0, sizeof(drm_i810_private_t));
- list_for_each(list, &dev->maplist->head) {
- drm_map_list_t *r_list = list_entry(list, drm_map_list_t, head);
+ list_for_each_entry(r_list, &dev->maplist, head) {
if (r_list->map &&
r_list->map->type == _DRM_SHM &&
r_list->map->flags & _DRM_CONTAINS_LOCK) {
diff --git a/linux-core/i915_drv.c b/linux-core/i915_drv.c
index d58ca589..e612a46c 100644
--- a/linux-core/i915_drv.c
+++ b/linux-core/i915_drv.c
@@ -42,9 +42,9 @@ static struct pci_device_id pciidlist[] = {
#ifdef I915_HAVE_FENCE
static drm_fence_driver_t i915_fence_driver = {
.num_classes = 1,
- .wrap_diff = (1 << 30),
- .flush_diff = (1 << 29),
- .sequence_mask = 0xffffffffU,
+ .wrap_diff = (1U << (BREADCRUMB_BITS - 1)),
+ .flush_diff = (1U << (BREADCRUMB_BITS - 2)),
+ .sequence_mask = BREADCRUMB_MASK,
.lazy_capable = 1,
.emit = i915_fence_emit_sequence,
.poke_flush = i915_poke_flush,
diff --git a/linux-core/i915_fence.c b/linux-core/i915_fence.c
index 88daa57c..00873485 100644
--- a/linux-core/i915_fence.c
+++ b/linux-core/i915_fence.c
@@ -61,7 +61,7 @@ static void i915_perform_flush(drm_device_t * dev)
* First update fences with the current breadcrumb.
*/
- diff = sequence - fc->last_exe_flush;
+ diff = (sequence - fc->last_exe_flush) & BREADCRUMB_MASK;
if (diff < driver->wrap_diff && diff != 0) {
drm_fence_handler(dev, 0, sequence, DRM_FENCE_TYPE_EXE);
}
diff --git a/linux-core/i915_ioc32.c b/linux-core/i915_ioc32.c
index 396f5c21..c1e776b7 100644
--- a/linux-core/i915_ioc32.c
+++ b/linux-core/i915_ioc32.c
@@ -30,7 +30,6 @@
* IN THE SOFTWARE.
*/
#include <linux/compat.h>
-#include <linux/ioctl32.h>
#include "drmP.h"
#include "drm.h"
diff --git a/linux-core/mga_ioc32.c b/linux-core/mga_ioc32.c
index 5775cd63..75f2a231 100644
--- a/linux-core/mga_ioc32.c
+++ b/linux-core/mga_ioc32.c
@@ -32,7 +32,6 @@
* IN THE SOFTWARE.
*/
#include <linux/compat.h>
-#include <linux/ioctl32.h>
#include "drmP.h"
#include "drm.h"
diff --git a/linux-core/nouveau_ioc32.c b/linux-core/nouveau_ioc32.c
index a752a581..f55ae7a2 100644
--- a/linux-core/nouveau_ioc32.c
+++ b/linux-core/nouveau_ioc32.c
@@ -32,7 +32,6 @@
*/
#include <linux/compat.h>
-#include <linux/ioctl32.h>
#include "drmP.h"
#include "drm.h"
diff --git a/linux-core/nouveau_notifier.c b/linux-core/nouveau_notifier.c
new file mode 120000
index 00000000..285469c5
--- /dev/null
+++ b/linux-core/nouveau_notifier.c
@@ -0,0 +1 @@
+../shared-core/nouveau_notifier.c \ No newline at end of file
diff --git a/linux-core/nv04_fifo.c b/linux-core/nv04_fifo.c
new file mode 120000
index 00000000..d10beb19
--- /dev/null
+++ b/linux-core/nv04_fifo.c
@@ -0,0 +1 @@
+../shared-core/nv04_fifo.c \ No newline at end of file
diff --git a/linux-core/nv10_fifo.c b/linux-core/nv10_fifo.c
new file mode 120000
index 00000000..8630ad04
--- /dev/null
+++ b/linux-core/nv10_fifo.c
@@ -0,0 +1 @@
+../shared-core/nv10_fifo.c \ No newline at end of file
diff --git a/linux-core/nv40_fifo.c b/linux-core/nv40_fifo.c
new file mode 120000
index 00000000..cc71e7a4
--- /dev/null
+++ b/linux-core/nv40_fifo.c
@@ -0,0 +1 @@
+../shared-core/nv40_fifo.c \ No newline at end of file
diff --git a/linux-core/nv50_fifo.c b/linux-core/nv50_fifo.c
new file mode 120000
index 00000000..4c9990a9
--- /dev/null
+++ b/linux-core/nv50_fifo.c
@@ -0,0 +1 @@
+../shared-core/nv50_fifo.c \ No newline at end of file
diff --git a/linux-core/nv50_graph.c b/linux-core/nv50_graph.c
new file mode 120000
index 00000000..03f69e68
--- /dev/null
+++ b/linux-core/nv50_graph.c
@@ -0,0 +1 @@
+../shared-core/nv50_graph.c \ No newline at end of file
diff --git a/linux-core/nv50_mc.c b/linux-core/nv50_mc.c
new file mode 120000
index 00000000..f4bb369e
--- /dev/null
+++ b/linux-core/nv50_mc.c
@@ -0,0 +1 @@
+../shared-core/nv50_mc.c \ No newline at end of file
diff --git a/linux-core/r128_ioc32.c b/linux-core/r128_ioc32.c
index 73630540..6b757576 100644
--- a/linux-core/r128_ioc32.c
+++ b/linux-core/r128_ioc32.c
@@ -30,7 +30,6 @@
* IN THE SOFTWARE.
*/
#include <linux/compat.h>
-#include <linux/ioctl32.h>
#include "drmP.h"
#include "drm.h"
diff --git a/linux-core/radeon_drv.c b/linux-core/radeon_drv.c
index 43b9aca0..327a6a97 100644
--- a/linux-core/radeon_drv.c
+++ b/linux-core/radeon_drv.c
@@ -61,7 +61,7 @@ static struct drm_driver driver = {
.driver_features =
DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG |
DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED |
- DRIVER_IRQ_VBL,
+ DRIVER_IRQ_VBL | DRIVER_IRQ_VBL2,
.dev_priv_size = sizeof(drm_radeon_buf_priv_t),
.load = radeon_driver_load,
.firstopen = radeon_driver_firstopen,
@@ -71,6 +71,7 @@ static struct drm_driver driver = {
.lastclose = radeon_driver_lastclose,
.unload = radeon_driver_unload,
.vblank_wait = radeon_driver_vblank_wait,
+ .vblank_wait2 = radeon_driver_vblank_wait2,
.dri_library_name = dri_library_name,
.irq_preinstall = radeon_driver_irq_preinstall,
.irq_postinstall = radeon_driver_irq_postinstall,
diff --git a/linux-core/radeon_ioc32.c b/linux-core/radeon_ioc32.c
index b980bedb..bc8aa35a 100644
--- a/linux-core/radeon_ioc32.c
+++ b/linux-core/radeon_ioc32.c
@@ -28,7 +28,6 @@
* IN THE SOFTWARE.
*/
#include <linux/compat.h>
-#include <linux/ioctl32.h>
#include "drmP.h"
#include "drm.h"
@@ -350,6 +349,36 @@ static int compat_radeon_irq_emit(struct file *file, unsigned int cmd,
DRM_IOCTL_RADEON_IRQ_EMIT, (unsigned long) request);
}
+/* The two 64-bit arches where alignof(u64)==4 in 32-bit code */
+#if defined (CONFIG_X86_64) || defined(CONFIG_IA64)
+typedef struct drm_radeon_setparam32 {
+ int param;
+ u64 value;
+} __attribute__((packed)) drm_radeon_setparam32_t;
+
+static int compat_radeon_cp_setparam(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_radeon_setparam32_t req32;
+ drm_radeon_setparam_t __user *request;
+
+ if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
+ return -EFAULT;
+
+ request = compat_alloc_user_space(sizeof(*request));
+ if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
+ || __put_user(req32.param, &request->param)
+ || __put_user((void __user *)(unsigned long)req32.value,
+ &request->value))
+ return -EFAULT;
+
+ return drm_ioctl(file->f_dentry->d_inode, file,
+ DRM_IOCTL_RADEON_SETPARAM, (unsigned long) request);
+}
+#else
+#define compat_radeon_cp_setparam NULL
+#endif /* X86_64 || IA64 */
+
drm_ioctl_compat_t *radeon_compat_ioctls[] = {
[DRM_RADEON_CP_INIT] = compat_radeon_cp_init,
[DRM_RADEON_CLEAR] = compat_radeon_cp_clear,
@@ -358,6 +387,7 @@ drm_ioctl_compat_t *radeon_compat_ioctls[] = {
[DRM_RADEON_VERTEX2] = compat_radeon_cp_vertex2,
[DRM_RADEON_CMDBUF] = compat_radeon_cp_cmdbuf,
[DRM_RADEON_GETPARAM] = compat_radeon_cp_getparam,
+ [DRM_RADEON_SETPARAM] = compat_radeon_cp_setparam,
[DRM_RADEON_ALLOC] = compat_radeon_mem_alloc,
[DRM_RADEON_IRQ_EMIT] = compat_radeon_irq_emit,
};
diff --git a/linux-core/sis_mm.c b/linux-core/sis_mm.c
index 5efbada4..21c1f2d7 100644
--- a/linux-core/sis_mm.c
+++ b/linux-core/sis_mm.c
@@ -233,7 +233,7 @@ static drm_local_map_t *sis_reg_init(drm_device_t *dev)
drm_map_list_t *entry;
drm_local_map_t *map;
- list_for_each_entry(entry, &dev->maplist->head, head) {
+ list_for_each_entry(entry, &dev->maplist, head) {
map = entry->map;
if (!map)
continue;
diff --git a/shared-core/drm_pciids.txt b/shared-core/drm_pciids.txt
index ad67dda2..126974d0 100644
--- a/shared-core/drm_pciids.txt
+++ b/shared-core/drm_pciids.txt
@@ -98,13 +98,20 @@
0x1002 0x5653 CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Radeon Mobility X700 M26"
0x1002 0x5834 CHIP_RS300|RADEON_IS_IGP "ATI Radeon RS300 9100 IGP"
0x1002 0x5835 CHIP_RS300|RADEON_IS_IGP|RADEON_IS_MOBILITY "ATI Radeon RS300 Mobility IGP"
+0x1002 0x5954 CHIP_RS400|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART "ATI RS480 XPRESS 200G"
0x1002 0x5955 CHIP_RS400|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART "ATI Radeon XPRESS 200M 5955"
+0x1002 0x5974 CHIP_RS400|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART "ATI Radeon RS482 XPRESS 200"
+0x1002 0x5975 CHIP_RS400|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART "ATI Radeon RS485 XPRESS 1100 IGP"
0x1002 0x5960 CHIP_RV280 "ATI Radeon RV280 9250"
0x1002 0x5961 CHIP_RV280 "ATI Radeon RV280 9200"
0x1002 0x5962 CHIP_RV280 "ATI Radeon RV280 9200"
0x1002 0x5964 CHIP_RV280 "ATI Radeon RV280 9200 SE"
0x1002 0x5965 CHIP_RV280 "ATI FireMV 2200 PCI"
0x1002 0x5969 CHIP_RV100 "ATI ES1000 RN50"
+0x1002 0x5a41 CHIP_RS400|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART "ATI Radeon RS400 XPRESS 200"
+0x1002 0x5a42 CHIP_RS400|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART "ATI Radeon RS400 XPRESS 200M"
+0x1002 0x5a61 CHIP_RS400|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART "ATI Radeon RC410 XPRESS 200"
+0x1002 0x5a62 CHIP_RS400|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART "ATI Radeon RC410 XPRESS 200M"
0x1002 0x5b60 CHIP_RV380|RADEON_NEW_MEMMAP "ATI Radeon RV370 X300 SE"
0x1002 0x5b62 CHIP_RV380|RADEON_NEW_MEMMAP "ATI Radeon RV370 X600 Pro"
0x1002 0x5b63 CHIP_RV380|RADEON_NEW_MEMMAP "ATI Radeon RV370 X550"
@@ -204,6 +211,8 @@
0x1039 0x6300 0 "SiS 630"
0x1039 0x6330 SIS_CHIP_315 "SiS 661"
0x1039 0x7300 0 "SiS 730"
+0x18CA 0x0040 SIS_CHIP_315 "Volari V3XT/V5/V8"
+0x18CA 0x0042 SIS_CHIP_315 "Volari Unknown"
[tdfx]
0x121a 0x0003 0 "3dfx Voodoo Banshee"
@@ -275,11 +284,16 @@
0x8086 0x2592 CHIP_I9XX|CHIP_I915 "Intel i915GM"
0x8086 0x2772 CHIP_I9XX|CHIP_I915 "Intel i945G"
0x8086 0x27A2 CHIP_I9XX|CHIP_I915 "Intel i945GM"
+0x8086 0x27AE CHIP_I9XX|CHIP_I915 "Intel i945GME"
0x8086 0x2972 CHIP_I9XX|CHIP_I965 "Intel i946GZ"
0x8086 0x2982 CHIP_I9XX|CHIP_I965 "Intel i965G"
0x8086 0x2992 CHIP_I9XX|CHIP_I965 "Intel i965Q"
0x8086 0x29A2 CHIP_I9XX|CHIP_I965 "Intel i965G"
0x8086 0x2A02 CHIP_I9XX|CHIP_I965 "Intel i965GM"
+0x8086 0x2A12 CHIP_I9XX|CHIP_I965 "Intel i965GME/GLE"
+0x8086 0x29C2 CHIP_I9XX|CHIP_I915 "Intel G33"
+0x8086 0x29B2 CHIP_I9XX|CHIP_I915 "Intel Q35"
+0x8086 0x29D2 CHIP_I9XX|CHIP_I915 "Intel Q33"
[imagine]
0x105d 0x2309 IMAGINE_128 "Imagine 128"
@@ -582,6 +596,9 @@
0x10de 0x018d NV_17 "GeForce4 448 Go"
0x10de 0x0191 NV_50 "GeForce 8800 GTX"
0x10de 0x0193 NV_50 "GeForce 8800 GTS"
+0x10de 0x0194 NV_50 "GeForce 8800 Ultra"
+0x10de 0x019d NV_50 "Quadro FX 5600"
+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 0x01d6 NV_44 "GeForce Go 7200"
@@ -688,6 +705,11 @@
0x10de 0x03d1 NV_44 "GeForce 6100 nForce 405"
0x10de 0x03d2 NV_44 "GeForce 6100 nForce 400"
0x10de 0x03d5 NV_44 "GeForce 6100 nForce 420"
+0x10de 0x0400 NV_50 "GeForce 8600 GTS"
+0x10de 0x0402 NV_50 "GeForce 8600 GT"
+0x10de 0x0421 NV_50 "GeForce 8500 GT"
+0x10de 0x0422 NV_50 "GeForce 8400 GS"
+0x10de 0x0423 NV_50 "GeForce 8300 GS"
0x12d2 0x0008 NV_03 "NV1"
0x12d2 0x0009 NV_03 "DAC64"
0x12d2 0x0018 NV_03 "Riva128"
diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c
index a5e51de4..c95f1857 100644
--- a/shared-core/i915_dma.c
+++ b/shared-core/i915_dma.c
@@ -78,19 +78,15 @@ void i915_kernel_lost_context(drm_device_t * dev)
dev_priv->sarea_priv->perf_boxes |= I915_BOX_RING_EMPTY;
}
-int i915_dma_cleanup(drm_device_t * dev)
+static int i915_dma_cleanup(drm_device_t * dev)
{
- drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
/* Make sure interrupts are disabled here because the uninstall ioctl
* may not have been called from userspace and after dev_private
* is freed, it's too late.
*/
- I915_WRITE(LP_RING + RING_LEN, 0);
-
if (dev->irq)
drm_irq_uninstall(dev);
-
return 0;
}
@@ -98,6 +94,8 @@ static int i915_initialize(drm_device_t * dev,
drm_i915_private_t * dev_priv,
drm_i915_init_t * init)
{
+ memset(dev_priv, 0, sizeof(drm_i915_private_t));
+
dev_priv->sarea = drm_getsarea(dev);
if (!dev_priv->sarea) {
DRM_ERROR("can not find sarea!\n");
@@ -106,11 +104,13 @@ static int i915_initialize(drm_device_t * dev,
return DRM_ERR(EINVAL);
}
- memset((void *)(dev_priv->ring.virtual_start), 0, dev_priv->ring.Size);
-
- I915_WRITE(LP_RING + RING_START, dev_priv->ring.Start);
- I915_WRITE(LP_RING + RING_LEN, ((dev_priv->ring.Size - 4096) & RING_NR_PAGES) | (RING_NO_REPORT | RING_VALID));
-
+ dev_priv->mmio_map = drm_core_findmap(dev, init->mmio_offset);
+ if (!dev_priv->mmio_map) {
+ dev->dev_private = (void *)dev_priv;
+ i915_dma_cleanup(dev);
+ DRM_ERROR("can not find mmio map!\n");
+ return DRM_ERR(EINVAL);
+ }
dev_priv->cpp = init->cpp;
dev_priv->sarea_priv->pf_current_page = 0;
@@ -128,24 +128,6 @@ static int i915_initialize(drm_device_t * dev,
*/
dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A;
- /* Program Hardware Status Page */
- dev_priv->status_page_dmah = drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE,
- 0xffffffff);
-
- if (!dev_priv->status_page_dmah) {
- dev->dev_private = (void *)dev_priv;
- i915_dma_cleanup(dev);
- DRM_ERROR("Can not allocate hardware status page\n");
- return DRM_ERR(ENOMEM);
- }
- dev_priv->hw_status_page = dev_priv->status_page_dmah->vaddr;
- dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr;
-
- memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
- DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page);
-
- I915_WRITE(0x02080, dev_priv->dma_status_page);
- DRM_DEBUG("Enabled hardware status page\n");
dev->dev_private = (void *)dev_priv;
return 0;
}
@@ -156,8 +138,15 @@ static int i915_dma_resume(drm_device_t * dev)
DRM_DEBUG("%s\n", __FUNCTION__);
- I915_WRITE(I915REG_HWS_PGA, dev_priv->dma_status_page);
- DRM_DEBUG("Enabled hardware status page\n");
+ if (!dev_priv->sarea) {
+ DRM_ERROR("can not find sarea!\n");
+ return DRM_ERR(EINVAL);
+ }
+
+ if (!dev_priv->mmio_map) {
+ DRM_ERROR("can not find mmio map!\n");
+ return DRM_ERR(EINVAL);
+ }
return 0;
}
@@ -353,10 +342,12 @@ void i915_emit_breadcrumb(drm_device_t *dev)
drm_i915_private_t *dev_priv = dev->dev_private;
RING_LOCALS;
- dev_priv->sarea_priv->last_enqueue = ++dev_priv->counter;
+ if (++dev_priv->counter > BREADCRUMB_MASK) {
+ dev_priv->counter = 1;
+ DRM_DEBUG("Breadcrumb counter wrapped around\n");
+ }
- if (dev_priv->counter > 0x7FFFFFFFUL)
- dev_priv->sarea_priv->last_enqueue = dev_priv->counter = 1;
+ dev_priv->sarea_priv->last_enqueue = dev_priv->counter;
BEGIN_LP_RING(4);
OUT_RING(CMD_STORE_DWORD_IDX);
@@ -391,7 +382,9 @@ int i915_emit_mi_flush(drm_device_t *dev, uint32_t flush)
static int i915_dispatch_cmdbuffer(drm_device_t * dev,
drm_i915_cmdbuffer_t * cmd)
{
+#ifdef I915_HAVE_FENCE
drm_i915_private_t *dev_priv = dev->dev_private;
+#endif
int nbox = cmd->num_cliprects;
int i = 0, count, ret;
@@ -776,7 +769,7 @@ static int i915_mmio(DRM_IOCTL_ARGS)
return DRM_ERR(EINVAL);
e = &mmio_table[mmio.reg];
- base = dev_priv->mmio_map->handle + e->offset;
+ base = (u8 *) dev_priv->mmio_map->handle + e->offset;
switch (mmio.read_write) {
case I915_MMIO_READ:
@@ -802,6 +795,47 @@ static int i915_mmio(DRM_IOCTL_ARGS)
return 0;
}
+static int i915_set_status_page(DRM_IOCTL_ARGS)
+{
+ DRM_DEVICE;
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ drm_i915_hws_addr_t hws;
+
+ if (!dev_priv) {
+ DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+ return DRM_ERR(EINVAL);
+ }
+ DRM_COPY_FROM_USER_IOCTL(hws, (drm_i915_hws_addr_t __user *) data,
+ sizeof(hws));
+ printk(KERN_DEBUG "set status page addr 0x%08x\n", (u32)hws.addr);
+
+ dev_priv->status_gfx_addr = hws.addr & (0x1ffff<<12);
+
+ dev_priv->hws_map.offset = dev->agp->agp_info.aper_base + hws.addr;
+ dev_priv->hws_map.size = 4*1024;
+ dev_priv->hws_map.type = 0;
+ dev_priv->hws_map.flags = 0;
+ dev_priv->hws_map.mtrr = 0;
+
+ drm_core_ioremap(&dev_priv->hws_map, dev);
+ if (dev_priv->hws_map.handle == NULL) {
+ dev->dev_private = (void *)dev_priv;
+ i915_dma_cleanup(dev);
+ dev_priv->status_gfx_addr = 0;
+ DRM_ERROR("can not ioremap virtual address for"
+ " G33 hw status page\n");
+ return DRM_ERR(ENOMEM);
+ }
+ dev_priv->hw_status_page = dev_priv->hws_map.handle;
+
+ memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
+ I915_WRITE(I915REG_HWS_PGA, dev_priv->status_gfx_addr);
+ DRM_DEBUG("load hws 0x2080 with gfx mem 0x%x\n",
+ dev_priv->status_gfx_addr);
+ DRM_DEBUG("load hws at %p\n", dev_priv->hw_status_page);
+ return 0;
+}
+
drm_ioctl_desc_t i915_ioctls[] = {
[DRM_IOCTL_NR(DRM_I915_INIT)] = {i915_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
[DRM_IOCTL_NR(DRM_I915_FLUSH)] = {i915_flush_ioctl, DRM_AUTH},
@@ -820,6 +854,7 @@ drm_ioctl_desc_t i915_ioctls[] = {
[DRM_IOCTL_NR(DRM_I915_GET_VBLANK_PIPE)] = { i915_vblank_pipe_get, DRM_AUTH },
[DRM_IOCTL_NR(DRM_I915_VBLANK_SWAP)] = {i915_vblank_swap, DRM_AUTH},
[DRM_IOCTL_NR(DRM_I915_MMIO)] = {i915_mmio, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I915_HWS_ADDR)] = {i915_set_status_page, DRM_AUTH},
};
int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
diff --git a/shared-core/i915_drm.h b/shared-core/i915_drm.h
index 1f32313e..1c6ff4d3 100644
--- a/shared-core/i915_drm.h
+++ b/shared-core/i915_drm.h
@@ -159,6 +159,7 @@ typedef struct _drm_i915_sarea {
#define DRM_I915_GET_VBLANK_PIPE 0x0e
#define DRM_I915_VBLANK_SWAP 0x0f
#define DRM_I915_MMIO 0x10
+#define DRM_I915_HWS_ADDR 0x11
#define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
#define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
@@ -314,4 +315,8 @@ typedef struct drm_i915_mmio {
void __user *data;
} drm_i915_mmio_t;
+typedef struct drm_i915_hws_addr {
+ uint64_t addr;
+} drm_i915_hws_addr_t;
+
#endif /* _I915_DRM_H_ */
diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h
index b0aa5df1..35451feb 100644
--- a/shared-core/i915_drv.h
+++ b/shared-core/i915_drv.h
@@ -103,6 +103,8 @@ typedef struct drm_i915_private {
void *hw_status_page;
dma_addr_t dma_status_page;
uint32_t counter;
+ unsigned int status_gfx_addr;
+ drm_local_map_t hws_map;
unsigned int cpp;
int use_mi_batchbuffer_start;
@@ -526,6 +528,9 @@ extern int i915_wait_ring(drm_device_t * dev, int n, const char *caller);
#define CMD_OP_DESTBUFFER_INFO ((0x3<<29)|(0x1d<<24)|(0x8e<<16)|1)
+#define BREADCRUMB_BITS 31
+#define BREADCRUMB_MASK ((1U << BREADCRUMB_BITS) - 1)
+
#define READ_BREADCRUMB(dev_priv) (((volatile u32*)(dev_priv->hw_status_page))[5])
#define READ_HWSP(dev_priv, reg) (((volatile u32*)(dev_priv->hw_status_page))[reg])
@@ -1012,12 +1017,18 @@ extern int i915_wait_ring(drm_device_t * dev, int n, const char *caller);
#define IS_I965G(dev) ((dev)->pci_device == 0x2972 || \
(dev)->pci_device == 0x2982 || \
(dev)->pci_device == 0x2992 || \
- (dev)->pci_device == 0x29A2)
+ (dev)->pci_device == 0x29A2 || \
+ (dev)->pci_device == 0x2A02 || \
+ (dev)->pci_device == 0x2A12)
#define IS_I9XX(dev) (IS_I915G(dev) || IS_I915GM(dev) || IS_I945G(dev) || \
IS_I945GM(dev) || IS_I965G(dev))
+#define IS_G33(dev) ((dev)->pci_device == 0x29C2 || \
+ (dev)->pci_device == 0x29B2 || \
+ (dev)->pci_device == 0x29D2)
+
#define IS_MOBILE(dev) (IS_I830(dev) || IS_I85X(dev) || IS_I915GM(dev) || \
IS_I945GM(dev))
diff --git a/shared-core/i915_init.c b/shared-core/i915_init.c
index 7516b2ce..83219e49 100644
--- a/shared-core/i915_init.c
+++ b/shared-core/i915_init.c
@@ -228,22 +228,23 @@ int i915_driver_load(drm_device_t *dev, unsigned long flags)
dev_priv->allow_batchbuffer = 1;
/* Program Hardware Status Page */
- dev_priv->status_page_dmah = drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE,
- 0xffffffff);
-
- if (!dev_priv->status_page_dmah) {
- dev->dev_private = (void *)dev_priv;
- i915_dma_cleanup(dev);
- DRM_ERROR("Can not allocate hardware status page\n");
- return DRM_ERR(ENOMEM);
+ if (!IS_G33(dev)) {
+ dev_priv->status_page_dmah =
+ drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, 0xffffffff);
+
+ if (!dev_priv->status_page_dmah) {
+ dev->dev_private = (void *)dev_priv;
+ i915_dma_cleanup(dev);
+ DRM_ERROR("Can not allocate hardware status page\n");
+ return DRM_ERR(ENOMEM);
+ }
+ dev_priv->hw_status_page = dev_priv->status_page_dmah->vaddr;
+ dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr;
+
+ memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
+
+ I915_WRITE(I915REG_HWS_PGA, dev_priv->dma_status_page);
}
- dev_priv->hw_status_page = dev_priv->status_page_dmah->vaddr;
- dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr;
-
- memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
- DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page);
-
- I915_WRITE(I915REG_HWS_PGA, dev_priv->dma_status_page);
DRM_DEBUG("Enabled hardware status page\n");
intel_modeset_init(dev);
diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c
index 2d4df76e..98f51b2b 100644
--- a/shared-core/i915_irq.c
+++ b/shared-core/i915_irq.c
@@ -381,13 +381,6 @@ void i915_user_irq_off(drm_i915_private_t *dev_priv)
spin_unlock(&dev_priv->user_irq_lock);
}
-static int wait_compare(struct drm_device *dev, void *priv)
-{
- drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
- int irq_nr = (u64)priv;
-
- return (READ_BREADCRUMB(dev_priv) >= irq_nr);
-}
static int i915_wait_irq(drm_device_t * dev, int irq_nr)
{
@@ -403,8 +396,8 @@ static int i915_wait_irq(drm_device_t * dev, int irq_nr)
dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
i915_user_irq_on(dev_priv);
- ret = drm_wait_on(dev, &dev_priv->irq_queue, 3 * DRM_HZ, wait_compare,
- (void *)(u64)irq_nr);
+ DRM_WAIT_ON(ret, dev_priv->irq_queue, 3 * DRM_HZ,
+ READ_BREADCRUMB(dev_priv) >= irq_nr);
i915_user_irq_off(dev_priv);
if (ret == DRM_ERR(EBUSY)) {
@@ -735,11 +728,7 @@ void i915_driver_irq_postinstall(drm_device_t * dev)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
- dev_priv->swaps_lock = SPIN_LOCK_UNLOCKED;
- INIT_LIST_HEAD(&dev_priv->vbl_swaps.head);
- dev_priv->swaps_pending = 0;
-
- dev_priv->swaps_lock = SPIN_LOCK_UNLOCKED;
+ spin_lock_init(&dev_priv->swaps_lock);
INIT_LIST_HEAD(&dev_priv->vbl_swaps.head);
dev_priv->swaps_pending = 0;
diff --git a/shared-core/mga_dma.c b/shared-core/mga_dma.c
index 78448282..d48313c7 100644
--- a/shared-core/mga_dma.c
+++ b/shared-core/mga_dma.c
@@ -551,7 +551,7 @@ static int mga_do_agp_dma_bootstrap(drm_device_t * dev,
drm_map_list_t *_entry;
unsigned long agp_token = 0;
- list_for_each_entry(_entry, &dev->maplist->head, head) {
+ list_for_each_entry(_entry, &dev->maplist, head) {
if (_entry->map == dev->agp_buffer_map)
agp_token = _entry->user_token;
}
diff --git a/shared-core/nouveau_drm.h b/shared-core/nouveau_drm.h
index 1e7322e0..0758991a 100644
--- a/shared-core/nouveau_drm.h
+++ b/shared-core/nouveau_drm.h
@@ -25,9 +25,12 @@
#ifndef __NOUVEAU_DRM_H__
#define __NOUVEAU_DRM_H__
-#define NOUVEAU_DRM_HEADER_PATCHLEVEL 6
+#define NOUVEAU_DRM_HEADER_PATCHLEVEL 7
typedef struct drm_nouveau_fifo_alloc {
+ uint32_t fb_ctxdma_handle;
+ uint32_t tt_ctxdma_handle;
+
int channel;
uint32_t put_base;
/* FIFO control regs */
@@ -36,29 +39,30 @@ typedef struct drm_nouveau_fifo_alloc {
/* DMA command buffer */
drm_handle_t cmdbuf;
int cmdbuf_size;
+ /* Notifier memory */
+ drm_handle_t notifier;
+ int notifier_size;
}
drm_nouveau_fifo_alloc_t;
-typedef struct drm_nouveau_object_init {
+typedef struct drm_nouveau_grobj_alloc {
int channel;
uint32_t handle;
int class;
}
-drm_nouveau_object_init_t;
+drm_nouveau_grobj_alloc_t;
#define NOUVEAU_MEM_ACCESS_RO 1
#define NOUVEAU_MEM_ACCESS_WO 2
#define NOUVEAU_MEM_ACCESS_RW 3
-typedef struct drm_nouveau_dma_object_init {
+typedef struct drm_nouveau_notifier_alloc {
int channel;
uint32_t handle;
- int class;
- int access;
- int target;
+ int count;
+
uint32_t offset;
- int size;
}
-drm_nouveau_dma_object_init_t;
+drm_nouveau_notifier_alloc_t;
#define NOUVEAU_MEM_FB 0x00000001
#define NOUVEAU_MEM_AGP 0x00000002
@@ -68,7 +72,7 @@ drm_nouveau_dma_object_init_t;
#define NOUVEAU_MEM_USER_BACKED 0x00000020
#define NOUVEAU_MEM_MAPPED 0x00000040
#define NOUVEAU_MEM_INSTANCE 0x00000080 /* internal */
-
+#define NOUVEAU_MEM_NOTIFIER 0x00000100 /* internal */
typedef struct drm_nouveau_mem_alloc {
int flags;
int alignment;
@@ -141,8 +145,8 @@ typedef struct drm_nouveau_sarea {
drm_nouveau_sarea_t;
#define DRM_NOUVEAU_FIFO_ALLOC 0x00
-#define DRM_NOUVEAU_OBJECT_INIT 0x01
-#define DRM_NOUVEAU_DMA_OBJECT_INIT 0x02
+#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
diff --git a/shared-core/nouveau_drv.h b/shared-core/nouveau_drv.h
index debee8e4..3cca07fc 100644
--- a/shared-core/nouveau_drv.h
+++ b/shared-core/nouveau_drv.h
@@ -34,7 +34,7 @@
#define DRIVER_MAJOR 0
#define DRIVER_MINOR 0
-#define DRIVER_PATCHLEVEL 6
+#define DRIVER_PATCHLEVEL 7
#define NOUVEAU_FAMILY 0x0000FFFF
#define NOUVEAU_FLAGS 0xFFFF0000
@@ -64,7 +64,6 @@ struct nouveau_object
int channel;
struct mem_block *instance;
- uint32_t ht_loc;
uint32_t handle;
int class;
@@ -83,6 +82,11 @@ struct nouveau_fifo
/* dma object for the command buffer itself */
struct mem_block *cmdbuf_mem;
struct nouveau_object *cmdbuf_obj;
+ uint32_t pushbuf_base;
+ /* notifier memory */
+ struct mem_block *notifier_block;
+ struct mem_block *notifier_heap;
+ drm_local_map_t *notifier_map;
/* PGRAPH context, for cards that keep it in RAMIN */
struct mem_block *ramin_grctx;
/* objects belonging to this fifo */
@@ -99,32 +103,42 @@ struct nouveau_config {
} cmdbuf;
};
-struct nouveau_engine_func {
+typedef struct nouveau_engine_func {
struct {
- int (*Init)(drm_device_t *dev);
- void (*Takedown)(drm_device_t *dev);
- } Mc;
+ int (*init)(drm_device_t *dev);
+ void (*takedown)(drm_device_t *dev);
+ } mc;
struct {
- int (*Init)(drm_device_t *dev);
- void (*Takedown)(drm_device_t *dev);
- } Timer;
+ int (*init)(drm_device_t *dev);
+ void (*takedown)(drm_device_t *dev);
+ } timer;
struct {
- int (*Init)(drm_device_t *dev);
- void (*Takedown)(drm_device_t *dev);
- } Fb;
+ int (*init)(drm_device_t *dev);
+ void (*takedown)(drm_device_t *dev);
+ } fb;
struct {
- int (*Init)(drm_device_t *dev);
- void (*Takedown)(drm_device_t *dev);
- } Graph;
+ int (*init)(drm_device_t *);
+ void (*takedown)(drm_device_t *);
+
+ int (*create_context)(drm_device_t *, int channel);
+ void (*destroy_context)(drm_device_t *, int channel);
+ int (*load_context)(drm_device_t *, int channel);
+ int (*save_context)(drm_device_t *, int channel);
+ } graph;
struct {
- int (*Init)(drm_device_t *dev);
- void (*Takedown)(drm_device_t *dev);
- } Fifo;
-};
+ int (*init)(drm_device_t *);
+ void (*takedown)(drm_device_t *);
+
+ int (*create_context)(drm_device_t *, int channel);
+ void (*destroy_context)(drm_device_t *, int channel);
+ int (*load_context)(drm_device_t *, int channel);
+ int (*save_context)(drm_device_t *, int channel);
+ } fifo;
+} nouveau_engine_func_t;
typedef struct drm_nouveau_private {
/* the card type, takes NV_* as values */
@@ -186,6 +200,12 @@ extern void nouveau_wait_for_idle(struct drm_device *dev);
extern int nouveau_ioctl_card_init(DRM_IOCTL_ARGS);
/* nouveau_mem.c */
+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,
+ DRMFILE);
+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(DRMFILE filp, struct mem_block *heap);
extern int nouveau_ioctl_mem_alloc(DRM_IOCTL_ARGS);
@@ -199,11 +219,13 @@ extern struct mem_block* nouveau_instmem_alloc(struct drm_device *dev,
uint32_t size, uint32_t align);
extern void nouveau_instmem_free(struct drm_device *dev,
struct mem_block *block);
-extern uint32_t nouveau_instmem_r32(drm_nouveau_private_t *dev_priv,
- struct mem_block *mem, int index);
-extern void nouveau_instmem_w32(drm_nouveau_private_t *dev_priv,
- struct mem_block *mem, int index,
- uint32_t val);
+
+/* nouveau_notifier.c */
+extern int nouveau_notifier_init_channel(drm_device_t *, int channel, DRMFILE);
+extern void nouveau_notifier_takedown_channel(drm_device_t *, int channel);
+extern int nouveau_notifier_alloc(drm_device_t *, int channel,
+ uint32_t handle, int cout, uint32_t *offset);
+extern int nouveau_ioctl_notifier_alloc(DRM_IOCTL_ARGS);
/* nouveau_fifo.c */
extern int nouveau_fifo_init(drm_device_t *dev);
@@ -214,7 +236,13 @@ extern int nouveau_fifo_owner(drm_device_t *dev, DRMFILE filp, int channel);
extern void nouveau_fifo_free(drm_device_t *dev, int channel);
/* nouveau_object.c */
+extern int nouveau_object_init_channel(drm_device_t *, int channel,
+ uint32_t vram_handle,
+ uint32_t tt_handle);
+extern void nouveau_object_takedown_channel(drm_device_t *dev, int channel);
extern void nouveau_object_cleanup(drm_device_t *dev, int channel);
+extern int nouveau_ramht_insert(drm_device_t *, int channel,
+ uint32_t handle, struct nouveau_object *);
extern struct nouveau_object *
nouveau_object_gr_create(drm_device_t *dev, int channel, int class);
extern struct nouveau_object *
@@ -222,8 +250,7 @@ nouveau_object_dma_create(drm_device_t *dev, int channel, int class,
uint32_t offset, uint32_t size,
int access, int target);
extern void nouveau_object_free(drm_device_t *dev, struct nouveau_object *obj);
-extern int nouveau_ioctl_object_init(DRM_IOCTL_ARGS);
-extern int nouveau_ioctl_dma_object_init(DRM_IOCTL_ARGS);
+extern int nouveau_ioctl_grobj_alloc(DRM_IOCTL_ARGS);
extern uint32_t nouveau_chip_instance_get(drm_device_t *dev, struct mem_block *mem);
/* nouveau_irq.c */
@@ -244,35 +271,82 @@ extern void nv10_fb_takedown(drm_device_t *dev);
extern int nv40_fb_init(drm_device_t *dev);
extern void nv40_fb_takedown(drm_device_t *dev);
+/* nv04_fifo.c */
+extern int nv04_fifo_create_context(drm_device_t *dev, int channel);
+extern void nv04_fifo_destroy_context(drm_device_t *dev, int channel);
+extern int nv04_fifo_load_context(drm_device_t *dev, int channel);
+extern int nv04_fifo_save_context(drm_device_t *dev, int channel);
+
+/* nv10_fifo.c */
+extern int nv10_fifo_create_context(drm_device_t *dev, int channel);
+extern void nv10_fifo_destroy_context(drm_device_t *dev, int channel);
+extern int nv10_fifo_load_context(drm_device_t *dev, int channel);
+extern int nv10_fifo_save_context(drm_device_t *dev, int channel);
+
+/* nv40_fifo.c */
+extern int nv40_fifo_create_context(drm_device_t *, int channel);
+extern void nv40_fifo_destroy_context(drm_device_t *, int channel);
+extern int nv40_fifo_load_context(drm_device_t *, int channel);
+extern int nv40_fifo_save_context(drm_device_t *, int channel);
+
+/* nv50_fifo.c */
+extern int nv50_fifo_init(drm_device_t *);
+extern void nv50_fifo_takedown(drm_device_t *);
+extern int nv50_fifo_create_context(drm_device_t *, int channel);
+extern void nv50_fifo_destroy_context(drm_device_t *, int channel);
+extern int nv50_fifo_load_context(drm_device_t *, int channel);
+extern int nv50_fifo_save_context(drm_device_t *, int channel);
+
/* nv04_graph.c */
extern void nouveau_nv04_context_switch(drm_device_t *dev);
-extern int nv04_graph_init(drm_device_t *dev);
+extern int nv04_graph_init(drm_device_t *dev);
extern void nv04_graph_takedown(drm_device_t *dev);
-extern int nv04_graph_context_create(drm_device_t *dev, int channel);
+extern int nv04_graph_create_context(drm_device_t *dev, int channel);
+extern void nv04_graph_destroy_context(drm_device_t *dev, int channel);
+extern int nv04_graph_load_context(drm_device_t *dev, int channel);
+extern int nv04_graph_save_context(drm_device_t *dev, int channel);
/* nv10_graph.c */
extern void nouveau_nv10_context_switch(drm_device_t *dev);
-extern int nv10_graph_init(drm_device_t *dev);
+extern int nv10_graph_init(drm_device_t *dev);
extern void nv10_graph_takedown(drm_device_t *dev);
-extern int nv10_graph_context_create(drm_device_t *dev, int channel);
+extern int nv10_graph_create_context(drm_device_t *dev, int channel);
+extern void nv10_graph_destroy_context(drm_device_t *dev, int channel);
+extern int nv10_graph_load_context(drm_device_t *dev, int channel);
+extern int nv10_graph_save_context(drm_device_t *dev, int channel);
/* nv20_graph.c */
extern void nouveau_nv20_context_switch(drm_device_t *dev);
-extern int nv20_graph_init(drm_device_t *dev);
+extern int nv20_graph_init(drm_device_t *dev);
extern void nv20_graph_takedown(drm_device_t *dev);
-extern int nv20_graph_context_create(drm_device_t *dev, int channel);
+extern int nv20_graph_create_context(drm_device_t *dev, int channel);
+extern void nv20_graph_destroy_context(drm_device_t *dev, int channel);
+extern int nv20_graph_load_context(drm_device_t *dev, int channel);
+extern int nv20_graph_save_context(drm_device_t *dev, int channel);
/* nv30_graph.c */
-extern int nv30_graph_init(drm_device_t *dev);
+extern int nv30_graph_init(drm_device_t *dev);
extern void nv30_graph_takedown(drm_device_t *dev);
-extern int nv30_graph_context_create(drm_device_t *dev, int channel);
+extern int nv30_graph_create_context(drm_device_t *, int channel);
+extern void nv30_graph_destroy_context(drm_device_t *, int channel);
+extern int nv30_graph_load_context(drm_device_t *, int channel);
+extern int nv30_graph_save_context(drm_device_t *, int channel);
/* nv40_graph.c */
-extern int nv40_graph_init(drm_device_t *dev);
-extern void nv40_graph_takedown(drm_device_t *dev);
-extern int nv40_graph_context_create(drm_device_t *dev, int channel);
-extern void nv40_graph_context_save_current(drm_device_t *dev);
-extern void nv40_graph_context_restore(drm_device_t *dev, int channel);
+extern int nv40_graph_init(drm_device_t *);
+extern void nv40_graph_takedown(drm_device_t *);
+extern int nv40_graph_create_context(drm_device_t *, int channel);
+extern void nv40_graph_destroy_context(drm_device_t *, int channel);
+extern int nv40_graph_load_context(drm_device_t *, int channel);
+extern int nv40_graph_save_context(drm_device_t *, int channel);
+
+/* nv50_graph.c */
+extern int nv50_graph_init(drm_device_t *);
+extern void nv50_graph_takedown(drm_device_t *);
+extern int nv50_graph_create_context(drm_device_t *, int channel);
+extern void nv50_graph_destroy_context(drm_device_t *, int channel);
+extern int nv50_graph_load_context(drm_device_t *, int channel);
+extern int nv50_graph_save_context(drm_device_t *, int channel);
/* nv04_mc.c */
extern int nv04_mc_init(drm_device_t *dev);
@@ -282,6 +356,10 @@ extern void nv04_mc_takedown(drm_device_t *dev);
extern int nv40_mc_init(drm_device_t *dev);
extern void nv40_mc_takedown(drm_device_t *dev);
+/* nv50_mc.c */
+extern int nv50_mc_init(drm_device_t *dev);
+extern void nv50_mc_takedown(drm_device_t *dev);
+
/* nv04_timer.c */
extern int nv04_timer_init(drm_device_t *dev);
extern void nv04_timer_takedown(drm_device_t *dev);
@@ -297,8 +375,17 @@ extern long nouveau_compat_ioctl(struct file *filp, unsigned int cmd,
#define NV_WRITE(reg,val) DRM_WRITE32( dev_priv->mmio, (reg), (val) )
#endif
-#define INSTANCE_WR(mem,ofs,val) nouveau_instmem_w32(dev_priv,(mem),(ofs),(val))
-#define INSTANCE_RD(mem,ofs) nouveau_instmem_r32(dev_priv,(mem),(ofs))
+/* PRAMIN access */
+#if defined(__powerpc__)
+#define NV_RI32(o) in_be32((void __iomem *)(dev_priv->ramin)->handle+(o))
+#define NV_WI32(o,v) out_be32((void __iomem*)(dev_priv->ramin)->handle+(o), (v))
+#else
+#define NV_RI32(o) DRM_READ32(dev_priv->ramin, (o))
+#define NV_WI32(o,v) DRM_WRITE32(dev_priv->ramin, (o), (v))
+#endif
+
+#define INSTANCE_RD(o,i) NV_RI32((o)->start + ((i)<<2))
+#define INSTANCE_WR(o,i,v) NV_WI32((o)->start + ((i)<<2), (v))
#endif /* __NOUVEAU_DRV_H__ */
diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c
index 8e66ca2e..81dbfcda 100644
--- a/shared-core/nouveau_fifo.c
+++ b/shared-core/nouveau_fifo.c
@@ -83,6 +83,8 @@ static int nouveau_fifo_instmem_configure(drm_device_t *dev)
case NV_50:
case NV_40:
NV_WRITE(NV40_PFIFO_RAMFC, 0x30002);
+ if((dev_priv->chipset == 0x49) || (dev_priv->chipset == 0x4b))
+ NV_WRITE(0x2230,0x00000001);
break;
case NV_44:
NV_WRITE(NV40_PFIFO_RAMFC, ((nouveau_mem_fb_amount(dev)-512*1024+dev_priv->ramfc_offset)>>16) |
@@ -232,235 +234,20 @@ nouveau_fifo_cmdbuf_alloc(struct drm_device *dev, int channel)
return DRM_ERR(ENOMEM);
}
+ dev_priv->fifos[channel].pushbuf_base = 0;
dev_priv->fifos[channel].cmdbuf_mem = cb;
dev_priv->fifos[channel].cmdbuf_obj = cb_dma;
return 0;
}
-#define RAMFC_WR(offset, val) NV_WRITE(fifoctx + NV04_RAMFC_##offset, (val))
-static void nouveau_nv04_context_init(drm_device_t *dev, int channel)
-{
- drm_nouveau_private_t *dev_priv = dev->dev_private;
- struct nouveau_object *cb_obj;
- uint32_t fifoctx, ctx_size = 32;
- int i;
-
- cb_obj = dev_priv->fifos[channel].cmdbuf_obj;
-
- fifoctx=NV_RAMIN+dev_priv->ramfc_offset+channel*ctx_size;
-
- // clear the fifo context
- for(i=0;i<ctx_size/4;i++)
- NV_WRITE(fifoctx+4*i,0x0);
-
- RAMFC_WR(DMA_INSTANCE , nouveau_chip_instance_get(dev, cb_obj->instance));
-
- RAMFC_WR(DMA_FETCH, NV_PFIFO_CACHE1_DMA_FETCH_TRIG_112_BYTES |
- NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES |
- NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_4 |
-#ifdef __BIG_ENDIAN
- NV_PFIFO_CACHE1_BIG_ENDIAN |
-#endif
- 0x00000000);
-}
-#undef RAMFC_WR
-
-#define RAMFC_WR(offset, val) NV_WRITE(fifoctx + NV10_RAMFC_##offset, (val))
-static void nouveau_nv10_context_init(drm_device_t *dev, int channel)
-{
- drm_nouveau_private_t *dev_priv = dev->dev_private;
- struct nouveau_object *cb_obj;
- uint32_t fifoctx;
- int ctx_size = nouveau_fifo_ctx_size(dev);
- int i;
- cb_obj = dev_priv->fifos[channel].cmdbuf_obj;
- fifoctx = NV_RAMIN + dev_priv->ramfc_offset + channel*ctx_size;
-
- for (i=0;i<ctx_size;i+=4)
- NV_WRITE(fifoctx + i, 0);
-
- /* Fill entries that are seen filled in dumps of nvidia driver just
- * after channel's is put into DMA mode
- */
-
- RAMFC_WR(DMA_INSTANCE , nouveau_chip_instance_get(dev,
- cb_obj->instance));
-
- RAMFC_WR(DMA_FETCH, NV_PFIFO_CACHE1_DMA_FETCH_TRIG_112_BYTES |
- NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES |
- NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_4 |
-#ifdef __BIG_ENDIAN
- NV_PFIFO_CACHE1_BIG_ENDIAN |
-#endif
- 0x00000000);
-}
-
-static void nouveau_nv30_context_init(drm_device_t *dev, int channel)
-{
- drm_nouveau_private_t *dev_priv = dev->dev_private;
- struct nouveau_fifo *chan = &dev_priv->fifos[channel];
- struct nouveau_object *cb_obj;
- uint32_t fifoctx, grctx_inst, cb_inst, ctx_size = 64;
- int i;
-
- cb_obj = dev_priv->fifos[channel].cmdbuf_obj;
- cb_inst = nouveau_chip_instance_get(dev, chan->cmdbuf_obj->instance);
- grctx_inst = nouveau_chip_instance_get(dev, chan->ramin_grctx);
- fifoctx = NV_RAMIN + dev_priv->ramfc_offset + channel * ctx_size;
-
- for (i = 0; i < ctx_size; i += 4)
- NV_WRITE(fifoctx + i, 0);
-
- RAMFC_WR(REF_CNT, NV_READ(NV10_PFIFO_CACHE1_REF_CNT));
- RAMFC_WR(DMA_INSTANCE, cb_inst);
- RAMFC_WR(DMA_STATE, NV_READ(NV04_PFIFO_CACHE1_DMA_STATE));
- RAMFC_WR(DMA_FETCH, NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES |
- NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES |
- NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8 |
-#ifdef __BIG_ENDIAN
- NV_PFIFO_CACHE1_BIG_ENDIAN |
-#endif
- 0x00000000);
-
- RAMFC_WR(ENGINE, NV_READ(NV04_PFIFO_CACHE1_ENGINE));
- RAMFC_WR(PULL1_ENGINE, NV_READ(NV04_PFIFO_CACHE1_PULL1));
- RAMFC_WR(ACQUIRE_VALUE, NV_READ(NV10_PFIFO_CACHE1_ACQUIRE_VALUE));
- RAMFC_WR(ACQUIRE_TIMESTAMP, NV_READ(NV10_PFIFO_CACHE1_ACQUIRE_TIMESTAMP));
- RAMFC_WR(ACQUIRE_TIMEOUT, NV_READ(NV10_PFIFO_CACHE1_ACQUIRE_TIMEOUT));
- RAMFC_WR(SEMAPHORE, NV_READ(NV10_PFIFO_CACHE1_SEMAPHORE));
-}
-
-#if 0
-static void nouveau_nv10_context_save(drm_device_t *dev)
-{
- drm_nouveau_private_t *dev_priv = dev->dev_private;
- uint32_t fifoctx;
- int channel;
-
- channel = NV_READ(NV03_PFIFO_CACHE1_PUSH1) & (nouveau_fifo_number(dev)-1);
- fifoctx = NV_RAMIN + dev_priv->ramfc_offset + channel*64;
-
- RAMFC_WR(DMA_PUT , NV_READ(NV04_PFIFO_CACHE1_DMA_PUT));
- RAMFC_WR(DMA_GET , NV_READ(NV04_PFIFO_CACHE1_DMA_GET));
- RAMFC_WR(REF_CNT , NV_READ(NV10_PFIFO_CACHE1_REF_CNT));
- RAMFC_WR(DMA_INSTANCE , NV_READ(NV04_PFIFO_CACHE1_DMA_INSTANCE));
- RAMFC_WR(DMA_STATE , NV_READ(NV04_PFIFO_CACHE1_DMA_STATE));
- RAMFC_WR(DMA_FETCH , NV_READ(NV04_PFIFO_CACHE1_DMA_FETCH));
- RAMFC_WR(ENGINE , NV_READ(NV04_PFIFO_CACHE1_ENGINE));
- RAMFC_WR(PULL1_ENGINE , NV_READ(NV04_PFIFO_CACHE1_PULL1));
- RAMFC_WR(ACQUIRE_VALUE , NV_READ(NV10_PFIFO_CACHE1_ACQUIRE_VALUE));
- RAMFC_WR(ACQUIRE_TIMESTAMP, NV_READ(NV10_PFIFO_CACHE1_ACQUIRE_TIMESTAMP));
- RAMFC_WR(ACQUIRE_TIMEOUT , NV_READ(NV10_PFIFO_CACHE1_ACQUIRE_TIMEOUT));
- RAMFC_WR(SEMAPHORE , NV_READ(NV10_PFIFO_CACHE1_SEMAPHORE));
- RAMFC_WR(DMA_SUBROUTINE , NV_READ(NV10_PFIFO_CACHE1_DMA_SUBROUTINE));
-}
-#endif
-#undef RAMFC_WR
-
-#define RAMFC_WR(offset, val) NV_WRITE(fifoctx + NV40_RAMFC_##offset, (val))
-static void nouveau_nv40_context_init(drm_device_t *dev, int channel)
-{
- drm_nouveau_private_t *dev_priv = dev->dev_private;
- struct nouveau_fifo *chan = &dev_priv->fifos[channel];
- uint32_t fifoctx, cb_inst, grctx_inst;
- int i;
-
- cb_inst = nouveau_chip_instance_get(dev, chan->cmdbuf_obj->instance);
- grctx_inst = nouveau_chip_instance_get(dev, chan->ramin_grctx);
- fifoctx = NV_RAMIN + dev_priv->ramfc_offset + channel*128;
- for (i=0;i<128;i+=4)
- NV_WRITE(fifoctx + i, 0);
-
- /* Fill entries that are seen filled in dumps of nvidia driver just
- * after channel's is put into DMA mode
- */
- RAMFC_WR(DMA_INSTANCE , cb_inst);
- RAMFC_WR(DMA_FETCH , NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES |
- NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES |
- NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8 |
-#ifdef __BIG_ENDIAN
- NV_PFIFO_CACHE1_BIG_ENDIAN |
-#endif
- 0x30000000 /* no idea.. */);
- RAMFC_WR(GRCTX_INSTANCE, grctx_inst);
- RAMFC_WR(DMA_TIMESLICE , 0x0001FFFF);
-}
-
-static void nouveau_nv40_context_save(drm_device_t *dev)
-{
- drm_nouveau_private_t *dev_priv = dev->dev_private;
- uint32_t fifoctx;
- int channel;
-
- channel = NV_READ(NV03_PFIFO_CACHE1_PUSH1) & (nouveau_fifo_number(dev)-1);
- fifoctx = NV_RAMIN + dev_priv->ramfc_offset + channel*128;
-
- RAMFC_WR(DMA_PUT , NV_READ(NV04_PFIFO_CACHE1_DMA_PUT));
- RAMFC_WR(DMA_GET , NV_READ(NV04_PFIFO_CACHE1_DMA_GET));
- RAMFC_WR(REF_CNT , NV_READ(NV10_PFIFO_CACHE1_REF_CNT));
- RAMFC_WR(DMA_INSTANCE , NV_READ(NV04_PFIFO_CACHE1_DMA_INSTANCE));
- RAMFC_WR(DMA_DCOUNT , NV_READ(NV10_PFIFO_CACHE1_DMA_DCOUNT));
- RAMFC_WR(DMA_STATE , NV_READ(NV04_PFIFO_CACHE1_DMA_STATE));
- RAMFC_WR(DMA_FETCH , NV_READ(NV04_PFIFO_CACHE1_DMA_FETCH));
- RAMFC_WR(ENGINE , NV_READ(NV04_PFIFO_CACHE1_ENGINE));
- RAMFC_WR(PULL1_ENGINE , NV_READ(NV04_PFIFO_CACHE1_PULL1));
- RAMFC_WR(ACQUIRE_VALUE , NV_READ(NV10_PFIFO_CACHE1_ACQUIRE_VALUE));
- RAMFC_WR(ACQUIRE_TIMESTAMP, NV_READ(NV10_PFIFO_CACHE1_ACQUIRE_TIMESTAMP));
- RAMFC_WR(ACQUIRE_TIMEOUT , NV_READ(NV10_PFIFO_CACHE1_ACQUIRE_TIMEOUT));
- RAMFC_WR(SEMAPHORE , NV_READ(NV10_PFIFO_CACHE1_SEMAPHORE));
- RAMFC_WR(DMA_SUBROUTINE , NV_READ(NV04_PFIFO_CACHE1_DMA_GET));
- RAMFC_WR(GRCTX_INSTANCE , NV_READ(NV40_PFIFO_GRCTX_INSTANCE));
- RAMFC_WR(DMA_TIMESLICE , NV_READ(NV04_PFIFO_DMA_TIMESLICE) & 0x1FFFF);
- RAMFC_WR(UNK_40 , NV_READ(NV40_PFIFO_UNK32E4));
-}
-#undef RAMFC_WR
-
-/* This function should load values from RAMFC into PFIFO, but for now
- * it just clobbers PFIFO with what nouveau_fifo_alloc used to setup
- * unconditionally.
- */
-static void
-nouveau_fifo_context_restore(drm_device_t *dev, int channel)
-{
- drm_nouveau_private_t *dev_priv = dev->dev_private;
- struct nouveau_fifo *chan = &dev_priv->fifos[channel];
- uint32_t cb_inst;
-
- cb_inst = nouveau_chip_instance_get(dev, chan->cmdbuf_obj->instance);
-
- // FIXME check if we need to refill the time quota with something like NV_WRITE(0x204C, 0x0003FFFF);
-
- if (dev_priv->card_type >= NV_40)
- NV_WRITE(NV03_PFIFO_CACHE1_PUSH1, 0x00010000|channel);
- else
- NV_WRITE(NV03_PFIFO_CACHE1_PUSH1, 0x00000100|channel);
-
- NV_WRITE(NV04_PFIFO_CACHE1_DMA_PUT, 0 /*RAMFC_DMA_PUT*/);
- NV_WRITE(NV04_PFIFO_CACHE1_DMA_GET, 0 /*RAMFC_DMA_GET*/);
- NV_WRITE(NV04_PFIFO_CACHE1_DMA_INSTANCE, cb_inst);
- NV_WRITE(NV04_PFIFO_SIZE , 0x0000FFFF);
- NV_WRITE(NV04_PFIFO_CACHE1_HASH, 0x0000FFFF);
-
- NV_WRITE(NV04_PFIFO_CACHE0_PULL1, 0x00000001);
- NV_WRITE(NV04_PFIFO_CACHE1_DMA_CTL, 0x00000000);
- NV_WRITE(NV04_PFIFO_CACHE1_DMA_STATE, 0x00000000);
- NV_WRITE(NV04_PFIFO_CACHE1_ENGINE, 0x00000000);
-
- NV_WRITE(NV04_PFIFO_CACHE1_DMA_FETCH, NV_PFIFO_CACHE1_DMA_FETCH_TRIG_112_BYTES |
- NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES |
- NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_4 |
-#ifdef __BIG_ENDIAN
- NV_PFIFO_CACHE1_BIG_ENDIAN |
-#endif
- 0x00000000);
-}
-
/* allocates and initializes a fifo for user space consumption */
-static int nouveau_fifo_alloc(drm_device_t* dev, int *chan_ret, DRMFILE filp)
+int nouveau_fifo_alloc(drm_device_t* dev, int *chan_ret, DRMFILE filp,
+ uint32_t vram_handle, uint32_t tt_handle)
{
int ret;
drm_nouveau_private_t *dev_priv = dev->dev_private;
- struct nouveau_object *cb_obj;
+ nouveau_engine_func_t *engine = &dev_priv->Engine;
+ struct nouveau_fifo *chan;
int channel;
/*
@@ -478,14 +265,16 @@ static int nouveau_fifo_alloc(drm_device_t* dev, int *chan_ret, DRMFILE filp)
if (channel==nouveau_fifo_number(dev))
return DRM_ERR(EINVAL);
(*chan_ret) = channel;
+ chan = &dev_priv->fifos[channel];
DRM_INFO("Allocating FIFO number %d\n", channel);
/* that fifo is used */
- dev_priv->fifos[channel].used = 1;
- dev_priv->fifos[channel].filp = filp;
+ chan->used = 1;
+ chan->filp = filp;
+
/* FIFO has no objects yet */
- dev_priv->fifos[channel].objs = NULL;
+ chan->objs = NULL;
/* allocate a command buffer, and create a dma object for the gpu */
ret = nouveau_fifo_cmdbuf_alloc(dev, channel);
@@ -493,7 +282,20 @@ static int nouveau_fifo_alloc(drm_device_t* dev, int *chan_ret, DRMFILE filp)
nouveau_fifo_free(dev, channel);
return ret;
}
- cb_obj = dev_priv->fifos[channel].cmdbuf_obj;
+
+ /* Setup channel's default objects */
+ ret = nouveau_object_init_channel(dev, channel, vram_handle, tt_handle);
+ if (ret) {
+ nouveau_fifo_free(dev, channel);
+ return ret;
+ }
+
+ /* Allocate space for per-channel fixed notifier memory */
+ ret = nouveau_notifier_init_channel(dev, channel, filp);
+ if (ret) {
+ nouveau_fifo_free(dev, channel);
+ return ret;
+ }
nouveau_wait_for_idle(dev);
@@ -503,73 +305,54 @@ static int nouveau_fifo_alloc(drm_device_t* dev, int *chan_ret, DRMFILE filp)
NV_WRITE(NV03_PFIFO_CACHE1_PUSH0, 0x00000000);
NV_WRITE(NV04_PFIFO_CACHE1_PULL0, 0x00000000);
+ /* Create a graphics context for new channel */
+ ret = engine->graph.create_context(dev, channel);
+ if (ret) {
+ nouveau_fifo_free(dev, channel);
+ return ret;
+ }
+
/* Construct inital RAMFC for new channel */
- switch(dev_priv->card_type)
- {
- case NV_04:
- case NV_05:
- nv04_graph_context_create(dev, channel);
- nouveau_nv04_context_init(dev, channel);
- break;
- case NV_10:
- case NV_17:
- nv10_graph_context_create(dev, channel);
- nouveau_nv10_context_init(dev, channel);
- break;
- case NV_20:
- ret = nv20_graph_context_create(dev, channel);
- if (ret) {
- nouveau_fifo_free(dev, channel);
- return ret;
- }
- nouveau_nv10_context_init(dev, channel);
- break;
- case NV_30:
- ret = nv30_graph_context_create(dev, channel);
- if (ret) {
- nouveau_fifo_free(dev, channel);
- return ret;
- }
- nouveau_nv30_context_init(dev, channel);
- break;
- case NV_40:
- case NV_44:
- case NV_50:
- ret = nv40_graph_context_create(dev, channel);
- if (ret) {
- nouveau_fifo_free(dev, channel);
- return ret;
- }
- nouveau_nv40_context_init(dev, channel);
- break;
+ ret = engine->fifo.create_context(dev, channel);
+ if (ret) {
+ nouveau_fifo_free(dev, channel);
+ return ret;
}
/* enable the fifo dma operation */
NV_WRITE(NV04_PFIFO_MODE,NV_READ(NV04_PFIFO_MODE)|(1<<channel));
/* setup channel's default get/put values */
- NV_WRITE(NV03_FIFO_REGS_DMAPUT(channel), 0);
- NV_WRITE(NV03_FIFO_REGS_DMAGET(channel), 0);
+ NV_WRITE(NV03_FIFO_REGS_DMAPUT(channel), chan->pushbuf_base);
+ NV_WRITE(NV03_FIFO_REGS_DMAGET(channel), chan->pushbuf_base);
/* If this is the first channel, setup PFIFO ourselves. For any
* other case, the GPU will handle this when it switches contexts.
*/
if (dev_priv->fifo_alloc_count == 0) {
- nouveau_fifo_context_restore(dev, channel);
- if (dev_priv->card_type >= NV_30) {
- struct nouveau_fifo *chan;
- uint32_t inst;
-
- chan = &dev_priv->fifos[channel];
- inst = nouveau_chip_instance_get(dev,
- chan->ramin_grctx);
-
- /* see comments in nv40_graph_context_restore() */
- NV_WRITE(NV10_PGRAPH_CHANNEL_CTX_SIZE, inst);
- if (dev_priv->card_type >= NV_40) {
- NV_WRITE(0x40032C, inst | 0x01000000);
- NV_WRITE(NV40_PFIFO_GRCTX_INSTANCE, inst);
- }
+ ret = engine->fifo.load_context(dev, channel);
+ if (ret) {
+ nouveau_fifo_free(dev, channel);
+ return ret;
+ }
+
+ ret = engine->graph.load_context(dev, channel);
+ if (ret) {
+ nouveau_fifo_free(dev, channel);
+ 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) {
+ 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);
}
}
@@ -591,9 +374,8 @@ static int nouveau_fifo_alloc(drm_device_t* dev, int *chan_ret, DRMFILE filp)
void nouveau_fifo_free(drm_device_t* dev, int channel)
{
drm_nouveau_private_t *dev_priv = dev->dev_private;
+ nouveau_engine_func_t *engine = &dev_priv->Engine;
struct nouveau_fifo *chan = &dev_priv->fifos[channel];
- int i;
- int ctx_size = nouveau_fifo_ctx_size(dev);
chan->used = 0;
DRM_INFO("%s: freeing fifo %d\n", __func__, channel);
@@ -604,25 +386,10 @@ void nouveau_fifo_free(drm_device_t* dev, int channel)
NV_WRITE(NV04_PFIFO_MODE, NV_READ(NV04_PFIFO_MODE)&~(1<<channel));
// FIXME XXX needs more code
- /* Clean RAMFC */
- for (i=0;i<ctx_size;i+=4) {
- DRM_DEBUG("RAMFC +%02x: 0x%08x\n", i, NV_READ(NV_RAMIN +
- dev_priv->ramfc_offset +
- channel*ctx_size + i));
- NV_WRITE(NV_RAMIN + dev_priv->ramfc_offset +
- channel*ctx_size + i, 0);
- }
+ engine->fifo.destroy_context(dev, channel);
/* Cleanup PGRAPH state */
- if (dev_priv->card_type >= NV_40)
- nouveau_instmem_free(dev, chan->ramin_grctx);
- else if (dev_priv->card_type >= NV_30) {
- }
- else if (dev_priv->card_type >= NV_20) {
- /* clear ctx table */
- INSTANCE_WR(dev_priv->ctx_table, channel, 0);
- nouveau_instmem_free(dev, chan->ramin_grctx);
- }
+ engine->graph.destroy_context(dev, channel);
/* reenable the fifo caches */
NV_WRITE(NV03_PFIFO_CACHES, 0x00000001);
@@ -631,6 +398,8 @@ void nouveau_fifo_free(drm_device_t* dev, int channel)
if (chan->cmdbuf_mem)
nouveau_mem_free(dev, chan->cmdbuf_mem);
+ nouveau_notifier_takedown_channel(dev, channel);
+
/* Destroy objects belonging to the channel */
nouveau_object_cleanup(dev, channel);
@@ -669,31 +438,42 @@ static int nouveau_ioctl_fifo_alloc(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_nouveau_private_t *dev_priv = dev->dev_private;
+ struct nouveau_fifo *chan;
drm_nouveau_fifo_alloc_t init;
int res;
DRM_COPY_FROM_USER_IOCTL(init, (drm_nouveau_fifo_alloc_t __user *) data,
sizeof(init));
- res = nouveau_fifo_alloc(dev, &init.channel, filp);
+ res = nouveau_fifo_alloc(dev, &init.channel, filp,
+ init.fb_ctxdma_handle,
+ init.tt_ctxdma_handle);
if (res)
return res;
+ chan = &dev_priv->fifos[init.channel];
- /* this should probably disappear in the next abi break? */
- init.put_base = 0;
+ init.put_base = chan->pushbuf_base;
/* make the fifo available to user space */
/* first, the fifo control regs */
init.ctrl = dev_priv->mmio->offset + NV03_FIFO_REGS(init.channel);
init.ctrl_size = NV03_FIFO_REGS_SIZE;
res = drm_addmap(dev, init.ctrl, init.ctrl_size, _DRM_REGISTERS,
- 0, &dev_priv->fifos[init.channel].regs);
+ 0, &chan->regs);
if (res != 0)
return res;
/* pass back FIFO map info to the caller */
- init.cmdbuf = dev_priv->fifos[init.channel].cmdbuf_mem->start;
- init.cmdbuf_size = dev_priv->fifos[init.channel].cmdbuf_mem->size;
+ init.cmdbuf = chan->cmdbuf_mem->start;
+ init.cmdbuf_size = chan->cmdbuf_mem->size;
+
+ /* and the notifier block */
+ init.notifier = chan->notifier_block->start;
+ init.notifier_size = chan->notifier_block->size;
+ res = drm_addmap(dev, init.notifier, init.notifier_size, _DRM_REGISTERS,
+ 0, &chan->notifier_map);
+ if (res != 0)
+ return res;
DRM_COPY_TO_USER_IOCTL((drm_nouveau_fifo_alloc_t __user *)data,
init, sizeof(init));
@@ -706,8 +486,8 @@ static int nouveau_ioctl_fifo_alloc(DRM_IOCTL_ARGS)
drm_ioctl_desc_t nouveau_ioctls[] = {
[DRM_IOCTL_NR(DRM_NOUVEAU_FIFO_ALLOC)] = {nouveau_ioctl_fifo_alloc, DRM_AUTH},
- [DRM_IOCTL_NR(DRM_NOUVEAU_OBJECT_INIT)] = {nouveau_ioctl_object_init, DRM_AUTH},
- [DRM_IOCTL_NR(DRM_NOUVEAU_DMA_OBJECT_INIT)] = {nouveau_ioctl_dma_object_init, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_NOUVEAU_GROBJ_ALLOC)] = {nouveau_ioctl_grobj_alloc, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_NOUVEAU_NOTIFIER_ALLOC)] = {nouveau_ioctl_notifier_alloc, DRM_AUTH},
[DRM_IOCTL_NR(DRM_NOUVEAU_MEM_ALLOC)] = {nouveau_ioctl_mem_alloc, DRM_AUTH},
[DRM_IOCTL_NR(DRM_NOUVEAU_MEM_FREE)] = {nouveau_ioctl_mem_free, DRM_AUTH},
[DRM_IOCTL_NR(DRM_NOUVEAU_GETPARAM)] = {nouveau_ioctl_getparam, DRM_AUTH},
diff --git a/shared-core/nouveau_mem.c b/shared-core/nouveau_mem.c
index a5343b99..d8ae52b7 100644
--- a/shared-core/nouveau_mem.c
+++ b/shared-core/nouveau_mem.c
@@ -77,8 +77,8 @@ out:
return p;
}
-static struct mem_block *alloc_block(struct mem_block *heap, uint64_t size,
- int align2, DRMFILE filp)
+struct mem_block *nouveau_mem_alloc_block(struct mem_block *heap, uint64_t size,
+ int align2, DRMFILE filp)
{
struct mem_block *p;
uint64_t mask = (1 << align2) - 1;
@@ -106,7 +106,7 @@ static struct mem_block *find_block(struct mem_block *heap, uint64_t start)
return NULL;
}
-static void free_block(struct mem_block *p)
+void nouveau_mem_free_block(struct mem_block *p)
{
p->filp = NULL;
@@ -132,7 +132,8 @@ static void free_block(struct mem_block *p)
/* Initialize. How to check for an uninitialized heap?
*/
-static int init_heap(struct mem_block **heap, uint64_t start, uint64_t size)
+int nouveau_mem_init_heap(struct mem_block **heap, uint64_t start,
+ uint64_t size)
{
struct mem_block *blocks = drm_alloc(sizeof(*blocks), DRM_MEM_BUFS);
@@ -331,7 +332,9 @@ int nouveau_mem_init(struct drm_device *dev)
goto no_agp;
}
- if (init_heap(&dev_priv->agp_heap, info.aperture_base, info.aperture_size))
+ if (nouveau_mem_init_heap(&dev_priv->agp_heap,
+ info.aperture_base,
+ info.aperture_size))
goto no_agp;
dev_priv->agp_phys = info.aperture_base;
@@ -357,12 +360,19 @@ no_agp:
if (fb_size>256*1024*1024) {
/* On cards with > 256Mb, you can't map everything.
* So we create a second FB heap for that type of memory */
- if (init_heap(&dev_priv->fb_heap, drm_get_resource_start(dev,1), 256*1024*1024))
+ if (nouveau_mem_init_heap(&dev_priv->fb_heap,
+ drm_get_resource_start(dev,1),
+ 256*1024*1024))
return DRM_ERR(ENOMEM);
- if (init_heap(&dev_priv->fb_nomap_heap, drm_get_resource_start(dev,1)+256*1024*1024, fb_size-256*1024*1024))
+ if (nouveau_mem_init_heap(&dev_priv->fb_nomap_heap,
+ drm_get_resource_start(dev,1) +
+ 256*1024*1024,
+ fb_size-256*1024*1024))
return DRM_ERR(ENOMEM);
} else {
- if (init_heap(&dev_priv->fb_heap, drm_get_resource_start(dev,1), fb_size))
+ if (nouveau_mem_init_heap(&dev_priv->fb_heap,
+ drm_get_resource_start(dev,1),
+ fb_size))
return DRM_ERR(ENOMEM);
dev_priv->fb_nomap_heap=NULL;
}
@@ -397,21 +407,25 @@ struct mem_block* nouveau_mem_alloc(struct drm_device *dev, int alignment, uint6
if (flags&NOUVEAU_MEM_AGP) {
type=NOUVEAU_MEM_AGP;
- block = alloc_block(dev_priv->agp_heap, size, alignment, filp);
+ block = nouveau_mem_alloc_block(dev_priv->agp_heap, size,
+ alignment, filp);
if (block) goto alloc_ok;
}
if (flags&(NOUVEAU_MEM_FB|NOUVEAU_MEM_FB_ACCEPTABLE)) {
type=NOUVEAU_MEM_FB;
if (!(flags&NOUVEAU_MEM_MAPPED)) {
- block = alloc_block(dev_priv->fb_nomap_heap, size, alignment, filp);
+ block = nouveau_mem_alloc_block(dev_priv->fb_nomap_heap,
+ size, alignment, filp);
if (block) goto alloc_ok;
}
- block = alloc_block(dev_priv->fb_heap, size, alignment, filp);
+ block = nouveau_mem_alloc_block(dev_priv->fb_heap, size,
+ alignment, filp);
if (block) goto alloc_ok;
}
if (flags&NOUVEAU_MEM_AGP_ACCEPTABLE) {
type=NOUVEAU_MEM_AGP;
- block = alloc_block(dev_priv->agp_heap, size, alignment, filp);
+ block = nouveau_mem_alloc_block(dev_priv->agp_heap, size,
+ alignment, filp);
if (block) goto alloc_ok;
}
@@ -432,7 +446,7 @@ alloc_ok:
ret = drm_addmap(dev, block->start, block->size,
_DRM_FRAME_BUFFER, 0, &block->map);
if (ret) {
- free_block(block);
+ nouveau_mem_free_block(block);
return NULL;
}
}
@@ -446,7 +460,7 @@ void nouveau_mem_free(struct drm_device* dev, struct mem_block* block)
DRM_INFO("freeing 0x%llx\n", block->start);
if (block->flags&NOUVEAU_MEM_MAPPED)
drm_rmmap(dev, block->map);
- free_block(block);
+ nouveau_mem_free_block(block);
}
static void
@@ -475,13 +489,8 @@ nouveau_instmem_determine_amount(struct drm_device *dev)
DRM_DEBUG("RAMIN size: %dKiB\n", dev_priv->ramin_size>>10);
/* Clear all of it, except the BIOS image that's in the first 64KiB */
- if (dev_priv->ramin) {
- for (i=(64*1024); i<dev_priv->ramin_size; i+=4)
- DRM_WRITE32(dev_priv->ramin, i, 0x00000000);
- } else {
- for (i=(64*1024); i<dev_priv->ramin_size; i+=4)
- DRM_WRITE32(dev_priv->mmio, NV_RAMIN + i, 0x00000000);
- }
+ for (i=(64*1024); i<dev_priv->ramin_size; i+=4)
+ NV_WI32(i, 0x00000000);
}
static void
@@ -549,8 +558,8 @@ int nouveau_instmem_init(struct drm_device *dev)
* the space that was reserved for RAMHT/FC/RO.
*/
offset = dev_priv->ramfc_offset + dev_priv->ramfc_size;
- ret = init_heap(&dev_priv->ramin_heap,
- offset, dev_priv->ramin_size - offset);
+ ret = nouveau_mem_init_heap(&dev_priv->ramin_heap,
+ offset, dev_priv->ramin_size - offset);
if (ret) {
dev_priv->ramin_heap = NULL;
DRM_ERROR("Failed to init RAMIN heap\n");
@@ -570,7 +579,8 @@ struct mem_block *nouveau_instmem_alloc(struct drm_device *dev,
return NULL;
}
- block = alloc_block(dev_priv->ramin_heap, size, align, (DRMFILE)-2);
+ block = nouveau_mem_alloc_block(dev_priv->ramin_heap, size, align,
+ (DRMFILE)-2);
if (block) {
block->flags = NOUVEAU_MEM_INSTANCE;
DRM_DEBUG("instance(size=%d, align=%d) alloc'd at 0x%08x\n",
@@ -583,39 +593,7 @@ struct mem_block *nouveau_instmem_alloc(struct drm_device *dev,
void nouveau_instmem_free(struct drm_device *dev, struct mem_block *block)
{
if (dev && block) {
- free_block(block);
- }
-}
-
-uint32_t nouveau_instmem_r32(drm_nouveau_private_t *dev_priv,
- struct mem_block *mem, int index)
-{
- uint32_t ofs = (uint32_t)mem->start + (index<<2);
-
- if (dev_priv->ramin) {
-#if defined(__powerpc__)
- return in_be32((void __iomem *)(dev_priv->ramin)->handle + ofs);
-#else
- return DRM_READ32(dev_priv->ramin, ofs);
-#endif
- } else {
- return NV_READ(NV_RAMIN+ofs);
- }
-}
-
-void nouveau_instmem_w32(drm_nouveau_private_t *dev_priv,
- struct mem_block *mem, int index, uint32_t val)
-{
- uint32_t ofs = (uint32_t)mem->start + (index<<2);
-
- if (dev_priv->ramin) {
-#if defined(__powerpc__)
- out_be32((void __iomem *)(dev_priv->ramin)->handle + ofs, val);
-#else
- DRM_WRITE32(dev_priv->ramin, ofs, val);
-#endif
- } else {
- NV_WRITE(NV_RAMIN+ofs, val);
+ nouveau_mem_free_block(block);
}
}
diff --git a/shared-core/nouveau_notifier.c b/shared-core/nouveau_notifier.c
new file mode 100644
index 00000000..0cfe733e
--- /dev/null
+++ b/shared-core/nouveau_notifier.c
@@ -0,0 +1,154 @@
+/*
+ * 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"
+
+int
+nouveau_notifier_init_channel(drm_device_t *dev, int channel, DRMFILE filp)
+{
+ drm_nouveau_private_t *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)
+ flags = NOUVEAU_MEM_AGP | NOUVEAU_MEM_FB_ACCEPTABLE;
+ else
+ flags = NOUVEAU_MEM_FB;
+
+ chan->notifier_block = nouveau_mem_alloc(dev, 0, PAGE_SIZE, flags,filp);
+ if (!chan->notifier_block)
+ return DRM_ERR(ENOMEM);
+
+ ret = nouveau_mem_init_heap(&chan->notifier_heap,
+ 0, chan->notifier_block->size);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+void
+nouveau_notifier_takedown_channel(drm_device_t *dev, int channel)
+{
+ drm_nouveau_private_t *dev_priv = dev->dev_private;
+ struct nouveau_fifo *chan = &dev_priv->fifos[channel];
+
+ if (chan->notifier_block) {
+ nouveau_mem_free(dev, chan->notifier_block);
+ chan->notifier_block = NULL;
+ }
+
+ /*XXX: heap destroy */
+}
+
+int
+nouveau_notifier_alloc(drm_device_t *dev, int channel, uint32_t handle,
+ int count, uint32_t *b_offset)
+{
+ drm_nouveau_private_t *dev_priv = dev->dev_private;
+ struct nouveau_fifo *chan = &dev_priv->fifos[channel];
+ struct nouveau_object *obj;
+ struct mem_block *mem;
+ uint32_t offset;
+ int target;
+
+ if (!chan->notifier_heap) {
+ DRM_ERROR("Channel %d doesn't have a notifier heap!\n",
+ channel);
+ return DRM_ERR(EINVAL);
+ }
+
+ mem = nouveau_mem_alloc_block(chan->notifier_heap, 32, 0, chan->filp);
+ if (!mem) {
+ DRM_ERROR("Channel %d notifier block full\n", channel);
+ return DRM_ERR(ENOMEM);
+ }
+ mem->flags = NOUVEAU_MEM_NOTIFIER;
+
+ offset = chan->notifier_block->start + mem->start;
+ if (chan->notifier_block->flags & NOUVEAU_MEM_FB) {
+ offset -= drm_get_resource_start(dev, 1);
+ target = NV_DMA_TARGET_VIDMEM;
+ } else if (chan->notifier_block->flags & NOUVEAU_MEM_AGP) {
+ offset -= dev_priv->agp_phys;
+ target = NV_DMA_TARGET_AGP;
+ } else {
+ DRM_ERROR("Bad DMA target, flags 0x%08x!\n",
+ chan->notifier_block->flags);
+ return DRM_ERR(EINVAL);
+ }
+
+ obj = nouveau_object_dma_create(dev, channel, NV_CLASS_DMA_IN_MEMORY,
+ offset, mem->size, NV_DMA_ACCESS_RW,
+ target);
+ if (!obj) {
+ nouveau_mem_free_block(mem);
+ DRM_ERROR("Error creating notifier ctxdma\n");
+ return DRM_ERR(ENOMEM);
+ }
+
+ obj->handle = handle;
+ if (nouveau_ramht_insert(dev, channel, handle, obj)) {
+ nouveau_object_free(dev, obj);
+ nouveau_mem_free_block(mem);
+ DRM_ERROR("Error inserting notifier ctxdma into RAMHT\n");
+ return DRM_ERR(ENOMEM);
+ }
+
+ *b_offset = mem->start;
+ return 0;
+}
+
+int
+nouveau_ioctl_notifier_alloc(DRM_IOCTL_ARGS)
+{
+ DRM_DEVICE;
+ drm_nouveau_notifier_alloc_t na;
+ int ret;
+
+ DRM_COPY_FROM_USER_IOCTL(na, (drm_nouveau_notifier_alloc_t __user*)data,
+ sizeof(na));
+
+ if (!nouveau_fifo_owner(dev, filp, na.channel)) {
+ DRM_ERROR("pid %d doesn't own channel %d\n",
+ DRM_CURRENTPID, na.channel);
+ return DRM_ERR(EPERM);
+ }
+
+ ret = nouveau_notifier_alloc(dev, na.channel, na.handle,
+ na.count, &na.offset);
+ if (ret)
+ return ret;
+
+ DRM_COPY_TO_USER_IOCTL((drm_nouveau_notifier_alloc_t __user*)data,
+ na, sizeof(na));
+ return 0;
+}
+
diff --git a/shared-core/nouveau_object.c b/shared-core/nouveau_object.c
index ace7c2aa..dac08df4 100644
--- a/shared-core/nouveau_object.c
+++ b/shared-core/nouveau_object.c
@@ -139,7 +139,7 @@ nouveau_object_handle_find(drm_device_t *dev, int channel, uint32_t handle)
is given as:
*/
static uint32_t
-nouveau_ht_handle_hash(drm_device_t *dev, int channel, uint32_t handle)
+nouveau_ramht_hash_handle(drm_device_t *dev, int channel, uint32_t handle)
{
drm_nouveau_private_t *dev_priv=dev->dev_private;
uint32_t hash = 0;
@@ -154,62 +154,89 @@ nouveau_ht_handle_hash(drm_device_t *dev, int channel, uint32_t handle)
}
static int
-nouveau_ht_object_insert(drm_device_t* dev, int channel, uint32_t handle,
- struct nouveau_object *obj)
+nouveau_ramht_entry_valid(drm_device_t *dev, uint32_t ramht, uint32_t offset)
{
drm_nouveau_private_t *dev_priv=dev->dev_private;
- int ht_base = NV_RAMIN + dev_priv->ramht_offset;
- int ht_end = ht_base + dev_priv->ramht_size;
- int o_ofs, ofs;
-
- obj->handle = handle;
- o_ofs = ofs = nouveau_ht_handle_hash(dev, channel, obj->handle);
-
- while (NV_READ(ht_base + ofs) || NV_READ(ht_base + ofs + 4)) {
- ofs += 8;
- if (ofs == ht_end) ofs = ht_base;
- if (ofs == o_ofs) {
- DRM_ERROR("no free hash table entries\n");
- return 1;
- }
+ uint32_t ctx = NV_RI32(ramht + offset + 4);
+
+ if (dev_priv->card_type < NV_40)
+ return ((ctx & NV_RAMHT_CONTEXT_VALID) != 0);
+ return (ctx != 0);
+}
+
+int
+nouveau_ramht_insert(drm_device_t* dev, int channel, uint32_t handle,
+ struct nouveau_object *obj)
+{
+ drm_nouveau_private_t *dev_priv=dev->dev_private;
+ uint32_t ramht = dev_priv->ramht_offset;
+ uint32_t ctx, co, ho;
+ uint32_t inst;
+
+ inst = nouveau_chip_instance_get(dev, obj->instance);
+ if (dev_priv->card_type < NV_40) {
+ ctx = NV_RAMHT_CONTEXT_VALID | inst |
+ (channel << NV_RAMHT_CONTEXT_CHANNEL_SHIFT) |
+ (obj->engine << NV_RAMHT_CONTEXT_ENGINE_SHIFT);
+ } else
+ if (dev_priv->card_type < NV_50) {
+ ctx = inst |
+ (channel << NV40_RAMHT_CONTEXT_CHANNEL_SHIFT) |
+ (obj->engine << NV40_RAMHT_CONTEXT_ENGINE_SHIFT);
+ } else {
+ ctx = inst |
+ (obj->engine << NV40_RAMHT_CONTEXT_ENGINE_SHIFT);
}
- ofs += ht_base;
-
- DRM_DEBUG("Channel %d - Handle 0x%08x at 0x%08x\n",
- channel, obj->handle, ofs);
-
- NV_WRITE(NV_RAMHT_HANDLE_OFFSET + ofs, obj->handle);
- if (dev_priv->card_type >= NV_40)
- NV_WRITE(NV_RAMHT_CONTEXT_OFFSET + ofs,
- (channel << NV40_RAMHT_CONTEXT_CHANNEL_SHIFT) |
- (obj->engine << NV40_RAMHT_CONTEXT_ENGINE_SHIFT) |
- nouveau_chip_instance_get(dev, obj->instance)
- );
- else
- NV_WRITE(NV_RAMHT_CONTEXT_OFFSET + ofs,
- NV_RAMHT_CONTEXT_VALID |
- (channel << NV_RAMHT_CONTEXT_CHANNEL_SHIFT) |
- (obj->engine << NV_RAMHT_CONTEXT_ENGINE_SHIFT) |
- nouveau_chip_instance_get(dev, obj->instance)
- );
-
- obj->ht_loc = ofs;
- return 0;
+
+ co = ho = nouveau_ramht_hash_handle(dev, channel, handle);
+ do {
+ if (!nouveau_ramht_entry_valid(dev, ramht, co)) {
+ DRM_DEBUG("insert ch%d 0x%08x: h=0x%08x, c=0x%08x\n",
+ channel, co, handle, ctx);
+ NV_WI32(ramht + co + 0, handle);
+ NV_WI32(ramht + co + 4, ctx);
+ obj->handle = handle;
+ return 0;
+ }
+ DRM_DEBUG("collision ch%d 0x%08x: h=0x%08x\n",
+ channel, co, NV_RI32(ramht + co));
+
+ co += 8;
+ if (co == dev_priv->ramht_size)
+ co = 0;
+ } while (co != ho);
+
+ DRM_ERROR("RAMHT space exhausted. ch=%d\n", channel);
+ return DRM_ERR(ENOMEM);
}
-static void nouveau_hash_table_remove(drm_device_t* dev,
- struct nouveau_object *obj)
+static void
+nouveau_ramht_remove(drm_device_t* dev, struct nouveau_object *obj)
{
drm_nouveau_private_t *dev_priv = dev->dev_private;
+ uint32_t ramht = dev_priv->ramht_offset;
+ uint32_t co, ho;
+
+ co = ho = nouveau_ramht_hash_handle(dev, obj->channel, obj->handle);
+ do {
+ if (nouveau_ramht_entry_valid(dev, ramht, co) &&
+ (obj->handle == NV_RI32(ramht + co))) {
+ DRM_DEBUG("remove ch%d 0x%08x: h=0x%08x, c=0x%08x\n",
+ obj->channel, co, obj->handle,
+ NV_RI32(ramht + co + 4));
+ NV_WI32(ramht + co + 0, 0x00000000);
+ NV_WI32(ramht + co + 4, 0x00000000);
+ obj->handle = ~0;
+ return;
+ }
- DRM_DEBUG("Remove handle 0x%08x at 0x%08x from HT\n",
- obj->handle, obj->ht_loc);
- if (obj->ht_loc) {
- DRM_DEBUG("... HT entry was: 0x%08x/0x%08x\n",
- NV_READ(obj->ht_loc), NV_READ(obj->ht_loc+4));
- NV_WRITE(obj->ht_loc , 0x00000000);
- NV_WRITE(obj->ht_loc+4, 0x00000000);
- }
+ co += 8;
+ if (co == dev_priv->ramht_size)
+ co = 0;
+ } while (co != ho);
+
+ DRM_ERROR("RAMHT entry not found. ch=%d, handle=0x%08x\n",
+ obj->channel, obj->handle);
}
static struct nouveau_object *
@@ -457,119 +484,74 @@ nouveau_object_free(drm_device_t *dev, struct nouveau_object *obj)
{
nouveau_object_instance_free(dev, obj);
if (obj->handle != ~0)
- nouveau_hash_table_remove(dev, obj);
+ nouveau_ramht_remove(dev, obj);
drm_free(obj, sizeof(struct nouveau_object), DRM_MEM_DRIVER);
}
-void nouveau_object_cleanup(drm_device_t *dev, int channel)
-{
- drm_nouveau_private_t *dev_priv=dev->dev_private;
-
- while (dev_priv->fifos[channel].objs) {
- nouveau_object_free(dev, dev_priv->fifos[channel].objs);
- }
-}
-
-int nouveau_ioctl_object_init(DRM_IOCTL_ARGS)
+int
+nouveau_object_init_channel(drm_device_t *dev, int channel,
+ uint32_t vram_handle,
+ uint32_t tt_handle)
{
- DRM_DEVICE;
- drm_nouveau_object_init_t init;
- struct nouveau_object *obj;
-
- DRM_COPY_FROM_USER_IOCTL(init, (drm_nouveau_object_init_t __user *)
- data, sizeof(init));
-
- if (!nouveau_fifo_owner(dev, filp, init.channel)) {
- DRM_ERROR("pid %d doesn't own channel %d\n",
- DRM_CURRENTPID, init.channel);
- return DRM_ERR(EINVAL);
+ drm_nouveau_private_t *dev_priv = dev->dev_private;
+ struct nouveau_object *gpuobj;
+ int ret;
+
+ /* VRAM ctxdma */
+ gpuobj = nouveau_object_dma_create(dev, channel, NV_CLASS_DMA_IN_MEMORY,
+ 0, dev_priv->fb_available_size,
+ NV_DMA_ACCESS_RW,
+ NV_DMA_TARGET_VIDMEM);
+ if (!gpuobj) {
+ DRM_ERROR("Error creating VRAM ctxdma: %d\n", DRM_ERR(ENOMEM));
+ return DRM_ERR(ENOMEM);
}
- //FIXME: check args, only allow trusted objects to be created
-
- if (nouveau_object_handle_find(dev, init.channel, init.handle)) {
- DRM_ERROR("Channel %d: handle 0x%08x already exists\n",
- init.channel, init.handle);
- return DRM_ERR(EINVAL);
+ ret = nouveau_ramht_insert(dev, channel, vram_handle, gpuobj);
+ if (ret) {
+ DRM_ERROR("Error referencing VRAM ctxdma: %d\n", ret);
+ return ret;
}
- obj = nouveau_object_gr_create(dev, init.channel, init.class);
- if (!obj)
+ /* non-AGP unimplemented */
+ if (dev_priv->agp_heap == NULL)
+ return 0;
+
+ /* GART ctxdma */
+ gpuobj = nouveau_object_dma_create(dev, channel, NV_CLASS_DMA_IN_MEMORY,
+ 0, dev_priv->agp_available_size,
+ NV_DMA_ACCESS_RW,
+ NV_DMA_TARGET_AGP);
+ if (!gpuobj) {
+ DRM_ERROR("Error creating TT ctxdma: %d\n", DRM_ERR(ENOMEM));
return DRM_ERR(ENOMEM);
+ }
- if (nouveau_ht_object_insert(dev, init.channel, init.handle, obj)) {
- nouveau_object_free(dev, obj);
- return DRM_ERR(ENOMEM);
+ ret = nouveau_ramht_insert(dev, channel, tt_handle, gpuobj);
+ if (ret) {
+ DRM_ERROR("Error referencing TT ctxdma: %d\n", ret);
+ return ret;
}
return 0;
}
-static int
-nouveau_dma_object_check_access(drm_device_t *dev,
- drm_nouveau_dma_object_init_t *init)
+void nouveau_object_cleanup(drm_device_t *dev, int channel)
{
- drm_nouveau_private_t *dev_priv = dev->dev_private;
- uint64_t limit;
-
- /* Check for known DMA object classes */
- switch (init->class) {
- case NV_CLASS_DMA_IN_MEMORY:
- case NV_CLASS_DMA_FROM_MEMORY:
- case NV_CLASS_DMA_TO_MEMORY:
- break;
- default:
- DRM_ERROR("invalid class = 0x%x\n", init->class);
- return DRM_ERR(EPERM);
- }
-
- /* Check access mode, and translate to NV_DMA_ACCESS_* */
- switch (init->access) {
- case NOUVEAU_MEM_ACCESS_RO:
- init->access = NV_DMA_ACCESS_RO;
- break;
- case NOUVEAU_MEM_ACCESS_WO:
- init->access = NV_DMA_ACCESS_WO;
- break;
- case NOUVEAU_MEM_ACCESS_RW:
- init->access = NV_DMA_ACCESS_RW;
- break;
- default:
- DRM_ERROR("invalid access mode = %d\n", init->access);
- return DRM_ERR(EPERM);
- }
-
- /* Check that request is within the allowed limits of "target" */
- switch (init->target) {
- case NOUVEAU_MEM_FB:
- limit = dev_priv->fb_available_size;
- init->target = NV_DMA_TARGET_VIDMEM;
- break;
- case NOUVEAU_MEM_AGP:
- limit = dev_priv->agp_available_size;
- init->target = NV_DMA_TARGET_AGP;
- break;
- default:
- DRM_ERROR("invalid target = 0x%x\n", init->target);
- return DRM_ERR(EPERM);
- }
+ drm_nouveau_private_t *dev_priv=dev->dev_private;
- if ((init->offset > limit) || (init->offset + init->size) > limit) {
- DRM_ERROR("access out of allowed range (%d,0x%08x,0x%08x)\n",
- init->target, init->offset, init->size);
- return DRM_ERR(EPERM);
+ while (dev_priv->fifos[channel].objs) {
+ nouveau_object_free(dev, dev_priv->fifos[channel].objs);
}
-
- return 0;
}
-int nouveau_ioctl_dma_object_init(DRM_IOCTL_ARGS)
+int nouveau_ioctl_grobj_alloc(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
- drm_nouveau_dma_object_init_t init;
+ drm_nouveau_grobj_alloc_t init;
struct nouveau_object *obj;
- DRM_COPY_FROM_USER_IOCTL(init, (drm_nouveau_dma_object_init_t __user *)
+ DRM_COPY_FROM_USER_IOCTL(init, (drm_nouveau_grobj_alloc_t __user *)
data, sizeof(init));
if (!nouveau_fifo_owner(dev, filp, init.channel)) {
@@ -578,8 +560,7 @@ int nouveau_ioctl_dma_object_init(DRM_IOCTL_ARGS)
return DRM_ERR(EINVAL);
}
- if (nouveau_dma_object_check_access(dev, &init))
- return DRM_ERR(EPERM);
+ //FIXME: check args, only allow trusted objects to be created
if (nouveau_object_handle_find(dev, init.channel, init.handle)) {
DRM_ERROR("Channel %d: handle 0x%08x already exists\n",
@@ -587,14 +568,11 @@ int nouveau_ioctl_dma_object_init(DRM_IOCTL_ARGS)
return DRM_ERR(EINVAL);
}
- obj = nouveau_object_dma_create(dev, init.channel, init.class,
- init.offset, init.size,
- init.access, init.target);
+ obj = nouveau_object_gr_create(dev, init.channel, init.class);
if (!obj)
return DRM_ERR(ENOMEM);
- obj->handle = init.handle;
- if (nouveau_ht_object_insert(dev, init.channel, init.handle, obj)) {
+ if (nouveau_ramht_insert(dev, init.channel, init.handle, obj)) {
nouveau_object_free(dev, obj);
return DRM_ERR(ENOMEM);
}
diff --git a/shared-core/nouveau_reg.h b/shared-core/nouveau_reg.h
index ea4a2f6b..4c013c53 100644
--- a/shared-core/nouveau_reg.h
+++ b/shared-core/nouveau_reg.h
@@ -135,6 +135,17 @@
#define NV10_PGRAPH_CTX_CACHE4 0x004001C0
#define NV04_PGRAPH_CTX_CACHE4 0x004001E0
#define NV10_PGRAPH_CTX_CACHE5 0x004001E0
+#define NV40_PGRAPH_CTXCTL_0304 0x00400304
+#define NV40_PGRAPH_CTXCTL_0304_XFER_CTX 0x00000001
+#define NV40_PGRAPH_CTXCTL_0310 0x00400310
+#define NV40_PGRAPH_CTXCTL_0310_XFER_SAVE 0x00000020
+#define NV40_PGRAPH_CTXCTL_0310_XFER_LOAD 0x00000040
+#define NV40_PGRAPH_CTXCTL_030C 0x0040030c
+#define NV40_PGRAPH_CTXCTL_UCODE_INDEX 0x00400324
+#define NV40_PGRAPH_CTXCTL_UCODE_DATA 0x00400328
+#define NV40_PGRAPH_CTXCTL_CUR 0x0040032c
+#define NV40_PGRAPH_CTXCTL_CUR_LOADED 0x01000000
+#define NV40_PGRAPH_CTXCTL_CUR_INST_MASK 0x000FFFFF
#define NV03_PGRAPH_ABS_X_RAM 0x00400400
#define NV03_PGRAPH_ABS_Y_RAM 0x00400480
#define NV03_PGRAPH_X_MISC 0x00400500
@@ -230,7 +241,11 @@
#define NV10_PGRAPH_SCALED_FORMAT 0x00400778
#define NV10_PGRAPH_CHANNEL_CTX_TABLE 0x00400780
#define NV10_PGRAPH_CHANNEL_CTX_SIZE 0x00400784
+#define NV20_PGRAPH_CHANNEL_CTX_POINTER 0x00400784
#define NV10_PGRAPH_CHANNEL_CTX_POINTER 0x00400788
+#define NV20_PGRAPH_CHANNEL_CTX_XFER 0x00400788
+#define NV20_PGRAPH_CHANNEL_CTX_XFER_LOAD 0x00000001
+#define NV20_PGRAPH_CHANNEL_CTX_XFER_SAVE 0x00000002
#define NV04_PGRAPH_PATT_COLOR0 0x00400800
#define NV04_PGRAPH_PATT_COLOR1 0x00400804
#define NV04_PGRAPH_PATTERN 0x00400808
@@ -404,7 +419,7 @@
#define NV10_PFIFO_CACHE1_SEMAPHORE 0x0000326C
#define NV03_PFIFO_CACHE1_GET 0x00003270
#define NV04_PFIFO_CACHE1_ENGINE 0x00003280
-#define NV10_PFIFO_CACHE1_DMA_DCOUNT 0x000032A0
+#define NV04_PFIFO_CACHE1_DMA_DCOUNT 0x000032A0
#define NV40_PFIFO_GRCTX_INSTANCE 0x000032E0
#define NV40_PFIFO_UNK32E4 0x000032E4
#define NV04_PFIFO_CACHE1_METHOD(i) (0x00003800+(i*8))
@@ -427,7 +442,10 @@
#define NV04_RAMFC_DMA_PUT 0x00
#define NV04_RAMFC_DMA_GET 0x04
#define NV04_RAMFC_DMA_INSTANCE 0x08
+#define NV04_RAMFC_DMA_STATE 0x0C
#define NV04_RAMFC_DMA_FETCH 0x10
+#define NV04_RAMFC_ENGINE 0x14
+#define NV04_RAMFC_PULL1_ENGINE 0x18
#define NV10_RAMFC_DMA_PUT 0x00
#define NV10_RAMFC_DMA_GET 0x04
@@ -462,6 +480,6 @@
#define NV40_RAMFC_UNK_40 0x40
#define NV40_RAMFC_UNK_44 0x44
#define NV40_RAMFC_UNK_48 0x48
-#define NV40_RAMFC_2088 0x4C
-#define NV40_RAMFC_3300 0x50
+#define NV40_RAMFC_UNK_4C 0x4C
+#define NV40_RAMFC_UNK_50 0x50
diff --git a/shared-core/nouveau_state.c b/shared-core/nouveau_state.c
index e7930b9e..fa773d28 100644
--- a/shared-core/nouveau_state.c
+++ b/shared-core/nouveau_state.c
@@ -51,6 +51,7 @@ static int nouveau_init_card_mappings(drm_device_t *dev)
DRM_DEBUG("regs mapped ok at 0x%lx\n", dev_priv->mmio->offset);
/* map larger RAMIN aperture on NV40 cards */
+ dev_priv->ramin = NULL;
if (dev_priv->card_type >= NV_40) {
int ramin_resource = 2;
if (drm_get_resource_len(dev, ramin_resource) == 0)
@@ -66,12 +67,26 @@ static int nouveau_init_card_mappings(drm_device_t *dev)
"limited instance memory available\n");
dev_priv->ramin = NULL;
}
- } else
- dev_priv->ramin = NULL;
+ }
+
+ /* On older cards (or if the above failed), create a map covering
+ * the BAR0 PRAMIN aperture */
+ if (!dev_priv->ramin) {
+ ret = drm_addmap(dev,
+ drm_get_resource_start(dev, 0) + NV_RAMIN,
+ (1*1024*1024),
+ _DRM_REGISTERS, _DRM_READ_ONLY,
+ &dev_priv->ramin);
+ if (ret) {
+ DRM_ERROR("Failed to map BAR0 PRAMIN: %d\n", ret);
+ return ret;
+ }
+ }
return 0;
}
+static int nouveau_stub_init(drm_device_t *dev) { return 0; }
static void nouveau_stub_takedown(drm_device_t *dev) {}
static int nouveau_init_engine_ptrs(drm_device_t *dev)
{
@@ -80,66 +95,126 @@ static int nouveau_init_engine_ptrs(drm_device_t *dev)
switch (dev_priv->chipset & 0xf0) {
case 0x00:
- engine->Mc.Init = nv04_mc_init;
- engine->Mc.Takedown = nv04_mc_takedown;
- engine->Timer.Init = nv04_timer_init;
- engine->Timer.Takedown = nv04_timer_takedown;
- engine->Fb.Init = nv04_fb_init;
- engine->Fb.Takedown = nv04_fb_takedown;
- engine->Graph.Init = nv04_graph_init;
- engine->Graph.Takedown = nv04_graph_takedown;
- engine->Fifo.Init = nouveau_fifo_init;
- engine->Fifo.Takedown = nouveau_stub_takedown;
+ engine->mc.init = nv04_mc_init;
+ engine->mc.takedown = nv04_mc_takedown;
+ engine->timer.init = nv04_timer_init;
+ engine->timer.takedown = nv04_timer_takedown;
+ engine->fb.init = nv04_fb_init;
+ engine->fb.takedown = nv04_fb_takedown;
+ engine->graph.init = nv04_graph_init;
+ engine->graph.takedown = nv04_graph_takedown;
+ engine->graph.create_context = nv04_graph_create_context;
+ engine->graph.destroy_context = nv04_graph_destroy_context;
+ engine->graph.load_context = nv04_graph_load_context;
+ engine->graph.save_context = nv04_graph_save_context;
+ engine->fifo.init = nouveau_fifo_init;
+ engine->fifo.takedown = nouveau_stub_takedown;
+ engine->fifo.create_context = nv04_fifo_create_context;
+ engine->fifo.destroy_context = nv04_fifo_destroy_context;
+ engine->fifo.load_context = nv04_fifo_load_context;
+ engine->fifo.save_context = nv04_fifo_save_context;
break;
case 0x10:
- engine->Mc.Init = nv04_mc_init;
- engine->Mc.Takedown = nv04_mc_takedown;
- engine->Timer.Init = nv04_timer_init;
- engine->Timer.Takedown = nv04_timer_takedown;
- engine->Fb.Init = nv10_fb_init;
- engine->Fb.Takedown = nv10_fb_takedown;
- engine->Graph.Init = nv10_graph_init;
- engine->Graph.Takedown = nv10_graph_takedown;
- engine->Fifo.Init = nouveau_fifo_init;
- engine->Fifo.Takedown = nouveau_stub_takedown;
+ engine->mc.init = nv04_mc_init;
+ engine->mc.takedown = nv04_mc_takedown;
+ engine->timer.init = nv04_timer_init;
+ engine->timer.takedown = nv04_timer_takedown;
+ engine->fb.init = nv10_fb_init;
+ engine->fb.takedown = nv10_fb_takedown;
+ engine->graph.init = nv10_graph_init;
+ engine->graph.takedown = nv10_graph_takedown;
+ engine->graph.create_context = nv10_graph_create_context;
+ engine->graph.destroy_context = nv10_graph_destroy_context;
+ engine->graph.load_context = nv10_graph_load_context;
+ engine->graph.save_context = nv10_graph_save_context;
+ engine->fifo.init = nouveau_fifo_init;
+ engine->fifo.takedown = nouveau_stub_takedown;
+ engine->fifo.create_context = nv10_fifo_create_context;
+ engine->fifo.destroy_context = nv10_fifo_destroy_context;
+ engine->fifo.load_context = nv10_fifo_load_context;
+ engine->fifo.save_context = nv10_fifo_save_context;
break;
case 0x20:
- engine->Mc.Init = nv04_mc_init;
- engine->Mc.Takedown = nv04_mc_takedown;
- engine->Timer.Init = nv04_timer_init;
- engine->Timer.Takedown = nv04_timer_takedown;
- engine->Fb.Init = nv10_fb_init;
- engine->Fb.Takedown = nv10_fb_takedown;
- engine->Graph.Init = nv20_graph_init;
- engine->Graph.Takedown = nv20_graph_takedown;
- engine->Fifo.Init = nouveau_fifo_init;
- engine->Fifo.Takedown = nouveau_stub_takedown;
+ engine->mc.init = nv04_mc_init;
+ engine->mc.takedown = nv04_mc_takedown;
+ engine->timer.init = nv04_timer_init;
+ engine->timer.takedown = nv04_timer_takedown;
+ engine->fb.init = nv10_fb_init;
+ engine->fb.takedown = nv10_fb_takedown;
+ engine->graph.init = nv20_graph_init;
+ engine->graph.takedown = nv20_graph_takedown;
+ engine->graph.create_context = nv20_graph_create_context;
+ engine->graph.destroy_context = nv20_graph_destroy_context;
+ engine->graph.load_context = nv20_graph_load_context;
+ engine->graph.save_context = nv20_graph_save_context;
+ engine->fifo.init = nouveau_fifo_init;
+ engine->fifo.takedown = nouveau_stub_takedown;
+ engine->fifo.create_context = nv10_fifo_create_context;
+ engine->fifo.destroy_context = nv10_fifo_destroy_context;
+ engine->fifo.load_context = nv10_fifo_load_context;
+ engine->fifo.save_context = nv10_fifo_save_context;
break;
case 0x30:
- engine->Mc.Init = nv04_mc_init;
- engine->Mc.Takedown = nv04_mc_takedown;
- engine->Timer.Init = nv04_timer_init;
- engine->Timer.Takedown = nv04_timer_takedown;
- engine->Fb.Init = nv10_fb_init;
- engine->Fb.Takedown = nv10_fb_takedown;
- engine->Graph.Init = nv30_graph_init;
- engine->Graph.Takedown = nv30_graph_takedown;
- engine->Fifo.Init = nouveau_fifo_init;
- engine->Fifo.Takedown = nouveau_stub_takedown;
+ engine->mc.init = nv04_mc_init;
+ engine->mc.takedown = nv04_mc_takedown;
+ engine->timer.init = nv04_timer_init;
+ engine->timer.takedown = nv04_timer_takedown;
+ engine->fb.init = nv10_fb_init;
+ engine->fb.takedown = nv10_fb_takedown;
+ engine->graph.init = nv30_graph_init;
+ engine->graph.takedown = nv30_graph_takedown;
+ engine->graph.create_context = nv30_graph_create_context;
+ engine->graph.destroy_context = nv30_graph_destroy_context;
+ engine->graph.load_context = nv30_graph_load_context;
+ engine->graph.save_context = nv30_graph_save_context;
+ engine->fifo.init = nouveau_fifo_init;
+ engine->fifo.takedown = nouveau_stub_takedown;
+ engine->fifo.create_context = nv10_fifo_create_context;
+ engine->fifo.destroy_context = nv10_fifo_destroy_context;
+ engine->fifo.load_context = nv10_fifo_load_context;
+ engine->fifo.save_context = nv10_fifo_save_context;
break;
case 0x40:
- engine->Mc.Init = nv40_mc_init;
- engine->Mc.Takedown = nv40_mc_takedown;
- engine->Timer.Init = nv04_timer_init;
- engine->Timer.Takedown = nv04_timer_takedown;
- engine->Fb.Init = nv40_fb_init;
- engine->Fb.Takedown = nv40_fb_takedown;
- engine->Graph.Init = nv40_graph_init;
- engine->Graph.Takedown = nv40_graph_takedown;
- engine->Fifo.Init = nouveau_fifo_init;
- engine->Fifo.Takedown = nouveau_stub_takedown;
+ engine->mc.init = nv40_mc_init;
+ engine->mc.takedown = nv40_mc_takedown;
+ engine->timer.init = nv04_timer_init;
+ engine->timer.takedown = nv04_timer_takedown;
+ engine->fb.init = nv40_fb_init;
+ engine->fb.takedown = nv40_fb_takedown;
+ engine->graph.init = nv40_graph_init;
+ engine->graph.takedown = nv40_graph_takedown;
+ engine->graph.create_context = nv40_graph_create_context;
+ 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.takedown = nouveau_stub_takedown;
+ engine->fifo.create_context = nv40_fifo_create_context;
+ engine->fifo.destroy_context = nv40_fifo_destroy_context;
+ engine->fifo.load_context = nv40_fifo_load_context;
+ engine->fifo.save_context = nv40_fifo_save_context;
break;
case 0x50:
+ case 0x80: /* gotta love NVIDIA's consistency.. */
+ engine->mc.init = nv50_mc_init;
+ engine->mc.takedown = nv50_mc_takedown;
+ engine->timer.init = nouveau_stub_init;
+ engine->timer.takedown = nouveau_stub_takedown;
+ engine->fb.init = nouveau_stub_init;
+ engine->fb.takedown = nouveau_stub_takedown;
+ engine->graph.init = nv50_graph_init;
+ engine->graph.takedown = nv50_graph_takedown;
+ engine->graph.create_context = nv50_graph_create_context;
+ engine->graph.destroy_context = nv50_graph_destroy_context;
+ engine->graph.load_context = nv50_graph_load_context;
+ engine->graph.save_context = nv50_graph_save_context;
+ engine->fifo.init = nv50_fifo_init;
+ engine->fifo.takedown = nv50_fifo_takedown;
+ engine->fifo.create_context = nv50_fifo_create_context;
+ engine->fifo.destroy_context = nv50_fifo_destroy_context;
+ engine->fifo.load_context = nv50_fifo_load_context;
+ engine->fifo.save_context = nv50_fifo_save_context;
+ break;
default:
DRM_ERROR("NV%02x unsupported\n", dev_priv->chipset);
return 1;
@@ -184,23 +259,23 @@ static int nouveau_card_init(drm_device_t *dev)
/* Parse BIOS tables / Run init tables? */
/* PMC */
- ret = engine->Mc.Init(dev);
+ ret = engine->mc.init(dev);
if (ret) return ret;
/* PTIMER */
- ret = engine->Timer.Init(dev);
+ ret = engine->timer.init(dev);
if (ret) return ret;
/* PFB */
- ret = engine->Fb.Init(dev);
+ ret = engine->fb.init(dev);
if (ret) return ret;
/* PGRAPH */
- ret = engine->Graph.Init(dev);
+ ret = engine->graph.init(dev);
if (ret) return ret;
/* PFIFO */
- ret = engine->Fifo.Init(dev);
+ ret = engine->fifo.init(dev);
if (ret) return ret;
/* what about PVIDEO/PCRTC/PRAMDAC etc? */
@@ -213,9 +288,9 @@ void nouveau_preclose(drm_device_t * dev, DRMFILE filp)
{
drm_nouveau_private_t *dev_priv = dev->dev_private;
+ nouveau_fifo_cleanup(dev, filp);
nouveau_mem_release(filp,dev_priv->fb_heap);
nouveau_mem_release(filp,dev_priv->agp_heap);
- nouveau_fifo_cleanup(dev, filp);
}
/* first module load, setup the mmio/fb mapping */
@@ -235,7 +310,6 @@ int nouveau_firstopen(struct drm_device *dev)
int nouveau_load(struct drm_device *dev, unsigned long flags)
{
drm_nouveau_private_t *dev_priv;
- int ret;
if (flags==NV_UNKNOWN)
return DRM_ERR(EINVAL);
diff --git a/shared-core/nv04_fifo.c b/shared-core/nv04_fifo.c
new file mode 100644
index 00000000..bfae432e
--- /dev/null
+++ b/shared-core/nv04_fifo.c
@@ -0,0 +1,126 @@
+/*
+ * 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"
+
+#define RAMFC_WR(offset, val) NV_WI32(fifoctx + NV04_RAMFC_##offset, (val))
+#define RAMFC_RD(offset) NV_RI32(fifoctx + NV04_RAMFC_##offset)
+#define NV04_RAMFC(c) (dev_priv->ramfc_offset + ((c) * NV04_RAMFC__SIZE))
+#define NV04_RAMFC__SIZE 32
+
+int
+nv04_fifo_create_context(drm_device_t *dev, int channel)
+{
+ drm_nouveau_private_t *dev_priv = dev->dev_private;
+ struct nouveau_fifo *chan = &dev_priv->fifos[channel];
+ struct nouveau_object *pb = chan->cmdbuf_obj;
+ uint32_t fifoctx = NV04_RAMFC(channel);
+ int i;
+
+ if (!pb || !pb->instance)
+ return DRM_ERR(EINVAL);
+
+ /* Clear RAMFC */
+ for (i=0; i<NV04_RAMFC__SIZE; i+=4)
+ NV_WI32(fifoctx + i, 0);
+
+ /* Setup initial state */
+ RAMFC_WR(DMA_PUT, chan->pushbuf_base);
+ RAMFC_WR(DMA_GET, chan->pushbuf_base);
+ RAMFC_WR(DMA_INSTANCE, nouveau_chip_instance_get(dev, pb->instance));
+ RAMFC_WR(DMA_FETCH, (NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES |
+ NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES |
+ NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8 |
+#ifdef __BIG_ENDIAN
+ NV_PFIFO_CACHE1_BIG_ENDIAN |
+#endif
+ 0));
+ return 0;
+}
+
+void
+nv04_fifo_destroy_context(drm_device_t *dev, int channel)
+{
+ drm_nouveau_private_t *dev_priv = dev->dev_private;
+ uint32_t fifoctx = NV04_RAMFC(channel);
+ int i;
+
+ for (i=0; i<NV04_RAMFC__SIZE; i+=4)
+ NV_WI32(fifoctx + i, 0);
+}
+
+int
+nv04_fifo_load_context(drm_device_t *dev, int channel)
+{
+ drm_nouveau_private_t *dev_priv = dev->dev_private;
+ uint32_t fifoctx = NV04_RAMFC(channel);
+ uint32_t tmp;
+
+ NV_WRITE(NV03_PFIFO_CACHE1_PUSH1, (1<<8) | channel);
+
+ NV_WRITE(NV04_PFIFO_CACHE1_DMA_GET, RAMFC_RD(DMA_GET));
+ NV_WRITE(NV04_PFIFO_CACHE1_DMA_PUT, RAMFC_RD(DMA_PUT));
+
+ tmp = RAMFC_RD(DMA_INSTANCE);
+ NV_WRITE(NV04_PFIFO_CACHE1_DMA_INSTANCE, tmp & 0xFFFF);
+ NV_WRITE(NV04_PFIFO_CACHE1_DMA_DCOUNT, tmp >> 16);
+
+ NV_WRITE(NV04_PFIFO_CACHE1_DMA_STATE, RAMFC_RD(DMA_STATE));
+ NV_WRITE(NV04_PFIFO_CACHE1_DMA_FETCH, RAMFC_RD(DMA_FETCH));
+ NV_WRITE(NV04_PFIFO_CACHE1_ENGINE, RAMFC_RD(ENGINE));
+ NV_WRITE(NV04_PFIFO_CACHE1_PULL1, RAMFC_RD(PULL1_ENGINE));
+
+ /* Reset NV04_PFIFO_CACHE1_DMA_CTL_AT_INFO to INVALID */
+ tmp = NV_READ(NV04_PFIFO_CACHE1_DMA_CTL) & ~(1<<31);
+ NV_WRITE(NV04_PFIFO_CACHE1_DMA_CTL, tmp);
+
+ return 0;
+}
+
+int
+nv04_fifo_save_context(drm_device_t *dev, int channel)
+{
+ drm_nouveau_private_t *dev_priv = dev->dev_private;
+ uint32_t fifoctx = NV04_RAMFC(channel);
+ uint32_t tmp;
+
+ RAMFC_WR(DMA_PUT, NV04_PFIFO_CACHE1_DMA_PUT);
+ RAMFC_WR(DMA_GET, NV04_PFIFO_CACHE1_DMA_GET);
+
+ tmp = NV_READ(NV04_PFIFO_CACHE1_DMA_DCOUNT) << 16;
+ tmp |= NV_READ(NV04_PFIFO_CACHE1_DMA_INSTANCE);
+ RAMFC_WR(DMA_INSTANCE, tmp);
+
+ RAMFC_WR(DMA_STATE, NV_READ(NV04_PFIFO_CACHE1_DMA_STATE));
+ RAMFC_WR(DMA_FETCH, NV_READ(NV04_PFIFO_CACHE1_DMA_FETCH));
+ RAMFC_WR(ENGINE, NV_READ(NV04_PFIFO_CACHE1_ENGINE));
+ RAMFC_WR(PULL1_ENGINE, NV_READ(NV04_PFIFO_CACHE1_PULL1));
+
+ return 0;
+}
+
diff --git a/shared-core/nv04_graph.c b/shared-core/nv04_graph.c
index 0cd4d3b8..1aaae33c 100644
--- a/shared-core/nv04_graph.c
+++ b/shared-core/nv04_graph.c
@@ -336,7 +336,7 @@ void nouveau_nv04_context_switch(drm_device_t *dev)
NV_WRITE(NV04_PGRAPH_FIFO,0x1);
}
-int nv04_graph_context_create(drm_device_t *dev, int channel) {
+int nv04_graph_create_context(drm_device_t *dev, int channel) {
drm_nouveau_private_t *dev_priv = dev->dev_private;
DRM_DEBUG("nv04_graph_context_create %d\n", channel);
@@ -351,6 +351,21 @@ int nv04_graph_context_create(drm_device_t *dev, int channel) {
return 0;
}
+void nv04_graph_destroy_context(drm_device_t *dev, int channel)
+{
+}
+
+int nv04_graph_load_context(drm_device_t *dev, int channel)
+{
+ DRM_ERROR("stub!\n");
+ return 0;
+}
+
+int nv04_graph_save_context(drm_device_t *dev, int channel)
+{
+ DRM_ERROR("stub!\n");
+ return 0;
+}
int nv04_graph_init(drm_device_t *dev) {
drm_nouveau_private_t *dev_priv = dev->dev_private;
diff --git a/shared-core/nv10_fifo.c b/shared-core/nv10_fifo.c
new file mode 100644
index 00000000..b84971de
--- /dev/null
+++ b/shared-core/nv10_fifo.c
@@ -0,0 +1,154 @@
+/*
+ * 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"
+
+#define RAMFC_WR(offset, val) NV_WI32(fifoctx + NV10_RAMFC_##offset, (val))
+#define RAMFC_RD(offset) NV_RI32(fifoctx + NV10_RAMFC_##offset)
+#define NV10_RAMFC(c) (dev_priv->ramfc_offset + NV10_RAMFC__SIZE)
+#define NV10_RAMFC__SIZE ((dev_priv->chipset) >= 0x17 ? 64 : 32)
+
+int
+nv10_fifo_create_context(drm_device_t *dev, int channel)
+{
+ drm_nouveau_private_t *dev_priv = dev->dev_private;
+ struct nouveau_fifo *chan = &dev_priv->fifos[channel];
+ uint32_t fifoctx = NV10_RAMFC(channel), pushbuf;
+ int i;
+
+ pushbuf = nouveau_chip_instance_get(dev, chan->cmdbuf_obj->instance);
+
+ for (i=0; i<NV10_RAMFC__SIZE; i+=4)
+ NV_WI32(fifoctx + i, 0);
+
+ /* Fill entries that are seen filled in dumps of nvidia driver just
+ * after channel's is put into DMA mode
+ */
+ RAMFC_WR(DMA_PUT , chan->pushbuf_base);
+ RAMFC_WR(DMA_GET , chan->pushbuf_base);
+ RAMFC_WR(DMA_INSTANCE , pushbuf);
+ RAMFC_WR(DMA_FETCH , NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES |
+ NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES |
+ NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8 |
+#ifdef __BIG_ENDIAN
+ NV_PFIFO_CACHE1_BIG_ENDIAN |
+#endif
+ 0);
+
+ return 0;
+}
+
+void
+nv10_fifo_destroy_context(drm_device_t *dev, int channel)
+{
+ drm_nouveau_private_t *dev_priv = dev->dev_private;
+ uint32_t fifoctx = NV10_RAMFC(channel);
+ int i;
+
+ for (i=0; i<NV10_RAMFC__SIZE; i+=4)
+ NV_WI32(fifoctx + i, 0);
+}
+
+int
+nv10_fifo_load_context(drm_device_t *dev, int channel)
+{
+ drm_nouveau_private_t *dev_priv = dev->dev_private;
+ uint32_t fifoctx = NV10_RAMFC(channel);
+ uint32_t tmp;
+
+ NV_WRITE(NV03_PFIFO_CACHE1_PUSH1 , 0x00000100 | channel);
+
+ NV_WRITE(NV04_PFIFO_CACHE1_DMA_GET , RAMFC_RD(DMA_GET));
+ NV_WRITE(NV04_PFIFO_CACHE1_DMA_PUT , RAMFC_RD(DMA_PUT));
+ NV_WRITE(NV10_PFIFO_CACHE1_REF_CNT , RAMFC_RD(REF_CNT));
+
+ tmp = RAMFC_RD(DMA_INSTANCE);
+ NV_WRITE(NV04_PFIFO_CACHE1_DMA_INSTANCE , tmp & 0xFFFF);
+ NV_WRITE(NV04_PFIFO_CACHE1_DMA_DCOUNT , tmp >> 16);
+
+ NV_WRITE(NV04_PFIFO_CACHE1_DMA_STATE , RAMFC_RD(DMA_STATE));
+ NV_WRITE(NV04_PFIFO_CACHE1_DMA_FETCH , RAMFC_RD(DMA_FETCH));
+ NV_WRITE(NV04_PFIFO_CACHE1_ENGINE , RAMFC_RD(ENGINE));
+ NV_WRITE(NV04_PFIFO_CACHE1_PULL1 , RAMFC_RD(PULL1_ENGINE));
+
+ if (dev_priv->chipset >= 0x17) {
+ NV_WRITE(NV10_PFIFO_CACHE1_ACQUIRE_VALUE,
+ RAMFC_RD(ACQUIRE_VALUE));
+ NV_WRITE(NV10_PFIFO_CACHE1_ACQUIRE_TIMESTAMP,
+ RAMFC_RD(ACQUIRE_TIMESTAMP));
+ NV_WRITE(NV10_PFIFO_CACHE1_ACQUIRE_TIMEOUT,
+ RAMFC_RD(ACQUIRE_TIMEOUT));
+ NV_WRITE(NV10_PFIFO_CACHE1_SEMAPHORE,
+ RAMFC_RD(SEMAPHORE));
+ NV_WRITE(NV10_PFIFO_CACHE1_DMA_SUBROUTINE,
+ RAMFC_RD(DMA_SUBROUTINE));
+ }
+
+ /* Reset NV04_PFIFO_CACHE1_DMA_CTL_AT_INFO to INVALID */
+ tmp = NV_READ(NV04_PFIFO_CACHE1_DMA_CTL) & ~(1<<31);
+ NV_WRITE(NV04_PFIFO_CACHE1_DMA_CTL, tmp);
+
+ return 0;
+}
+
+int
+nv10_fifo_save_context(drm_device_t *dev, int channel)
+{
+ drm_nouveau_private_t *dev_priv = dev->dev_private;
+ uint32_t fifoctx = NV10_RAMFC(channel);
+ uint32_t tmp;
+
+ RAMFC_WR(DMA_PUT , NV_READ(NV04_PFIFO_CACHE1_DMA_PUT));
+ RAMFC_WR(DMA_GET , NV_READ(NV04_PFIFO_CACHE1_DMA_GET));
+ RAMFC_WR(REF_CNT , NV_READ(NV10_PFIFO_CACHE1_REF_CNT));
+
+ tmp = NV_READ(NV04_PFIFO_CACHE1_DMA_INSTANCE) & 0xFFFF;
+ tmp |= (NV_READ(NV04_PFIFO_CACHE1_DMA_DCOUNT) << 16);
+ RAMFC_WR(DMA_INSTANCE , tmp);
+
+ RAMFC_WR(DMA_STATE , NV_READ(NV04_PFIFO_CACHE1_DMA_STATE));
+ RAMFC_WR(DMA_FETCH , NV_READ(NV04_PFIFO_CACHE1_DMA_FETCH));
+ RAMFC_WR(ENGINE , NV_READ(NV04_PFIFO_CACHE1_ENGINE));
+ RAMFC_WR(PULL1_ENGINE , NV_READ(NV04_PFIFO_CACHE1_PULL1));
+
+ if (dev_priv->chipset >= 0x17) {
+ RAMFC_WR(ACQUIRE_VALUE,
+ NV_READ(NV10_PFIFO_CACHE1_ACQUIRE_VALUE));
+ RAMFC_WR(ACQUIRE_TIMESTAMP,
+ NV_READ(NV10_PFIFO_CACHE1_ACQUIRE_TIMESTAMP));
+ RAMFC_WR(ACQUIRE_TIMEOUT,
+ NV_READ(NV10_PFIFO_CACHE1_ACQUIRE_TIMEOUT));
+ RAMFC_WR(SEMAPHORE,
+ NV_READ(NV10_PFIFO_CACHE1_SEMAPHORE));
+ RAMFC_WR(DMA_SUBROUTINE,
+ NV_READ(NV04_PFIFO_CACHE1_DMA_GET));
+ }
+
+ return 0;
+}
+
diff --git a/shared-core/nv10_graph.c b/shared-core/nv10_graph.c
index fb189709..d1fe0a54 100644
--- a/shared-core/nv10_graph.c
+++ b/shared-core/nv10_graph.c
@@ -611,7 +611,7 @@ void nouveau_nv10_context_switch(drm_device_t *dev)
if (offset > 0) \
fifo->pgraph_ctx[offset] = val; \
} while (0)
-int nv10_graph_context_create(drm_device_t *dev, int channel) {
+int nv10_graph_create_context(drm_device_t *dev, int channel) {
drm_nouveau_private_t *dev_priv = dev->dev_private;
struct nouveau_fifo *fifo = &dev_priv->fifos[channel];
uint32_t tmp, vramsz;
@@ -663,6 +663,21 @@ int nv10_graph_context_create(drm_device_t *dev, int channel) {
return 0;
}
+void nv10_graph_destroy_context(drm_device_t *dev, int channel)
+{
+}
+
+int nv10_graph_load_context(drm_device_t *dev, int channel)
+{
+ DRM_ERROR("stub!\n");
+ return 0;
+}
+
+int nv10_graph_save_context(drm_device_t *dev, int channel)
+{
+ DRM_ERROR("stub!\n");
+ return 0;
+}
int nv10_graph_init(drm_device_t *dev) {
drm_nouveau_private_t *dev_priv = dev->dev_private;
diff --git a/shared-core/nv20_graph.c b/shared-core/nv20_graph.c
index 7190fc84..1b8a6727 100644
--- a/shared-core/nv20_graph.c
+++ b/shared-core/nv20_graph.c
@@ -29,7 +29,7 @@
#define NV20_GRCTX_SIZE (3529*4)
-int nv20_graph_context_create(drm_device_t *dev, int channel) {
+int nv20_graph_create_context(drm_device_t *dev, int channel) {
drm_nouveau_private_t *dev_priv =
(drm_nouveau_private_t *)dev->dev_private;
struct nouveau_fifo *chan = &dev_priv->fifos[channel];
@@ -47,10 +47,21 @@ int nv20_graph_context_create(drm_device_t *dev, int channel) {
INSTANCE_WR(chan->ramin_grctx, 10, channel << 24); /* CTX_USER */
INSTANCE_WR(dev_priv->ctx_table, channel, nouveau_chip_instance_get(dev, chan->ramin_grctx));
-
return 0;
}
+void nv20_graph_destroy_context(drm_device_t *dev, int channel) {
+ drm_nouveau_private_t *dev_priv = dev->dev_private;
+ struct nouveau_fifo *chan = &dev_priv->fifos[channel];
+
+ if (chan->ramin_grctx) {
+ nouveau_instmem_free(dev, chan->ramin_grctx);
+ chan->ramin_grctx = NULL;
+ }
+
+ INSTANCE_WR(dev_priv->ctx_table, channel, 0);
+}
+
static void nv20_graph_rdi(drm_device_t *dev) {
drm_nouveau_private_t *dev_priv =
(drm_nouveau_private_t *)dev->dev_private;
@@ -65,40 +76,42 @@ static void nv20_graph_rdi(drm_device_t *dev) {
/* Save current context (from PGRAPH) into the channel's context
*/
-static void nv20_graph_context_save_current(drm_device_t *dev, int channel) {
+int nv20_graph_save_context(drm_device_t *dev, int channel) {
drm_nouveau_private_t *dev_priv =
(drm_nouveau_private_t *)dev->dev_private;
uint32_t instance;
instance = INSTANCE_RD(dev_priv->ctx_table, channel);
if (!instance) {
- return;
+ return DRM_ERR(EINVAL);
}
if (instance != nouveau_chip_instance_get(dev, dev_priv->fifos[channel].ramin_grctx))
- DRM_ERROR("nv20_graph_context_save_current : bad instance\n");
+ DRM_ERROR("nv20_graph_save_context : bad instance\n");
NV_WRITE(NV10_PGRAPH_CHANNEL_CTX_SIZE, instance);
NV_WRITE(NV10_PGRAPH_CHANNEL_CTX_POINTER, 2 /* save ctx */);
+ return 0;
}
/* Restore the context for a specific channel into PGRAPH
*/
-static void nv20_graph_context_restore(drm_device_t *dev, int channel) {
+int nv20_graph_load_context(drm_device_t *dev, int channel) {
drm_nouveau_private_t *dev_priv =
(drm_nouveau_private_t *)dev->dev_private;
uint32_t instance;
instance = INSTANCE_RD(dev_priv->ctx_table, channel);
if (!instance) {
- return;
+ return DRM_ERR(EINVAL);
}
if (instance != nouveau_chip_instance_get(dev, dev_priv->fifos[channel].ramin_grctx))
- DRM_ERROR("nv20_graph_context_restore_current : bad instance\n");
+ DRM_ERROR("nv20_graph_load_context_current : bad instance\n");
NV_WRITE(NV10_PGRAPH_CTX_USER, channel << 24);
NV_WRITE(NV10_PGRAPH_CHANNEL_CTX_SIZE, instance);
NV_WRITE(NV10_PGRAPH_CHANNEL_CTX_POINTER, 1 /* restore ctx */);
+ return 0;
}
void nouveau_nv20_context_switch(drm_device_t *dev)
@@ -113,13 +126,13 @@ void nouveau_nv20_context_switch(drm_device_t *dev)
NV_WRITE(NV04_PGRAPH_FIFO,0x0);
- nv20_graph_context_save_current(dev, channel_old);
+ nv20_graph_save_context(dev, channel_old);
nouveau_wait_for_idle(dev);
NV_WRITE(NV10_PGRAPH_CTX_CONTROL, 0x10000000);
- nv20_graph_context_restore(dev, channel);
+ nv20_graph_load_context(dev, channel);
nouveau_wait_for_idle(dev);
diff --git a/shared-core/nv30_graph.c b/shared-core/nv30_graph.c
index f4faadd8..7a87990a 100644
--- a/shared-core/nv30_graph.c
+++ b/shared-core/nv30_graph.c
@@ -100,7 +100,7 @@ static void nv30_graph_context_init(drm_device_t *dev, struct mem_block *ctx)
}
-int nv30_graph_context_create(drm_device_t *dev, int channel)
+int nv30_graph_create_context(drm_device_t *dev, int channel)
{
drm_nouveau_private_t *dev_priv =
(drm_nouveau_private_t *)dev->dev_private;
@@ -132,6 +132,72 @@ int nv30_graph_context_create(drm_device_t *dev, int channel)
return 0;
}
+void nv30_graph_destroy_context(drm_device_t *dev, int channel)
+{
+ drm_nouveau_private_t *dev_priv =
+ (drm_nouveau_private_t *)dev->dev_private;
+ struct nouveau_fifo *chan = &dev_priv->fifos[channel];
+
+ if (chan->ramin_grctx) {
+ nouveau_instmem_free(dev, chan->ramin_grctx);
+ chan->ramin_grctx = NULL;
+ }
+
+ INSTANCE_WR(dev_priv->ctx_table, channel, 0);
+}
+
+static int
+nouveau_graph_wait_idle(drm_device_t *dev)
+{
+ drm_nouveau_private_t *dev_priv = dev->dev_private;
+ int tv = 1000;
+
+ while (tv--) {
+ if (NV_READ(0x400700) == 0)
+ break;
+ }
+
+ if (NV_READ(0x400700)) {
+ DRM_ERROR("timeout!\n");
+ return DRM_ERR(EBUSY);
+ }
+ return 0;
+}
+
+int nv30_graph_load_context(drm_device_t *dev, int channel)
+{
+ drm_nouveau_private_t *dev_priv = dev->dev_private;
+ struct nouveau_fifo *chan = &dev_priv->fifos[channel];
+ uint32_t inst;
+
+ if (!chan->ramin_grctx)
+ return DRM_ERR(EINVAL);
+ inst = nouveau_chip_instance_get(dev, chan->ramin_grctx);
+
+ NV_WRITE(NV20_PGRAPH_CHANNEL_CTX_POINTER, inst);
+ NV_WRITE(NV20_PGRAPH_CHANNEL_CTX_XFER,
+ NV20_PGRAPH_CHANNEL_CTX_XFER_LOAD);
+
+ return nouveau_graph_wait_idle(dev);
+}
+
+int nv30_graph_save_context(drm_device_t *dev, int channel)
+{
+ drm_nouveau_private_t *dev_priv = dev->dev_private;
+ struct nouveau_fifo *chan = &dev_priv->fifos[channel];
+ uint32_t inst;
+
+ if (!chan->ramin_grctx)
+ return DRM_ERR(EINVAL);
+ inst = nouveau_chip_instance_get(dev, chan->ramin_grctx);
+
+ NV_WRITE(NV20_PGRAPH_CHANNEL_CTX_POINTER, inst);
+ NV_WRITE(NV20_PGRAPH_CHANNEL_CTX_XFER,
+ NV20_PGRAPH_CHANNEL_CTX_XFER_SAVE);
+
+ return nouveau_graph_wait_idle(dev);
+}
+
int nv30_graph_init(drm_device_t *dev)
{
drm_nouveau_private_t *dev_priv =
diff --git a/shared-core/nv40_fifo.c b/shared-core/nv40_fifo.c
new file mode 100644
index 00000000..6f25349c
--- /dev/null
+++ b/shared-core/nv40_fifo.c
@@ -0,0 +1,189 @@
+/*
+ * 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 "nouveau_drv.h"
+#include "nouveau_drm.h"
+
+#define RAMFC_WR(offset, val) NV_WI32(fifoctx + NV40_RAMFC_##offset, (val))
+#define RAMFC_RD(offset) NV_RI32(fifoctx + NV40_RAMFC_##offset)
+#define NV40_RAMFC(c) (dev_priv->ramfc_offset + ((c)*NV40_RAMFC__SIZE))
+#define NV40_RAMFC__SIZE 128
+
+int
+nv40_fifo_create_context(drm_device_t *dev, int channel)
+{
+ drm_nouveau_private_t *dev_priv = dev->dev_private;
+ struct nouveau_fifo *chan = &dev_priv->fifos[channel];
+ uint32_t fifoctx = NV40_RAMFC(channel), grctx, pushbuf;
+ int i;
+
+ for (i = 0; i < NV40_RAMFC__SIZE; i+=4)
+ NV_WI32(fifoctx + i, 0);
+
+ grctx = nouveau_chip_instance_get(dev, chan->ramin_grctx);
+ pushbuf = nouveau_chip_instance_get(dev, chan->cmdbuf_obj->instance);
+
+ /* Fill entries that are seen filled in dumps of nvidia driver just
+ * after channel's is put into DMA mode
+ */
+ RAMFC_WR(DMA_PUT , chan->pushbuf_base);
+ RAMFC_WR(DMA_GET , chan->pushbuf_base);
+ RAMFC_WR(DMA_INSTANCE , pushbuf);
+ RAMFC_WR(DMA_FETCH , NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES |
+ NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES |
+ NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8 |
+#ifdef __BIG_ENDIAN
+ NV_PFIFO_CACHE1_BIG_ENDIAN |
+#endif
+ 0x30000000 /* no idea.. */);
+ RAMFC_WR(DMA_SUBROUTINE, 0);
+ RAMFC_WR(GRCTX_INSTANCE, grctx);
+ RAMFC_WR(DMA_TIMESLICE , 0x0001FFFF);
+
+ return 0;
+}
+
+void
+nv40_fifo_destroy_context(drm_device_t *dev, int channel)
+{
+ drm_nouveau_private_t *dev_priv = dev->dev_private;
+ uint32_t fifoctx = NV40_RAMFC(channel);
+ int i;
+
+ for (i = 0; i < NV40_RAMFC__SIZE; i+=4)
+ NV_WI32(fifoctx + i, 0);
+}
+
+int
+nv40_fifo_load_context(drm_device_t *dev, int channel)
+{
+ drm_nouveau_private_t *dev_priv = dev->dev_private;
+ uint32_t fifoctx = NV40_RAMFC(channel);
+ uint32_t tmp, tmp2;
+
+ NV_WRITE(NV04_PFIFO_CACHE1_DMA_GET , RAMFC_RD(DMA_GET));
+ NV_WRITE(NV04_PFIFO_CACHE1_DMA_PUT , RAMFC_RD(DMA_PUT));
+ NV_WRITE(NV10_PFIFO_CACHE1_REF_CNT , RAMFC_RD(REF_CNT));
+ NV_WRITE(NV04_PFIFO_CACHE1_DMA_INSTANCE , RAMFC_RD(DMA_INSTANCE));
+ NV_WRITE(NV04_PFIFO_CACHE1_DMA_DCOUNT , RAMFC_RD(DMA_DCOUNT));
+ NV_WRITE(NV04_PFIFO_CACHE1_DMA_STATE , RAMFC_RD(DMA_STATE));
+
+ /* No idea what 0x2058 is.. */
+ tmp = RAMFC_RD(DMA_FETCH);
+ tmp2 = NV_READ(0x2058) & 0xFFF;
+ tmp2 |= (tmp & 0x30000000);
+ NV_WRITE(0x2058, tmp2);
+ tmp &= ~0x30000000;
+ NV_WRITE(NV04_PFIFO_CACHE1_DMA_FETCH , tmp);
+
+ NV_WRITE(NV04_PFIFO_CACHE1_ENGINE , RAMFC_RD(ENGINE));
+ NV_WRITE(NV04_PFIFO_CACHE1_PULL1 , RAMFC_RD(PULL1_ENGINE));
+ NV_WRITE(NV10_PFIFO_CACHE1_ACQUIRE_VALUE , RAMFC_RD(ACQUIRE_VALUE));
+ NV_WRITE(NV10_PFIFO_CACHE1_ACQUIRE_TIMESTAMP, RAMFC_RD(ACQUIRE_TIMESTAMP));
+ NV_WRITE(NV10_PFIFO_CACHE1_ACQUIRE_TIMEOUT , RAMFC_RD(ACQUIRE_TIMEOUT));
+ NV_WRITE(NV10_PFIFO_CACHE1_SEMAPHORE , RAMFC_RD(SEMAPHORE));
+ NV_WRITE(NV10_PFIFO_CACHE1_DMA_SUBROUTINE , RAMFC_RD(DMA_SUBROUTINE));
+ NV_WRITE(NV40_PFIFO_GRCTX_INSTANCE , RAMFC_RD(GRCTX_INSTANCE));
+ NV_WRITE(0x32e4, RAMFC_RD(UNK_40));
+ /* NVIDIA does this next line twice... */
+ NV_WRITE(0x32e8, RAMFC_RD(UNK_44));
+ NV_WRITE(0x2088, RAMFC_RD(UNK_4C));
+ NV_WRITE(0x3300, RAMFC_RD(UNK_50));
+
+ /* not sure what part is PUT, and which is GET.. never seen a non-zero
+ * value appear in a mmio-trace yet..
+ */
+#if 0
+ tmp = NV_READ(UNK_84);
+ NV_WRITE(NV_PFIFO_CACHE1_GET, tmp ???);
+ NV_WRITE(NV_PFIFO_CACHE1_PUT, tmp ???);
+#endif
+
+ /* Don't clobber the TIMEOUT_ENABLED flag when restoring from RAMFC */
+ tmp = NV_READ(NV04_PFIFO_DMA_TIMESLICE) & ~0x1FFFF;
+ tmp |= RAMFC_RD(DMA_TIMESLICE) & 0x1FFFF;
+ NV_WRITE(NV04_PFIFO_DMA_TIMESLICE, tmp);
+
+ /* Set channel active, and in DMA mode */
+ NV_WRITE(NV03_PFIFO_CACHE1_PUSH1 , 0x00010000 | channel);
+ /* 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);
+
+ return 0;
+}
+
+int
+nv40_fifo_save_context(drm_device_t *dev, int channel)
+{
+ drm_nouveau_private_t *dev_priv = dev->dev_private;
+ uint32_t fifoctx = NV40_RAMFC(channel);
+ uint32_t tmp;
+
+ RAMFC_WR(DMA_PUT , NV_READ(NV04_PFIFO_CACHE1_DMA_PUT));
+ RAMFC_WR(DMA_GET , NV_READ(NV04_PFIFO_CACHE1_DMA_GET));
+ RAMFC_WR(REF_CNT , NV_READ(NV10_PFIFO_CACHE1_REF_CNT));
+ RAMFC_WR(DMA_INSTANCE , NV_READ(NV04_PFIFO_CACHE1_DMA_INSTANCE));
+ RAMFC_WR(DMA_DCOUNT , NV_READ(NV04_PFIFO_CACHE1_DMA_DCOUNT));
+ RAMFC_WR(DMA_STATE , NV_READ(NV04_PFIFO_CACHE1_DMA_STATE));
+
+ tmp = NV_READ(NV04_PFIFO_CACHE1_DMA_FETCH);
+ tmp |= NV_READ(0x2058) & 0x30000000;
+ RAMFC_WR(DMA_FETCH , tmp);
+
+ RAMFC_WR(ENGINE , NV_READ(NV04_PFIFO_CACHE1_ENGINE));
+ RAMFC_WR(PULL1_ENGINE , NV_READ(NV04_PFIFO_CACHE1_PULL1));
+ RAMFC_WR(ACQUIRE_VALUE , NV_READ(NV10_PFIFO_CACHE1_ACQUIRE_VALUE));
+ tmp = NV_READ(NV10_PFIFO_CACHE1_ACQUIRE_TIMESTAMP);
+ RAMFC_WR(ACQUIRE_TIMESTAMP, tmp);
+ RAMFC_WR(ACQUIRE_TIMEOUT , NV_READ(NV10_PFIFO_CACHE1_ACQUIRE_TIMEOUT));
+ RAMFC_WR(SEMAPHORE , NV_READ(NV10_PFIFO_CACHE1_SEMAPHORE));
+
+ /* NVIDIA read 0x3228 first, then write DMA_GET here.. maybe something
+ * more involved depending on the value of 0x3228?
+ */
+ RAMFC_WR(DMA_SUBROUTINE , NV_READ(NV04_PFIFO_CACHE1_DMA_GET));
+
+ RAMFC_WR(GRCTX_INSTANCE , NV_READ(NV40_PFIFO_GRCTX_INSTANCE));
+
+ /* No idea what the below is for exactly, ripped from a mmio-trace */
+ RAMFC_WR(UNK_40 , NV_READ(NV40_PFIFO_UNK32E4));
+
+ /* NVIDIA do this next line twice.. bug? */
+ RAMFC_WR(UNK_44 , NV_READ(0x32e8));
+ RAMFC_WR(UNK_4C , NV_READ(0x2088));
+ RAMFC_WR(UNK_50 , NV_READ(0x3300));
+
+#if 0 /* no real idea which is PUT/GET in UNK_48.. */
+ tmp = NV_READ(NV04_PFIFO_CACHE1_GET);
+ tmp |= (NV_READ(NV04_PFIFO_CACHE1_PUT) << 16);
+ RAMFC_WR(UNK_48 , tmp);
+#endif
+
+ return 0;
+}
+
diff --git a/shared-core/nv40_graph.c b/shared-core/nv40_graph.c
index 792734ed..6fb575db 100644
--- a/shared-core/nv40_graph.c
+++ b/shared-core/nv40_graph.c
@@ -1,7 +1,32 @@
+/*
+ * 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_drm.h"
/* The sizes are taken from the difference between the start of two
* grctx addresses while running the nvidia driver. Probably slightly
@@ -11,7 +36,9 @@
#define NV40_GRCTX_SIZE (175*1024)
#define NV43_GRCTX_SIZE (70*1024)
#define NV46_GRCTX_SIZE (70*1024) /* probably ~64KiB */
+#define NV49_GRCTX_SIZE (164640)
#define NV4A_GRCTX_SIZE (64*1024)
+#define NV4B_GRCTX_SIZE (164640)
#define NV4C_GRCTX_SIZE (25*1024)
#define NV4E_GRCTX_SIZE (25*1024)
@@ -19,7 +46,8 @@
* contexts are taken from dumps just after the 3D object is
* created.
*/
-static void nv40_graph_context_init(drm_device_t *dev, struct mem_block *ctx)
+static void
+nv40_graph_context_init(drm_device_t *dev, struct mem_block *ctx)
{
drm_nouveau_private_t *dev_priv = dev->dev_private;
int i;
@@ -275,7 +303,8 @@ nv43_graph_context_init(drm_device_t *dev, struct mem_block *ctx)
INSTANCE_WR(ctx, i/4, 0x3f800000);
};
-static void nv46_graph_context_init(drm_device_t *dev, struct mem_block *ctx)
+static void
+nv46_graph_context_init(drm_device_t *dev, struct mem_block *ctx)
{
drm_nouveau_private_t *dev_priv = dev->dev_private;
int i;
@@ -425,7 +454,231 @@ static void nv46_graph_context_init(drm_device_t *dev, struct mem_block *ctx)
INSTANCE_WR(ctx, i/4, 0x3f800000);
}
-static void nv4a_graph_context_init(drm_device_t *dev, struct mem_block *ctx)
+static void
+nv49_graph_context_init(drm_device_t *dev, struct mem_block *ctx)
+{
+ drm_nouveau_private_t *dev_priv = dev->dev_private;
+ int i;
+
+ INSTANCE_WR(ctx, 0x00000/4, nouveau_chip_instance_get(dev, ctx));
+ INSTANCE_WR(ctx, 0x00004/4, 0x0000c040);
+ INSTANCE_WR(ctx, 0x00008/4, 0x0000c040);
+ INSTANCE_WR(ctx, 0x0000c/4, 0x0000c040);
+ INSTANCE_WR(ctx, 0x00010/4, 0x0000c040);
+ INSTANCE_WR(ctx, 0x00014/4, 0x0000c040);
+ INSTANCE_WR(ctx, 0x00018/4, 0x0000c040);
+ INSTANCE_WR(ctx, 0x0001c/4, 0x0000c040);
+ INSTANCE_WR(ctx, 0x00020/4, 0x0000c040);
+ INSTANCE_WR(ctx, 0x000c4/4, 0x0000ffff);
+ INSTANCE_WR(ctx, 0x000c8/4, 0x0000ffff);
+ INSTANCE_WR(ctx, 0x000d0/4, 0x00000001);
+ INSTANCE_WR(ctx, 0x001bc/4, 0x20010001);
+ INSTANCE_WR(ctx, 0x001c0/4, 0x0f73ef00);
+ INSTANCE_WR(ctx, 0x001c8/4, 0x02008821);
+ INSTANCE_WR(ctx, 0x00218/4, 0x00000040);
+ INSTANCE_WR(ctx, 0x0021c/4, 0x00000040);
+ INSTANCE_WR(ctx, 0x00220/4, 0x00000040);
+ INSTANCE_WR(ctx, 0x00228/4, 0x00000040);
+ INSTANCE_WR(ctx, 0x00234/4, 0x80000000);
+ INSTANCE_WR(ctx, 0x00238/4, 0x80000000);
+ INSTANCE_WR(ctx, 0x0023c/4, 0x80000000);
+ INSTANCE_WR(ctx, 0x00240/4, 0x80000000);
+ INSTANCE_WR(ctx, 0x00244/4, 0x80000000);
+ INSTANCE_WR(ctx, 0x00248/4, 0x80000000);
+ INSTANCE_WR(ctx, 0x0024c/4, 0x80000000);
+ INSTANCE_WR(ctx, 0x00250/4, 0x80000000);
+ INSTANCE_WR(ctx, 0x00270/4, 0x0b0b0b0c);
+ INSTANCE_WR(ctx, 0x003e0/4, 0x00040000);
+ INSTANCE_WR(ctx, 0x003f0/4, 0x55555555);
+ INSTANCE_WR(ctx, 0x003f4/4, 0x55555555);
+ INSTANCE_WR(ctx, 0x003f8/4, 0x55555555);
+ INSTANCE_WR(ctx, 0x003fc/4, 0x55555555);
+ INSTANCE_WR(ctx, 0x00428/4, 0x00000008);
+ INSTANCE_WR(ctx, 0x0043c/4, 0x00001010);
+ INSTANCE_WR(ctx, 0x00460/4, 0x00000111);
+ INSTANCE_WR(ctx, 0x00464/4, 0x00000111);
+ INSTANCE_WR(ctx, 0x00468/4, 0x00000111);
+ INSTANCE_WR(ctx, 0x0046c/4, 0x00000111);
+ INSTANCE_WR(ctx, 0x00470/4, 0x00000111);
+ INSTANCE_WR(ctx, 0x00474/4, 0x00000111);
+ INSTANCE_WR(ctx, 0x00478/4, 0x00000111);
+ INSTANCE_WR(ctx, 0x0047c/4, 0x00000111);
+ INSTANCE_WR(ctx, 0x00480/4, 0x00000111);
+ INSTANCE_WR(ctx, 0x00484/4, 0x00000111);
+ INSTANCE_WR(ctx, 0x00488/4, 0x00000111);
+ INSTANCE_WR(ctx, 0x0048c/4, 0x00000111);
+ INSTANCE_WR(ctx, 0x00490/4, 0x00000111);
+ INSTANCE_WR(ctx, 0x00494/4, 0x00000111);
+ INSTANCE_WR(ctx, 0x00498/4, 0x00000111);
+ INSTANCE_WR(ctx, 0x0049c/4, 0x00000111);
+ INSTANCE_WR(ctx, 0x004f4/4, 0x00000111);
+ INSTANCE_WR(ctx, 0x004f8/4, 0x00080060);
+ INSTANCE_WR(ctx, 0x00514/4, 0x00000080);
+ INSTANCE_WR(ctx, 0x00518/4, 0xffff0000);
+ INSTANCE_WR(ctx, 0x0051c/4, 0x00000001);
+ INSTANCE_WR(ctx, 0x00530/4, 0x46400000);
+ INSTANCE_WR(ctx, 0x00540/4, 0xffff0000);
+ INSTANCE_WR(ctx, 0x00544/4, 0x88888888);
+ INSTANCE_WR(ctx, 0x00548/4, 0x88888888);
+ INSTANCE_WR(ctx, 0x0054c/4, 0x88888888);
+ INSTANCE_WR(ctx, 0x00550/4, 0x88888888);
+ INSTANCE_WR(ctx, 0x00554/4, 0x88888888);
+ INSTANCE_WR(ctx, 0x00558/4, 0x88888888);
+ INSTANCE_WR(ctx, 0x0055c/4, 0x88888888);
+ INSTANCE_WR(ctx, 0x00560/4, 0x88888888);
+ INSTANCE_WR(ctx, 0x00564/4, 0x88888888);
+ INSTANCE_WR(ctx, 0x00568/4, 0x88888888);
+ INSTANCE_WR(ctx, 0x0056c/4, 0x88888888);
+ INSTANCE_WR(ctx, 0x00570/4, 0x88888888);
+ INSTANCE_WR(ctx, 0x00574/4, 0x88888888);
+ INSTANCE_WR(ctx, 0x00578/4, 0x88888888);
+ INSTANCE_WR(ctx, 0x0057c/4, 0x88888888);
+ INSTANCE_WR(ctx, 0x00580/4, 0x88888888);
+ INSTANCE_WR(ctx, 0x00594/4, 0x0fff0000);
+ INSTANCE_WR(ctx, 0x00598/4, 0x0fff0000);
+ INSTANCE_WR(ctx, 0x005a0/4, 0x00011100);
+ INSTANCE_WR(ctx, 0x005bc/4, 0x07ff0000);
+ INSTANCE_WR(ctx, 0x005c0/4, 0x07ff0000);
+ INSTANCE_WR(ctx, 0x005c4/4, 0x07ff0000);
+ INSTANCE_WR(ctx, 0x005c8/4, 0x07ff0000);
+ INSTANCE_WR(ctx, 0x005cc/4, 0x07ff0000);
+ INSTANCE_WR(ctx, 0x005d0/4, 0x07ff0000);
+ INSTANCE_WR(ctx, 0x005d4/4, 0x07ff0000);
+ INSTANCE_WR(ctx, 0x005d8/4, 0x07ff0000);
+ INSTANCE_WR(ctx, 0x005dc/4, 0x07ff0000);
+ INSTANCE_WR(ctx, 0x005e0/4, 0x07ff0000);
+ INSTANCE_WR(ctx, 0x005e4/4, 0x07ff0000);
+ INSTANCE_WR(ctx, 0x005e8/4, 0x07ff0000);
+ INSTANCE_WR(ctx, 0x005ec/4, 0x07ff0000);
+ INSTANCE_WR(ctx, 0x005f0/4, 0x07ff0000);
+ INSTANCE_WR(ctx, 0x005f4/4, 0x07ff0000);
+ INSTANCE_WR(ctx, 0x005f8/4, 0x07ff0000);
+ INSTANCE_WR(ctx, 0x00604/4, 0x4b7fffff);
+ INSTANCE_WR(ctx, 0x0062c/4, 0x30201000);
+ INSTANCE_WR(ctx, 0x00630/4, 0x70605040);
+ INSTANCE_WR(ctx, 0x00634/4, 0xb8a89888);
+ INSTANCE_WR(ctx, 0x00638/4, 0xf8e8d8c8);
+ INSTANCE_WR(ctx, 0x0064c/4, 0x40100000);
+ INSTANCE_WR(ctx, 0x00668/4, 0x0000ffff);
+ INSTANCE_WR(ctx, 0x0069c/4, 0x435185d6);
+ INSTANCE_WR(ctx, 0x006a0/4, 0x2155b699);
+ INSTANCE_WR(ctx, 0x006a4/4, 0xfedcba98);
+ INSTANCE_WR(ctx, 0x006a8/4, 0x00000098);
+ INSTANCE_WR(ctx, 0x006b8/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x006bc/4, 0x00ff7000);
+ INSTANCE_WR(ctx, 0x006c0/4, 0x0000ffff);
+ INSTANCE_WR(ctx, 0x006d0/4, 0x00ff0000);
+ INSTANCE_WR(ctx, 0x0070c/4, 0x00ffff00);
+ for (i=0x00750; i<=0x0078c; i+=4)
+ INSTANCE_WR(ctx, i/4, 0x00018488);
+ for (i=0x00790; i<=0x007cc; i+=4)
+ INSTANCE_WR(ctx, i/4, 0x00028202);
+ for (i=0x00810; i<=0x0084c; i+=4)
+ INSTANCE_WR(ctx, i/4, 0x0000aae4);
+ for (i=0x00850; i<=0x0088c; i+=4)
+ INSTANCE_WR(ctx, i/4, 0x01012000);
+ for (i=0x00890; i<=0x008cc; i+=4)
+ INSTANCE_WR(ctx, i/4, 0x00080008);
+ for (i=0x00910; i<=0x0094c; i+=4)
+ INSTANCE_WR(ctx, i/4, 0x00100008);
+ for (i=0x009a0; i<=0x009ac; i+=4)
+ INSTANCE_WR(ctx, i/4, 0x0001bc80);
+ for (i=0x009b0; i<=0x009bc; i+=4)
+ INSTANCE_WR(ctx, i/4, 0x00000202);
+ for (i=0x009d0; i<=0x009dc; i+=4)
+ INSTANCE_WR(ctx, i/4, 0x00000008);
+ for (i=0x009f0; i<=0x009fc; i+=4)
+ INSTANCE_WR(ctx, i/4, 0x00080008);
+ INSTANCE_WR(ctx, 0x00a10/4, 0x00000002);
+ INSTANCE_WR(ctx, 0x00a44/4, 0x00000421);
+ INSTANCE_WR(ctx, 0x00a48/4, 0x030c30c3);
+ INSTANCE_WR(ctx, 0x00a54/4, 0x3e020200);
+ INSTANCE_WR(ctx, 0x00a58/4, 0x00ffffff);
+ INSTANCE_WR(ctx, 0x00a5c/4, 0x20103f00);
+ INSTANCE_WR(ctx, 0x00a68/4, 0x00040000);
+ INSTANCE_WR(ctx, 0x00aa0/4, 0x00008100);
+ INSTANCE_WR(ctx, 0x00b2c/4, 0x00000001);
+ INSTANCE_WR(ctx, 0x00b70/4, 0x00001001);
+ INSTANCE_WR(ctx, 0x00b7c/4, 0x00000003);
+ INSTANCE_WR(ctx, 0x00b80/4, 0x00888001);
+ INSTANCE_WR(ctx, 0x00bb0/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00bb4/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00bb8/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00bbc/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00bc0/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00bc4/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00bc8/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00bcc/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00bd0/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00bd4/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00bd8/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00bdc/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00be0/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00be4/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00be8/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00bec/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00bf0/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00bf4/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00bf8/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00bfc/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00c00/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00c04/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00c08/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00c0c/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00c10/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00c14/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00c18/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00c1c/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00c20/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00c24/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00c28/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00c2c/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00c54/4, 0x00000005);
+ INSTANCE_WR(ctx, 0x00c60/4, 0x0000ffff);
+ INSTANCE_WR(ctx, 0x00c7c/4, 0x00005555);
+ INSTANCE_WR(ctx, 0x00c80/4, 0x00005555);
+ INSTANCE_WR(ctx, 0x00c84/4, 0x00005555);
+ INSTANCE_WR(ctx, 0x00c88/4, 0x00005555);
+ INSTANCE_WR(ctx, 0x00c8c/4, 0x00005555);
+ INSTANCE_WR(ctx, 0x00c90/4, 0x00005555);
+ INSTANCE_WR(ctx, 0x00c94/4, 0x00005555);
+ INSTANCE_WR(ctx, 0x00c98/4, 0x00005555);
+ INSTANCE_WR(ctx, 0x00c9c/4, 0x00000001);
+ INSTANCE_WR(ctx, 0x00cd4/4, 0x00000001);
+ INSTANCE_WR(ctx, 0x00cd8/4, 0x08e00001);
+ INSTANCE_WR(ctx, 0x00cdc/4, 0x000e3000);
+ for(i=0x030a0; i<=0x03118; i+=8)
+ INSTANCE_WR(ctx, i/4, 0x3f800000);
+ for(i=0x098a0; i<=0x0ba90; i+=24)
+ INSTANCE_WR(ctx, i/4, 0x00000001);
+ for(i=0x0baa0; i<=0x0be90; i+=16)
+ INSTANCE_WR(ctx, i/4, 0x3f800000);
+ for(i=0x0e2e0; i<=0x0fff0; i+=24)
+ INSTANCE_WR(ctx, i/4, 0x00000001);
+ for(i=0x10008; i<=0x104d0; i+=24)
+ INSTANCE_WR(ctx, i/4, 0x00000001);
+ for(i=0x104e0; i<=0x108d0; i+=16)
+ INSTANCE_WR(ctx, i/4, 0x3f800000);
+ for(i=0x12d20; i<=0x14f10; i+=24)
+ INSTANCE_WR(ctx, i/4, 0x00000001);
+ for(i=0x14f20; i<=0x15310; i+=16)
+ INSTANCE_WR(ctx, i/4, 0x3f800000);
+ for(i=0x17760; i<=0x19950; i+=24)
+ INSTANCE_WR(ctx, i/4, 0x00000001);
+ for(i=0x19960; i<=0x19d50; i+=16)
+ INSTANCE_WR(ctx, i/4, 0x3f800000);
+ for(i=0x1c1a0; i<=0x1e390; i+=24)
+ INSTANCE_WR(ctx, i/4, 0x00000001);
+ for(i=0x1e3a0; i<=0x1e790; i+=16)
+ INSTANCE_WR(ctx, i/4, 0x3f800000);
+ for(i=0x20be0; i<=0x22dd0; i+=24)
+ INSTANCE_WR(ctx, i/4, 0x00000001);
+ for(i=0x22de0; i<=0x231d0; i+=16)
+ INSTANCE_WR(ctx, i/4, 0x3f800000);
+}
+
+static void
+nv4a_graph_context_init(drm_device_t *dev, struct mem_block *ctx)
{
drm_nouveau_private_t *dev_priv = dev->dev_private;
int i;
@@ -541,8 +794,223 @@ static void nv4a_graph_context_init(drm_device_t *dev, struct mem_block *ctx)
INSTANCE_WR(ctx, i/4, 0x3f800000);
}
+static void
+nv4b_graph_context_init(drm_device_t *dev, struct mem_block *ctx)
+{
+ drm_nouveau_private_t *dev_priv = dev->dev_private;
+ int i;
+
+ INSTANCE_WR(ctx, 0x00000/4, nouveau_chip_instance_get(dev, ctx));
+ INSTANCE_WR(ctx, 0x00004/4, 0x0000c040);
+ INSTANCE_WR(ctx, 0x00008/4, 0x0000c040);
+ INSTANCE_WR(ctx, 0x0000c/4, 0x0000c040);
+ INSTANCE_WR(ctx, 0x00010/4, 0x0000c040);
+ INSTANCE_WR(ctx, 0x00014/4, 0x0000c040);
+ INSTANCE_WR(ctx, 0x00018/4, 0x0000c040);
+ INSTANCE_WR(ctx, 0x0001c/4, 0x0000c040);
+ INSTANCE_WR(ctx, 0x00020/4, 0x0000c040);
+ INSTANCE_WR(ctx, 0x000c4/4, 0x0000ffff);
+ INSTANCE_WR(ctx, 0x000c8/4, 0x0000ffff);
+ INSTANCE_WR(ctx, 0x000d0/4, 0x00000001);
+ INSTANCE_WR(ctx, 0x001bc/4, 0x20010001);
+ INSTANCE_WR(ctx, 0x001c0/4, 0x0f73ef00);
+ INSTANCE_WR(ctx, 0x001c8/4, 0x02008821);
+ INSTANCE_WR(ctx, 0x00218/4, 0x00000040);
+ INSTANCE_WR(ctx, 0x0021c/4, 0x00000040);
+ INSTANCE_WR(ctx, 0x00220/4, 0x00000040);
+ INSTANCE_WR(ctx, 0x00228/4, 0x00000040);
+ INSTANCE_WR(ctx, 0x00234/4, 0x80000000);
+ INSTANCE_WR(ctx, 0x00238/4, 0x80000000);
+ INSTANCE_WR(ctx, 0x0023c/4, 0x80000000);
+ INSTANCE_WR(ctx, 0x00240/4, 0x80000000);
+ INSTANCE_WR(ctx, 0x00244/4, 0x80000000);
+ INSTANCE_WR(ctx, 0x00248/4, 0x80000000);
+ INSTANCE_WR(ctx, 0x0024c/4, 0x80000000);
+ INSTANCE_WR(ctx, 0x00250/4, 0x80000000);
+ INSTANCE_WR(ctx, 0x00270/4, 0x0b0b0b0c);
+ INSTANCE_WR(ctx, 0x003e0/4, 0x00040000);
+ INSTANCE_WR(ctx, 0x003f0/4, 0x55555555);
+ INSTANCE_WR(ctx, 0x003f4/4, 0x55555555);
+ INSTANCE_WR(ctx, 0x003f8/4, 0x55555555);
+ INSTANCE_WR(ctx, 0x003fc/4, 0x55555555);
+ INSTANCE_WR(ctx, 0x00428/4, 0x00000008);
+ INSTANCE_WR(ctx, 0x0043c/4, 0x00001010);
+ INSTANCE_WR(ctx, 0x00460/4, 0x00000111);
+ INSTANCE_WR(ctx, 0x00464/4, 0x00000111);
+ INSTANCE_WR(ctx, 0x00468/4, 0x00000111);
+ INSTANCE_WR(ctx, 0x0046c/4, 0x00000111);
+ INSTANCE_WR(ctx, 0x00470/4, 0x00000111);
+ INSTANCE_WR(ctx, 0x00474/4, 0x00000111);
+ INSTANCE_WR(ctx, 0x00478/4, 0x00000111);
+ INSTANCE_WR(ctx, 0x0047c/4, 0x00000111);
+ INSTANCE_WR(ctx, 0x00480/4, 0x00000111);
+ INSTANCE_WR(ctx, 0x00484/4, 0x00000111);
+ INSTANCE_WR(ctx, 0x00488/4, 0x00000111);
+ INSTANCE_WR(ctx, 0x0048c/4, 0x00000111);
+ INSTANCE_WR(ctx, 0x00490/4, 0x00000111);
+ INSTANCE_WR(ctx, 0x00494/4, 0x00000111);
+ INSTANCE_WR(ctx, 0x00498/4, 0x00000111);
+ INSTANCE_WR(ctx, 0x0049c/4, 0x00000111);
+ INSTANCE_WR(ctx, 0x004f4/4, 0x00000111);
+ INSTANCE_WR(ctx, 0x004f8/4, 0x00080060);
+ INSTANCE_WR(ctx, 0x00514/4, 0x00000080);
+ INSTANCE_WR(ctx, 0x00518/4, 0xffff0000);
+ INSTANCE_WR(ctx, 0x0051c/4, 0x00000001);
+ INSTANCE_WR(ctx, 0x00530/4, 0x46400000);
+ INSTANCE_WR(ctx, 0x00540/4, 0xffff0000);
+ INSTANCE_WR(ctx, 0x00544/4, 0x88888888);
+ INSTANCE_WR(ctx, 0x00548/4, 0x88888888);
+ INSTANCE_WR(ctx, 0x0054c/4, 0x88888888);
+ INSTANCE_WR(ctx, 0x00550/4, 0x88888888);
+ INSTANCE_WR(ctx, 0x00554/4, 0x88888888);
+ INSTANCE_WR(ctx, 0x00558/4, 0x88888888);
+ INSTANCE_WR(ctx, 0x0055c/4, 0x88888888);
+ INSTANCE_WR(ctx, 0x00560/4, 0x88888888);
+ INSTANCE_WR(ctx, 0x00564/4, 0x88888888);
+ INSTANCE_WR(ctx, 0x00568/4, 0x88888888);
+ INSTANCE_WR(ctx, 0x0056c/4, 0x88888888);
+ INSTANCE_WR(ctx, 0x00570/4, 0x88888888);
+ INSTANCE_WR(ctx, 0x00574/4, 0x88888888);
+ INSTANCE_WR(ctx, 0x00578/4, 0x88888888);
+ INSTANCE_WR(ctx, 0x0057c/4, 0x88888888);
+ INSTANCE_WR(ctx, 0x00580/4, 0x88888888);
+ INSTANCE_WR(ctx, 0x00594/4, 0x0fff0000);
+ INSTANCE_WR(ctx, 0x00598/4, 0x0fff0000);
+ INSTANCE_WR(ctx, 0x005a0/4, 0x00011100);
+ INSTANCE_WR(ctx, 0x005bc/4, 0x07ff0000);
+ INSTANCE_WR(ctx, 0x005c0/4, 0x07ff0000);
+ INSTANCE_WR(ctx, 0x005c4/4, 0x07ff0000);
+ INSTANCE_WR(ctx, 0x005c8/4, 0x07ff0000);
+ INSTANCE_WR(ctx, 0x005cc/4, 0x07ff0000);
+ INSTANCE_WR(ctx, 0x005d0/4, 0x07ff0000);
+ INSTANCE_WR(ctx, 0x005d4/4, 0x07ff0000);
+ INSTANCE_WR(ctx, 0x005d8/4, 0x07ff0000);
+ INSTANCE_WR(ctx, 0x005dc/4, 0x07ff0000);
+ INSTANCE_WR(ctx, 0x005e0/4, 0x07ff0000);
+ INSTANCE_WR(ctx, 0x005e4/4, 0x07ff0000);
+ INSTANCE_WR(ctx, 0x005e8/4, 0x07ff0000);
+ INSTANCE_WR(ctx, 0x005ec/4, 0x07ff0000);
+ INSTANCE_WR(ctx, 0x005f0/4, 0x07ff0000);
+ INSTANCE_WR(ctx, 0x005f4/4, 0x07ff0000);
+ INSTANCE_WR(ctx, 0x005f8/4, 0x07ff0000);
+ INSTANCE_WR(ctx, 0x00604/4, 0x4b7fffff);
+ INSTANCE_WR(ctx, 0x0062c/4, 0x30201000);
+ INSTANCE_WR(ctx, 0x00630/4, 0x70605040);
+ INSTANCE_WR(ctx, 0x00634/4, 0xb8a89888);
+ INSTANCE_WR(ctx, 0x00638/4, 0xf8e8d8c8);
+ INSTANCE_WR(ctx, 0x0064c/4, 0x40100000);
+ INSTANCE_WR(ctx, 0x00668/4, 0x0000ffff);
+ INSTANCE_WR(ctx, 0x0069c/4, 0x435185d6);
+ INSTANCE_WR(ctx, 0x006a0/4, 0x2155b699);
+ INSTANCE_WR(ctx, 0x006a4/4, 0xfedcba98);
+ INSTANCE_WR(ctx, 0x006a8/4, 0x00000098);
+ INSTANCE_WR(ctx, 0x006b8/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x006bc/4, 0x00ff7000);
+ INSTANCE_WR(ctx, 0x006c0/4, 0x0000ffff);
+ INSTANCE_WR(ctx, 0x006d0/4, 0x00ff0000);
+ INSTANCE_WR(ctx, 0x0070c/4, 0x00ffff00);
+ for (i=0x00750; i<=0x0078c; i+=4)
+ INSTANCE_WR(ctx, i/4, 0x00018488);
+ for (i=0x00790; i<=0x007cc; i+=4)
+ INSTANCE_WR(ctx, i/4, 0x00028202);
+ for (i=0x00810; i<=0x0084c; i+=4)
+ INSTANCE_WR(ctx, i/4, 0x0000aae4);
+ for (i=0x00850; i<=0x0088c; i+=4)
+ INSTANCE_WR(ctx, i/4, 0x01012000);
+ for (i=0x00890; i<=0x008cc; i+=4)
+ INSTANCE_WR(ctx, i/4, 0x00080008);
+ for (i=0x00910; i<=0x0094c; i+=4)
+ INSTANCE_WR(ctx, i/4, 0x00100008);
+ for (i=0x009a0; i<=0x009ac; i+=4)
+ INSTANCE_WR(ctx, i/4, 0x0001bc80);
+ for (i=0x009b0; i<=0x009bc; i+=4)
+ INSTANCE_WR(ctx, i/4, 0x00000202);
+ for (i=0x009d0; i<=0x009dc; i+=4)
+ INSTANCE_WR(ctx, i/4, 0x00000008);
+ for (i=0x009f0; i<=0x009fc; i+=4)
+ INSTANCE_WR(ctx, i/4, 0x00080008);
+ INSTANCE_WR(ctx, 0x00a10/4, 0x00000002);
+ INSTANCE_WR(ctx, 0x00a44/4, 0x00000421);
+ INSTANCE_WR(ctx, 0x00a48/4, 0x030c30c3);
+ INSTANCE_WR(ctx, 0x00a54/4, 0x3e020200);
+ INSTANCE_WR(ctx, 0x00a58/4, 0x00ffffff);
+ INSTANCE_WR(ctx, 0x00a5c/4, 0x20103f00);
+ INSTANCE_WR(ctx, 0x00a68/4, 0x00040000);
+ INSTANCE_WR(ctx, 0x00aa0/4, 0x00008100);
+ INSTANCE_WR(ctx, 0x00b2c/4, 0x00000001);
+ INSTANCE_WR(ctx, 0x00b70/4, 0x00001001);
+ INSTANCE_WR(ctx, 0x00b7c/4, 0x00000003);
+ INSTANCE_WR(ctx, 0x00b80/4, 0x00888001);
+ INSTANCE_WR(ctx, 0x00bb0/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00bb4/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00bb8/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00bbc/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00bc0/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00bc4/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00bc8/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00bcc/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00bd0/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00bd4/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00bd8/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00bdc/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00be0/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00be4/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00be8/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00bec/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00bf0/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00bf4/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00bf8/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00bfc/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00c00/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00c04/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00c08/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00c0c/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00c10/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00c14/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00c18/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00c1c/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00c20/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00c24/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00c28/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00c2c/4, 0xffffffff);
+ INSTANCE_WR(ctx, 0x00c54/4, 0x00000005);
+ INSTANCE_WR(ctx, 0x00c60/4, 0x0000ffff);
+ INSTANCE_WR(ctx, 0x00c7c/4, 0x00005555);
+ INSTANCE_WR(ctx, 0x00c80/4, 0x00005555);
+ INSTANCE_WR(ctx, 0x00c84/4, 0x00005555);
+ INSTANCE_WR(ctx, 0x00c88/4, 0x00005555);
+ INSTANCE_WR(ctx, 0x00c8c/4, 0x00005555);
+ INSTANCE_WR(ctx, 0x00c90/4, 0x00005555);
+ INSTANCE_WR(ctx, 0x00c94/4, 0x00005555);
+ INSTANCE_WR(ctx, 0x00c98/4, 0x00005555);
+ INSTANCE_WR(ctx, 0x00c9c/4, 0x00000001);
+ INSTANCE_WR(ctx, 0x00cd4/4, 0x00000001);
+ INSTANCE_WR(ctx, 0x00cd8/4, 0x08e00001);
+ INSTANCE_WR(ctx, 0x00cdc/4, 0x000e3000);
+ for(i=0x030a0; i<=0x03118; i+=8)
+ INSTANCE_WR(ctx, i/4, 0x3f800000);
+ for(i=0x098a0; i<=0x0ba90; i+=24)
+ INSTANCE_WR(ctx, i/4, 0x00000001);
+ for(i=0x0baa0; i<=0x0be90; i+=16)
+ INSTANCE_WR(ctx, i/4, 0x3f800000);
+ for(i=0x0e2e0; i<=0x0fff0; i+=24)
+ INSTANCE_WR(ctx, i/4, 0x00000001);
+ for(i=0x10008; i<=0x104d0; i+=24)
+ INSTANCE_WR(ctx, i/4, 0x00000001);
+ for(i=0x104e0; i<=0x108d0; i+=16)
+ INSTANCE_WR(ctx, i/4, 0x3f800000);
+ for(i=0x12d20; i<=0x14f10; i+=24)
+ INSTANCE_WR(ctx, i/4, 0x00000001);
+ for(i=0x14f20; i<=0x15310; i+=16)
+ INSTANCE_WR(ctx, i/4, 0x3f800000);
+ for(i=0x17760; i<=0x19950; i+=24)
+ INSTANCE_WR(ctx, i/4, 0x00000001);
+ for(i=0x19960; i<=0x19d50; i+=16)
+ INSTANCE_WR(ctx, i/4, 0x3f800000);
+}
-static void nv4c_graph_context_init(drm_device_t *dev, struct mem_block *ctx)
+static void
+nv4c_graph_context_init(drm_device_t *dev, struct mem_block *ctx)
{
drm_nouveau_private_t *dev_priv = dev->dev_private;
int i;
@@ -648,7 +1116,8 @@ static void nv4c_graph_context_init(drm_device_t *dev, struct mem_block *ctx)
INSTANCE_WR(ctx, i/4, 0x3f800000);
}
-static void nv4e_graph_context_init(drm_device_t *dev, struct mem_block *ctx)
+static void
+nv4e_graph_context_init(drm_device_t *dev, struct mem_block *ctx)
{
drm_nouveau_private_t *dev_priv = dev->dev_private;
int i;
@@ -755,7 +1224,7 @@ static void nv4e_graph_context_init(drm_device_t *dev, struct mem_block *ctx)
}
int
-nv40_graph_context_create(drm_device_t *dev, int channel)
+nv40_graph_create_context(drm_device_t *dev, int channel)
{
drm_nouveau_private_t *dev_priv =
(drm_nouveau_private_t *)dev->dev_private;
@@ -777,10 +1246,18 @@ nv40_graph_context_create(drm_device_t *dev, int channel)
ctx_size = NV46_GRCTX_SIZE;
ctx_init = nv46_graph_context_init;
break;
+ case 0x49:
+ ctx_size = NV49_GRCTX_SIZE;
+ ctx_init = nv49_graph_context_init;
+ break;
case 0x4a:
ctx_size = NV4A_GRCTX_SIZE;
ctx_init = nv4a_graph_context_init;
break;
+ case 0x4b:
+ ctx_size = NV4B_GRCTX_SIZE;
+ ctx_init = nv4b_graph_context_init;
+ break;
case 0x4c:
ctx_size = NV4C_GRCTX_SIZE;
ctx_init = nv4c_graph_context_init;
@@ -808,89 +1285,99 @@ nv40_graph_context_create(drm_device_t *dev, int channel)
return 0;
}
-/* Save current context (from PGRAPH) into the channel's context
- *XXX: fails sometimes, not sure why..
- */
void
-nv40_graph_context_save_current(drm_device_t *dev)
+nv40_graph_destroy_context(drm_device_t *dev, int channel)
{
- drm_nouveau_private_t *dev_priv =
- (drm_nouveau_private_t *)dev->dev_private;
- uint32_t instance;
- int i;
-
- NV_WRITE(NV04_PGRAPH_FIFO, 0);
+ drm_nouveau_private_t *dev_priv = dev->dev_private;
+ struct nouveau_fifo *chan = &dev_priv->fifos[channel];
- instance = NV_READ(0x40032C) & 0xFFFFF;
- if (!instance) {
- NV_WRITE(NV04_PGRAPH_FIFO, 1);
- return;
+ if (chan->ramin_grctx) {
+ nouveau_instmem_free(dev, chan->ramin_grctx);
+ chan->ramin_grctx = NULL;
}
+}
+
+static int
+nv40_graph_transfer_context(drm_device_t *dev, uint32_t inst, int save)
+{
+ drm_nouveau_private_t *dev_priv = dev->dev_private;
+ uint32_t old_cp, tv = 1000;
+ int i;
- NV_WRITE(0x400784, instance);
- NV_WRITE(0x400310, NV_READ(0x400310) | 0x20);
- NV_WRITE(0x400304, 1);
- /* just in case, we don't want to spin in-kernel forever */
- for (i=0; i<1000; i++) {
- if (NV_READ(0x40030C) == 0)
+ old_cp = NV_READ(NV20_PGRAPH_CHANNEL_CTX_POINTER);
+ NV_WRITE(NV20_PGRAPH_CHANNEL_CTX_POINTER, inst);
+ NV_WRITE(NV40_PGRAPH_CTXCTL_0310,
+ save ? NV40_PGRAPH_CTXCTL_0310_XFER_SAVE :
+ NV40_PGRAPH_CTXCTL_0310_XFER_LOAD);
+ NV_WRITE(NV40_PGRAPH_CTXCTL_0304, NV40_PGRAPH_CTXCTL_0304_XFER_CTX);
+
+ for (i = 0; i < tv; i++) {
+ if (NV_READ(NV40_PGRAPH_CTXCTL_030C) == 0)
break;
}
- if (i==1000) {
- DRM_ERROR("failed to save current grctx to ramin\n");
- DRM_ERROR("instance = 0x%08x\n", NV_READ(0x40032C));
- DRM_ERROR("0x40030C = 0x%08x\n", NV_READ(0x40030C));
- NV_WRITE(NV04_PGRAPH_FIFO, 1);
- return;
+ NV_WRITE(NV20_PGRAPH_CHANNEL_CTX_POINTER, old_cp);
+
+ if (i == tv) {
+ DRM_ERROR("failed: inst=0x%08x save=%d\n", inst, save);
+ DRM_ERROR("0x40030C = 0x%08x\n",
+ NV_READ(NV40_PGRAPH_CTXCTL_030C));
+ return DRM_ERR(EBUSY);
}
- NV_WRITE(NV04_PGRAPH_FIFO, 1);
+ return 0;
+}
+
+/* Save current context (from PGRAPH) into the channel's context
+ *XXX: fails sometimes, not sure why..
+ */
+int
+nv40_graph_save_context(drm_device_t *dev, int channel)
+{
+ drm_nouveau_private_t *dev_priv = dev->dev_private;
+ struct nouveau_fifo *chan = &dev_priv->fifos[channel];
+ uint32_t inst;
+
+ if (!chan->ramin_grctx)
+ return DRM_ERR(EINVAL);
+ inst = nouveau_chip_instance_get(dev, chan->ramin_grctx);
+
+ return nv40_graph_transfer_context(dev, inst, 1);
}
/* Restore the context for a specific channel into PGRAPH
* XXX: fails sometimes.. not sure why
*/
-void
-nv40_graph_context_restore(drm_device_t *dev, int channel)
+int
+nv40_graph_load_context(drm_device_t *dev, int channel)
{
- drm_nouveau_private_t *dev_priv =
- (drm_nouveau_private_t *)dev->dev_private;
+ drm_nouveau_private_t *dev_priv = dev->dev_private;
struct nouveau_fifo *chan = &dev_priv->fifos[channel];
- uint32_t instance;
- int i;
+ uint32_t inst;
+ int ret;
- instance = nouveau_chip_instance_get(dev, chan->ramin_grctx);
-
- NV_WRITE(NV04_PGRAPH_FIFO, 0);
- NV_WRITE(0x400784, instance);
- NV_WRITE(0x400310, NV_READ(0x400310) | 0x40);
- NV_WRITE(0x400304, 1);
- /* just in case, we don't want to spin in-kernel forever */
- for (i=0; i<1000; i++) {
- if (NV_READ(0x40030C) == 0)
- break;
- }
- if (i==1000) {
- DRM_ERROR("failed to restore grctx for ch%d to PGRAPH\n",
- channel);
- DRM_ERROR("instance = 0x%08x\n", instance);
- DRM_ERROR("0x40030C = 0x%08x\n", NV_READ(0x40030C));
- NV_WRITE(NV04_PGRAPH_FIFO, 1);
- return;
- }
+ if (!chan->ramin_grctx)
+ return DRM_ERR(EINVAL);
+ inst = nouveau_chip_instance_get(dev, chan->ramin_grctx);
+ ret = nv40_graph_transfer_context(dev, inst, 0);
+ if (ret)
+ return ret;
/* 0x40032C, no idea of it's exact function. Could simply be a
* record of the currently active PGRAPH context. It's currently
* unknown as to what bit 24 does. The nv ddx has it set, so we will
* set it here too.
*/
- NV_WRITE(0x40032C, instance | 0x01000000);
+ NV_WRITE(NV20_PGRAPH_CHANNEL_CTX_POINTER, inst);
+ NV_WRITE(NV40_PGRAPH_CTXCTL_CUR,
+ (inst & NV40_PGRAPH_CTXCTL_CUR_INST_MASK) |
+ NV40_PGRAPH_CTXCTL_CUR_LOADED);
/* 0x32E0 records the instance address of the active FIFO's PGRAPH
* context. If at any time this doesn't match 0x40032C, you will
* recieve PGRAPH_INTR_CONTEXT_SWITCH
*/
- NV_WRITE(NV40_PFIFO_GRCTX_INSTANCE, instance);
- NV_WRITE(NV04_PGRAPH_FIFO, 1);
+ NV_WRITE(NV40_PFIFO_GRCTX_INSTANCE, inst);
+ return 0;
}
/* Some voodoo that makes context switching work without the binary driver
@@ -1007,6 +1494,39 @@ static uint32_t nv46_ctx_voodoo[] = {
0x00600009, 0x00700005, 0x00700006, 0x0060000e, ~0
};
+//this is used for nv49 and nv4b
+static uint32_t nv49_4b_ctx_voodoo[] ={
+ 0x00400564, 0x00400505, 0x00408165, 0x00408206, 0x00409e68, 0x00200020,
+ 0x0060000a, 0x00700080, 0x00104042, 0x00200020, 0x0060000a, 0x00700000,
+ 0x001040c5, 0x00400f26, 0x00401068, 0x0060000d, 0x0070008f, 0x0070000e,
+ 0x00408d68, 0x004015e6, 0x007000a0, 0x00700080, 0x0040180f, 0x00700000,
+ 0x00200029, 0x0060000a, 0x0011814d, 0x00110158, 0x00105401, 0x0020003a,
+ 0x00100051, 0x001040c5, 0x0010c1c4, 0x001041c9, 0x0010c1dc, 0x00150210,
+ 0x0012c225, 0x00108238, 0x0010823e, 0x001242c0, 0x00200040, 0x00100280,
+ 0x00128100, 0x00128120, 0x00128143, 0x0011415f, 0x0010815c, 0x0010c140,
+ 0x00104029, 0x00110400, 0x00104d12, 0x00500060, 0x004071e6, 0x00200118,
+ 0x0060000a, 0x00200020, 0x00100620, 0x00154650, 0x00104668, 0x0017466d,
+ 0x0011068b, 0x00168691, 0x001046ae, 0x001046b0, 0x001206b4, 0x001046c4,
+ 0x001146c6, 0x00200022, 0x001006cc, 0x001246f0, 0x002000c0, 0x00100700,
+ 0x0010c3d7, 0x001043e1, 0x00500060, 0x00200290, 0x0060000a, 0x00104800,
+ 0x00108901, 0x00124920, 0x0020001f, 0x00100940, 0x00140965, 0x00144a00,
+ 0x00104a19, 0x0010ca1c, 0x00110b00, 0x00200028, 0x00100b08, 0x00134c2e,
+ 0x0010cd00, 0x0010cd04, 0x00120d08, 0x00104d80, 0x00104e00, 0x0012d600,
+ 0x00105c00, 0x00104f06, 0x00105406, 0x00105709, 0x00200340, 0x0060000a,
+ 0x00300000, 0x00200680, 0x00406a0f, 0x00200684, 0x00800001, 0x00200b88,
+ 0x0060000a, 0x00209540, 0x0040708a, 0x00201350, 0x00800041, 0x00407c0f,
+ 0x00600006, 0x00407ce6, 0x00700080, 0x002000a2, 0x0060000a, 0x00104280,
+ 0x00200340, 0x0060000a, 0x00200004, 0x00800001, 0x0070008e, 0x00408d68,
+ 0x0040020f, 0x00600006, 0x00409e68, 0x00600007, 0x0070000f, 0x0070000e,
+ 0x00408d68, 0x0091a880, 0x00901ffe, 0x10940000, 0x00200020, 0x0060000b,
+ 0x00500069, 0x0060000c, 0x00401568, 0x00700000, 0x00200001, 0x0040910e,
+ 0x00200021, 0x0060000a, 0x00409b0d, 0x00104a40, 0x00104a50, 0x00104a60,
+ 0x00104a70, 0x00104a80, 0x00104a90, 0x00104aa0, 0x00104ab0, 0x00407e0e,
+ 0x0040130f, 0x00408568, 0x0040a006, 0x0040a105, 0x00600009, 0x00700005,
+ 0x00700006, 0x0060000e, ~0
+};
+
+
static uint32_t nv4a_ctx_voodoo[] = {
0x00400889, 0x00200000, 0x0060000a, 0x00200000, 0x00300000, 0x00800001,
0x00700009, 0x0060000e, 0x00400d64, 0x00400d05, 0x00409965, 0x00409e06,
@@ -1100,7 +1620,9 @@ nv40_graph_init(drm_device_t *dev)
case 0x40: ctx_voodoo = nv40_ctx_voodoo; break;
case 0x43: ctx_voodoo = nv43_ctx_voodoo; break;
case 0x46: ctx_voodoo = nv46_ctx_voodoo; break;
+ case 0x49: ctx_voodoo = nv49_4b_ctx_voodoo; break;
case 0x4a: ctx_voodoo = nv4a_ctx_voodoo; break;
+ case 0x4b: ctx_voodoo = nv49_4b_ctx_voodoo; break;
case 0x4e: ctx_voodoo = nv4e_ctx_voodoo; break;
default:
DRM_ERROR("Unknown ctx_voodoo for chipset 0x%02x\n",
@@ -1114,15 +1636,15 @@ nv40_graph_init(drm_device_t *dev)
DRM_DEBUG("Loading context-switch voodoo\n");
i = 0;
- NV_WRITE(0x400324, 0);
+ NV_WRITE(NV40_PGRAPH_CTXCTL_UCODE_INDEX, 0);
while (ctx_voodoo[i] != ~0) {
- NV_WRITE(0x400328, ctx_voodoo[i]);
+ NV_WRITE(NV40_PGRAPH_CTXCTL_UCODE_DATA, ctx_voodoo[i]);
i++;
}
}
/* No context present currently */
- NV_WRITE(0x40032C, 0x00000000);
+ NV_WRITE(NV40_PGRAPH_CTXCTL_CUR, 0x00000000);
NV_WRITE(NV03_PGRAPH_INTR_EN, 0x00000000);
NV_WRITE(NV03_PGRAPH_INTR , 0xFFFFFFFF);
diff --git a/shared-core/nv50_fifo.c b/shared-core/nv50_fifo.c
new file mode 100644
index 00000000..e5d37949
--- /dev/null
+++ b/shared-core/nv50_fifo.c
@@ -0,0 +1,83 @@
+/*
+ * 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"
+
+static void
+nv50_fifo_init_reset(drm_device_t *dev)
+{
+ drm_nouveau_private_t *dev_priv = dev->dev_private;
+ uint32_t pmc_e;
+
+ pmc_e = NV_READ(NV03_PMC_ENABLE);
+ NV_WRITE(NV03_PMC_ENABLE, pmc_e & ~NV_PMC_ENABLE_PFIFO);
+ pmc_e = NV_READ(NV03_PMC_ENABLE);
+ NV_WRITE(NV03_PMC_ENABLE, pmc_e | NV_PMC_ENABLE_PFIFO);
+}
+
+int
+nv50_fifo_init(drm_device_t *dev)
+{
+ nv50_fifo_init_reset(dev);
+
+ DRM_ERROR("stub!\n");
+ return 0;
+}
+
+void
+nv50_fifo_takedown(drm_device_t *dev)
+{
+ DRM_ERROR("stub!\n");
+}
+
+int
+nv50_fifo_create_context(drm_device_t *dev, int channel)
+{
+ DRM_ERROR("stub!\n");
+ return 0;
+}
+
+void
+nv50_fifo_destroy_context(drm_device_t *dev, int channel)
+{
+}
+
+int
+nv50_fifo_load_context(drm_device_t *dev, int channel)
+{
+ DRM_ERROR("stub!\n");
+ return 0;
+}
+
+int
+nv50_fifo_save_context(drm_device_t *dev, int channel)
+{
+ DRM_ERROR("stub!\n");
+ return 0;
+}
+
diff --git a/shared-core/nv50_graph.c b/shared-core/nv50_graph.c
new file mode 100644
index 00000000..8c3e2b9b
--- /dev/null
+++ b/shared-core/nv50_graph.c
@@ -0,0 +1,84 @@
+/*
+ * 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"
+
+static void
+nv50_graph_init_reset(drm_device_t *dev)
+{
+ drm_nouveau_private_t *dev_priv = dev->dev_private;
+ uint32_t pmc_e;
+
+ pmc_e = NV_READ(NV03_PMC_ENABLE);
+ NV_WRITE(NV03_PMC_ENABLE, pmc_e & ~NV_PMC_ENABLE_PGRAPH);
+ pmc_e = NV_READ(NV03_PMC_ENABLE);
+ NV_WRITE(NV03_PMC_ENABLE, pmc_e | NV_PMC_ENABLE_PGRAPH);
+}
+
+int
+nv50_graph_init(drm_device_t *dev)
+{
+ nv50_graph_init_reset(dev);
+
+ DRM_ERROR("stub!\n");
+ return 0;
+}
+
+void
+nv50_graph_takedown(drm_device_t *dev)
+{
+ DRM_ERROR("stub!\n");
+}
+
+int
+nv50_graph_create_context(drm_device_t *dev, int channel)
+{
+ DRM_ERROR("stub!\n");
+ return 0;
+}
+
+void
+nv50_graph_destroy_context(drm_device_t *dev, int channel)
+{
+ DRM_ERROR("stub!\n");
+}
+
+int
+nv50_graph_load_context(drm_device_t *dev, int channel)
+{
+ DRM_ERROR("stub!\n");
+ return 0;
+}
+
+int
+nv50_graph_save_context(drm_device_t *dev, int channel)
+{
+ DRM_ERROR("stub!\n");
+ return 0;
+}
+
diff --git a/shared-core/nv50_mc.c b/shared-core/nv50_mc.c
new file mode 100644
index 00000000..7f7537f0
--- /dev/null
+++ b/shared-core/nv50_mc.c
@@ -0,0 +1,42 @@
+/*
+ * 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"
+
+int
+nv50_mc_init(drm_device_t *dev)
+{
+ drm_nouveau_private_t *dev_priv = dev->dev_private;
+
+ NV_WRITE(NV03_PMC_ENABLE, 0xFFFFFFFF);
+ return 0;
+}
+
+void nv50_mc_takedown(drm_device_t *dev)
+{
+}
diff --git a/shared-core/r300_cmdbuf.c b/shared-core/r300_cmdbuf.c
index d3c52d43..0cd5d7e2 100644
--- a/shared-core/r300_cmdbuf.c
+++ b/shared-core/r300_cmdbuf.c
@@ -155,7 +155,8 @@ void r300_init_reg_flags(void)
ADD_RANGE(R300_VAP_INPUT_CNTL_0, 2);
ADD_RANGE(0x21DC, 1);
ADD_RANGE(R300_VAP_UNKNOWN_221C, 1);
- ADD_RANGE(0x2220, 4);
+ ADD_RANGE(R300_VAP_CLIP_X_0, 4);
+ ADD_RANGE(R300_VAP_PVS_WAITIDLE, 1);
ADD_RANGE(R300_VAP_UNKNOWN_2288, 1);
ADD_RANGE(R300_VAP_OUTPUT_VTX_FMT_0, 2);
ADD_RANGE(R300_VAP_PVS_CNTL_1, 3);
diff --git a/shared-core/r300_reg.h b/shared-core/r300_reg.h
index 0a31f0b9..e59919be 100644
--- a/shared-core/r300_reg.h
+++ b/shared-core/r300_reg.h
@@ -116,6 +116,8 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
# define R300_VAP_OUTPUT_VTX_FMT_0__PT_SIZE_PRESENT (1<<16) /* GUESS */
#define R300_VAP_OUTPUT_VTX_FMT_1 0x2094
+ /* each of the following is 3 bits wide, specifies number
+ of components */
# define R300_VAP_OUTPUT_VTX_FMT_1__TEX_0_COMP_CNT_SHIFT 0
# define R300_VAP_OUTPUT_VTX_FMT_1__TEX_1_COMP_CNT_SHIFT 3
# define R300_VAP_OUTPUT_VTX_FMT_1__TEX_2_COMP_CNT_SHIFT 6
@@ -299,6 +301,18 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
# define R300_221C_NORMAL 0x00000000
# define R300_221C_CLEAR 0x0001C000
+/* These seem to be per-pixel and per-vertex X and Y clipping planes. The first
+ * plane is per-pixel and the second plane is per-vertex.
+ *
+ * This was determined by experimentation alone but I believe it is correct.
+ *
+ * These registers are called X_QUAD0_1_FL to X_QUAD0_4_FL by glxtest.
+ */
+#define R300_VAP_CLIP_X_0 0x2220
+#define R300_VAP_CLIP_X_1 0x2224
+#define R300_VAP_CLIP_Y_0 0x2228
+#define R300_VAP_CLIP_Y_1 0x2230
+
/* gap */
/* Sometimes, END_OF_PKT and 0x2284=0 are the only commands sent between
@@ -322,13 +336,15 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
* The meaning of the two UNKNOWN fields is obviously not known. However,
* experiments so far have shown that both *must* point to an instruction
* inside the vertex program, otherwise the GPU locks up.
+ *
* fglrx usually sets CNTL_3_UNKNOWN to the end of the program and
- * CNTL_1_UNKNOWN points to instruction where last write to position takes
- * place.
+ * R300_PVS_CNTL_1_POS_END_SHIFT points to instruction where last write to
+ * position takes place.
+ *
* Most likely this is used to ignore rest of the program in cases
* where group of verts arent visible. For some reason this "section"
* is sometimes accepted other instruction that have no relationship with
- *position calculations.
+ * position calculations.
*/
#define R300_VAP_PVS_CNTL_1 0x22D0
# define R300_PVS_CNTL_1_PROGRAM_START_SHIFT 0
@@ -967,7 +983,6 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
* first node is stored in NODE_2, the second node is stored in NODE_3.
*
* Offsets are relative to the master offset from PFS_CNTL_2.
- * LAST_NODE is set for the last node, and only for the last node.
*/
#define R300_PFS_NODE_0 0x4610
#define R300_PFS_NODE_1 0x4614
@@ -981,7 +996,6 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
# define R300_PFS_NODE_TEX_OFFSET_MASK (31 << 12)
# define R300_PFS_NODE_TEX_END_SHIFT 17
# define R300_PFS_NODE_TEX_END_MASK (31 << 17)
-/*# define R300_PFS_NODE_LAST_NODE (1 << 22) */
# define R300_PFS_NODE_OUTPUT_COLOR (1 << 22)
# define R300_PFS_NODE_OUTPUT_DEPTH (1 << 23)
@@ -1591,6 +1605,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
# define R300_EB_UNK1_SHIFT 24
# define R300_EB_UNK1 (0x80<<24)
# define R300_EB_UNK2 0x0810
+#define R300_PACKET3_3D_DRAW_VBUF_2 0x00003400
#define R300_PACKET3_3D_DRAW_INDX_2 0x00003600
/* END: Packet 3 commands */
diff --git a/shared-core/radeon_cp.c b/shared-core/radeon_cp.c
index bde98b30..ec2e688b 100644
--- a/shared-core/radeon_cp.c
+++ b/shared-core/radeon_cp.c
@@ -1190,9 +1190,15 @@ static void radeon_cp_init_ring_buffer(drm_device_t * dev,
/* Set ring buffer size */
#ifdef __BIG_ENDIAN
RADEON_WRITE(RADEON_CP_RB_CNTL,
- dev_priv->ring.size_l2qw | RADEON_BUF_SWAP_32BIT);
+ RADEON_BUF_SWAP_32BIT |
+ (dev_priv->ring.fetch_size_l2ow << 18) |
+ (dev_priv->ring.rptr_update_l2qw << 8) |
+ dev_priv->ring.size_l2qw);
#else
- RADEON_WRITE(RADEON_CP_RB_CNTL, dev_priv->ring.size_l2qw);
+ RADEON_WRITE(RADEON_CP_RB_CNTL,
+ (dev_priv->ring.fetch_size_l2ow << 18) |
+ (dev_priv->ring.rptr_update_l2qw << 8) |
+ dev_priv->ring.size_l2qw);
#endif
/* Start with assuming that writeback doesn't work */
@@ -1391,8 +1397,7 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
DRM_DEBUG("\n");
/* if we require new memory map but we don't have it fail */
- if ((dev_priv->flags & RADEON_NEW_MEMMAP) && !dev_priv->new_memmap)
- {
+ if ((dev_priv->flags & RADEON_NEW_MEMMAP) && !dev_priv->new_memmap) {
DRM_ERROR("Cannot initialise DRM on this card\nThis card requires a new X.org DDX for 3D\n");
radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL);
@@ -1424,6 +1429,10 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
return DRM_ERR(EINVAL);
}
+ /* Enable vblank on CRTC1 for older X servers
+ */
+ dev_priv->vblank_crtc = DRM_RADEON_VBLANK_CRTC1;
+
switch(init->func) {
case RADEON_INIT_R200_CP:
dev_priv->microcode_version = UCODE_R200;
@@ -1663,6 +1672,12 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
dev_priv->ring.size = init->ring_size;
dev_priv->ring.size_l2qw = drm_order(init->ring_size / 8);
+ dev_priv->ring.rptr_update = /* init->rptr_update */ 4096;
+ dev_priv->ring.rptr_update_l2qw = drm_order( /* init->rptr_update */ 4096 / 8);
+
+ dev_priv->ring.fetch_size = /* init->fetch_size */ 32;
+ dev_priv->ring.fetch_size_l2ow = drm_order( /* init->fetch_size */ 32 / 16);
+
dev_priv->ring.tail_mask = (dev_priv->ring.size / sizeof(u32)) - 1;
dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK;
diff --git a/shared-core/radeon_drm.h b/shared-core/radeon_drm.h
index e96e7851..6a57b804 100644
--- a/shared-core/radeon_drm.h
+++ b/shared-core/radeon_drm.h
@@ -655,6 +655,7 @@ typedef struct drm_radeon_indirect {
#define RADEON_PARAM_GART_TEX_HANDLE 10
#define RADEON_PARAM_SCRATCH_OFFSET 11
#define RADEON_PARAM_CARD_TYPE 12
+#define RADEON_PARAM_VBLANK_CRTC 13 /* VBLANK CRTC */
typedef struct drm_radeon_getparam {
int param;
@@ -709,7 +710,7 @@ typedef struct drm_radeon_setparam {
#define RADEON_SETPARAM_NEW_MEMMAP 4 /* Use new memory map */
#define RADEON_SETPARAM_PCIGART_TABLE_SIZE 5 /* PCI GART Table Size */
-
+#define RADEON_SETPARAM_VBLANK_CRTC 6 /* VBLANK CRTC */
/* 1.14: Clients can allocate/free a surface
*/
typedef struct drm_radeon_surface_alloc {
@@ -722,5 +723,7 @@ typedef struct drm_radeon_surface_free {
unsigned int address;
} drm_radeon_surface_free_t;
+#define DRM_RADEON_VBLANK_CRTC1 1
+#define DRM_RADEON_VBLANK_CRTC2 2
#endif
diff --git a/shared-core/radeon_drv.h b/shared-core/radeon_drv.h
index 4a36ea70..92a9b65e 100644
--- a/shared-core/radeon_drv.h
+++ b/shared-core/radeon_drv.h
@@ -97,10 +97,11 @@
* new packet type)
* 1.26- Add support for variable size PCI(E) gart aperture
* 1.27- Add support for IGP GART
+ * 1.28- Add support for VBL on CRTC2
*/
#define DRIVER_MAJOR 1
-#define DRIVER_MINOR 27
+#define DRIVER_MINOR 28
#define DRIVER_PATCHLEVEL 0
/*
@@ -163,8 +164,14 @@ typedef struct drm_radeon_freelist {
typedef struct drm_radeon_ring_buffer {
u32 *start;
u32 *end;
- int size;
- int size_l2qw;
+ int size; /* Double Words */
+ int size_l2qw; /* log2 Quad Words */
+
+ int rptr_update; /* Double Words */
+ int rptr_update_l2qw; /* log2 Quad Words */
+
+ int fetch_size; /* Double Words */
+ int fetch_size_l2ow; /* log2 Oct Words */
u32 tail;
u32 tail_mask;
@@ -279,6 +286,9 @@ typedef struct drm_radeon_private {
/* SW interrupt */
wait_queue_head_t swi_queue;
atomic_t swi_emitted;
+ int vblank_crtc;
+ uint32_t irq_enable_reg;
+ int irq_enabled;
struct radeon_surface surfaces[RADEON_MAX_SURFACES];
struct radeon_virt_surface virt_surfaces[2*RADEON_MAX_SURFACES];
@@ -355,10 +365,14 @@ extern int radeon_irq_wait(DRM_IOCTL_ARGS);
extern void radeon_do_release(drm_device_t * dev);
extern int radeon_driver_vblank_wait(drm_device_t * dev,
unsigned int *sequence);
+extern int radeon_driver_vblank_wait2(drm_device_t * dev,
+ unsigned int *sequence);
extern irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS);
extern void radeon_driver_irq_preinstall(drm_device_t * dev);
extern void radeon_driver_irq_postinstall(drm_device_t * dev);
extern void radeon_driver_irq_uninstall(drm_device_t * dev);
+extern int radeon_vblank_crtc_get(drm_device_t *dev);
+extern int radeon_vblank_crtc_set(drm_device_t *dev, int64_t value);
extern int radeon_driver_load(struct drm_device *dev, unsigned long flags);
extern int radeon_driver_unload(struct drm_device *dev);
@@ -495,12 +509,15 @@ extern int r300_do_cp_cmdbuf(drm_device_t *dev, DRMFILE filp,
#define RADEON_GEN_INT_CNTL 0x0040
# define RADEON_CRTC_VBLANK_MASK (1 << 0)
+# define RADEON_CRTC2_VBLANK_MASK (1 << 9)
# define RADEON_GUI_IDLE_INT_ENABLE (1 << 19)
# define RADEON_SW_INT_ENABLE (1 << 25)
#define RADEON_GEN_INT_STATUS 0x0044
# define RADEON_CRTC_VBLANK_STAT (1 << 0)
# define RADEON_CRTC_VBLANK_STAT_ACK (1 << 0)
+# define RADEON_CRTC2_VBLANK_STAT (1 << 9)
+# define RADEON_CRTC2_VBLANK_STAT_ACK (1 << 9)
# define RADEON_GUI_IDLE_INT_TEST_ACK (1 << 19)
# define RADEON_SW_INT_TEST (1 << 25)
# define RADEON_SW_INT_TEST_ACK (1 << 25)
@@ -601,9 +618,51 @@ extern int r300_do_cp_cmdbuf(drm_device_t *dev, DRMFILE filp,
# define RADEON_SOFT_RESET_E2 (1 << 5)
# define RADEON_SOFT_RESET_RB (1 << 6)
# define RADEON_SOFT_RESET_HDP (1 << 7)
+/*
+ * 6:0 Available slots in the FIFO
+ * 8 Host Interface active
+ * 9 CP request active
+ * 10 FIFO request active
+ * 11 Host Interface retry active
+ * 12 CP retry active
+ * 13 FIFO retry active
+ * 14 FIFO pipeline busy
+ * 15 Event engine busy
+ * 16 CP command stream busy
+ * 17 2D engine busy
+ * 18 2D portion of render backend busy
+ * 20 3D setup engine busy
+ * 26 GA engine busy
+ * 27 CBA 2D engine busy
+ * 31 2D engine busy or 3D engine busy or FIFO not empty or CP busy or
+ * command stream queue not empty or Ring Buffer not empty
+ */
#define RADEON_RBBM_STATUS 0x0e40
+/* Same as the previous RADEON_RBBM_STATUS; this is a mirror of that register. */
+/* #define RADEON_RBBM_STATUS 0x1740 */
+/* bits 6:0 are dword slots available in the cmd fifo */
# define RADEON_RBBM_FIFOCNT_MASK 0x007f
-# define RADEON_RBBM_ACTIVE (1 << 31)
+# define RADEON_HIRQ_ON_RBB (1 << 8)
+# define RADEON_CPRQ_ON_RBB (1 << 9)
+# define RADEON_CFRQ_ON_RBB (1 << 10)
+# define RADEON_HIRQ_IN_RTBUF (1 << 11)
+# define RADEON_CPRQ_IN_RTBUF (1 << 12)
+# define RADEON_CFRQ_IN_RTBUF (1 << 13)
+# define RADEON_PIPE_BUSY (1 << 14)
+# define RADEON_ENG_EV_BUSY (1 << 15)
+# define RADEON_CP_CMDSTRM_BUSY (1 << 16)
+# define RADEON_E2_BUSY (1 << 17)
+# define RADEON_RB2D_BUSY (1 << 18)
+# define RADEON_RB3D_BUSY (1 << 19) /* not used on r300 */
+# define RADEON_VAP_BUSY (1 << 20)
+# define RADEON_RE_BUSY (1 << 21) /* not used on r300 */
+# define RADEON_TAM_BUSY (1 << 22) /* not used on r300 */
+# define RADEON_TDM_BUSY (1 << 23) /* not used on r300 */
+# define RADEON_PB_BUSY (1 << 24) /* not used on r300 */
+# define RADEON_TIM_BUSY (1 << 25) /* not used on r300 */
+# define RADEON_GA_BUSY (1 << 26)
+# define RADEON_CBA2D_BUSY (1 << 27)
+# define RADEON_RBBM_ACTIVE (1 << 31)
#define RADEON_RE_LINE_PATTERN 0x1cd0
#define RADEON_RE_MISC 0x26c4
#define RADEON_RE_TOP_LEFT 0x26c0
diff --git a/shared-core/radeon_irq.c b/shared-core/radeon_irq.c
index 3ff0baa2..a4be86e3 100644
--- a/shared-core/radeon_irq.c
+++ b/shared-core/radeon_irq.c
@@ -73,18 +73,35 @@ irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS)
* outside the DRM
*/
stat = radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK |
- RADEON_CRTC_VBLANK_STAT));
+ RADEON_CRTC_VBLANK_STAT |
+ RADEON_CRTC2_VBLANK_STAT));
if (!stat)
return IRQ_NONE;
+ stat &= dev_priv->irq_enable_reg;
+
/* SW interrupt */
if (stat & RADEON_SW_INT_TEST) {
DRM_WAKEUP(&dev_priv->swi_queue);
}
/* VBLANK interrupt */
- if (stat & RADEON_CRTC_VBLANK_STAT) {
- atomic_inc(&dev->vbl_received);
+ if (stat & (RADEON_CRTC_VBLANK_STAT|RADEON_CRTC2_VBLANK_STAT)) {
+ int vblank_crtc = dev_priv->vblank_crtc;
+
+ if ((vblank_crtc &
+ (DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) ==
+ (DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) {
+ if (stat & RADEON_CRTC_VBLANK_STAT)
+ atomic_inc(&dev->vbl_received);
+ if (stat & RADEON_CRTC2_VBLANK_STAT)
+ atomic_inc(&dev->vbl_received2);
+ } else if (((stat & RADEON_CRTC_VBLANK_STAT) &&
+ (vblank_crtc & DRM_RADEON_VBLANK_CRTC1)) ||
+ ((stat & RADEON_CRTC2_VBLANK_STAT) &&
+ (vblank_crtc & DRM_RADEON_VBLANK_CRTC2)))
+ atomic_inc(&dev->vbl_received);
+
DRM_WAKEUP(&dev->vbl_queue);
drm_vbl_send_signals(dev);
}
@@ -127,19 +144,30 @@ static int radeon_wait_irq(drm_device_t * dev, int swi_nr)
return ret;
}
-int radeon_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence)
+int radeon_driver_vblank_do_wait(drm_device_t * dev, unsigned int *sequence,
+ int crtc)
{
drm_radeon_private_t *dev_priv =
(drm_radeon_private_t *) dev->dev_private;
unsigned int cur_vblank;
int ret = 0;
-
+ int ack = 0;
+ atomic_t *counter;
if (!dev_priv) {
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
return DRM_ERR(EINVAL);
}
- radeon_acknowledge_irqs(dev_priv, RADEON_CRTC_VBLANK_STAT);
+ if (crtc == DRM_RADEON_VBLANK_CRTC1) {
+ counter = &dev->vbl_received;
+ ack |= RADEON_CRTC_VBLANK_STAT;
+ } else if (crtc == DRM_RADEON_VBLANK_CRTC2) {
+ counter = &dev->vbl_received2;
+ ack |= RADEON_CRTC2_VBLANK_STAT;
+ } else
+ return DRM_ERR(EINVAL);
+
+ radeon_acknowledge_irqs(dev_priv, ack);
dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
@@ -148,7 +176,7 @@ int radeon_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence)
* using vertical blanks...
*/
DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
- (((cur_vblank = atomic_read(&dev->vbl_received))
+ (((cur_vblank = atomic_read(counter))
- *sequence) <= (1 << 23)));
*sequence = cur_vblank;
@@ -156,6 +184,16 @@ int radeon_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence)
return ret;
}
+int radeon_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence)
+{
+ return radeon_driver_vblank_do_wait(dev, sequence, DRM_RADEON_VBLANK_CRTC1);
+}
+
+int radeon_driver_vblank_wait2(drm_device_t *dev, unsigned int *sequence)
+{
+ return radeon_driver_vblank_do_wait(dev, sequence, DRM_RADEON_VBLANK_CRTC2);
+}
+
/* Needs the lock as it touches the ring.
*/
int radeon_irq_emit(DRM_IOCTL_ARGS)
@@ -204,6 +242,21 @@ int radeon_irq_wait(DRM_IOCTL_ARGS)
return radeon_wait_irq(dev, irqwait.irq_seq);
}
+static void radeon_enable_interrupt(drm_device_t *dev)
+{
+ drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private;
+
+ dev_priv->irq_enable_reg = RADEON_SW_INT_ENABLE;
+ if (dev_priv->vblank_crtc & DRM_RADEON_VBLANK_CRTC1)
+ dev_priv->irq_enable_reg |= RADEON_CRTC_VBLANK_MASK;
+
+ if (dev_priv->vblank_crtc & DRM_RADEON_VBLANK_CRTC2)
+ dev_priv->irq_enable_reg |= RADEON_CRTC2_VBLANK_MASK;
+
+ RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg);
+ dev_priv->irq_enabled = 1;
+}
+
/* drm_dma.h hooks
*/
void radeon_driver_irq_preinstall(drm_device_t * dev)
@@ -216,7 +269,8 @@ void radeon_driver_irq_preinstall(drm_device_t * dev)
/* Clear bits if they're already high */
radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK |
- RADEON_CRTC_VBLANK_STAT));
+ RADEON_CRTC_VBLANK_STAT |
+ RADEON_CRTC2_VBLANK_STAT));
}
void radeon_driver_irq_postinstall(drm_device_t * dev)
@@ -227,9 +281,7 @@ void radeon_driver_irq_postinstall(drm_device_t * dev)
atomic_set(&dev_priv->swi_emitted, 0);
DRM_INIT_WAITQUEUE(&dev_priv->swi_queue);
- /* Turn on SW and VBL ints */
- RADEON_WRITE(RADEON_GEN_INT_CNTL,
- RADEON_CRTC_VBLANK_MASK | RADEON_SW_INT_ENABLE);
+ radeon_enable_interrupt(dev);
}
void radeon_driver_irq_uninstall(drm_device_t * dev)
@@ -239,6 +291,38 @@ void radeon_driver_irq_uninstall(drm_device_t * dev)
if (!dev_priv)
return;
+ dev_priv->irq_enabled = 0;
+
/* Disable *all* interrupts */
RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
}
+
+
+int radeon_vblank_crtc_get(drm_device_t *dev)
+{
+ drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private;
+ u32 flag;
+ u32 value;
+
+ flag = RADEON_READ(RADEON_GEN_INT_CNTL);
+ value = 0;
+
+ if (flag & RADEON_CRTC_VBLANK_MASK)
+ value |= DRM_RADEON_VBLANK_CRTC1;
+
+ if (flag & RADEON_CRTC2_VBLANK_MASK)
+ value |= DRM_RADEON_VBLANK_CRTC2;
+ return value;
+}
+
+int radeon_vblank_crtc_set(drm_device_t *dev, int64_t value)
+{
+ drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private;
+ if (value & ~(DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) {
+ DRM_ERROR("called with invalid crtc 0x%x\n", (unsigned int)value);
+ return DRM_ERR(EINVAL);
+ }
+ dev_priv->vblank_crtc = (unsigned int)value;
+ radeon_enable_interrupt(dev);
+ return 0;
+}
diff --git a/shared-core/radeon_state.c b/shared-core/radeon_state.c
index bad054d7..8ccd0981 100644
--- a/shared-core/radeon_state.c
+++ b/shared-core/radeon_state.c
@@ -3131,6 +3131,9 @@ static int radeon_cp_getparam(DRM_IOCTL_ARGS)
else
value = RADEON_CARD_PCI;
break;
+ case RADEON_PARAM_VBLANK_CRTC:
+ value = radeon_vblank_crtc_get(dev);
+ break;
default:
DRM_DEBUG( "Invalid parameter %d\n", param.param );
return DRM_ERR(EINVAL);
@@ -3192,6 +3195,9 @@ static int radeon_cp_setparam(DRM_IOCTL_ARGS)
if (dev_priv->gart_info.table_size < RADEON_PCIGART_TABLE_SIZE)
dev_priv->gart_info.table_size = RADEON_PCIGART_TABLE_SIZE;
break;
+ case RADEON_SETPARAM_VBLANK_CRTC:
+ return radeon_vblank_crtc_set(dev, sp.value);
+ break;
default:
DRM_DEBUG("Invalid parameter %d\n", sp.param);
return DRM_ERR(EINVAL);
diff --git a/shared-core/sis_drv.h b/shared-core/sis_drv.h
index 006d148c..ec572ad4 100644
--- a/shared-core/sis_drv.h
+++ b/shared-core/sis_drv.h
@@ -33,11 +33,11 @@
#define DRIVER_AUTHOR "SIS, Tungsten Graphics"
#define DRIVER_NAME "sis"
-#define DRIVER_DESC "SIS 300/630/540"
-#define DRIVER_DATE "20060619"
+#define DRIVER_DESC "SIS 300/630/540 and XGI V3XE/V5/V8"
+#define DRIVER_DATE "20070626"
#define DRIVER_MAJOR 1
-#define DRIVER_MINOR 2
-#define DRIVER_PATCHLEVEL 1
+#define DRIVER_MINOR 3
+#define DRIVER_PATCHLEVEL 0
enum sis_family {
SIS_OTHER = 0,
diff --git a/shared-core/via_dma.c b/shared-core/via_dma.c
index c73634e4..333c4bcf 100644
--- a/shared-core/via_dma.c
+++ b/shared-core/via_dma.c
@@ -84,9 +84,9 @@ static uint32_t via_cmdbuf_lag(drm_via_private_t *dev_priv)
{
uint32_t agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
uint32_t hw_addr = *(dev_priv->hw_addr_ptr) - agp_base;
-
- return ((hw_addr <= dev_priv->dma_low) ?
- (dev_priv->dma_low - hw_addr) :
+
+ return ((hw_addr <= dev_priv->dma_low) ?
+ (dev_priv->dma_low - hw_addr) :
(dev_priv->dma_wrap + dev_priv->dma_low - hw_addr));
}
@@ -103,7 +103,7 @@ via_cmdbuf_wait(drm_via_private_t * dev_priv, unsigned int size)
uint32_t count;
hw_addr_ptr = dev_priv->hw_addr_ptr;
cur_addr = dev_priv->dma_low;
- next_addr = cur_addr + size + 512*1024;
+ next_addr = cur_addr + size + 512 * 1024;
count = 1000000;
do {
hw_addr = *hw_addr_ptr - agp_base;
@@ -207,8 +207,8 @@ static int via_initialize(drm_device_t * dev,
dev_priv->dma_offset = init->offset;
dev_priv->last_pause_ptr = NULL;
dev_priv->hw_addr_ptr =
- (volatile uint32_t *)((char *)dev_priv->mmio->handle +
- init->reg_pause_addr);
+ (volatile uint32_t *)((char *)dev_priv->mmio->handle +
+ init->reg_pause_addr);
via_cmdbuf_start(dev_priv);
@@ -239,8 +239,8 @@ static int via_dma_init(DRM_IOCTL_ARGS)
retcode = via_dma_cleanup(dev);
break;
case VIA_DMA_INITIALIZED:
- retcode = (dev_priv->ring.virtual_start != NULL) ?
- 0: DRM_ERR( EFAULT );
+ retcode = (dev_priv->ring.virtual_start != NULL) ?
+ 0 : DRM_ERR(EFAULT);
break;
default:
retcode = DRM_ERR(EINVAL);
@@ -268,8 +268,7 @@ static int via_dispatch_cmdbuffer(drm_device_t * dev, drm_via_cmdbuffer_t * cmd)
if (cmd->size > VIA_PCI_BUF_SIZE) {
return DRM_ERR(ENOMEM);
- }
-
+ }
if (DRM_COPY_FROM_USER(dev_priv->pci_buf, cmd->buf, cmd->size))
return DRM_ERR(EFAULT);
@@ -292,7 +291,7 @@ static int via_dispatch_cmdbuffer(drm_device_t * dev, drm_via_cmdbuffer_t * cmd)
}
memcpy(vb, dev_priv->pci_buf, cmd->size);
-
+
dev_priv->dma_low += cmd->size;
/*
@@ -301,7 +300,7 @@ static int via_dispatch_cmdbuffer(drm_device_t * dev, drm_via_cmdbuffer_t * cmd)
*/
if (cmd->size < 0x100)
- via_pad_cache(dev_priv,(0x100 - cmd->size) >> 3);
+ via_pad_cache(dev_priv, (0x100 - cmd->size) >> 3);
via_cmdbuf_pause(dev_priv);
return 0;
@@ -321,7 +320,7 @@ static int via_flush_ioctl(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
- LOCK_TEST_WITH_RETURN( dev, filp );
+ LOCK_TEST_WITH_RETURN(dev, filp);
return via_driver_dma_quiescent(dev);
}
@@ -332,7 +331,7 @@ static int via_cmdbuffer(DRM_IOCTL_ARGS)
drm_via_cmdbuffer_t cmdbuf;
int ret;
- LOCK_TEST_WITH_RETURN( dev, filp );
+ LOCK_TEST_WITH_RETURN(dev, filp);
DRM_COPY_FROM_USER_IOCTL(cmdbuf, (drm_via_cmdbuffer_t __user *) data,
sizeof(cmdbuf));
@@ -355,16 +354,16 @@ static int via_dispatch_pci_cmdbuffer(drm_device_t * dev,
if (cmd->size > VIA_PCI_BUF_SIZE) {
return DRM_ERR(ENOMEM);
- }
+ }
if (DRM_COPY_FROM_USER(dev_priv->pci_buf, cmd->buf, cmd->size))
return DRM_ERR(EFAULT);
-
- if ((ret =
- via_verify_command_stream((uint32_t *)dev_priv->pci_buf,
+
+ if ((ret =
+ via_verify_command_stream((uint32_t *) dev_priv->pci_buf,
cmd->size, dev, 0))) {
return ret;
}
-
+
ret =
via_parse_command_stream(dev, (const uint32_t *)dev_priv->pci_buf,
cmd->size);
@@ -377,7 +376,7 @@ static int via_pci_cmdbuffer(DRM_IOCTL_ARGS)
drm_via_cmdbuffer_t cmdbuf;
int ret;
- LOCK_TEST_WITH_RETURN( dev, filp );
+ LOCK_TEST_WITH_RETURN(dev, filp);
DRM_COPY_FROM_USER_IOCTL(cmdbuf, (drm_via_cmdbuffer_t __user *) data,
sizeof(cmdbuf));
@@ -393,7 +392,6 @@ static int via_pci_cmdbuffer(DRM_IOCTL_ARGS)
return 0;
}
-
static inline uint32_t *via_align_buffer(drm_via_private_t * dev_priv,
uint32_t * vb, int qw_count)
{
@@ -403,7 +401,6 @@ static inline uint32_t *via_align_buffer(drm_via_private_t * dev_priv,
return vb;
}
-
/*
* This function is used internally by ring buffer mangement code.
*
@@ -419,8 +416,7 @@ static inline uint32_t *via_get_dma(drm_via_private_t * dev_priv)
* modifying the pause address stored in the buffer itself. If
* the regulator has already paused, restart it.
*/
-
-static int via_hook_segment(drm_via_private_t *dev_priv,
+static int via_hook_segment(drm_via_private_t * dev_priv,
uint32_t pause_addr_hi, uint32_t pause_addr_lo,
int no_pci_fire)
{
@@ -479,7 +475,7 @@ static int via_wait_idle(drm_via_private_t * dev_priv)
}
static uint32_t *via_align_cmd(drm_via_private_t * dev_priv, uint32_t cmd_type,
- uint32_t addr, uint32_t *cmd_addr_hi,
+ uint32_t addr, uint32_t *cmd_addr_hi,
uint32_t *cmd_addr_lo, int skip_wait)
{
uint32_t agp_base;
@@ -508,9 +504,6 @@ static uint32_t *via_align_cmd(drm_via_private_t * dev_priv, uint32_t cmd_type,
return vb;
}
-
-
-
static void via_cmdbuf_start(drm_via_private_t * dev_priv)
{
uint32_t pause_addr_lo, pause_addr_hi;
diff --git a/shared-core/via_verifier.c b/shared-core/via_verifier.c
index b5a1d33a..4b844af0 100644
--- a/shared-core/via_verifier.c
+++ b/shared-core/via_verifier.c
@@ -255,7 +255,6 @@ static __inline__ drm_local_map_t *via_drm_lookup_agp_map(drm_via_state_t * seq,
drm_device_t * dev)
{
#ifdef __linux__
- struct list_head *list;
drm_map_list_t *r_list;
#endif
drm_local_map_t *map = seq->map_cache;
@@ -265,8 +264,7 @@ static __inline__ drm_local_map_t *via_drm_lookup_agp_map(drm_via_state_t * seq,
return map;
}
#ifdef __linux__
- list_for_each(list, &dev->maplist->head) {
- r_list = (drm_map_list_t *) list;
+ list_for_each_entry(r_list, &dev->maplist, head) {
map = r_list->map;
if (!map)
continue;