summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2014-08-10 04:10:21 +1000
committerBen Skeggs <bskeggs@redhat.com>2014-08-10 04:43:28 +1000
commitb7c81f0355379b9d0fcdf624a8df1b7119f28efc (patch)
tree21c37810cbdc088158e06ee75ee303a4af99d0f2
parentc0368d5441d90c6a2ac0583d7d2144c6d6baab8c (diff)
downloadnouveau-b7c81f0355379b9d0fcdf624a8df1b7119f28efc.tar.gz
nvif: import library functions for the ioctl/event interfaces
This is a wrapper around the interfaces defined in an earlier commit, and is also used by various userspace (either by a libdrm backend, or libpciaccess) tools/tests. In the future this will be extended to handle channels, replacing some long-unloved code we currently use, and allow fifo/display/mpeg (hi Ilia ;)) engines to all be exposed in the same way. Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r--Makefile.am2
-rw-r--r--bin/Makefile.am8
-rw-r--r--bin/nv_aux.c37
-rw-r--r--bin/nv_disp.c36
-rw-r--r--bin/nv_i2c.c37
-rw-r--r--bin/nv_init.c39
-rw-r--r--bin/nv_perfmon.c68
-rw-r--r--bin/nv_rd08.c2
-rw-r--r--bin/nv_rd16.c2
-rw-r--r--bin/nv_rd32.c2
-rw-r--r--bin/nv_rdfuc.c43
-rw-r--r--bin/nv_rdfunc.h27
-rw-r--r--bin/nv_rffunc.h12
-rw-r--r--bin/nv_rifunc.h12
-rw-r--r--bin/nv_rs08.c2
-rw-r--r--bin/nv_rs16.c2
-rw-r--r--bin/nv_rs32.c2
-rw-r--r--bin/nv_rsfunc.h16
-rw-r--r--bin/nv_rv08.c2
-rw-r--r--bin/nv_rv16.c2
-rw-r--r--bin/nv_rv32.c2
-rw-r--r--bin/nv_rvfunc.h10
-rw-r--r--bin/nv_wffunc.h12
-rw-r--r--bin/nv_wifunc.h12
-rw-r--r--bin/nv_wr08.c2
-rw-r--r--bin/nv_wr16.c2
-rw-r--r--bin/nv_wr32.c2
-rw-r--r--bin/nv_wrfunc.h27
-rw-r--r--bin/nv_ws08.c2
-rw-r--r--bin/nv_ws16.c2
-rw-r--r--bin/nv_ws32.c2
-rw-r--r--bin/nv_wsfunc.h10
-rw-r--r--bin/nv_wv08.c2
-rw-r--r--bin/nv_wv16.c2
-rw-r--r--bin/nv_wv32.c2
-rw-r--r--bin/nv_wvfunc.h10
-rw-r--r--configure.ac1
-rw-r--r--drm/Kbuild6
l---------drm/nvif/client.c1
l---------drm/nvif/client.h1
l---------drm/nvif/device.c1
l---------drm/nvif/device.h1
l---------drm/nvif/driver.h1
l---------drm/nvif/notify.c1
l---------drm/nvif/notify.h1
l---------drm/nvif/object.c1
l---------drm/nvif/object.h1
l---------drm/nvif/os.h1
-rw-r--r--lib/Makefile.am6
-rw-r--r--lib/core/os.h29
-rw-r--r--lib/main.c176
-rw-r--r--lib/priv.h8
-rw-r--r--nvif/Makefile.am12
-rw-r--r--nvif/client.c130
-rw-r--r--nvif/client.h39
-rw-r--r--nvif/device.c78
-rw-r--r--nvif/device.h66
-rw-r--r--nvif/driver.h20
-rw-r--r--nvif/list.h353
-rw-r--r--nvif/notify.c237
-rw-r--r--nvif/notify.h39
-rw-r--r--nvif/object.c302
-rw-r--r--nvif/object.h77
l---------nvif/os.h1
-rw-r--r--nvkm/Makefile.am10
-rw-r--r--nvkm/core/handle.c2
-rw-r--r--nvkm/engine/Makefile.engine3
-rw-r--r--nvkm/include/core/class.h2
68 files changed, 1711 insertions, 350 deletions
diff --git a/Makefile.am b/Makefile.am
index 5ef0598f5..bfd427ca0 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -2,4 +2,4 @@ AUTOMAKE_OPTIONS = foreign
ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
-SUBDIRS = nvkm lib bin
+SUBDIRS = nvkm lib nvif bin
diff --git a/bin/Makefile.am b/bin/Makefile.am
index a32acd71b..13f75fd5e 100644
--- a/bin/Makefile.am
+++ b/bin/Makefile.am
@@ -7,9 +7,7 @@ bin_PROGRAMS = \
nv_disp nv_i2c nv_aux nv_init nv_rdfuc nv_perfmon
AM_CPPFLAGS = -I$(top_srcdir)/nvkm/include \
- -I$(top_srcdir)/nvkm \
- -I$(top_srcdir)/lib/
+ -I$(top_srcdir)/lib/ \
+ -I$(top_srcdir)/
-LDADD = -lpciaccess -lncurses -lmenu -lform \
- $(top_srcdir)/lib/libpciaccessos.la \
- $(top_srcdir)/nvkm/libnouveau.la
+LDFLAGS = $(top_srcdir)/nvif/libnvif.la -lncurses -lmenu -lform
diff --git a/bin/nv_aux.c b/bin/nv_aux.c
index a1e4fe81f..00da6b305 100644
--- a/bin/nv_aux.c
+++ b/bin/nv_aux.c
@@ -2,17 +2,11 @@
#include <limits.h>
#include <unistd.h>
-#include <core/os.h>
-#include <core/object.h>
+#include <nvif/client.h>
+#include <nvif/device.h>
+#include <nvif/class.h>
#include <core/class.h>
-#include <core/device.h>
-
-#include <subdev/i2c.h>
-
-struct nouveau_object *client;
-struct nouveau_object *device;
-
static void
print_chan(struct nouveau_i2c_port *chan)
{
@@ -22,6 +16,12 @@ print_chan(struct nouveau_i2c_port *chan)
int
main(int argc, char **argv)
{
+ const char *drv = "libnvkm";
+ const char *cfg = NULL;
+ const char *dbg = "error";
+ u64 dev = ~0ULL;
+ struct nvif_client *client;
+ struct nvif_device *device;
struct nouveau_i2c_port *chan;
struct nouveau_i2c *i2c;
int action = -1, index = -1;
@@ -29,8 +29,12 @@ main(int argc, char **argv)
int ret, c;
u8 data;
- while ((c = getopt(argc, argv, "-")) != -1) {
+ while ((c = getopt(argc, argv, "-a:b:c:d:")) != -1) {
switch (c) {
+ case 'a': dev = strtoull(optarg, NULL, 0); break;
+ case 'b': drv = optarg; break;
+ case 'c': cfg = optarg; break;
+ case 'd': dbg = optarg; break;
case 1:
if (action < 0) {
if (!strcasecmp(optarg, "rd"))
@@ -60,12 +64,12 @@ main(int argc, char **argv)
}
}
- ret = os_client_new(NULL, "error", argc, argv, &client);
+ ret = nvif_client_new(drv, argv[0], dev, cfg, dbg, &client);
if (ret)
return ret;
- ret = nouveau_object_new(client, ~0, 0, 0x0080,
- &(struct nv_device_class) {
+ ret = nvif_device_new(nvif_object(client), 0x00000000, NV_DEVICE_CLASS,
+ &(struct nv_device_class) {
.device = ~0ULL,
.disable = ~(NV_DEVICE_DISABLE_MMIO |
NV_DEVICE_DISABLE_IDENTIFY|
@@ -73,11 +77,12 @@ main(int argc, char **argv)
NV_DEVICE_DISABLE_CORE),
.debug0 = ~((1 << NVDEV_SUBDEV_VBIOS) |
(1 << NVDEV_SUBDEV_I2C)),
- }, sizeof(struct nv_device_class), &device);
+ }, sizeof(struct nv_device_class), &device);
+ nvif_client_ref(NULL, &client);
if (ret)
return ret;
- i2c = nouveau_i2c(device);
+ i2c = nvkm_i2c(device);
if (action < 0) {
list_for_each_entry(chan, &i2c->ports, head) {
@@ -113,6 +118,6 @@ main(int argc, char **argv)
}
done:
- os_client_del(&client);
+ nvif_device_ref(NULL, &device);
return ret;
}
diff --git a/bin/nv_disp.c b/bin/nv_disp.c
index b083e5219..7cf5a2c51 100644
--- a/bin/nv_disp.c
+++ b/bin/nv_disp.c
@@ -1,31 +1,27 @@
#include <stdlib.h>
-#include <core/os.h>
-#include <core/object.h>
-#include <core/device.h>
+#include <nvif/device.h>
static unsigned long chan = 0;
static void
-nv_disp(struct nouveau_object *device, u16 mthd, u32 data)
+nv_disp(struct nvif_device *device, u16 mthd, u32 data)
{
- if (nv_device(device)->card_type >= NV_50 &&
- nv_device(device)->chipset < 0xd0) {
- u32 ctrl = nv_ro32(device, 0x610300 + (chan * 8));
- nv_wo32(device, 0x610300 + (chan * 8), ctrl | 0x00000001);
- nv_wo32(device, 0x610304 + (chan * 8), data);
- nv_wo32(device, 0x610300 + (chan * 8), mthd | 0x80000001);
- while (nv_ro32(device, 0x610300 + (chan * 8)) & 0x80000000) {}
- nv_wo32(device, 0x610300 + (chan * 8), ctrl);
+ if (device->info.chipset >= 0xd0) {
+ u32 ctrl = nvif_rd32(device, 0x610700 + (chan * 16));
+ nvif_wr32(device, 0x610700 + (chan * 16), ctrl | 0x00000001);
+ nvif_wr32(device, 0x610704 + (chan * 16), data);
+ nvif_wr32(device, 0x610700 + (chan * 16), mthd | 0x80000001);
+ while (nvif_rd32(device, 0x610700 + (chan * 16)) & 0x80000000) {}
+ nvif_wr32(device, 0x610700 + (chan * 16), ctrl);
} else
- if (nv_device(device)->chipset >= 0xd0 &&
- nv_device(device)->card_type <= NV_E0) {
- u32 ctrl = nv_ro32(device, 0x610700 + (chan * 16));
- nv_wo32(device, 0x610700 + (chan * 16), ctrl | 0x00000001);
- nv_wo32(device, 0x610704 + (chan * 16), data);
- nv_wo32(device, 0x610700 + (chan * 16), mthd | 0x80000001);
- while (nv_ro32(device, 0x610700 + (chan * 16)) & 0x80000000) {}
- nv_wo32(device, 0x610700 + (chan * 16), ctrl);
+ if (device->info.family >= NV_DEVICE_INFO_V0_TESLA) {
+ u32 ctrl = nvif_rd32(device, 0x610300 + (chan * 8));
+ nvif_wr32(device, 0x610300 + (chan * 8), ctrl | 0x00000001);
+ nvif_wr32(device, 0x610304 + (chan * 8), data);
+ nvif_wr32(device, 0x610300 + (chan * 8), mthd | 0x80000001);
+ while (nvif_rd32(device, 0x610300 + (chan * 8)) & 0x80000000) {}
+ nvif_wr32(device, 0x610300 + (chan * 8), ctrl);
} else {
printk("unsupported chipset\n");
exit(1);
diff --git a/bin/nv_i2c.c b/bin/nv_i2c.c
index 3b7114568..7b1c87952 100644
--- a/bin/nv_i2c.c
+++ b/bin/nv_i2c.c
@@ -2,17 +2,11 @@
#include <limits.h>
#include <unistd.h>
-#include <core/os.h>
-#include <core/object.h>
+#include <nvif/client.h>
+#include <nvif/device.h>
+#include <nvif/class.h>
#include <core/class.h>
-#include <core/device.h>
-
-#include <subdev/i2c.h>
-
-struct nouveau_object *client;
-struct nouveau_object *device;
-
static void
print_port(struct nouveau_i2c_port *port)
{
@@ -22,14 +16,24 @@ print_port(struct nouveau_i2c_port *port)
int
main(int argc, char **argv)
{
+ const char *drv = "libnvkm";
+ const char *cfg = NULL;
+ const char *dbg = "error";
+ u64 dev = ~0ULL;
+ struct nvif_client *client;
+ struct nvif_device *device;
struct nouveau_i2c_port *port;
struct nouveau_i2c *i2c;
int addr = -1, reg = -1, val = -1;
int action = -1, index = -1;
int ret, c;
- while ((c = getopt(argc, argv, "-")) != -1) {
+ while ((c = getopt(argc, argv, "-a:b:c:d:")) != -1) {
switch (c) {
+ case 'a': dev = strtoull(optarg, NULL, 0); break;
+ case 'b': drv = optarg; break;
+ case 'c': cfg = optarg; break;
+ case 'd': dbg = optarg; break;
case 1:
if (action < 0) {
if (!strcasecmp(optarg, "scan"))
@@ -66,12 +70,12 @@ main(int argc, char **argv)
}
}
- ret = os_client_new(NULL, "error", argc, argv, &client);
+ ret = nvif_client_new(drv, argv[0], dev, cfg, dbg, &client);
if (ret)
return ret;
- ret = nouveau_object_new(client, ~0, 0, 0x0080,
- &(struct nv_device_class) {
+ ret = nvif_device_new(nvif_object(client), 0, NV_DEVICE_CLASS,
+ &(struct nv_device_class) {
.device = ~0ULL,
.disable = ~(NV_DEVICE_DISABLE_MMIO |
NV_DEVICE_DISABLE_IDENTIFY|
@@ -79,11 +83,12 @@ main(int argc, char **argv)
NV_DEVICE_DISABLE_CORE),
.debug0 = ~((1 << NVDEV_SUBDEV_VBIOS) |
(1 << NVDEV_SUBDEV_I2C)),
- }, sizeof(struct nv_device_class), &device);
+ }, sizeof(struct nv_device_class), &device);
+ nvif_client_ref(NULL, &client);
if (ret)
return ret;
- i2c = nouveau_i2c(device);
+ i2c = nvkm_i2c(device);
if (action < 0) {
list_for_each_entry(port, &i2c->ports, head) {
@@ -146,6 +151,6 @@ main(int argc, char **argv)
}
done:
- os_client_del(&client);
+ nvif_device_ref(NULL, &device);
return ret;
}
diff --git a/bin/nv_init.c b/bin/nv_init.c
index fcd8c6ede..d012aa79e 100644
--- a/bin/nv_init.c
+++ b/bin/nv_init.c
@@ -2,23 +2,30 @@
#include <limits.h>
#include <unistd.h>
-#include <core/os.h>
-#include <core/object.h>
+#include <nvif/client.h>
+#include <nvif/driver.h>
+#include <nvif/device.h>
+#include <nvif/class.h>
#include <core/class.h>
-#include <core/device.h>
-
-struct nouveau_object *client;
-struct nouveau_object *device;
-
int
main(int argc, char **argv)
{
+ const char *drv = NULL;
+ const char *cfg = NULL;
+ const char *dbg = "info";
+ u64 dev = ~0ULL;
+ struct nvif_client *client;
+ struct nvif_device *device;
bool suspend = false, wait = false;
int ret, c;
- while ((c = getopt(argc, argv, "-sw")) != -1) {
+ while ((c = getopt(argc, argv, "-a:b:c:d:sw")) != -1) {
switch (c) {
+ case 'a': dev = strtoull(optarg, NULL, 0); break;
+ case 'b': drv = optarg; break;
+ case 'c': cfg = optarg; break;
+ case 'd': dbg = optarg; break;
case 's':
suspend = true;
break;
@@ -30,22 +37,23 @@ main(int argc, char **argv)
}
}
- ret = os_client_new(NULL, "info", argc, argv, &client);
+ ret = nvif_client_new(drv, argv[0], dev, cfg, dbg, &client);
if (ret)
return ret;
- ret = nouveau_object_new(client, ~0, 0, 0x0080,
- &(struct nv_device_class) {
+ ret = nvif_device_new(nvif_object(client), 0, NV_DEVICE_CLASS,
+ &(struct nv_device_class) {
.device = ~0ULL,
.disable = 0ULL,
.debug0 = 0ULL,
- }, sizeof(struct nv_device_class), &device);
+ }, sizeof(struct nv_device_class), &device);
+ nvif_client_ref(NULL, &client);
if (ret)
return ret;
if (suspend) {
- os_suspend();
- os_resume();
+ client->driver->suspend(client);
+ client->driver->resume(client);
}
while (wait && (c = getchar()) == EOF) {
@@ -53,8 +61,7 @@ main(int argc, char **argv)
}
printf("shutting down...\n");
- os_client_del(&client);
- nouveau_object_debug();
+ nvif_device_ref(NULL, &device);
printf("done!\n");
return ret;
}
diff --git a/bin/nv_perfmon.c b/bin/nv_perfmon.c
index 9285d7dbe..611a327a0 100644
--- a/bin/nv_perfmon.c
+++ b/bin/nv_perfmon.c
@@ -28,14 +28,14 @@
#include <menu.h>
#include <form.h>
-#include <core/object.h>
-#include <core/device.h>
+#include <nvif/client.h>
+#include <nvif/device.h>
+#include <nvif/class.h>
#include <core/class.h>
#include <sys/time.h>
-static struct nouveau_object *client;
-static struct nouveau_object *device;
+static struct nvif_device *device;
static char **signals;
static int nr_signals;
@@ -250,7 +250,7 @@ ui_menu_win = {
struct ui_main {
struct list_head head;
u32 handle;
- struct nouveau_object *object;
+ struct nvif_object object;
const char *name;
u32 clk;
u32 ctr;
@@ -263,7 +263,7 @@ static u32 ui_main_handle = 0xc0000000;
static void
ui_main_remove(struct ui_main *item)
{
- int ret = nouveau_object_del(client, 0x00000000, item->handle);
+ nvif_object_fini(&item->object);
list_del(&item->head);
free(item);
}
@@ -281,20 +281,19 @@ ui_main_select(void)
for (i = 0; i < nr_signals; i++) {
item = calloc(1, sizeof(*item));
item->handle = ui_main_handle++;
- item->object = NULL;
item->name = signals[i];
item->incr = 0;
- ret = nouveau_object_new(client, 0x00000000, item->handle,
- NV_PERFCTR_CLASS,
- &(struct nv_perfctr_class) {
+ ret = nvif_object_init(nvif_object(device), NULL, item->handle,
+ NV_PERFCTR_CLASS,
+ &(struct nv_perfctr_class) {
.logic_op = 0xaaaa,
.signal[0].name =
(char *)item->name,
.signal[0].size =
strlen(item->name)
- }, sizeof(struct nv_perfctr_class),
- &item->object);
+ }, sizeof(struct nv_perfctr_class),
+ &item->object);
assert(ret == 0);
list_add_tail(&item->head, &ui_main_list);
}
@@ -315,13 +314,14 @@ ui_main_alarm_handler(int signal)
if (!sampled) {
struct nv_perfctr_sample args;
- ret = nv_exec(item->object, NV_PERFCTR_SAMPLE,
- &args, sizeof(args));
+ ret = nvif_exec(&item->object, NV_PERFCTR_SAMPLE,
+ &args, sizeof(args));
assert(ret == 0);
sampled = true;
}
- ret = nv_exec(item->object, NV_PERFCTR_READ, &args, sizeof(args));
+ ret = nvif_exec(&item->object, NV_PERFCTR_READ,
+ &args, sizeof(args));
assert(ret == 0 || ret == -EAGAIN);
if (ret == 0) {
@@ -598,13 +598,22 @@ ui_resize(void)
int
main(int argc, char **argv)
{
+ const char *drv = NULL;
+ const char *cfg = NULL;
+ const char *dbg = "error";
+ u64 dev = ~0ULL;
+ struct nvif_client *client;
struct nv_perfctr_query args = {};
- struct nouveau_object *object;
+ struct nvif_object object;
int ret, c, k;
int scan = 0;
- while ((c = getopt(argc, argv, "-s")) != -1) {
+ while ((c = getopt(argc, argv, "-a:b:c:d:s")) != -1) {
switch (c) {
+ case 'a': dev = strtoull(optarg, NULL, 0); break;
+ case 'b': drv = optarg; break;
+ case 'c': cfg = optarg; break;
+ case 'd': dbg = optarg; break;
case 's':
scan = 1;
break;
@@ -613,13 +622,12 @@ main(int argc, char **argv)
}
}
-
- ret = os_client_new(NULL, "error", argc, argv, &client);
+ ret = nvif_client_new(drv, argv[0], dev, cfg, dbg, &client);
if (ret)
return ret;
- ret = nouveau_object_new(client, 0xffffffff, 0x00000000,
- NV_DEVICE_CLASS, &(struct nv_device_class) {
+ ret = nvif_device_new(nvif_object(client), 0x00000000,
+ NV_DEVICE_CLASS, &(struct nv_device_class) {
.device = ~0ULL,
.disable = ~(NV_DEVICE_DISABLE_MMIO |
NV_DEVICE_DISABLE_VBIOS |
@@ -627,7 +635,8 @@ main(int argc, char **argv)
NV_DEVICE_DISABLE_IDENTIFY),
.debug0 = ~((1ULL << NVDEV_SUBDEV_TIMER) |
(1ULL << NVDEV_ENGINE_PERFMON)),
- }, sizeof(struct nv_device_class), &device);
+ }, sizeof(struct nv_device_class), &device);
+ nvif_client_ref(NULL, &client);
if (ret)
return ret;
@@ -636,15 +645,15 @@ main(int argc, char **argv)
return 1;
}
- ret = nouveau_object_new(client, 0x00000000, 0xdeadbeef,
- NV_PERFCTR_CLASS, &(struct nv_perfctr_class) {
- }, sizeof(struct nv_perfctr_class), &object);
+ ret = nvif_object_init(nvif_object(device), NULL, 0xdeadbeef,
+ NV_PERFCTR_CLASS, &(struct nv_perfctr_class) {
+ }, sizeof(struct nv_perfctr_class), &object);
assert(ret == 0);
do {
u32 prev_iter = args.iter;
args.name = NULL;
- ret = nv_exec(object, NV_PERFCTR_QUERY, &args, sizeof(args));
+ ret = nvif_exec(&object, NV_PERFCTR_QUERY, &args, sizeof(args));
assert(ret == 0);
if (prev_iter) {
@@ -654,12 +663,12 @@ main(int argc, char **argv)
args.iter = prev_iter;
args.name = signals[nr_signals - 1];
- ret = nv_exec(object, NV_PERFCTR_QUERY,
- &args, sizeof(args));
+ ret = nvif_exec(&object, NV_PERFCTR_QUERY,
+ &args, sizeof(args));
assert(ret == 0);
}
} while (args.iter != 0xffffffff);
- nouveau_object_del(client, 0x00000000, 0xdeadbeef);
+ nvif_object_fini(&object);
initscr();
keypad(stdscr, TRUE);
@@ -692,5 +701,6 @@ main(int argc, char **argv)
while (nr_signals--)
free(signals[nr_signals]);
free(signals);
+ nvif_device_ref(NULL, &device);
return 0;
}
diff --git a/bin/nv_rd08.c b/bin/nv_rd08.c
index f3384416f..f368951fa 100644
--- a/bin/nv_rd08.c
+++ b/bin/nv_rd08.c
@@ -2,6 +2,6 @@
#define FMTDATA "0x%02x"
#define NAME "nv_rd08"
#define CAST u8
-#define READ(o) nv_ro08(device, (o))
+#define READ(o) nvif_rd08(device, (o))
#define MAIN main
#include "nv_rdfunc.h"
diff --git a/bin/nv_rd16.c b/bin/nv_rd16.c
index 4c37cb7a5..0b48a0b4f 100644
--- a/bin/nv_rd16.c
+++ b/bin/nv_rd16.c
@@ -2,6 +2,6 @@
#define FMTDATA "0x%04x"
#define NAME "nv_rd16"
#define CAST u16
-#define READ(o) nv_ro16(device, (o))
+#define READ(o) nvif_rd16(device, (o))
#define MAIN main
#include "nv_rdfunc.h"
diff --git a/bin/nv_rd32.c b/bin/nv_rd32.c
index 95cbd3b5c..88022a950 100644
--- a/bin/nv_rd32.c
+++ b/bin/nv_rd32.c
@@ -2,6 +2,6 @@
#define FMTDATA "0x%08x"
#define NAME "nv_rd32"
#define CAST u32
-#define READ(o) nv_ro32(device, (o))
+#define READ(o) nvif_rd32(device, (o))
#define MAIN main
#include "nv_rdfunc.h"
diff --git a/bin/nv_rdfuc.c b/bin/nv_rdfuc.c
index 540ac4253..1478eb13d 100644
--- a/bin/nv_rdfuc.c
+++ b/bin/nv_rdfuc.c
@@ -2,21 +2,28 @@
#include <limits.h>
#include <unistd.h>
-#include <core/os.h>
-#include <core/object.h>
+#include <nvif/client.h>
+#include <nvif/device.h>
+#include <nvif/class.h>
#include <core/class.h>
int
main(int argc, char **argv)
{
- struct nouveau_object *client;
- struct nouveau_object *device;
+ const char *drv = NULL;
+ const char *cfg = NULL;
+ const char *dbg = "error";
+ u64 dev = ~0ULL;
+ struct nvif_client *client;
+ struct nvif_device *device;
u32 fucbase = ~0;
int segment = -1;
int ret, c, i;
- while ((c = getopt(argc, argv, "-cd")) != -1) {
+ while ((c = getopt(argc, argv, "-a:b:cd")) != -1) {
switch (c) {
+ case 'a': dev = strtoull(optarg, NULL, 0); break;
+ case 'b': drv = optarg; break;
case 'c':
segment = 0;
break;
@@ -32,35 +39,35 @@ main(int argc, char **argv)
if (fucbase == ~0 || segment < 0 || segment > 1)
return 1;
- ret = os_client_new(NULL, "info", argc, argv, &client);
+ ret = nvif_client_new(drv, argv[0], dev, cfg, dbg, &client);
if (ret)
return ret;
- ret = nouveau_object_new(client, ~0, 0, 0x0080,
- &(struct nv_device_class) {
+ ret = nvif_device_new(nvif_object(client), 0x00000000, NV_DEVICE_CLASS,
+ &(struct nv_device_class) {
.device = ~0ULL,
.disable = ~NV_DEVICE_DISABLE_MMIO,
.debug0 = 0,
- }, sizeof(struct nv_device_class), &device);
+ }, sizeof(struct nv_device_class), &device);
+ nvif_client_ref(NULL, &client);
if (ret)
return ret;
if (segment == 0) {
- u32 size = (nv_ro32(device, fucbase + 0x0108) & 0x1ff) << 8;
- nv_wo32(device, fucbase + 0x0180, 0x02000000);
+ u32 size = (nvif_rd32(device, fucbase + 0x0108) & 0x1ff) << 8;
+ nvif_wr32(device, fucbase + 0x0180, 0x02000000);
for (i = 0; i < size; i += 4) {
if (!(i & 0xff))
- nv_wo32(device, fucbase + 0x0188, i >> 8);
- printf("0x%08x\n", nv_ro32(device, fucbase + 0x0184));
+ nvif_wr32(device, fucbase + 0x0188, i >> 8);
+ printf("0x%08x\n", nvif_rd32(device, fucbase + 0x0184));
}
} else {
- u32 size = (nv_ro32(device, fucbase + 0x0108) & 0x3fe00) >> 1;
- nv_wo32(device, fucbase + 0x01c0, 0x02000000);
+ u32 size = (nvif_rd32(device, fucbase + 0x0108) & 0x3fe00) >> 1;
+ nvif_wr32(device, fucbase + 0x01c0, 0x02000000);
for (i = 0; i < size; i += 4)
- printf("0x%08x\n", nv_ro32(device, fucbase + 0x01c4));
+ printf("0x%08x\n", nvif_rd32(device, fucbase + 0x01c4));
}
-
- os_client_del(&client);
+ nvif_device_ref(NULL, &device);
return 0;
}
diff --git a/bin/nv_rdfunc.h b/bin/nv_rdfunc.h
index d840ddd3e..fef29de7a 100644
--- a/bin/nv_rdfunc.h
+++ b/bin/nv_rdfunc.h
@@ -2,8 +2,9 @@
#include <limits.h>
#include <unistd.h>
-#include <core/os.h>
-#include <core/object.h>
+#include <nvif/client.h>
+#include <nvif/device.h>
+#include <nvif/class.h>
#include <core/class.h>
#ifndef ENABLE
@@ -16,8 +17,12 @@
int
main(int argc, char **argv)
{
- struct nouveau_object *client;
- struct nouveau_object *device;
+ const char *drv = NULL;
+ const char *cfg = NULL;
+ const char *dbg = "fatal";
+ u64 dev = ~0ULL;
+ struct nvif_client *client;
+ struct nvif_device *device;
struct nv_device_class args;
char *rstr = NULL;
enum {
@@ -34,8 +39,12 @@ main(int argc, char **argv)
int ndata = 0;
int ret, c;
- while ((c = getopt(argc, argv, "-qrw")) != -1) {
+ while ((c = getopt(argc, argv, "-a:b:c:d:qrw")) != -1) {
switch (c) {
+ case 'a': dev = strtoull(optarg, NULL, 0); break;
+ case 'b': drv = optarg; break;
+ case 'c': cfg = optarg; break;
+ case 'd': dbg = optarg; break;
case 'q': mode = QUIET; break;
case 'r': mode = RATES; break;
case 'w': mode = WATCH; break;
@@ -47,7 +56,7 @@ main(int argc, char **argv)
}
}
- ret = os_client_new(NULL, "fatal", argc, argv, &client);
+ ret = nvif_client_new(drv, argv[0], dev, cfg, dbg, &client);
if (ret)
return ret;
@@ -55,8 +64,9 @@ main(int argc, char **argv)
args.disable = ~ENABLE;
args.debug0 = ~DEBUG0;
- ret = nouveau_object_new(client, ~0, 0, 0x0080, &args, sizeof(args),
- &device);
+ ret = nvif_device_new(nvif_object(client), 0x00000000, NV_DEVICE_CLASS,
+ &args, sizeof(args), &device);
+ nvif_client_ref(NULL, &client);
if (ret)
return ret;
@@ -140,5 +150,6 @@ main(int argc, char **argv)
}
free(data);
+ nvif_device_ref(NULL, &device);
return 0;
}
diff --git a/bin/nv_rffunc.h b/bin/nv_rffunc.h
index f7db0317f..31dc5c88e 100644
--- a/bin/nv_rffunc.h
+++ b/bin/nv_rffunc.h
@@ -1,20 +1,18 @@
#include <stdlib.h>
-#include <core/os.h>
-#include <core/object.h>
-#include <core/device.h>
+#include <nvif/device.h>
static void __iomem *map = NULL;
static u64 map_page = ~0ULL;
static CAST
-nv_rfb(struct nouveau_object *device, u64 offset)
+nv_rfb(struct nvif_device *device, u64 offset)
{
u64 page = (offset & ~(PAGE_SIZE - 1));
u64 addr = (offset & (PAGE_SIZE - 1));
- if (nv_device(device)->card_type < NV_04 ||
- nv_device(device)->card_type > NV_E0) {
+ if (device->info.family < NV_DEVICE_INFO_V0_TNT ||
+ device->info.family > NV_DEVICE_INFO_V0_MAXWELL) {
printk("unsupported chipset\n");
exit(1);
}
@@ -23,7 +21,7 @@ nv_rfb(struct nouveau_object *device, u64 offset)
if (map)
iounmap(map);
- map = ioremap(pci_resource_start(nv_device(device)->pdev, 1) +
+ map = ioremap(pci_resource_start(nvkm_device(device)->pdev, 1) +
page, PAGE_SIZE);
if (!map) {
printk("map failed\n");
diff --git a/bin/nv_rifunc.h b/bin/nv_rifunc.h
index 82fa77ba7..8041ea1b4 100644
--- a/bin/nv_rifunc.h
+++ b/bin/nv_rifunc.h
@@ -1,21 +1,19 @@
#include <stdlib.h>
-#include <core/os.h>
-#include <core/object.h>
-#include <core/device.h>
+#include <nvif/device.h>
static void __iomem *map = NULL;
static u64 map_page = ~0ULL;
static CAST
-nv_rfb(struct nouveau_object *device, u64 offset)
+nv_rfb(struct nvif_device *device, u64 offset)
{
- struct pci_dev *pdev = nv_device(device)->pdev;
+ struct pci_dev *pdev = nvkm_device(device)->pdev;
u64 page = (offset & ~(PAGE_SIZE - 1));
u64 addr = (offset & (PAGE_SIZE - 1));
- if (nv_device(device)->card_type < NV_40 ||
- nv_device(device)->card_type > NV_E0) {
+ if (device->info.family < NV_DEVICE_INFO_V0_CURIE ||
+ device->info.family > NV_DEVICE_INFO_V0_MAXWELL) {
printk("unsupported chipset\n");
exit(1);
}
diff --git a/bin/nv_rs08.c b/bin/nv_rs08.c
index b379d7fe8..63ad4f206 100644
--- a/bin/nv_rs08.c
+++ b/bin/nv_rs08.c
@@ -3,5 +3,5 @@
#define NAME "nv_rs08"
#define CAST u8
#define MAIN main
-#define RSYS nv_ro08
+#define RSYS nvif_rd08
#include "nv_rsfunc.h"
diff --git a/bin/nv_rs16.c b/bin/nv_rs16.c
index 6582197e6..148ee85c7 100644
--- a/bin/nv_rs16.c
+++ b/bin/nv_rs16.c
@@ -3,5 +3,5 @@
#define NAME "nv_rs16"
#define CAST u16
#define MAIN main
-#define RSYS nv_ro16
+#define RSYS nvif_rd16
#include "nv_rsfunc.h"
diff --git a/bin/nv_rs32.c b/bin/nv_rs32.c
index 326f49fd9..d29eb8755 100644
--- a/bin/nv_rs32.c
+++ b/bin/nv_rs32.c
@@ -3,5 +3,5 @@
#define NAME "nv_rs32"
#define CAST u32
#define MAIN main
-#define RSYS nv_ro32
+#define RSYS nvif_rd32
#include "nv_rsfunc.h"
diff --git a/bin/nv_rsfunc.h b/bin/nv_rsfunc.h
index c73f1f737..47b53fee8 100644
--- a/bin/nv_rsfunc.h
+++ b/bin/nv_rsfunc.h
@@ -1,19 +1,17 @@
#include <stdlib.h>
-#include <core/os.h>
-#include <core/object.h>
-#include <core/device.h>
+#include <nvif/device.h>
static CAST
-nv_rsys(struct nouveau_object *device, u64 addr)
+nv_rsys(struct nvif_device *device, u64 addr)
{
- if (nv_device(device)->card_type >= NV_50 &&
- nv_device(device)->card_type <= NV_E0) {
+ if (device->info.family >= NV_DEVICE_INFO_V0_TESLA &&
+ device->info.family <= NV_DEVICE_INFO_V0_MAXWELL) {
CAST data;
- u32 pmem = nv_ro32(device, 0x001700);
- nv_wo32(device, 0x001700, 0x02000000 | (addr >> 16));
+ u32 pmem = nvif_rd32(device, 0x001700);
+ nvif_wr32(device, 0x001700, 0x02000000 | (addr >> 16));
data = RSYS(device, 0x700000 + (addr & 0xffffULL));
- nv_wo32(device, 0x001700, pmem);
+ nvif_wr32(device, 0x001700, pmem);
return data;
} else {
printk("unsupported chipset\n");
diff --git a/bin/nv_rv08.c b/bin/nv_rv08.c
index 1b51c8f40..92a5ffbf1 100644
--- a/bin/nv_rv08.c
+++ b/bin/nv_rv08.c
@@ -3,5 +3,5 @@
#define NAME "nv_rv08"
#define CAST u8
#define MAIN main
-#define RVRAM nv_ro08
+#define RVRAM nvif_rd08
#include "nv_rvfunc.h"
diff --git a/bin/nv_rv16.c b/bin/nv_rv16.c
index 9f6b6e47e..c39e02da6 100644
--- a/bin/nv_rv16.c
+++ b/bin/nv_rv16.c
@@ -3,5 +3,5 @@
#define NAME "nv_rv16"
#define CAST u16
#define MAIN main
-#define RVRAM nv_ro16
+#define RVRAM nvif_rd16
#include "nv_rvfunc.h"
diff --git a/bin/nv_rv32.c b/bin/nv_rv32.c
index d147bf17a..f8320bea9 100644
--- a/bin/nv_rv32.c
+++ b/bin/nv_rv32.c
@@ -3,5 +3,5 @@
#define NAME "nv_rv32"
#define CAST u32
#define MAIN main
-#define RVRAM nv_ro32
+#define RVRAM nvif_rd32
#include "nv_rvfunc.h"
diff --git a/bin/nv_rvfunc.h b/bin/nv_rvfunc.h
index 18f43219c..590e959b2 100644
--- a/bin/nv_rvfunc.h
+++ b/bin/nv_rvfunc.h
@@ -1,14 +1,12 @@
#include <stdlib.h>
-#include <core/os.h>
-#include <core/object.h>
-#include <core/device.h>
+#include <nvif/device.h>
static CAST
-nv_rvram(struct nouveau_object *device, u64 addr)
+nv_rvram(struct nvif_device *device, u64 addr)
{
- if (nv_device(device)->card_type >= NV_50 &&
- nv_device(device)->card_type <= NV_E0) {
+ if (device->info.family >= NV_DEVICE_INFO_V0_TESLA &&
+ device->info.family <= NV_DEVICE_INFO_V0_MAXWELL) {
CAST data;
u32 pmem = nv_ro32(device, 0x001700);
nv_wo32(device, 0x001700, 0x00000000 | (addr >> 16));
diff --git a/bin/nv_wffunc.h b/bin/nv_wffunc.h
index 4166afd89..6aaf13176 100644
--- a/bin/nv_wffunc.h
+++ b/bin/nv_wffunc.h
@@ -1,20 +1,18 @@
#include <stdlib.h>
-#include <core/os.h>
-#include <core/object.h>
-#include <core/device.h>
+#include <nvif/device.h>
static void __iomem *map = NULL;
static u64 map_page = ~0ULL;
static void
-nv_wfb(struct nouveau_object *device, u64 offset, CAST data)
+nv_wfb(struct nvif_device *device, u64 offset, CAST data)
{
u64 page = (offset & ~(PAGE_SIZE - 1));
u64 addr = (offset & (PAGE_SIZE - 1));
- if (nv_device(device)->card_type < NV_04 ||
- nv_device(device)->card_type > NV_E0) {
+ if (device->info.family < NV_DEVICE_INFO_V0_TNT ||
+ device->info.family > NV_DEVICE_INFO_V0_MAXWELL) {
printk("unsupported chipset\n");
exit(1);
}
@@ -23,7 +21,7 @@ nv_wfb(struct nouveau_object *device, u64 offset, CAST data)
if (map)
iounmap(map);
- map = ioremap(pci_resource_start(nv_device(device)->pdev, 1) +
+ map = ioremap(pci_resource_start(nvkm_device(device)->pdev, 1) +
page, PAGE_SIZE);
if (!map) {
printk("map failed\n");
diff --git a/bin/nv_wifunc.h b/bin/nv_wifunc.h
index fa47d69ce..2ae519228 100644
--- a/bin/nv_wifunc.h
+++ b/bin/nv_wifunc.h
@@ -1,21 +1,19 @@
#include <stdlib.h>
-#include <core/os.h>
-#include <core/object.h>
-#include <core/device.h>
+#include <nvif/device.h>
static void __iomem *map = NULL;
static u64 map_page = ~0ULL;
static void
-nv_wfb(struct nouveau_object *device, u64 offset, CAST data)
+nv_wfb(struct nvif_device *device, u64 offset, CAST data)
{
- struct pci_dev *pdev = nv_device(device)->pdev;
+ struct pci_dev *pdev = nvkm_device(device)->pdev;
u64 page = (offset & ~(PAGE_SIZE - 1));
u64 addr = (offset & (PAGE_SIZE - 1));
- if (nv_device(device)->card_type < NV_40 ||
- nv_device(device)->card_type > NV_E0) {
+ if (device->info.family < NV_DEVICE_INFO_V0_CURIE ||
+ device->info.family > NV_DEVICE_INFO_V0_MAXWELL) {
printk("unsupported chipset\n");
exit(1);
}
diff --git a/bin/nv_wr08.c b/bin/nv_wr08.c
index 184bfef46..c81b69a79 100644
--- a/bin/nv_wr08.c
+++ b/bin/nv_wr08.c
@@ -2,6 +2,6 @@
#define FMTDATA "0x%02x"
#define NAME "nv_wr08"
#define CAST u8
-#define WRITE(o,v) nv_wo08(device, (o), (v))
+#define WRITE(o,v) nvif_wr08(device, (o), (v))
#define MAIN main
#include "nv_wrfunc.h"
diff --git a/bin/nv_wr16.c b/bin/nv_wr16.c
index 0e2271eb6..004b198a3 100644
--- a/bin/nv_wr16.c
+++ b/bin/nv_wr16.c
@@ -2,6 +2,6 @@
#define FMTDATA "0x%04x"
#define NAME "nv_wr16"
#define CAST u16
-#define WRITE(o,v) nv_wo16(device, (o), (v))
+#define WRITE(o,v) nvif_wr16(device, (o), (v))
#define MAIN main
#include "nv_wrfunc.h"
diff --git a/bin/nv_wr32.c b/bin/nv_wr32.c
index 6dd188840..2b8b60f32 100644
--- a/bin/nv_wr32.c
+++ b/bin/nv_wr32.c
@@ -2,6 +2,6 @@
#define FMTDATA "0x%08x"
#define NAME "nv_wr32"
#define CAST u32
-#define WRITE(o,v) nv_wo32(device, (o), (v))
+#define WRITE(o,v) nvif_wr32(device, (o), (v))
#define MAIN main
#include "nv_wrfunc.h"
diff --git a/bin/nv_wrfunc.h b/bin/nv_wrfunc.h
index eae75c248..c0e24efd1 100644
--- a/bin/nv_wrfunc.h
+++ b/bin/nv_wrfunc.h
@@ -2,8 +2,9 @@
#include <limits.h>
#include <unistd.h>
-#include <core/os.h>
-#include <core/object.h>
+#include <nvif/client.h>
+#include <nvif/device.h>
+#include <nvif/class.h>
#include <core/class.h>
#ifndef ENABLE
@@ -16,16 +17,24 @@
int
MAIN(int argc, char **argv)
{
- struct nouveau_object *client;
- struct nouveau_object *device;
+ const char *drv = NULL;
+ const char *cfg = NULL;
+ const char *dbg = "fatal";
+ u64 dev = ~0ULL;
+ struct nvif_client *client;
+ struct nvif_device *device;
struct nv_device_class args;
char *rstr = NULL;
char *vstr = NULL;
int quiet = 0;
int ret, c;
- while ((c = getopt(argc, argv, "-q")) != -1) {
+ while ((c = getopt(argc, argv, "-a:b:c:d:q")) != -1) {
switch (c) {
+ case 'a': dev = strtoull(optarg, NULL, 0); break;
+ case 'b': drv = optarg; break;
+ case 'c': cfg = optarg; break;
+ case 'd': dbg = optarg; break;
case 'q':
quiet = 1;
break;
@@ -41,7 +50,7 @@ MAIN(int argc, char **argv)
}
}
- ret = os_client_new(NULL, "fatal", argc, argv, &client);
+ ret = nvif_client_new(drv, argv[0], dev, cfg, dbg, &client);
if (ret)
return ret;
@@ -49,8 +58,9 @@ MAIN(int argc, char **argv)
args.disable = ~ENABLE;
args.debug0 = ~DEBUG0;
- ret = nouveau_object_new(client, ~0, 0, 0x0080, &args, sizeof(args),
- &device);
+ ret = nvif_device_new(nvif_object(client), 0, NV_DEVICE_CLASS,
+ &args, sizeof(args), &device);
+ nvif_client_ref(NULL, &client);
if (ret)
return ret;
@@ -97,5 +107,6 @@ MAIN(int argc, char **argv)
}
}
+ nvif_device_ref(NULL, &device);
return 0;
}
diff --git a/bin/nv_ws08.c b/bin/nv_ws08.c
index 5d49f2edc..3a301d3e8 100644
--- a/bin/nv_ws08.c
+++ b/bin/nv_ws08.c
@@ -3,5 +3,5 @@
#define NAME "nv_rs08"
#define CAST u8
#define MAIN main
-#define WSYS nv_wo08
+#define WSYS nvif_wr08
#include "nv_wsfunc.h"
diff --git a/bin/nv_ws16.c b/bin/nv_ws16.c
index a3f0702be..d53d1f6c5 100644
--- a/bin/nv_ws16.c
+++ b/bin/nv_ws16.c
@@ -3,5 +3,5 @@
#define NAME "nv_ws16"
#define CAST u16
#define MAIN main
-#define WSYS nv_wo16
+#define WSYS nvif_wr16
#include "nv_wsfunc.h"
diff --git a/bin/nv_ws32.c b/bin/nv_ws32.c
index 78756fe09..26103e064 100644
--- a/bin/nv_ws32.c
+++ b/bin/nv_ws32.c
@@ -3,5 +3,5 @@
#define NAME "nv_ws32"
#define CAST u32
#define MAIN main
-#define WSYS nv_wo32
+#define WSYS nvif_wr32
#include "nv_wsfunc.h"
diff --git a/bin/nv_wsfunc.h b/bin/nv_wsfunc.h
index 596eede5f..70feefb10 100644
--- a/bin/nv_wsfunc.h
+++ b/bin/nv_wsfunc.h
@@ -1,14 +1,12 @@
#include <stdlib.h>
-#include <core/os.h>
-#include <core/object.h>
-#include <core/device.h>
+#include <nvif/device.h>
static void
-nv_wsys(struct nouveau_object *device, u64 addr, CAST data)
+nv_wsys(struct nvif_device *device, u64 addr, CAST data)
{
- if (nv_device(device)->card_type >= NV_50 &&
- nv_device(device)->card_type <= NV_E0) {
+ if (device->info.family >= NV_DEVICE_INFO_V0_TESLA &&
+ device->info.family <= NV_DEVICE_INFO_V0_MAXWELL) {
u32 pmem = nv_ro32(device, 0x001700);
nv_wo32(device, 0x001700, 0x02000000 | (addr >> 16));
WSYS(device, 0x700000 + (addr & 0xffffULL), data);
diff --git a/bin/nv_wv08.c b/bin/nv_wv08.c
index c78d42e83..7c032b4f8 100644
--- a/bin/nv_wv08.c
+++ b/bin/nv_wv08.c
@@ -3,5 +3,5 @@
#define NAME "nv_wv08"
#define CAST u8
#define MAIN main
-#define WVRAM nv_wo08
+#define WVRAM nvif_wr08
#include "nv_wvfunc.h"
diff --git a/bin/nv_wv16.c b/bin/nv_wv16.c
index d738cf89f..853330657 100644
--- a/bin/nv_wv16.c
+++ b/bin/nv_wv16.c
@@ -3,5 +3,5 @@
#define NAME "nv_wv16"
#define CAST u16
#define MAIN main
-#define WVRAM nv_wo16
+#define WVRAM nvif_wr16
#include "nv_wvfunc.h"
diff --git a/bin/nv_wv32.c b/bin/nv_wv32.c
index ba381a38e..e414246c6 100644
--- a/bin/nv_wv32.c
+++ b/bin/nv_wv32.c
@@ -3,5 +3,5 @@
#define NAME "nv_wv32"
#define CAST u32
#define MAIN main
-#define WVRAM nv_wo32
+#define WVRAM nvif_wr32
#include "nv_wvfunc.h"
diff --git a/bin/nv_wvfunc.h b/bin/nv_wvfunc.h
index 1f218ffc6..2832f168d 100644
--- a/bin/nv_wvfunc.h
+++ b/bin/nv_wvfunc.h
@@ -1,14 +1,12 @@
#include <stdlib.h>
-#include <core/os.h>
-#include <core/object.h>
-#include <core/device.h>
+#include <nvif/device.h>
static void
-nv_wvram(struct nouveau_object *device, u64 addr, CAST data)
+nv_wvram(struct nvif_device *device, u64 addr, CAST data)
{
- if (nv_device(device)->card_type >= NV_50 &&
- nv_device(device)->card_type <= NV_E0) {
+ if (device->info.family >= NV_DEVICE_INFO_V0_TESLA &&
+ device->info.family <= NV_DEVICE_INFO_V0_MAXWELL) {
u32 pmem = nv_ro32(device, 0x001700);
nv_wo32(device, 0x001700, 0x00000000 | (addr >> 16));
WVRAM(device, 0x700000 + (addr & 0xffffULL), data);
diff --git a/configure.ac b/configure.ac
index 412617c70..1fe543a90 100644
--- a/configure.ac
+++ b/configure.ac
@@ -100,6 +100,7 @@ AC_OUTPUT( Makefile \
nvkm/engine/ppp/Makefile \
nvkm/engine/software/Makefile \
nvkm/engine/vp/Makefile \
+ nvif/Makefile \
lib/Makefile \
bin/Makefile \
)
diff --git a/drm/Kbuild b/drm/Kbuild
index dfab37646..3cddb955a 100644
--- a/drm/Kbuild
+++ b/drm/Kbuild
@@ -327,6 +327,12 @@ nouveau-y += core/engine/vp/nv98.o
nouveau-y += core/engine/vp/nvc0.o
nouveau-y += core/engine/vp/nve0.o
+# nvif
+nouveau-y += nvif/object.o
+nouveau-y += nvif/client.o
+nouveau-y += nvif/device.o
+nouveau-y += nvif/notify.o
+
# drm/core
nouveau-y += nouveau_drm.o nouveau_chan.o nouveau_dma.o nouveau_fence.o
nouveau-y += nouveau_vga.o nouveau_agp.o
diff --git a/drm/nvif/client.c b/drm/nvif/client.c
new file mode 120000
index 000000000..15dd1fc4c
--- /dev/null
+++ b/drm/nvif/client.c
@@ -0,0 +1 @@
+../../nvif/client.c \ No newline at end of file
diff --git a/drm/nvif/client.h b/drm/nvif/client.h
new file mode 120000
index 000000000..67ad32bab
--- /dev/null
+++ b/drm/nvif/client.h
@@ -0,0 +1 @@
+../../nvif/client.h \ No newline at end of file
diff --git a/drm/nvif/device.c b/drm/nvif/device.c
new file mode 120000
index 000000000..a72119778
--- /dev/null
+++ b/drm/nvif/device.c
@@ -0,0 +1 @@
+../../nvif/device.c \ No newline at end of file
diff --git a/drm/nvif/device.h b/drm/nvif/device.h
new file mode 120000
index 000000000..10e177638
--- /dev/null
+++ b/drm/nvif/device.h
@@ -0,0 +1 @@
+../../nvif/device.h \ No newline at end of file
diff --git a/drm/nvif/driver.h b/drm/nvif/driver.h
new file mode 120000
index 000000000..9623126e0
--- /dev/null
+++ b/drm/nvif/driver.h
@@ -0,0 +1 @@
+../../nvif/driver.h \ No newline at end of file
diff --git a/drm/nvif/notify.c b/drm/nvif/notify.c
new file mode 120000
index 000000000..3d890a74f
--- /dev/null
+++ b/drm/nvif/notify.c
@@ -0,0 +1 @@
+../../nvif/notify.c \ No newline at end of file
diff --git a/drm/nvif/notify.h b/drm/nvif/notify.h
new file mode 120000
index 000000000..1b142d2c2
--- /dev/null
+++ b/drm/nvif/notify.h
@@ -0,0 +1 @@
+../../nvif/notify.h \ No newline at end of file
diff --git a/drm/nvif/object.c b/drm/nvif/object.c
new file mode 120000
index 000000000..50285b0ce
--- /dev/null
+++ b/drm/nvif/object.c
@@ -0,0 +1 @@
+../../nvif/object.c \ No newline at end of file
diff --git a/drm/nvif/object.h b/drm/nvif/object.h
new file mode 120000
index 000000000..3c8a9e1de
--- /dev/null
+++ b/drm/nvif/object.h
@@ -0,0 +1 @@
+../../nvif/object.h \ No newline at end of file
diff --git a/drm/nvif/os.h b/drm/nvif/os.h
new file mode 120000
index 000000000..bd744b2cf
--- /dev/null
+++ b/drm/nvif/os.h
@@ -0,0 +1 @@
+../core/os.h \ No newline at end of file
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 352dd9f31..9eef51dca 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -1,8 +1,10 @@
noinst_LTLIBRARIES = libpciaccessos.la
libpciaccessos_la_CPPFLAGS = -I${top_srcdir}/nvkm/include \
- -I${top_srcdir}/nvkm
+ -I${top_srcdir}/nvkm \
+ -I${top_srcdir}
libpciaccessos_la_CFLAGS = @PCIACCESS_CFLAGS@
-libpciaccessos_la_LDFLAGS = @PCIACCESS_LIBS@ -lpthread
+libpciaccessos_la_LIBADD = @PCIACCESS_LIBS@ -lpthread \
+ $(top_srcdir)/nvkm/libnvkm.la
libpciaccessos_la_SOURCES = intr.c \
main.c
diff --git a/lib/core/os.h b/lib/core/os.h
index df8b1497e..fba954229 100644
--- a/lib/core/os.h
+++ b/lib/core/os.h
@@ -26,18 +26,6 @@
#define __NOUVEAU_OS_H__
/******************************************************************************
- * bootstrap interface
- *****************************************************************************/
-struct nouveau_object;
-
-int os_client_new(char *cfg, char *dbg, int argc, char **argv,
- struct nouveau_object **);
-void os_client_del(struct nouveau_object **);
-void os_suspend(void);
-void os_resume(void);
-void os_backtrace(void);
-
-/******************************************************************************
* types
*****************************************************************************/
#include <stddef.h>
@@ -45,15 +33,15 @@ void os_backtrace(void);
#include <stdbool.h>
#include <limits.h>
-#define u64 uint64_t
-#define u32 uint32_t
-#define u16 uint16_t
-#define u8 uint8_t
+typedef uint64_t u64;
+typedef uint32_t u32;
+typedef uint16_t u16;
+typedef uint8_t u8;
-#define s64 int64_t
-#define s32 int32_t
-#define s16 int16_t
-#define s8 int8_t
+typedef int64_t s64;
+typedef int32_t s32;
+typedef int16_t s16;
+typedef int8_t s8;
#ifndef _ASM_GENERIC_INT_LL64_H
typedef uint64_t __u64;
@@ -73,6 +61,7 @@ typedef dma_addr_t resource_size_t;
* various random macros
*****************************************************************************/
#define noinline __attribute__ ((noinline))
+#define __packed __attribute__ ((packed))
#define max(a,b) ((a) > (b) ? (a) : (b))
#define min(a,b) ((a) > (b) ? (b) : (a))
#define max_t(t,a,b) max((t)(a), (t)(b))
diff --git a/lib/main.c b/lib/main.c
index 0c62049bd..d18bd95fb 100644
--- a/lib/main.c
+++ b/lib/main.c
@@ -22,22 +22,29 @@
* Authors: Ben Skeggs
*/
-#include <core/os.h>
+#include <nvif/client.h>
+#include <nvif/driver.h>
+#include <nvif/notify.h>
+#include <nvif/ioctl.h>
+#include <nvif/class.h>
+#include <nvif/event.h>
#include <core/object.h>
+#include <core/handle.h>
#include <core/client.h>
#include <core/device.h>
#include <core/intr.h>
-#include <core/class.h>
+#include <core/ioctl.h>
+#include <core/event.h>
#include <engine/device.h>
#include <subdev/mc.h>
#include "priv.h"
+static DEFINE_MUTEX(os_mutex);
static LIST_HEAD(os_device_list);
-static LIST_HEAD(os_client_list);
-static int os_client_id = 0;
+static int os_client_nr = 0;
/******************************************************************************
* horrific stuff to implement linux's ioremap interface on top of pciaccess
@@ -126,7 +133,7 @@ nvos_iounmap(void __iomem *ptr)
* client interfaces
*****************************************************************************/
static int
-os_init_device(struct pci_device *pdev, u64 handle, char *cfg, char *dbg)
+os_init_device(struct pci_device *pdev, u64 handle, const char *cfg, const char *dbg)
{
struct os_device *odev;
struct pci_dev *ldev;
@@ -152,10 +159,7 @@ os_init_device(struct pci_device *pdev, u64 handle, char *cfg, char *dbg)
ldev->device = pdev->dev;
ldev->subsystem_vendor = pdev->subvendor_id;
ldev->subsystem_device = pdev->subdevice_id;
-
name = strdup(_name);
- cfg = cfg ? strdup(cfg) : NULL;
- dbg = dbg ? strdup(dbg) : NULL;
ret = nouveau_device_create(ldev, NOUVEAU_BUS_PCI, handle, name,
cfg, dbg, &odev);
@@ -166,13 +170,11 @@ os_init_device(struct pci_device *pdev, u64 handle, char *cfg, char *dbg)
list_add_tail(&odev->head, &os_device_list);
odev->name = name;
- odev->cfg = cfg;
- odev->dbg = dbg;
return 0;
}
static int
-os_init(char *cfg, char *dbg, bool init)
+os_init(const char *cfg, const char *dbg, bool init)
{
struct pci_device_iterator *iter;
struct pci_device *pdev;
@@ -217,120 +219,88 @@ os_fini(void)
list_for_each_entry_safe(odev, temp, &os_device_list, head) {
struct pci_dev *ldev = odev->base.pdev;
char *name = odev->name;
- char *cfg = odev->cfg;
- char *dbg = odev->dbg;
list_del(&odev->head);
nouveau_object_ref(NULL, (struct nouveau_object **)&odev);
- free(dbg); free(cfg); free(name); free(ldev);
+ free(name); free(ldev);
}
nouveau_object_debug();
pci_system_cleanup();
}
-int
-os_client_new(char *cfg, char *dbg, int argc, char **argv,
- struct nouveau_object **pclient)
+static void
+os_client_unmap(void *priv, void *ptr, u32 size)
{
- struct os_device *device = NULL, *odev;
- struct os_client *client;
- u64 handle = ~0ULL;
- int ret, c;
-
- while ((c = getopt(argc, argv, "la:i:c:d:")) != -1) {
- switch (c) {
- case 'l':
- return os_init(NULL, NULL, false);
- case 'a':
- handle = strtoull(optarg, NULL, 0);
- break;
- case 'c':
- cfg = optarg;
- break;
- case 'd':
- dbg = optarg;
- break;
- case '?':
- return -EINVAL;
- default:
- break;
- }
- }
-
- if (list_empty(&os_client_list)) {
- ret = os_init(cfg, dbg, true);
- if (ret)
- return ret;
- }
-
- c = 0;
- list_for_each_entry(odev, &os_device_list, head) {
- if (handle == ~0ULL || handle == c++ ||
- handle == odev->base.handle) {
- device = odev;
- break;
- }
- }
-
- if (device) {
- char name[16];
-
- snprintf(name, sizeof(name), "CLIENT%2d", os_client_id++);
-
- ret = nouveau_client_create(name, device->base.handle,
- cfg, dbg, &client);
- *pclient = nv_object(client);
- if (ret)
- return ret;
-
- list_add(&client->head, &os_client_list);
- return 0;
- }
-
- return -ENODEV;
+ iounmap(ptr);
}
-void
-os_client_del(struct nouveau_object **pclient)
+static void *
+os_client_map(void *priv, u64 handle, u32 size)
{
- struct nouveau_object *client = *pclient;
-
- if (client) {
- struct os_client *ocli = (void *)client;
-
- list_del(&ocli->head);
+ return ioremap(handle, size);
+}
- nouveau_client_fini(nv_client(client), false);
- atomic_set(&client->refcount, 1);
- nouveau_object_ref(NULL, &client);
+static int
+os_client_ioctl(void *priv, bool super, void *data, u32 size, void **hack)
+{
+ return nvkm_ioctl(priv, super, data, size, hack);
+}
- if (list_empty(&os_client_list))
- os_fini();
- }
+static int
+os_client_resume(void *priv)
+{
+ return nouveau_client_init(priv);
+}
- *pclient = NULL;
+static int
+os_client_suspend(void *priv)
+{
+ return nouveau_client_fini(priv, true);
}
-void
-os_suspend()
+static void
+os_client_fini(void *priv)
{
- struct os_client *client;
- int ret;
+ struct nouveau_object *object = priv;
- list_for_each_entry(client, &os_client_list, head) {
- ret = nouveau_client_fini(&client->base, true);
- assert(ret == 0);
- }
+ nouveau_client_fini(nv_client(object), false);
+ atomic_set(&object->refcount, 1);
+ nouveau_object_ref(NULL, &object);
+
+ mutex_lock(&os_mutex);
+ if (--os_client_nr == 0)
+ os_fini();
+ mutex_unlock(&os_mutex);
}
-void
-os_resume()
+static int
+os_client_init(const char *name, u64 device, const char *cfg,
+ const char *dbg, void **ppriv)
{
- struct os_client *client;
+ struct nouveau_client *client;
int ret;
- list_for_each_entry(client, &os_client_list, head) {
- ret = nouveau_client_init(&client->base);
- assert(ret == 0);
- }
+ mutex_lock(&os_mutex);
+ if (os_client_nr++ == 0)
+ os_init(cfg, dbg, true);
+ mutex_unlock(&os_mutex);
+
+ ret = nouveau_client_create(name, device, cfg, dbg, &client);
+ *ppriv = client;
+ if (ret == 0)
+ client->ntfy = nvif_notify;
+ return ret;
}
+
+const struct nvif_driver
+nvif_driver_lib = {
+ .name = "lib",
+ .init = os_client_init,
+ .fini = os_client_fini,
+ .suspend = os_client_suspend,
+ .resume = os_client_resume,
+ .ioctl = os_client_ioctl,
+ .map = os_client_map,
+ .unmap = os_client_unmap,
+ .keep = false,
+};
diff --git a/lib/priv.h b/lib/priv.h
index 161e23dd3..f9a12f23b 100644
--- a/lib/priv.h
+++ b/lib/priv.h
@@ -1,8 +1,7 @@
#ifndef __OS_PRIV_H__
#define __OS_PRIV_H__
-#include <core/os.h>
-#include <core/client.h>
+#include <core/device.h>
#include <pthread.h>
#include <unistd.h>
@@ -15,9 +14,4 @@ struct os_device {
char *dbg;
};
-struct os_client {
- struct nouveau_client base;
- struct list_head head;
-};
-
#endif
diff --git a/nvif/Makefile.am b/nvif/Makefile.am
new file mode 100644
index 000000000..23e331733
--- /dev/null
+++ b/nvif/Makefile.am
@@ -0,0 +1,12 @@
+lib_LTLIBRARIES = libnvif.la
+
+# XXX: /lib shouldn't be here, but is needed while we include core headers
+libnvif_la_CPPFLAGS = -I${top_srcdir}/nvkm/include \
+ -I${top_srcdir}/nvkm \
+ -I${top_srcdir}/lib \
+ -I${top_srcdir}
+libnvif_la_LIBADD = $(top_srcdir)/lib/libpciaccessos.la
+libnvif_la_SOURCES = object.c \
+ client.c \
+ device.c \
+ notify.c
diff --git a/nvif/client.c b/nvif/client.c
new file mode 100644
index 000000000..7048fd91b
--- /dev/null
+++ b/nvif/client.c
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2013 Red Hat Inc.
+ *
+ * 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 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 HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs <bskeggs@redhat.com>
+ */
+
+#include "client.h"
+#include "driver.h"
+#include "ioctl.h"
+
+int
+nvif_client_ioctl(struct nvif_client *client, void *data, u32 size)
+{
+ return client->driver->ioctl(client->base.priv, client->super, data, size, NULL);
+}
+
+int
+nvif_client_suspend(struct nvif_client *client)
+{
+ return client->driver->suspend(client->base.priv);
+}
+
+int
+nvif_client_resume(struct nvif_client *client)
+{
+ return client->driver->resume(client->base.priv);
+}
+
+void
+nvif_client_fini(struct nvif_client *client)
+{
+ if (client->driver) {
+ client->driver->fini(client->base.priv);
+ client->driver = NULL;
+ client->base.parent = NULL;
+ nvif_object_fini(&client->base);
+ }
+}
+
+const struct nvif_driver *
+nvif_drivers[] = {
+#ifdef __KERNEL__
+#if 0
+ &nvif_driver_nvkm,
+#endif
+#else
+ &nvif_driver_lib,
+#endif
+ NULL
+};
+
+int
+nvif_client_init(void (*dtor)(struct nvif_client *), const char *driver,
+ const char *name, u64 device, const char *cfg, const char *dbg,
+ struct nvif_client *client)
+{
+ int ret, i;
+
+ ret = nvif_object_init(NULL, (void*)dtor, 0, 0, NULL, 0, &client->base);
+ if (ret)
+ return ret;
+
+ client->base.parent = &client->base;
+ client->base.handle = ~0;
+ client->object = &client->base;
+ client->super = true;
+
+ for (i = 0, ret = -EINVAL; (client->driver = nvif_drivers[i]); i++) {
+ if (!driver || !strcmp(client->driver->name, driver)) {
+ ret = client->driver->init(name, device, cfg, dbg,
+ &client->base.priv);
+ if (!ret || driver)
+ break;
+ }
+ }
+
+ if (ret)
+ nvif_client_fini(client);
+ return ret;
+}
+
+static void
+nvif_client_del(struct nvif_client *client)
+{
+ nvif_client_fini(client);
+ kfree(client);
+}
+
+int
+nvif_client_new(const char *driver, const char *name, u64 device,
+ const char *cfg, const char *dbg,
+ struct nvif_client **pclient)
+{
+ struct nvif_client *client = kzalloc(sizeof(*client), GFP_KERNEL);
+ if (client) {
+ int ret = nvif_client_init(nvif_client_del, driver, name,
+ device, cfg, dbg, client);
+ if (ret) {
+ kfree(client);
+ client = NULL;
+ }
+ *pclient = client;
+ return ret;
+ }
+ return -ENOMEM;
+}
+
+void
+nvif_client_ref(struct nvif_client *client, struct nvif_client **pclient)
+{
+ nvif_object_ref(&client->base, (struct nvif_object **)pclient);
+}
diff --git a/nvif/client.h b/nvif/client.h
new file mode 100644
index 000000000..28352f088
--- /dev/null
+++ b/nvif/client.h
@@ -0,0 +1,39 @@
+#ifndef __NVIF_CLIENT_H__
+#define __NVIF_CLIENT_H__
+
+#include "object.h"
+
+struct nvif_client {
+ struct nvif_object base;
+ struct nvif_object *object; /*XXX: hack for nvif_object() */
+ const struct nvif_driver *driver;
+ bool super;
+};
+
+static inline struct nvif_client *
+nvif_client(struct nvif_object *object)
+{
+ while (object && object->parent != object)
+ object = object->parent;
+ return (void *)object;
+}
+
+int nvif_client_init(void (*dtor)(struct nvif_client *), const char *,
+ const char *, u64, const char *, const char *,
+ struct nvif_client *);
+void nvif_client_fini(struct nvif_client *);
+int nvif_client_new(const char *, const char *, u64, const char *,
+ const char *, struct nvif_client **);
+void nvif_client_ref(struct nvif_client *, struct nvif_client **);
+int nvif_client_ioctl(struct nvif_client *, void *, u32);
+int nvif_client_suspend(struct nvif_client *);
+int nvif_client_resume(struct nvif_client *);
+
+/*XXX*/
+#include <core/client.h>
+#define nvkm_client(a) ({ \
+ struct nvif_client *_client = nvif_client(nvif_object(a)); \
+ nouveau_client(_client->base.priv); \
+})
+
+#endif
diff --git a/nvif/device.c b/nvif/device.c
new file mode 100644
index 000000000..f47757972
--- /dev/null
+++ b/nvif/device.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2014 Red Hat Inc.
+ *
+ * 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 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 HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs <bskeggs@redhat.com>
+ */
+
+#include "device.h"
+
+void
+nvif_device_fini(struct nvif_device *device)
+{
+ nvif_object_fini(&device->base);
+}
+
+int
+nvif_device_init(struct nvif_object *parent, void (*dtor)(struct nvif_device *),
+ u32 handle, u32 oclass, void *data, u32 size,
+ struct nvif_device *device)
+{
+ int ret = nvif_object_init(parent, (void *)dtor, handle, oclass,
+ data, size, &device->base);
+ if (ret == 0) {
+ device->object = &device->base;
+ device->info.version = 0;
+ ret = nvif_object_mthd(&device->base, NV_DEVICE_V0_INFO,
+ &device->info, sizeof(device->info));
+ }
+ return ret;
+}
+
+static void
+nvif_device_del(struct nvif_device *device)
+{
+ nvif_device_fini(device);
+ kfree(device);
+}
+
+int
+nvif_device_new(struct nvif_object *parent, u32 handle, u32 oclass,
+ void *data, u32 size, struct nvif_device **pdevice)
+{
+ struct nvif_device *device = kzalloc(sizeof(*device), GFP_KERNEL);
+ if (device) {
+ int ret = nvif_device_init(parent, nvif_device_del, handle,
+ oclass, data, size, device);
+ if (ret) {
+ kfree(device);
+ device = NULL;
+ }
+ *pdevice = device;
+ return ret;
+ }
+ return -ENOMEM;
+}
+
+void
+nvif_device_ref(struct nvif_device *device, struct nvif_device **pdevice)
+{
+ nvif_object_ref(&device->base, (struct nvif_object **)pdevice);
+}
diff --git a/nvif/device.h b/nvif/device.h
new file mode 100644
index 000000000..c208bad98
--- /dev/null
+++ b/nvif/device.h
@@ -0,0 +1,66 @@
+#ifndef __NVIF_DEVICE_H__
+#define __NVIF_DEVICE_H__
+
+#include "object.h"
+#include "class.h"
+
+struct nvif_device {
+ struct nvif_object base;
+ struct nvif_object *object; /*XXX: hack for nvif_object() */
+ struct nv_device_info_v0 info;
+};
+
+static inline struct nvif_device *
+nvif_device(struct nvif_object *object)
+{
+ while (object && object->oclass != 0x0080 /*XXX: NV_DEVICE_CLASS*/ )
+ object = object->parent;
+ return (void *)object;
+}
+
+int nvif_device_init(struct nvif_object *, void (*dtor)(struct nvif_device *),
+ u32 handle, u32 oclass, void *, u32,
+ struct nvif_device *);
+void nvif_device_fini(struct nvif_device *);
+int nvif_device_new(struct nvif_object *, u32 handle, u32 oclass,
+ void *, u32, struct nvif_device **);
+void nvif_device_ref(struct nvif_device *, struct nvif_device **);
+
+/*XXX*/
+#include <subdev/bios.h>
+#include <subdev/fb.h>
+#include <subdev/instmem.h>
+#include <subdev/vm.h>
+#include <subdev/bar.h>
+#include <subdev/gpio.h>
+#include <subdev/clock.h>
+#include <subdev/i2c.h>
+#include <subdev/timer.h>
+#include <subdev/therm.h>
+
+#define nvkm_device(a) nv_device(nvkm_object((a)))
+#define nvkm_bios(a) nouveau_bios(nvkm_device(a))
+#define nvkm_fb(a) nouveau_fb(nvkm_device(a))
+#define nvkm_instmem(a) nouveau_instmem(nvkm_device(a))
+#define nvkm_vmmgr(a) nouveau_vmmgr(nvkm_device(a))
+#define nvkm_bar(a) nouveau_bar(nvkm_device(a))
+#define nvkm_gpio(a) nouveau_gpio(nvkm_device(a))
+#define nvkm_clock(a) nouveau_clock(nvkm_device(a))
+#define nvkm_i2c(a) nouveau_i2c(nvkm_device(a))
+#define nvkm_timer(a) nouveau_timer(nvkm_device(a))
+#define nvkm_wait(a,b,c,d) nv_wait(nvkm_timer(a), (b), (c), (d))
+#define nvkm_wait_cb(a,b,c) nv_wait_cb(nvkm_timer(a), (b), (c))
+#define nvkm_therm(a) nouveau_therm(nvkm_device(a))
+
+#include <engine/device.h>
+#include <engine/fifo.h>
+#include <engine/disp.h>
+#include <engine/graph.h>
+#include <engine/software.h>
+
+#define nvkm_fifo(a) nouveau_fifo(nvkm_device(a))
+#define nvkm_fifo_chan(a) ((struct nouveau_fifo_chan *)nvkm_object(a))
+#define nvkm_disp(a) nouveau_disp(nvkm_device(a))
+#define nvkm_gr(a) ((struct nouveau_graph *)nouveau_engine(nvkm_object(a), NVDEV_ENGINE_GR))
+
+#endif
diff --git a/nvif/driver.h b/nvif/driver.h
new file mode 100644
index 000000000..ea5b1b880
--- /dev/null
+++ b/nvif/driver.h
@@ -0,0 +1,20 @@
+#ifndef __NVIF_DRIVER_H__
+#define __NVIF_DRIVER_H__
+
+struct nvif_driver {
+ const char *name;
+ int (*init)(const char *name, u64 device, const char *cfg,
+ const char *dbg, void **priv);
+ void (*fini)(void *priv);
+ int (*suspend)(void *priv);
+ int (*resume)(void *priv);
+ int (*ioctl)(void *priv, bool super, void *data, u32 size, void **hack);
+ void *(*map)(void *priv, u64 handle, u32 size);
+ void (*unmap)(void *priv, void *ptr, u32 size);
+ bool keep;
+};
+
+extern const struct nvif_driver nvif_driver_nvkm;
+extern const struct nvif_driver nvif_driver_lib;
+
+#endif
diff --git a/nvif/list.h b/nvif/list.h
new file mode 100644
index 000000000..8af5d144e
--- /dev/null
+++ b/nvif/list.h
@@ -0,0 +1,353 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ * Copyright © 2010 Francisco Jerez <currojerez@riseup.net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+
+/* Modified by Ben Skeggs <bskeggs@redhat.com> to match kernel list APIs */
+
+#ifndef _XORG_LIST_H_
+#define _XORG_LIST_H_
+
+/**
+ * @file Classic doubly-link circular list implementation.
+ * For real usage examples of the linked list, see the file test/list.c
+ *
+ * Example:
+ * We need to keep a list of struct foo in the parent struct bar, i.e. what
+ * we want is something like this.
+ *
+ * struct bar {
+ * ...
+ * struct foo *list_of_foos; -----> struct foo {}, struct foo {}, struct foo{}
+ * ...
+ * }
+ *
+ * We need one list head in bar and a list element in all list_of_foos (both are of
+ * data type 'struct list_head').
+ *
+ * struct bar {
+ * ...
+ * struct list_head list_of_foos;
+ * ...
+ * }
+ *
+ * struct foo {
+ * ...
+ * struct list_head entry;
+ * ...
+ * }
+ *
+ * Now we initialize the list head:
+ *
+ * struct bar bar;
+ * ...
+ * INIT_LIST_HEAD(&bar.list_of_foos);
+ *
+ * Then we create the first element and add it to this list:
+ *
+ * struct foo *foo = malloc(...);
+ * ....
+ * list_add(&foo->entry, &bar.list_of_foos);
+ *
+ * Repeat the above for each element you want to add to the list. Deleting
+ * works with the element itself.
+ * list_del(&foo->entry);
+ * free(foo);
+ *
+ * Note: calling list_del(&bar.list_of_foos) will set bar.list_of_foos to an empty
+ * list again.
+ *
+ * Looping through the list requires a 'struct foo' as iterator and the
+ * name of the field the subnodes use.
+ *
+ * struct foo *iterator;
+ * list_for_each_entry(iterator, &bar.list_of_foos, entry) {
+ * if (iterator->something == ...)
+ * ...
+ * }
+ *
+ * Note: You must not call list_del() on the iterator if you continue the
+ * loop. You need to run the safe for-each loop instead:
+ *
+ * struct foo *iterator, *next;
+ * list_for_each_entry_safe(iterator, next, &bar.list_of_foos, entry) {
+ * if (...)
+ * list_del(&iterator->entry);
+ * }
+ *
+ */
+
+/**
+ * The linkage struct for list nodes. This struct must be part of your
+ * to-be-linked struct. struct list_head is required for both the head of the
+ * list and for each list node.
+ *
+ * Position and name of the struct list_head field is irrelevant.
+ * There are no requirements that elements of a list are of the same type.
+ * There are no requirements for a list head, any struct list_head can be a list
+ * head.
+ */
+struct list_head {
+ struct list_head *next, *prev;
+};
+
+/**
+ * Initialize the list as an empty list.
+ *
+ * Example:
+ * INIT_LIST_HEAD(&bar->list_of_foos);
+ *
+ * @param The list to initialized.
+ */
+#define LIST_HEAD_INIT(name) { &(name), &(name) }
+
+#define LIST_HEAD(name) \
+ struct list_head name = LIST_HEAD_INIT(name)
+
+static inline void
+INIT_LIST_HEAD(struct list_head *list)
+{
+ list->next = list->prev = list;
+}
+
+static inline void
+__list_add(struct list_head *entry,
+ struct list_head *prev, struct list_head *next)
+{
+ next->prev = entry;
+ entry->next = next;
+ entry->prev = prev;
+ prev->next = entry;
+}
+
+/**
+ * Insert a new element after the given list head. The new element does not
+ * need to be initialised as empty list.
+ * The list changes from:
+ * head → some element → ...
+ * to
+ * head → new element → older element → ...
+ *
+ * Example:
+ * struct foo *newfoo = malloc(...);
+ * list_add(&newfoo->entry, &bar->list_of_foos);
+ *
+ * @param entry The new element to prepend to the list.
+ * @param head The existing list.
+ */
+static inline void
+list_add(struct list_head *entry, struct list_head *head)
+{
+ __list_add(entry, head, head->next);
+}
+
+/**
+ * Append a new element to the end of the list given with this list head.
+ *
+ * The list changes from:
+ * head → some element → ... → lastelement
+ * to
+ * head → some element → ... → lastelement → new element
+ *
+ * Example:
+ * struct foo *newfoo = malloc(...);
+ * list_add_tail(&newfoo->entry, &bar->list_of_foos);
+ *
+ * @param entry The new element to prepend to the list.
+ * @param head The existing list.
+ */
+static inline void
+list_add_tail(struct list_head *entry, struct list_head *head)
+{
+ __list_add(entry, head->prev, head);
+}
+
+static inline void
+__list_del(struct list_head *prev, struct list_head *next)
+{
+ next->prev = prev;
+ prev->next = next;
+}
+
+/**
+ * Remove the element from the list it is in. Using this function will reset
+ * the pointers to/from this element so it is removed from the list. It does
+ * NOT free the element itself or manipulate it otherwise.
+ *
+ * Using list_del on a pure list head (like in the example at the top of
+ * this file) will NOT remove the first element from
+ * the list but rather reset the list as empty list.
+ *
+ * Example:
+ * list_del(&foo->entry);
+ *
+ * @param entry The element to remove.
+ */
+static inline void
+list_del(struct list_head *entry)
+{
+ __list_del(entry->prev, entry->next);
+}
+
+static inline void
+list_del_init(struct list_head *entry)
+{
+ __list_del(entry->prev, entry->next);
+ INIT_LIST_HEAD(entry);
+}
+
+static inline void list_move_tail(struct list_head *list,
+ struct list_head *head)
+{
+ __list_del(list->prev, list->next);
+ list_add_tail(list, head);
+}
+
+/**
+ * Check if the list is empty.
+ *
+ * Example:
+ * list_empty(&bar->list_of_foos);
+ *
+ * @return True if the list contains one or more elements or False otherwise.
+ */
+static inline bool
+list_empty(struct list_head *head)
+{
+ return head->next == head;
+}
+
+/**
+ * Returns a pointer to the container of this list element.
+ *
+ * Example:
+ * struct foo* f;
+ * f = container_of(&foo->entry, struct foo, entry);
+ * assert(f == foo);
+ *
+ * @param ptr Pointer to the struct list_head.
+ * @param type Data type of the list element.
+ * @param member Member name of the struct list_head field in the list element.
+ * @return A pointer to the data struct containing the list head.
+ */
+#ifndef container_of
+#define container_of(ptr, type, member) \
+ (type *)((char *)(ptr) - (char *) &((type *)0)->member)
+#endif
+
+/**
+ * Alias of container_of
+ */
+#define list_entry(ptr, type, member) \
+ container_of(ptr, type, member)
+
+/**
+ * Retrieve the first list entry for the given list pointer.
+ *
+ * Example:
+ * struct foo *first;
+ * first = list_first_entry(&bar->list_of_foos, struct foo, list_of_foos);
+ *
+ * @param ptr The list head
+ * @param type Data type of the list element to retrieve
+ * @param member Member name of the struct list_head field in the list element.
+ * @return A pointer to the first list element.
+ */
+#define list_first_entry(ptr, type, member) \
+ list_entry((ptr)->next, type, member)
+
+/**
+ * Retrieve the last list entry for the given listpointer.
+ *
+ * Example:
+ * struct foo *first;
+ * first = list_last_entry(&bar->list_of_foos, struct foo, list_of_foos);
+ *
+ * @param ptr The list head
+ * @param type Data type of the list element to retrieve
+ * @param member Member name of the struct list_head field in the list element.
+ * @return A pointer to the last list element.
+ */
+#define list_last_entry(ptr, type, member) \
+ list_entry((ptr)->prev, type, member)
+
+#define __container_of(ptr, sample, member) \
+ (void *)container_of((ptr), typeof(*(sample)), member)
+
+/**
+ * Loop through the list given by head and set pos to struct in the list.
+ *
+ * Example:
+ * struct foo *iterator;
+ * list_for_each_entry(iterator, &bar->list_of_foos, entry) {
+ * [modify iterator]
+ * }
+ *
+ * This macro is not safe for node deletion. Use list_for_each_entry_safe
+ * instead.
+ *
+ * @param pos Iterator variable of the type of the list elements.
+ * @param head List head
+ * @param member Member name of the struct list_head in the list elements.
+ *
+ */
+#define list_for_each_entry(pos, head, member) \
+ for (pos = __container_of((head)->next, pos, member); \
+ &pos->member != (head); \
+ pos = __container_of(pos->member.next, pos, member))
+
+/**
+ * Loop through the list, keeping a backup pointer to the element. This
+ * macro allows for the deletion of a list element while looping through the
+ * list.
+ *
+ * See list_for_each_entry for more details.
+ */
+#define list_for_each_entry_safe(pos, tmp, head, member) \
+ for (pos = __container_of((head)->next, pos, member), \
+ tmp = __container_of(pos->member.next, pos, member); \
+ &pos->member != (head); \
+ pos = tmp, tmp = __container_of(pos->member.next, tmp, member))
+
+
+#define list_for_each_entry_reverse(pos, head, member) \
+ for (pos = __container_of((head)->prev, pos, member); \
+ &pos->member != (head); \
+ pos = __container_of(pos->member.prev, pos, member))
+
+#define list_for_each_entry_continue(pos, head, member) \
+ for (pos = __container_of(pos->member.next, pos, member); \
+ &pos->member != (head); \
+ pos = __container_of(pos->member.next, pos, member))
+
+#define list_for_each_entry_continue_reverse(pos, head, member) \
+ for (pos = __container_of(pos->member.prev, pos, member); \
+ &pos->member != (head); \
+ pos = __container_of(pos->member.prev, pos, member))
+
+#define list_for_each_entry_from(pos, head, member) \
+ for (; \
+ &pos->member != (head); \
+ pos = __container_of(pos->member.next, pos, member))
+
+#endif
diff --git a/nvif/notify.c b/nvif/notify.c
new file mode 100644
index 000000000..7c06123a5
--- /dev/null
+++ b/nvif/notify.c
@@ -0,0 +1,237 @@
+/*
+ * Copyright 2014 Red Hat Inc.
+ *
+ * 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 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 HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs <bskeggs@redhat.com>
+ */
+
+#include <nvif/client.h>
+#include <nvif/driver.h>
+#include <nvif/notify.h>
+#include <nvif/object.h>
+#include <nvif/ioctl.h>
+#include <nvif/event.h>
+
+static inline int
+nvif_notify_put_(struct nvif_notify *notify)
+{
+ struct nvif_object *object = notify->object;
+ struct {
+ struct nvif_ioctl_v0 ioctl;
+ struct nvif_ioctl_ntfy_put_v0 ntfy;
+ } args = {
+ .ioctl.type = NVIF_IOCTL_V0_NTFY_PUT,
+ .ntfy.index = notify->index,
+ };
+
+ if (atomic_inc_return(&notify->putcnt) != 1)
+ return 0;
+
+ return nvif_object_ioctl(object, &args, sizeof(args), NULL);
+}
+
+int
+nvif_notify_put(struct nvif_notify *notify)
+{
+ if (likely(notify->object) &&
+ test_and_clear_bit(NVIF_NOTIFY_USER, &notify->flags)) {
+ int ret = nvif_notify_put_(notify);
+ if (test_bit(NVIF_NOTIFY_WORK, &notify->flags))
+ flush_work(&notify->work);
+ return ret;
+ }
+ return 0;
+}
+
+static inline int
+nvif_notify_get_(struct nvif_notify *notify)
+{
+ struct nvif_object *object = notify->object;
+ struct {
+ struct nvif_ioctl_v0 ioctl;
+ struct nvif_ioctl_ntfy_get_v0 ntfy;
+ } args = {
+ .ioctl.type = NVIF_IOCTL_V0_NTFY_GET,
+ .ntfy.index = notify->index,
+ };
+
+ if (atomic_dec_return(&notify->putcnt) != 0)
+ return 0;
+
+ return nvif_object_ioctl(object, &args, sizeof(args), NULL);
+}
+
+int
+nvif_notify_get(struct nvif_notify *notify)
+{
+ if (likely(notify->object) &&
+ !test_and_set_bit(NVIF_NOTIFY_USER, &notify->flags))
+ return nvif_notify_get_(notify);
+ return 0;
+}
+
+static void
+nvif_notify_work(struct work_struct *work)
+{
+ struct nvif_notify *notify = container_of(work, typeof(*notify), work);
+ if (notify->func(notify) == NVIF_NOTIFY_KEEP)
+ nvif_notify_get_(notify);
+}
+
+int
+nvif_notify(const void *header, u32 length, const void *data, u32 size)
+{
+ struct nvif_notify *notify = NULL;
+ const union {
+ struct nvif_notify_rep_v0 v0;
+ } *args = header;
+ int ret = NVIF_NOTIFY_DROP;
+
+ if (length == sizeof(args->v0) && args->v0.version == 0) {
+ if (WARN_ON(args->v0.route))
+ return NVIF_NOTIFY_DROP;
+ notify = (void *)(unsigned long)args->v0.token;
+ }
+
+ if (!WARN_ON(notify == NULL)) {
+ struct nvif_client *client = nvif_client(notify->object);
+ if (!WARN_ON(notify->size != size)) {
+ if (test_bit(NVIF_NOTIFY_WORK, &notify->flags)) {
+ atomic_inc(&notify->putcnt);
+ memcpy((void *)notify->data, data, size);
+ schedule_work(&notify->work);
+ return NVIF_NOTIFY_DROP;
+ }
+ notify->data = data;
+ ret = notify->func(notify);
+ notify->data = NULL;
+ if (ret != NVIF_NOTIFY_DROP && client->driver->keep) {
+ atomic_inc(&notify->putcnt);
+ nvif_notify_get_(notify);
+ }
+ }
+ }
+
+ return ret;
+}
+
+int
+nvif_notify_fini(struct nvif_notify *notify)
+{
+ struct nvif_object *object = notify->object;
+ struct {
+ struct nvif_ioctl_v0 ioctl;
+ struct nvif_ioctl_ntfy_del_v0 ntfy;
+ } args = {
+ .ioctl.type = NVIF_IOCTL_V0_NTFY_DEL,
+ .ntfy.index = notify->index,
+ };
+ int ret = nvif_notify_put(notify);
+ if (ret >= 0 && object) {
+ ret = nvif_object_ioctl(object, &args, sizeof(args), NULL);
+ if (ret == 0) {
+ nvif_object_ref(NULL, &notify->object);
+ kfree((void *)notify->data);
+ }
+ }
+ return ret;
+}
+
+int
+nvif_notify_init(struct nvif_object *object, void (*dtor)(struct nvif_notify *),
+ int (*func)(struct nvif_notify *), bool work, u8 event,
+ void *data, u32 size, u32 reply, struct nvif_notify *notify)
+{
+ struct {
+ struct nvif_ioctl_v0 ioctl;
+ struct nvif_ioctl_ntfy_new_v0 ntfy;
+ struct nvif_notify_req_v0 req;
+ } *args;
+ int ret = -ENOMEM;
+
+ notify->object = NULL;
+ nvif_object_ref(object, &notify->object);
+ notify->flags = 0;
+ atomic_set(&notify->putcnt, 1);
+ notify->dtor = dtor;
+ notify->func = func;
+ notify->data = NULL;
+ notify->size = reply;
+ if (work) {
+ INIT_WORK(&notify->work, nvif_notify_work);
+ set_bit(NVIF_NOTIFY_WORK, &notify->flags);
+ notify->data = kmalloc(notify->size, GFP_KERNEL);
+ if (!notify->data)
+ goto done;
+ }
+
+ if (!(args = kmalloc(sizeof(*args) + size, GFP_KERNEL)))
+ goto done;
+ args->ioctl.version = 0;
+ args->ioctl.type = NVIF_IOCTL_V0_NTFY_NEW;
+ args->ntfy.version = 0;
+ args->ntfy.event = event;
+ args->req.version = 0;
+ args->req.reply = notify->size;
+ args->req.route = 0;
+ args->req.token = (unsigned long)(void *)notify;
+
+ memcpy(args->req.data, data, size);
+ ret = nvif_object_ioctl(object, args, sizeof(*args) + size, NULL);
+ notify->index = args->ntfy.index;
+ kfree(args);
+done:
+ if (ret)
+ nvif_notify_fini(notify);
+ return ret;
+}
+
+static void
+nvif_notify_del(struct nvif_notify *notify)
+{
+ nvif_notify_fini(notify);
+ kfree(notify);
+}
+
+void
+nvif_notify_ref(struct nvif_notify *notify, struct nvif_notify **pnotify)
+{
+ BUG_ON(notify != NULL);
+ if (*pnotify)
+ (*pnotify)->dtor(*pnotify);
+ *pnotify = notify;
+}
+
+int
+nvif_notify_new(struct nvif_object *object, int (*func)(struct nvif_notify *),
+ bool work, u8 type, void *data, u32 size, u32 reply,
+ struct nvif_notify **pnotify)
+{
+ struct nvif_notify *notify = kzalloc(sizeof(*notify), GFP_KERNEL);
+ if (notify) {
+ int ret = nvif_notify_init(object, nvif_notify_del, func, work,
+ type, data, size, reply, notify);
+ if (ret)
+ kfree(notify);
+ *pnotify = notify;
+ return ret;
+ }
+ return -ENOMEM;
+}
diff --git a/nvif/notify.h b/nvif/notify.h
new file mode 100644
index 000000000..9ebfa3b45
--- /dev/null
+++ b/nvif/notify.h
@@ -0,0 +1,39 @@
+#ifndef __NVIF_NOTIFY_H__
+#define __NVIF_NOTIFY_H__
+
+struct nvif_notify {
+ struct nvif_object *object;
+ int index;
+
+#define NVIF_NOTIFY_USER 0
+#define NVIF_NOTIFY_WORK 1
+ unsigned long flags;
+ atomic_t putcnt;
+ void (*dtor)(struct nvif_notify *);
+#define NVIF_NOTIFY_DROP 0
+#define NVIF_NOTIFY_KEEP 1
+ int (*func)(struct nvif_notify *);
+
+ /* this is const for a *very* good reason - the data might be on the
+ * stack from an irq handler. if you're not nvif/notify.c then you
+ * should probably think twice before casting it away...
+ */
+ const void *data;
+ u32 size;
+ struct work_struct work;
+};
+
+int nvif_notify_init(struct nvif_object *, void (*dtor)(struct nvif_notify *),
+ int (*func)(struct nvif_notify *), bool work, u8 type,
+ void *data, u32 size, u32 reply, struct nvif_notify *);
+int nvif_notify_fini(struct nvif_notify *);
+int nvif_notify_get(struct nvif_notify *);
+int nvif_notify_put(struct nvif_notify *);
+int nvif_notify(const void *, u32, const void *, u32);
+
+int nvif_notify_new(struct nvif_object *, int (*func)(struct nvif_notify *),
+ bool work, u8 type, void *data, u32 size, u32 reply,
+ struct nvif_notify **);
+void nvif_notify_ref(struct nvif_notify *, struct nvif_notify **);
+
+#endif
diff --git a/nvif/object.c b/nvif/object.c
new file mode 100644
index 000000000..b0c82206e
--- /dev/null
+++ b/nvif/object.c
@@ -0,0 +1,302 @@
+/*
+ * Copyright 2014 Red Hat Inc.
+ *
+ * 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 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 HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs <bskeggs@redhat.com>
+ */
+
+#include "object.h"
+#include "client.h"
+#include "driver.h"
+#include "ioctl.h"
+
+int
+nvif_object_ioctl(struct nvif_object *object, void *data, u32 size, void **hack)
+{
+ struct nvif_client *client = nvif_client(object);
+ union {
+ struct nvif_ioctl_v0 v0;
+ } *args = data;
+
+ if (size >= sizeof(*args) && args->v0.version == 0) {
+ args->v0.owner = NVIF_IOCTL_V0_OWNER_ANY;
+ args->v0.path_nr = 0;
+ while (args->v0.path_nr < ARRAY_SIZE(args->v0.path)) {
+ args->v0.path[args->v0.path_nr++] = object->handle;
+ if (object->parent == object)
+ break;
+ object = object->parent;
+ }
+ } else
+ return -ENOSYS;
+
+ return client->driver->ioctl(client->base.priv, client->super, data, size, hack);
+}
+
+int
+nvif_object_sclass(struct nvif_object *object, u32 *oclass, int count)
+{
+ struct {
+ struct nvif_ioctl_v0 ioctl;
+ struct nvif_ioctl_sclass_v0 sclass;
+ } *args;
+ u32 size = count * sizeof(args->sclass.oclass[0]);
+ int ret;
+
+ if (!(args = kmalloc(sizeof(*args) + size, GFP_KERNEL)))
+ return -ENOMEM;
+ args->ioctl.version = 0;
+ args->ioctl.type = NVIF_IOCTL_V0_SCLASS;
+ args->sclass.version = 0;
+ args->sclass.count = count;
+
+ memcpy(args->sclass.oclass, oclass, size);
+ ret = nvif_object_ioctl(object, args, sizeof(*args) + size, NULL);
+ ret = ret ? ret : args->sclass.count;
+ memcpy(oclass, args->sclass.oclass, size);
+ kfree(args);
+ return ret;
+}
+
+u32
+nvif_object_rd(struct nvif_object *object, int size, u64 addr)
+{
+ struct {
+ struct nvif_ioctl_v0 ioctl;
+ struct nvif_ioctl_rd_v0 rd;
+ } args = {
+ .ioctl.type = NVIF_IOCTL_V0_RD,
+ .rd.size = size,
+ .rd.addr = addr,
+ };
+ int ret = nvif_object_ioctl(object, &args, sizeof(args), NULL);
+ if (ret) {
+ /*XXX: warn? */
+ return 0;
+ }
+ return args.rd.data;
+}
+
+void
+nvif_object_wr(struct nvif_object *object, int size, u64 addr, u32 data)
+{
+ struct {
+ struct nvif_ioctl_v0 ioctl;
+ struct nvif_ioctl_wr_v0 wr;
+ } args = {
+ .ioctl.type = NVIF_IOCTL_V0_WR,
+ .wr.size = size,
+ .wr.addr = addr,
+ .wr.data = data,
+ };
+ int ret = nvif_object_ioctl(object, &args, sizeof(args), NULL);
+ if (ret) {
+ /*XXX: warn? */
+ }
+}
+
+int
+nvif_object_mthd(struct nvif_object *object, u32 mthd, void *data, u32 size)
+{
+ struct {
+ struct nvif_ioctl_v0 ioctl;
+ struct nvif_ioctl_mthd_v0 mthd;
+ } *args;
+ u8 stack[128];
+ int ret;
+
+ if (sizeof(*args) + size > sizeof(stack)) {
+ if (!(args = kmalloc(sizeof(*args) + size, GFP_KERNEL)))
+ return -ENOMEM;
+ } else {
+ args = (void *)stack;
+ }
+ args->ioctl.version = 0;
+ args->ioctl.type = NVIF_IOCTL_V0_MTHD;
+ args->mthd.version = 0;
+ args->mthd.method = mthd;
+
+ memcpy(args->mthd.data, data, size);
+ ret = nvif_object_ioctl(object, args, sizeof(*args) + size, NULL);
+ memcpy(data, args->mthd.data, size);
+ if (args != (void *)stack)
+ kfree(args);
+ return ret;
+}
+
+void
+nvif_object_unmap(struct nvif_object *object)
+{
+ if (object->map.size) {
+ struct nvif_client *client = nvif_client(object);
+ struct {
+ struct nvif_ioctl_v0 ioctl;
+ struct nvif_ioctl_unmap unmap;
+ } args = {
+ .ioctl.type = NVIF_IOCTL_V0_UNMAP,
+ };
+
+ if (object->map.ptr) {
+ client->driver->unmap(client, object->map.ptr,
+ object->map.size);
+ object->map.ptr = NULL;
+ }
+
+ nvif_object_ioctl(object, &args, sizeof(args), NULL);
+ object->map.size = 0;
+ }
+}
+
+int
+nvif_object_map(struct nvif_object *object)
+{
+ struct nvif_client *client = nvif_client(object);
+ struct {
+ struct nvif_ioctl_v0 ioctl;
+ struct nvif_ioctl_map_v0 map;
+ } args = {
+ .ioctl.type = NVIF_IOCTL_V0_MAP,
+ };
+ int ret = nvif_object_ioctl(object, &args, sizeof(args), NULL);
+ if (ret == 0) {
+ object->map.size = args.map.length;
+ object->map.ptr = client->driver->map(client, args.map.handle,
+ object->map.size);
+ if (ret = -ENOMEM, object->map.ptr)
+ return 0;
+ nvif_object_unmap(object);
+ }
+ return ret;
+}
+
+struct ctor {
+ struct nvif_ioctl_v0 ioctl;
+ struct nvif_ioctl_new_v0 new;
+};
+
+void
+nvif_object_fini(struct nvif_object *object)
+{
+ struct ctor *ctor = container_of(object->data, typeof(*ctor), new.data);
+ if (object->parent) {
+ struct {
+ struct nvif_ioctl_v0 ioctl;
+ struct nvif_ioctl_del del;
+ } args = {
+ .ioctl.type = NVIF_IOCTL_V0_DEL,
+ };
+
+ nvif_object_unmap(object);
+ nvif_object_ioctl(object, &args, sizeof(args), NULL);
+ if (object->data) {
+ object->size = 0;
+ object->data = NULL;
+ kfree(ctor);
+ }
+ nvif_object_ref(NULL, &object->parent);
+ }
+}
+
+int
+nvif_object_init(struct nvif_object *parent, void (*dtor)(struct nvif_object *),
+ u32 handle, u32 oclass, void *data, u32 size,
+ struct nvif_object *object)
+{
+ struct ctor *ctor;
+ int ret = 0;
+
+ object->parent = NULL;
+ object->object = object;
+ nvif_object_ref(parent, &object->parent);
+ kref_init(&object->refcount);
+ object->handle = handle;
+ object->oclass = oclass;
+ object->data = NULL;
+ object->size = 0;
+ object->dtor = dtor;
+ object->map.ptr = NULL;
+ object->map.size = 0;
+
+ if (object->parent) {
+ if (!(ctor = kmalloc(sizeof(*ctor) + size, GFP_KERNEL))) {
+ nvif_object_fini(object);
+ return -ENOMEM;
+ }
+ object->data = ctor->new.data;
+ object->size = size;
+ memcpy(object->data, data, size);
+
+ ctor->ioctl.version = 0;
+ ctor->ioctl.type = NVIF_IOCTL_V0_NEW;
+ ctor->new.version = 0;
+ ctor->new.route = NVIF_IOCTL_V0_ROUTE_NVIF;
+ ctor->new.token = (unsigned long)(void *)object;
+ ctor->new.handle = handle;
+ ctor->new.oclass = oclass;
+
+ ret = nvif_object_ioctl(parent, ctor, sizeof(*ctor) +
+ object->size, &object->priv);
+ }
+
+ if (ret)
+ nvif_object_fini(object);
+ return ret;
+}
+
+static void
+nvif_object_del(struct nvif_object *object)
+{
+ nvif_object_fini(object);
+ kfree(object);
+}
+
+int
+nvif_object_new(struct nvif_object *parent, u32 handle, u32 oclass,
+ void *data, u32 size, struct nvif_object **pobject)
+{
+ struct nvif_object *object = kzalloc(sizeof(*object), GFP_KERNEL);
+ if (object) {
+ int ret = nvif_object_init(parent, nvif_object_del, handle,
+ oclass, data, size, object);
+ if (ret)
+ kfree(object);
+ *pobject = object;
+ return ret;
+ }
+ return -ENOMEM;
+}
+
+static void
+nvif_object_put(struct kref *kref)
+{
+ struct nvif_object *object =
+ container_of(kref, typeof(*object), refcount);
+ object->dtor(object);
+}
+
+void
+nvif_object_ref(struct nvif_object *object, struct nvif_object **pobject)
+{
+ if (object)
+ kref_get(&object->refcount);
+ if (*pobject)
+ kref_put(&(*pobject)->refcount, nvif_object_put);
+ *pobject = object;
+}
diff --git a/nvif/object.h b/nvif/object.h
new file mode 100644
index 000000000..dce62736f
--- /dev/null
+++ b/nvif/object.h
@@ -0,0 +1,77 @@
+#ifndef __NVIF_OBJECT_H__
+#define __NVIF_OBJECT_H__
+
+#include <nvif/os.h>
+
+struct nvif_object {
+ struct nvif_object *parent;
+ struct nvif_object *object; /*XXX: hack for nvif_object() */
+ struct kref refcount;
+ u32 handle;
+ u32 oclass;
+ void *data;
+ u32 size;
+ void *priv; /*XXX: hack */
+ void (*dtor)(struct nvif_object *);
+ struct {
+ void *ptr;
+ u32 size;
+ } map;
+};
+
+int nvif_object_init(struct nvif_object *, void (*dtor)(struct nvif_object *),
+ u32 handle, u32 oclass, void *, u32,
+ struct nvif_object *);
+void nvif_object_fini(struct nvif_object *);
+int nvif_object_new(struct nvif_object *, u32 handle, u32 oclass,
+ void *, u32, struct nvif_object **);
+void nvif_object_ref(struct nvif_object *, struct nvif_object **);
+int nvif_object_ioctl(struct nvif_object *, void *, u32, void **);
+int nvif_object_sclass(struct nvif_object *, u32 *, int);
+u32 nvif_object_rd(struct nvif_object *, int, u64);
+void nvif_object_wr(struct nvif_object *, int, u64, u32);
+int nvif_object_mthd(struct nvif_object *, u32, void *, u32);
+int nvif_object_map(struct nvif_object *);
+void nvif_object_unmap(struct nvif_object *);
+
+#define nvif_object(a) (a)->object
+
+#define ioread8_native ioread8
+#define iowrite8_native iowrite8
+#define nvif_rd(a,b,c) ({ \
+ struct nvif_object *_object = nvif_object(a); \
+ u32 _data; \
+ if (likely(_object->map.ptr)) \
+ _data = ioread##b##_native((u8 *)_object->map.ptr + (c)); \
+ else \
+ _data = nvif_object_rd(_object, (b) / 8, (c)); \
+ _data; \
+})
+#define nvif_wr(a,b,c,d) ({ \
+ struct nvif_object *_object = nvif_object(a); \
+ if (likely(_object->map.ptr)) \
+ iowrite##b##_native((d), (u8 *)_object->map.ptr + (c)); \
+ else \
+ nvif_object_wr(_object, (b) / 8, (c), (d)); \
+})
+
+#define nvif_rd08(a,b) ({ u8 _v = nvif_rd((a), 8, (b)); _v; })
+#define nvif_rd16(a,b) ({ u16 _v = nvif_rd((a), 16, (b)); _v; })
+#define nvif_rd32(a,b) ({ u32 _v = nvif_rd((a), 32, (b)); _v; })
+#define nvif_wr08(a,b,c) nvif_wr((a), 8, (b), (u8)(c))
+#define nvif_wr16(a,b,c) nvif_wr((a), 16, (b), (u16)(c))
+#define nvif_wr32(a,b,c) nvif_wr((a), 32, (b), (u32)(c))
+#define nvif_mask(a,b,c,d) ({ \
+ u32 _v = nvif_rd32(nvif_object(a), (b)); \
+ nvif_wr32(nvif_object(a), (b), (_v & ~(c)) | (d)); \
+ _v; \
+})
+
+#define nvif_mthd(a,b,c,d) nvif_object_mthd(nvif_object(a), (b), (c), (d))
+
+/*XXX*/
+#include <core/object.h>
+#define nvkm_object(a) ((struct nouveau_object *)nvif_object(a)->priv)
+#define nvif_exec(a,b,c,d) nv_exec(nvkm_object(a), (b), (c), (d))
+
+#endif
diff --git a/nvif/os.h b/nvif/os.h
new file mode 120000
index 000000000..db919475b
--- /dev/null
+++ b/nvif/os.h
@@ -0,0 +1 @@
+../lib/core/os.h \ No newline at end of file
diff --git a/nvkm/Makefile.am b/nvkm/Makefile.am
index 81f349cea..64edaa775 100644
--- a/nvkm/Makefile.am
+++ b/nvkm/Makefile.am
@@ -1,8 +1,8 @@
SUBDIRS = core subdev engine
-noinst_LTLIBRARIES = libnouveau.la
+noinst_LTLIBRARIES = libnvkm.la
-libnouveau_la_SOURCES =
-libnouveau_la_LIBADD = core/libcore.la \
- subdev/libsubdev.la \
- engine/libengine.la
+libnvkm_la_SOURCES =
+libnvkm_la_LIBADD = core/libcore.la \
+ subdev/libsubdev.la \
+ engine/libengine.la
diff --git a/nvkm/core/handle.c b/nvkm/core/handle.c
index 734777ce4..a490b805d 100644
--- a/nvkm/core/handle.c
+++ b/nvkm/core/handle.c
@@ -146,9 +146,7 @@ nouveau_handle_create(struct nouveau_object *parent, u32 _parent, u32 _handle,
}
hprintk(handle, TRACE, "created\n");
-
*phandle = handle;
-
return 0;
}
diff --git a/nvkm/engine/Makefile.engine b/nvkm/engine/Makefile.engine
index 513c6c87b..2222873f6 100644
--- a/nvkm/engine/Makefile.engine
+++ b/nvkm/engine/Makefile.engine
@@ -1,3 +1,4 @@
AM_CPPFLAGS = -I${top_srcdir}/nvkm \
-I${top_srcdir}/nvkm/include \
- -I${top_srcdir}/lib
+ -I${top_srcdir}/lib \
+ -I${top_srcdir}
diff --git a/nvkm/include/core/class.h b/nvkm/include/core/class.h
index d6fd2cbe4..37d47cb44 100644
--- a/nvkm/include/core/class.h
+++ b/nvkm/include/core/class.h
@@ -1,6 +1,8 @@
#ifndef __NOUVEAU_CLASS_H__
#define __NOUVEAU_CLASS_H__
+#include <nvif/class.h>
+
/* Device class
*
* 0080: NV_DEVICE