From b7c81f0355379b9d0fcdf624a8df1b7119f28efc Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Sun, 10 Aug 2014 04:10:21 +1000 Subject: 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 --- Makefile.am | 2 +- bin/Makefile.am | 8 +- bin/nv_aux.c | 37 +++-- bin/nv_disp.c | 36 ++--- bin/nv_i2c.c | 37 +++-- bin/nv_init.c | 39 +++-- bin/nv_perfmon.c | 68 +++++---- bin/nv_rd08.c | 2 +- bin/nv_rd16.c | 2 +- bin/nv_rd32.c | 2 +- bin/nv_rdfuc.c | 43 +++--- bin/nv_rdfunc.h | 27 +++- bin/nv_rffunc.h | 12 +- bin/nv_rifunc.h | 12 +- bin/nv_rs08.c | 2 +- bin/nv_rs16.c | 2 +- bin/nv_rs32.c | 2 +- bin/nv_rsfunc.h | 16 +- bin/nv_rv08.c | 2 +- bin/nv_rv16.c | 2 +- bin/nv_rv32.c | 2 +- bin/nv_rvfunc.h | 10 +- bin/nv_wffunc.h | 12 +- bin/nv_wifunc.h | 12 +- bin/nv_wr08.c | 2 +- bin/nv_wr16.c | 2 +- bin/nv_wr32.c | 2 +- bin/nv_wrfunc.h | 27 +++- bin/nv_ws08.c | 2 +- bin/nv_ws16.c | 2 +- bin/nv_ws32.c | 2 +- bin/nv_wsfunc.h | 10 +- bin/nv_wv08.c | 2 +- bin/nv_wv16.c | 2 +- bin/nv_wv32.c | 2 +- bin/nv_wvfunc.h | 10 +- configure.ac | 1 + drm/Kbuild | 6 + drm/nvif/client.c | 1 + drm/nvif/client.h | 1 + drm/nvif/device.c | 1 + drm/nvif/device.h | 1 + drm/nvif/driver.h | 1 + drm/nvif/notify.c | 1 + drm/nvif/notify.h | 1 + drm/nvif/object.c | 1 + drm/nvif/object.h | 1 + drm/nvif/os.h | 1 + lib/Makefile.am | 6 +- lib/core/os.h | 29 ++-- lib/main.c | 176 +++++++++------------- lib/priv.h | 8 +- nvif/Makefile.am | 12 ++ nvif/client.c | 130 ++++++++++++++++ nvif/client.h | 39 +++++ nvif/device.c | 78 ++++++++++ nvif/device.h | 66 +++++++++ nvif/driver.h | 20 +++ nvif/list.h | 353 ++++++++++++++++++++++++++++++++++++++++++++ nvif/notify.c | 237 +++++++++++++++++++++++++++++ nvif/notify.h | 39 +++++ nvif/object.c | 302 +++++++++++++++++++++++++++++++++++++ nvif/object.h | 77 ++++++++++ nvif/os.h | 1 + nvkm/Makefile.am | 10 +- nvkm/core/handle.c | 2 - nvkm/engine/Makefile.engine | 3 +- nvkm/include/core/class.h | 2 + 68 files changed, 1711 insertions(+), 350 deletions(-) create mode 120000 drm/nvif/client.c create mode 120000 drm/nvif/client.h create mode 120000 drm/nvif/device.c create mode 120000 drm/nvif/device.h create mode 120000 drm/nvif/driver.h create mode 120000 drm/nvif/notify.c create mode 120000 drm/nvif/notify.h create mode 120000 drm/nvif/object.c create mode 120000 drm/nvif/object.h create mode 120000 drm/nvif/os.h create mode 100644 nvif/Makefile.am create mode 100644 nvif/client.c create mode 100644 nvif/client.h create mode 100644 nvif/device.c create mode 100644 nvif/device.h create mode 100644 nvif/driver.h create mode 100644 nvif/list.h create mode 100644 nvif/notify.c create mode 100644 nvif/notify.h create mode 100644 nvif/object.c create mode 100644 nvif/object.h create mode 120000 nvif/os.h 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 #include -#include -#include +#include +#include +#include #include -#include - -#include - -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 -#include -#include -#include +#include 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 #include -#include -#include +#include +#include +#include #include -#include - -#include - -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 #include -#include -#include +#include +#include +#include +#include #include -#include - -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 #include -#include -#include +#include +#include +#include #include #include -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 #include -#include -#include +#include +#include +#include #include 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 #include -#include -#include +#include +#include +#include #include #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 -#include -#include -#include +#include 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 -#include -#include -#include +#include 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 -#include -#include -#include +#include 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 -#include -#include -#include +#include 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 -#include -#include -#include +#include 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 -#include -#include -#include +#include 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 #include -#include -#include +#include +#include +#include #include #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 -#include -#include -#include +#include 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 -#include -#include -#include +#include 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 @@ -25,18 +25,6 @@ #ifndef __NOUVEAU_OS_H__ #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 *****************************************************************************/ @@ -45,15 +33,15 @@ void os_backtrace(void); #include #include -#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 +#include +#include +#include +#include +#include +#include #include +#include #include #include #include -#include +#include +#include #include #include #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 -#include +#include #include #include @@ -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 + */ + +#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 +#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 + */ + +#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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 +#include +#include +#include +#include + +#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 + * + * 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 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 + */ + +#include +#include +#include +#include +#include +#include + +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(¬ify->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, ¬ify->flags)) { + int ret = nvif_notify_put_(notify); + if (test_bit(NVIF_NOTIFY_WORK, ¬ify->flags)) + flush_work(¬ify->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(¬ify->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, ¬ify->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, ¬ify->flags)) { + atomic_inc(¬ify->putcnt); + memcpy((void *)notify->data, data, size); + schedule_work(¬ify->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(¬ify->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, ¬ify->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, ¬ify->object); + notify->flags = 0; + atomic_set(¬ify->putcnt, 1); + notify->dtor = dtor; + notify->func = func; + notify->data = NULL; + notify->size = reply; + if (work) { + INIT_WORK(¬ify->work, nvif_notify_work); + set_bit(NVIF_NOTIFY_WORK, ¬ify->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 + */ + +#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 + +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 +#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 + /* Device class * * 0080: NV_DEVICE -- cgit v1.2.1