summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJérôme Glisse <jglisse@redhat.com>2018-03-06 16:21:26 -0500
committerJérôme Glisse <jglisse@redhat.com>2018-03-06 16:21:26 -0500
commit2f73b7129501cc32c085651ba6e5fc1e30d2c7ed (patch)
treecbe0f58667adaeec8b64243a96fa0fb7f9f37896
parent75b6bec395ac8aefea5de22cfcc58b6346ea0cac (diff)
moche: initial basic testHEADmaster
This just write thread.idx to a buffer. Signed-off-by: Jérôme Glisse <jglisse@redhat.com>
-rw-r--r--Makefile21
-rw-r--r--moche.c537
-rw-r--r--nvif/cl0002.h67
-rw-r--r--nvif/cl0046.h29
-rw-r--r--nvif/cl006b.h12
-rw-r--r--nvif/cl0080.h47
-rw-r--r--nvif/cl506e.h13
-rw-r--r--nvif/cl506f.h14
-rw-r--r--nvif/cl5070.h96
-rw-r--r--nvif/cl507a.h12
-rw-r--r--nvif/cl507b.h12
-rw-r--r--nvif/cl507c.h13
-rw-r--r--nvif/cl507d.h12
-rw-r--r--nvif/cl507e.h13
-rw-r--r--nvif/cl826e.h15
-rw-r--r--nvif/cl826f.h16
-rw-r--r--nvif/cl906f.h16
-rw-r--r--nvif/cl9097.h45
-rw-r--r--nvif/cla06f.h31
-rw-r--r--nvif/class.h188
-rw-r--r--nvif/client.h28
-rw-r--r--nvif/device.h72
-rw-r--r--nvif/driver.h27
-rw-r--r--nvif/event.h63
-rw-r--r--nvif/if0000.h20
-rw-r--r--nvif/if0001.h47
-rw-r--r--nvif/if0002.h39
-rw-r--r--nvif/if0003.h34
-rw-r--r--nvif/if0004.h14
-rw-r--r--nvif/if0005.h5
-rw-r--r--nvif/if0008.h42
-rw-r--r--nvif/if000a.h22
-rw-r--r--nvif/if000b.h11
-rw-r--r--nvif/if000c.h72
-rw-r--r--nvif/if000d.h12
-rw-r--r--nvif/if500b.h25
-rw-r--r--nvif/if500d.h21
-rw-r--r--nvif/if900b.h23
-rw-r--r--nvif/if900d.h21
-rw-r--r--nvif/ifb00d.h27
-rw-r--r--nvif/ifc00d.h21
-rw-r--r--nvif/ioctl.h137
-rw-r--r--nvif/list.h353
-rw-r--r--nvif/mem.h18
-rw-r--r--nvif/mmu.h56
-rw-r--r--nvif/notify.h34
-rw-r--r--nvif/object.h108
-rw-r--r--nvif/os.h37
-rw-r--r--nvif/unpack.h29
-rw-r--r--nvif/vmm.h42
50 files changed, 2669 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..149488a
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,21 @@
+# Copyright 2018 Jérôme Glisse <jglisse@redhat.com>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# version 2 as published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+CFLAGS = -std=c99 -Wall -O0 -g -D_GNU_SOURCE -I/usr/include/drm
+LFLAGS = -lm -ldrm -ldrm_nouveau
+CC = gcc
+
+all: moche
+
+moche: moche.o
+ $(CC) $(CFLAGS) $? -o $@ $(LFLAGS)
+
+clean:
+ rm moche *.o
diff --git a/moche.c b/moche.c
new file mode 100644
index 0000000..5b16a0d
--- /dev/null
+++ b/moche.c
@@ -0,0 +1,537 @@
+/*
+ * Copyright 2018 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Authors: Jérôme Glisse <jglisse@redhat.com>
+ */
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <strings.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <stdio.h>
+#include <fcntl.h>
+
+#include "xf86drm.h"
+#include "libdrm/nouveau/nouveau.h"
+#include "nvif/class.h"
+#include "nvif/cl0080.h"
+#include "nvif/if0008.h"
+#include "nvif/if000c.h"
+
+struct nvk_00f0_cp_desc {
+ uint32_t unk0[8];
+ uint32_t entry;
+ uint32_t unk9[2];
+ uint32_t unk11_0 : 30;
+ uint32_t linked_tsc : 1;
+ uint32_t unk11_31 : 1;
+ uint32_t griddim_x : 31;
+ uint32_t unk12 : 1;
+ uint16_t griddim_y;
+ uint16_t unk13;
+ uint16_t griddim_z;
+ uint16_t unk14;
+ uint32_t unk15[2];
+ uint32_t shared_size : 18;
+ uint32_t unk17 : 14;
+ uint16_t unk18;
+ uint16_t blockdim_x;
+ uint16_t blockdim_y;
+ uint16_t blockdim_z;
+ uint32_t cb_mask : 8;
+ uint32_t unk20 : 24;
+ uint32_t unk21[8];
+ uint32_t local_size_p : 24;
+ uint32_t unk29 : 3;
+ uint32_t bar_alloc : 5;
+ uint32_t local_size_n : 24;
+ uint32_t gpr_alloc : 8;
+ uint32_t cstack_size : 24;
+ uint32_t unk31 : 8;
+ struct {
+ uint32_t address_l;
+ uint32_t address_h : 17;
+ uint32_t reserved : 2;
+ uint32_t size_sh4 : 13;
+ } cb[8];
+ uint32_t unk48[16];
+};
+
+
+typedef struct {
+ struct nouveau_client *nvclient;
+ struct nouveau_device *nvdevice;
+ struct nouveau_object *nvchannel;
+ struct nouveau_object *nvcompute;
+ struct nouveau_pushbuf *nvpushbuf;
+ struct nouveau_drm *nvdrm;
+ void *hole;
+ int fd;
+} moche_t;
+
+#define DRM_FILE_PAGE_OFFSET (0x100000000ULL)
+
+int moche_init_hmm(moche_t *moche)
+{
+ moche->hole = mmap((void *)(1UL << 30), (2UL << 30), PROT_NONE,
+ MAP_PRIVATE, moche->fd, DRM_FILE_PAGE_OFFSET);
+ printf("hmm init %p\n", moche->hole);
+ return 0;
+}
+
+int moche_init(moche_t *moche)
+{
+ int r;
+
+ moche->fd = drmOpen("nouveau", NULL);
+ if (moche->fd < 0) {
+ printf("EE: failed to open nouveau device file (%d)\n", moche->fd);
+ return -1;
+ }
+
+ if ((r = nouveau_drm_new(moche->fd, &moche->nvdrm))) {
+ printf("EE: failed to create nouveau drm (%d)\n", r);
+ return r;
+ }
+
+ {
+ struct nv_device_v0 arg = {0};
+ uint32_t oclass, size;
+ void *data;
+
+ arg.device = ~0ULL;
+ oclass = NV_DEVICE;
+ size = sizeof(arg);
+ data = &arg;
+ if ((r = nouveau_device_new(&moche->nvdrm->client, oclass, data,
+ size, &moche->nvdevice))) {
+ printf("EE: failed to create nouveau device (%d)\n", r);
+ goto nouveau_device;
+ }
+ }
+
+ if ((r = nouveau_client_new(moche->nvdevice, &moche->nvclient))) {
+ printf("EE: failed to create nouveau client (%d)\n", r);
+ goto nouveau_client;
+ }
+
+ if ((r = moche_init_hmm(moche))) {
+ printf("EE: failed to enbable HMM (%d)\n", r);
+ goto nouveau_hmm;
+ }
+
+ {
+ struct nve0_fifo arg = {0};
+ uint32_t oclass, size;
+ void *data;
+
+ oclass = NOUVEAU_FIFO_CHANNEL_CLASS;
+ arg.engine = 0x01 | 0x10 | 0x20; // NVA06F_V0_ENGINE_CE0 | NVA06F_V0_ENGINE_CE1
+ size = sizeof(arg);
+ data = &arg;
+ if ((r = nouveau_object_new(&moche->nvdevice->object, 0, oclass,
+ data, size, &moche->nvchannel))) {
+ printf("EE: failed to create nouveau channel (%d)\n", r);
+ goto nouveau_channel;
+ }
+ }
+
+ {
+ if ((r = nouveau_pushbuf_new(moche->nvclient, moche->nvchannel, 2,
+ 64 * 1024, 1, &moche->nvpushbuf))) {
+ printf("EE: failed to create nouveau pushbuf (%d)\n", r);
+ goto nouveau_pushbuf;
+ }
+ }
+
+ {
+ if ((r = nouveau_object_new(moche->nvchannel, 0xcafec1c0,
+ 0xc1c0, NULL, 0, &moche->nvcompute))) {
+ printf("EE: failed to create nouveau channel (%d)\n", r);
+ goto nouveau_compute;
+ }
+ }
+
+ return 0;
+
+nouveau_compute:
+nouveau_pushbuf:
+ nouveau_object_del(&moche->nvchannel);
+nouveau_channel:
+nouveau_hmm:
+ nouveau_client_del(&moche->nvclient);
+nouveau_client:
+ nouveau_device_del(&moche->nvdevice);
+nouveau_device:
+ nouveau_drm_del(&moche->nvdrm);
+ return r;
+}
+
+void moche_fini(moche_t *moche)
+{
+ nouveau_object_del(&moche->nvcompute);
+ nouveau_pushbuf_del(&moche->nvpushbuf);
+ nouveau_object_del(&moche->nvchannel);
+ nouveau_client_del(&moche->nvclient);
+ nouveau_device_del(&moche->nvdevice);
+ nouveau_drm_del(&moche->nvdrm);
+}
+
+static inline void moche_push_data(moche_t *moche, uint32_t data)
+{
+ *moche->nvpushbuf->cur++ = data;
+}
+
+static inline int moche_push_kick(moche_t *moche)
+{
+ return nouveau_pushbuf_kick(moche->nvpushbuf, moche->nvchannel);
+}
+
+static inline void moche_push_refn(moche_t *moche,
+ struct nouveau_bo *bo, uint32_t flags)
+{
+ struct nouveau_pushbuf_refn ref = { bo, flags };
+
+ nouveau_pushbuf_refn(moche->nvpushbuf, &ref, 1);
+}
+
+static inline uint32_t nvk_sq_cmd(unsigned subc, unsigned method, unsigned len)
+{
+ return ((method >> 2) & 0x1fff) |
+ ((len & 0xfff) << 16) |
+ ((subc & 0x7) << 13) |
+ (0x1 << 29);
+}
+
+static inline uint32_t nvk_ni_cmd(unsigned subc, unsigned method, unsigned len)
+{
+ return ((method >> 2) & 0x1fff) |
+ ((len & 0xfff) << 16) |
+ ((subc & 0x7) << 13) |
+ (0x3 << 29);
+}
+
+static inline uint32_t nvk_addr_high(uint64_t offset)
+{
+ return (offset >> 32) & 0xffffffff;
+}
+
+static inline uint32_t nvk_addr_low(uint64_t offset)
+{
+ return offset & 0xffffffff;
+}
+
+static inline uint32_t nvk_size_high(uint64_t offset)
+{
+ return (offset >> 32) & 0xffffffff;
+}
+
+static inline uint32_t nvk_size_low(uint64_t offset)
+{
+ return offset & 0xffffffff;
+}
+
+int moche_pushbuf_test(moche_t *moche)
+{
+ struct nouveau_bo *bo;
+ uint32_t *ptr;
+ int r, i;
+
+ if ((r = nouveau_bo_new(moche->nvdevice, NOUVEAU_BO_GART,
+ 0, 4 * 1024, NULL, &bo))) {
+ printf("EE: failed to create nouveau bo (%d)\n", r);
+ goto nouveau_bo_new;
+ }
+ if ((r = nouveau_bo_map(bo, NOUVEAU_BO_WR, moche->nvclient))) {
+ printf("EE: failed to map nouveau bo (%d)\n", r);
+ goto nouveau_bo_map;
+ }
+
+ ptr = bo->map;
+ ptr[0] = 0xcafedead;
+
+ if ((r = nouveau_pushbuf_space(moche->nvpushbuf, 9, 1, 0))) {
+ printf("EE: pushbuf full (%d)\n", r);
+ goto nouveau_bo_new;
+ }
+ moche_push_refn(moche, bo, NOUVEAU_BO_GART | NOUVEAU_BO_WR);
+ moche_push_data(moche, nvk_sq_cmd(1, 0x0000, 1));
+ moche_push_data(moche, moche->nvcompute->oclass);
+ moche_push_data(moche, nvk_sq_cmd(1, 0x0110, 1));
+ moche_push_data(moche, 0x00000000);
+#if 1
+ moche_push_data(moche, nvk_sq_cmd(1, 0x1b00, 4));
+ moche_push_data(moche, nvk_addr_high(bo->offset));
+ moche_push_data(moche, nvk_addr_low(bo->offset));
+ moche_push_data(moche, 0xdeadcafe);
+ moche_push_data(moche, 0x00000000);
+#else
+ moche_push_data(moche, nvk_sq_cmd(1, 0x0010, 4));
+ moche_push_data(moche, nvk_addr_high(bo->offset));
+ moche_push_data(moche, nvk_addr_low(bo->offset));
+ moche_push_data(moche, 0xdeadcafe);
+ moche_push_data(moche, 0x00000002);
+#endif
+
+ if ((r = moche_push_kick(moche))) {
+ printf("EE: pushbuf kick (%d)\n", r);
+ goto nouveau_push_kick;
+ }
+
+ for (i = 0; i < 10 && ptr[0] != 0xdeadcafe; ++i) {
+ nouveau_bo_wait(bo, NOUVEAU_BO_RD, moche->nvclient);
+ }
+ if (ptr[0] == 0xdeadcafe) {
+ printf("OK: pusbuf test 0x%08x\n", ptr[0]);
+ } else {
+ printf("EE: pusbuf test 0x%08x\n", ptr[0]);
+ }
+
+nouveau_push_kick:
+nouveau_bo_map:
+ nouveau_bo_ref(NULL, &bo);
+nouveau_bo_new:
+ return r;
+}
+
+int moche_compute_test(moche_t *moche, uint64_t doffset,
+ uint32_t *rptr, unsigned nelem,
+ struct nouveau_bo *bor)
+{
+ uint64_t code[] = {
+ //testtx:
+ // sched 0x7f1 0x207f9 0x7f9
+ // mov $r2 $tid.x
+ // lea 0x1 cc $r0 $r2 c0[0x0] 0x2
+ // lea hi x 0x1 $r1 $r2 c0[0x4] 0x0 0x2
+ // sched 0x7f9 0x7f5 0x7ff
+ // stg e b32 ncg[$r0] $r2
+ // exit
+ // exit
+ 0x001fe440ff2007f1ul,
+ 0xf0c8000002170002ul,
+ 0x4bd7810000070200ul,
+ 0x1a177f8000170201ul,
+ 0x001ffc00fea007f9ul,
+ 0xeedc200000070002ul,
+ 0xe30000000007000ful,
+ 0xe30000000007000ful,
+ };
+ struct nouveau_bo *bom, *tls;
+ struct nvk_00f0_cp_desc *desc;
+ uint32_t *mptr;
+ int r, i, tls_size;
+
+ tls_size = 16 << 20;
+ if ((r = nouveau_bo_new(moche->nvdevice, NOUVEAU_BO_GART,
+ 0, tls_size, NULL, &tls))) {
+ printf("EE: failed to create nouveau bo (%d)\n", r);
+ goto nouveau_tls_new;
+ }
+ if ((r = nouveau_bo_new(moche->nvdevice, NOUVEAU_BO_GART,
+ 0, 64 * 1024, NULL, &bom))) {
+ printf("EE: failed to create nouveau bo (%d)\n", r);
+ goto nouveau_bom_new;
+ }
+ if ((r = nouveau_bo_map(bom, NOUVEAU_BO_WR, moche->nvclient))) {
+ printf("EE: failed to map nouveau bo (%d)\n", r);
+ goto nouveau_bom_map;
+ }
+
+ mptr = bom->map;
+ printf("bom offset 0x%lx\n", (unsigned long)bom->offset);
+
+ // initialize result bo
+ memset(rptr, 0, nelem * 4);
+
+ // fence
+ mptr[0] = 0xcafedead;
+ memcpy(&mptr[1024], code, sizeof(code));
+
+ // param
+ mptr[64] = nvk_addr_low(doffset);
+ mptr[65] = nvk_addr_high(doffset);
+
+ // compute descriptor
+ desc = (void *)&mptr[128];
+ memset(desc, 0, sizeof(*desc));
+ desc->griddim_x = nelem;
+ desc->griddim_y = 1;
+ desc->griddim_z = 1;
+ desc->blockdim_x = 32;
+ desc->blockdim_y = 1;
+ desc->blockdim_z = 1;
+ desc->entry = 0x0;
+ desc->shared_size = 0;
+ desc->local_size_p = 0;
+ desc->bar_alloc = 0;
+ desc->local_size_n = 0;
+ desc->gpr_alloc = 8;
+ desc->cstack_size = 0x1000;
+ desc->cb_mask = 1;
+ desc->cb[0].address_h = nvk_addr_high(bom->offset + 64 * 4);
+ desc->cb[0].address_l = nvk_addr_low(bom->offset + 64 * 4);
+ desc->cb[0].size_sh4 = 256 >> 4;
+ desc->unk0[4] = 0x40;
+ desc->unk11_0 = 0x04014000;
+
+ if ((r = nouveau_pushbuf_space(moche->nvpushbuf, 1024, 3, 0))) {
+ printf("EE: pushbuf full (%d)\n", r);
+ goto nouveau_push_space;
+ }
+ moche_push_refn(moche, bom, NOUVEAU_BO_GART | NOUVEAU_BO_WR);
+ if (bor)
+ moche_push_refn(moche, bor, NOUVEAU_BO_GART | NOUVEAU_BO_WR);
+ moche_push_refn(moche, tls, NOUVEAU_BO_GART | NOUVEAU_BO_WR);
+ moche_push_data(moche, nvk_sq_cmd(1, 0x0000, 1));
+ moche_push_data(moche, moche->nvcompute->oclass);
+ moche_push_data(moche, nvk_sq_cmd(1, 0x0110, 1));
+ moche_push_data(moche, 0x00000000);
+
+ tls_size = tls_size / 16;
+ moche_push_data(moche, nvk_sq_cmd(1, 0x0790, 2));
+ moche_push_data(moche, nvk_addr_high(tls->offset));
+ moche_push_data(moche, nvk_addr_low(tls->offset));
+ moche_push_data(moche, nvk_sq_cmd(1, 0x02e4, 3));
+ moche_push_data(moche, nvk_addr_high(tls_size));
+ moche_push_data(moche, nvk_addr_low(tls_size) & ~0x7fff);
+ moche_push_data(moche, 0x000000ff);
+ moche_push_data(moche, nvk_sq_cmd(1, 0x02f0, 3));
+ moche_push_data(moche, nvk_addr_high(tls_size));
+ moche_push_data(moche, nvk_addr_low(tls_size) & ~0x7fff);
+ moche_push_data(moche, 0x000000ff);
+ moche_push_data(moche, nvk_sq_cmd(1, 0x077c, 1));
+ moche_push_data(moche, 0xff000000);
+ moche_push_data(moche, nvk_sq_cmd(1, 0x0214, 1));
+ moche_push_data(moche, 0xfe000000);
+ moche_push_data(moche, nvk_sq_cmd(1, 0x1608, 2));
+ moche_push_data(moche, nvk_addr_high(bom->offset + 1024 * 4));
+ moche_push_data(moche, nvk_addr_low(bom->offset + 1024 * 4));
+ moche_push_data(moche, nvk_sq_cmd(1, 0x0310, 1));
+ moche_push_data(moche, 0x00000400);
+ moche_push_data(moche, nvk_ni_cmd(1, 0x0248, 64));
+ for (int i = 63; i >= 0; --i) {
+ moche_push_data(moche, 0x00038000 | i);
+ }
+ moche_push_data(moche, nvk_ni_cmd(1, 0x0110, 1));
+ moche_push_data(moche, 0x00000000);
+ moche_push_data(moche, nvk_sq_cmd(1, 0x2608, 1));
+ moche_push_data(moche, 0x00000000);
+ moche_push_data(moche, nvk_sq_cmd(1, 0x1698, 1));
+ moche_push_data(moche, 0x00001000);
+ moche_push_data(moche, nvk_sq_cmd(1, 0x021c, 1));
+ moche_push_data(moche, 0x00001017);
+ moche_push_data(moche, nvk_sq_cmd(1, 0x02b4, 1));
+ moche_push_data(moche, (bom->offset + 128 * 4) >> 8);
+ moche_push_data(moche, nvk_sq_cmd(1, 0x02bc, 1));
+ moche_push_data(moche, 0x00000003);
+ moche_push_data(moche, nvk_sq_cmd(1, 0x0110, 1));
+ moche_push_data(moche, 0x00000000);
+
+ moche_push_data(moche, nvk_sq_cmd(1, 0x0110, 1));
+ moche_push_data(moche, 0x00000000);
+ moche_push_data(moche, nvk_sq_cmd(1, 0x1b00, 4));
+ moche_push_data(moche, nvk_addr_high(bom->offset));
+ moche_push_data(moche, nvk_addr_low(bom->offset));
+ moche_push_data(moche, 0xdeadcafe);
+ moche_push_data(moche, 0x00000000);
+
+ if ((r = moche_push_kick(moche))) {
+ printf("EE: pushbuf kick (%d)\n", r);
+ goto nouveau_push_kick;
+ }
+
+ for (i = 0; i < 10 && mptr[0] != 0xdeadcafe; ++i) {
+ nouveau_bo_wait(bom, NOUVEAU_BO_RD, moche->nvclient);
+ }
+ if (mptr[0] == 0xdeadcafe) {
+ printf("OK: compute test 0x%08x 0x%08x 0x%08x 0x%08x\n",
+ mptr[0], rptr[0], rptr[1], rptr[nelem - 1]);
+ } else {
+ printf("EE: compute test 0x%08x\n", mptr[0]);
+ }
+ for (i = 0; i < nelem; ++i) {
+ if (rptr[i] != i) {
+ printf("EE: rptr[%d] != %d -> %d\n", i, i, rptr[i]);
+ break;
+ }
+ }
+
+nouveau_push_kick:
+nouveau_push_space:
+nouveau_bom_map:
+ nouveau_bo_ref(NULL, &bom);
+nouveau_bom_new:
+ nouveau_bo_ref(NULL, &tls);
+nouveau_tls_new:
+ return r;
+}
+
+int main(int argc, char *argv[])
+{
+ struct nouveau_bo *bor = NULL;
+ unsigned nelem = 512 * 1024;
+ moche_t moche = {0};
+ int r;
+
+ if ((r = moche_init(&moche))) {
+ return r;
+ }
+
+ printf("OK: fd %d ok chipset 0x%08x (press enter to run)\n",
+ moche.fd, moche.nvdevice->chipset);
+ getchar();
+
+ if ((r = moche_pushbuf_test(&moche))) {
+ return r;
+ }
+
+ if (0) {
+ uint32_t *rptr;
+
+ if ((r = nouveau_bo_new(moche.nvdevice, NOUVEAU_BO_GART,
+ 0, 4 * nelem, NULL, &bor))) {
+ printf("EE: failed to create nouveau bo (%d)\n", r);
+ goto nouveau_bor_new;
+ }
+ if ((r = nouveau_bo_map(bor, NOUVEAU_BO_WR, moche.nvclient))) {
+ printf("EE: failed to map nouveau bo (%d)\n", r);
+ goto nouveau_bor_map;
+ }
+ rptr = bor->map;
+ printf("bor offset 0x%lx\n", (unsigned long)bor->offset);
+
+ if ((r = moche_compute_test(&moche, bor->offset, rptr, nelem, bor))) {
+ return r;
+ }
+ } else {
+ uint32_t *rptr;
+
+ rptr = malloc(nelem * 4);
+ printf("bor offset 0x%lx\n", (unsigned long)rptr);
+ if ((r = moche_compute_test(&moche, (uint64_t)rptr, rptr, nelem, NULL))) {
+ return r;
+ }
+ }
+
+nouveau_bor_map:
+ if (bor)
+ nouveau_bo_ref(NULL, &bor);
+nouveau_bor_new:
+ moche_fini(&moche);
+ return 0;
+}
diff --git a/nvif/cl0002.h b/nvif/cl0002.h
new file mode 100644
index 0000000..1a8b45b
--- /dev/null
+++ b/nvif/cl0002.h
@@ -0,0 +1,67 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __NVIF_CL0002_H__
+#define __NVIF_CL0002_H__
+
+struct nv_dma_v0 {
+ __u8 version;
+#define NV_DMA_V0_TARGET_VM 0x00
+#define NV_DMA_V0_TARGET_VRAM 0x01
+#define NV_DMA_V0_TARGET_PCI 0x02
+#define NV_DMA_V0_TARGET_PCI_US 0x03
+#define NV_DMA_V0_TARGET_AGP 0x04
+ __u8 target;
+#define NV_DMA_V0_ACCESS_VM 0x00
+#define NV_DMA_V0_ACCESS_RD 0x01
+#define NV_DMA_V0_ACCESS_WR 0x02
+#define NV_DMA_V0_ACCESS_RDWR (NV_DMA_V0_ACCESS_RD | NV_DMA_V0_ACCESS_WR)
+ __u8 access;
+ __u8 pad03[5];
+ __u64 start;
+ __u64 limit;
+ /* ... chipset-specific class data */
+};
+
+struct nv50_dma_v0 {
+ __u8 version;
+#define NV50_DMA_V0_PRIV_VM 0x00
+#define NV50_DMA_V0_PRIV_US 0x01
+#define NV50_DMA_V0_PRIV__S 0x02
+ __u8 priv;
+#define NV50_DMA_V0_PART_VM 0x00
+#define NV50_DMA_V0_PART_256 0x01
+#define NV50_DMA_V0_PART_1KB 0x02
+ __u8 part;
+#define NV50_DMA_V0_COMP_NONE 0x00
+#define NV50_DMA_V0_COMP_1 0x01
+#define NV50_DMA_V0_COMP_2 0x02
+#define NV50_DMA_V0_COMP_VM 0x03
+ __u8 comp;
+#define NV50_DMA_V0_KIND_PITCH 0x00
+#define NV50_DMA_V0_KIND_VM 0x7f
+ __u8 kind;
+ __u8 pad05[3];
+};
+
+struct gf100_dma_v0 {
+ __u8 version;
+#define GF100_DMA_V0_PRIV_VM 0x00
+#define GF100_DMA_V0_PRIV_US 0x01
+#define GF100_DMA_V0_PRIV__S 0x02
+ __u8 priv;
+#define GF100_DMA_V0_KIND_PITCH 0x00
+#define GF100_DMA_V0_KIND_VM 0xff
+ __u8 kind;
+ __u8 pad03[5];
+};
+
+struct gf119_dma_v0 {
+ __u8 version;
+#define GF119_DMA_V0_PAGE_LP 0x00
+#define GF119_DMA_V0_PAGE_SP 0x01
+ __u8 page;
+#define GF119_DMA_V0_KIND_PITCH 0x00
+#define GF119_DMA_V0_KIND_VM 0xff
+ __u8 kind;
+ __u8 pad03[5];
+};
+#endif
diff --git a/nvif/cl0046.h b/nvif/cl0046.h
new file mode 100644
index 0000000..c0d5eba
--- /dev/null
+++ b/nvif/cl0046.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __NVIF_CL0046_H__
+#define __NVIF_CL0046_H__
+
+#define NV04_DISP_NTFY_VBLANK 0x00
+#define NV04_DISP_NTFY_CONN 0x01
+
+struct nv04_disp_mthd_v0 {
+ __u8 version;
+#define NV04_DISP_SCANOUTPOS 0x00
+ __u8 method;
+ __u8 head;
+ __u8 pad03[5];
+};
+
+struct nv04_disp_scanoutpos_v0 {
+ __u8 version;
+ __u8 pad01[7];
+ __s64 time[2];
+ __u16 vblanks;
+ __u16 vblanke;
+ __u16 vtotal;
+ __u16 vline;
+ __u16 hblanks;
+ __u16 hblanke;
+ __u16 htotal;
+ __u16 hline;
+};
+#endif
diff --git a/nvif/cl006b.h b/nvif/cl006b.h
new file mode 100644
index 0000000..d0e8f35
--- /dev/null
+++ b/nvif/cl006b.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __NVIF_CL006B_H__
+#define __NVIF_CL006B_H__
+
+struct nv03_channel_dma_v0 {
+ __u8 version;
+ __u8 chid;
+ __u8 pad02[2];
+ __u32 offset;
+ __u64 pushbuf;
+};
+#endif
diff --git a/nvif/cl0080.h b/nvif/cl0080.h
new file mode 100644
index 0000000..2740278
--- /dev/null
+++ b/nvif/cl0080.h
@@ -0,0 +1,47 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __NVIF_CL0080_H__
+#define __NVIF_CL0080_H__
+
+struct nv_device_v0 {
+ __u8 version;
+ __u8 pad01[7];
+ __u64 device; /* device identifier, ~0 for client default */
+};
+
+#define NV_DEVICE_V0_INFO 0x00
+#define NV_DEVICE_V0_TIME 0x01
+
+struct nv_device_info_v0 {
+ __u8 version;
+#define NV_DEVICE_INFO_V0_IGP 0x00
+#define NV_DEVICE_INFO_V0_PCI 0x01
+#define NV_DEVICE_INFO_V0_AGP 0x02
+#define NV_DEVICE_INFO_V0_PCIE 0x03
+#define NV_DEVICE_INFO_V0_SOC 0x04
+ __u8 platform;
+ __u16 chipset; /* from NV_PMC_BOOT_0 */
+ __u8 revision; /* from NV_PMC_BOOT_0 */
+#define NV_DEVICE_INFO_V0_TNT 0x01
+#define NV_DEVICE_INFO_V0_CELSIUS 0x02
+#define NV_DEVICE_INFO_V0_KELVIN 0x03
+#define NV_DEVICE_INFO_V0_RANKINE 0x04
+#define NV_DEVICE_INFO_V0_CURIE 0x05
+#define NV_DEVICE_INFO_V0_TESLA 0x06
+#define NV_DEVICE_INFO_V0_FERMI 0x07
+#define NV_DEVICE_INFO_V0_KEPLER 0x08
+#define NV_DEVICE_INFO_V0_MAXWELL 0x09
+#define NV_DEVICE_INFO_V0_PASCAL 0x0a
+ __u8 family;
+ __u8 pad06[2];
+ __u64 ram_size;
+ __u64 ram_user;
+ char chip[16];
+ char name[64];
+};
+
+struct nv_device_time_v0 {
+ __u8 version;
+ __u8 pad01[7];
+ __u64 time;
+};
+#endif
diff --git a/nvif/cl506e.h b/nvif/cl506e.h
new file mode 100644
index 0000000..989690f
--- /dev/null
+++ b/nvif/cl506e.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __NVIF_CL506E_H__
+#define __NVIF_CL506E_H__
+
+struct nv50_channel_dma_v0 {
+ __u8 version;
+ __u8 chid;
+ __u8 pad02[6];
+ __u64 vmm;
+ __u64 pushbuf;
+ __u64 offset;
+};
+#endif
diff --git a/nvif/cl506f.h b/nvif/cl506f.h
new file mode 100644
index 0000000..5137b68
--- /dev/null
+++ b/nvif/cl506f.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __NVIF_CL506F_H__
+#define __NVIF_CL506F_H__
+
+struct nv50_channel_gpfifo_v0 {
+ __u8 version;
+ __u8 chid;
+ __u8 pad02[2];
+ __u32 ilength;
+ __u64 ioffset;
+ __u64 pushbuf;
+ __u64 vmm;
+};
+#endif
diff --git a/nvif/cl5070.h b/nvif/cl5070.h
new file mode 100644
index 0000000..7cdf536
--- /dev/null
+++ b/nvif/cl5070.h
@@ -0,0 +1,96 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __NVIF_CL5070_H__
+#define __NVIF_CL5070_H__
+
+#define NV50_DISP_MTHD 0x00
+
+struct nv50_disp_mthd_v0 {
+ __u8 version;
+#define NV50_DISP_SCANOUTPOS 0x00
+ __u8 method;
+ __u8 head;
+ __u8 pad03[5];
+};
+
+struct nv50_disp_scanoutpos_v0 {
+ __u8 version;
+ __u8 pad01[7];
+ __s64 time[2];
+ __u16 vblanks;
+ __u16 vblanke;
+ __u16 vtotal;
+ __u16 vline;
+ __u16 hblanks;
+ __u16 hblanke;
+ __u16 htotal;
+ __u16 hline;
+};
+
+struct nv50_disp_mthd_v1 {
+ __u8 version;
+#define NV50_DISP_MTHD_V1_ACQUIRE 0x01
+#define NV50_DISP_MTHD_V1_RELEASE 0x02
+#define NV50_DISP_MTHD_V1_DAC_LOAD 0x11
+#define NV50_DISP_MTHD_V1_SOR_HDA_ELD 0x21
+#define NV50_DISP_MTHD_V1_SOR_HDMI_PWR 0x22
+#define NV50_DISP_MTHD_V1_SOR_LVDS_SCRIPT 0x23
+#define NV50_DISP_MTHD_V1_SOR_DP_MST_LINK 0x25
+#define NV50_DISP_MTHD_V1_SOR_DP_MST_VCPI 0x26
+ __u8 method;
+ __u16 hasht;
+ __u16 hashm;
+ __u8 pad06[2];
+};
+
+struct nv50_disp_acquire_v0 {
+ __u8 version;
+ __u8 or;
+ __u8 link;
+ __u8 pad03[5];
+};
+
+struct nv50_disp_dac_load_v0 {
+ __u8 version;
+ __u8 load;
+ __u8 pad02[2];
+ __u32 data;
+};
+
+struct nv50_disp_sor_hda_eld_v0 {
+ __u8 version;
+ __u8 pad01[7];
+ __u8 data[];
+};
+
+struct nv50_disp_sor_hdmi_pwr_v0 {
+ __u8 version;
+ __u8 state;
+ __u8 max_ac_packet;
+ __u8 rekey;
+ __u8 avi_infoframe_length;
+ __u8 vendor_infoframe_length;
+ __u8 pad06[2];
+};
+
+struct nv50_disp_sor_lvds_script_v0 {
+ __u8 version;
+ __u8 pad01[1];
+ __u16 script;
+ __u8 pad04[4];
+};
+
+struct nv50_disp_sor_dp_mst_link_v0 {
+ __u8 version;
+ __u8 state;
+ __u8 pad02[6];
+};
+
+struct nv50_disp_sor_dp_mst_vcpi_v0 {
+ __u8 version;
+ __u8 pad01[1];
+ __u8 start_slot;
+ __u8 num_slots;
+ __u16 pbn;
+ __u16 aligned_pbn;
+};
+#endif
diff --git a/nvif/cl507a.h b/nvif/cl507a.h
new file mode 100644
index 0000000..36e5372
--- /dev/null
+++ b/nvif/cl507a.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __NVIF_CL507A_H__
+#define __NVIF_CL507A_H__
+
+struct nv50_disp_cursor_v0 {
+ __u8 version;
+ __u8 head;
+ __u8 pad02[6];
+};
+
+#define NV50_DISP_CURSOR_V0_NTFY_UEVENT 0x00
+#endif
diff --git a/nvif/cl507b.h b/nvif/cl507b.h
new file mode 100644
index 0000000..3e643b7
--- /dev/null
+++ b/nvif/cl507b.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __NVIF_CL507B_H__
+#define __NVIF_CL507B_H__
+
+struct nv50_disp_overlay_v0 {
+ __u8 version;
+ __u8 head;
+ __u8 pad02[6];
+};
+
+#define NV50_DISP_OVERLAY_V0_NTFY_UEVENT 0x00
+#endif
diff --git a/nvif/cl507c.h b/nvif/cl507c.h
new file mode 100644
index 0000000..fd9e336
--- /dev/null
+++ b/nvif/cl507c.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __NVIF_CL507C_H__
+#define __NVIF_CL507C_H__
+
+struct nv50_disp_base_channel_dma_v0 {
+ __u8 version;
+ __u8 head;
+ __u8 pad02[6];
+ __u64 pushbuf;
+};
+
+#define NV50_DISP_BASE_CHANNEL_DMA_V0_NTFY_UEVENT 0x00
+#endif
diff --git a/nvif/cl507d.h b/nvif/cl507d.h
new file mode 100644
index 0000000..e994c68
--- /dev/null
+++ b/nvif/cl507d.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __NVIF_CL507D_H__
+#define __NVIF_CL507D_H__
+
+struct nv50_disp_core_channel_dma_v0 {
+ __u8 version;
+ __u8 pad01[7];
+ __u64 pushbuf;
+};
+
+#define NV50_DISP_CORE_CHANNEL_DMA_V0_NTFY_UEVENT 0x00
+#endif
diff --git a/nvif/cl507e.h b/nvif/cl507e.h
new file mode 100644
index 0000000..8082d2f
--- /dev/null
+++ b/nvif/cl507e.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __NVIF_CL507E_H__
+#define __NVIF_CL507E_H__
+
+struct nv50_disp_overlay_channel_dma_v0 {
+ __u8 version;
+ __u8 head;
+ __u8 pad02[6];
+ __u64 pushbuf;
+};
+
+#define NV50_DISP_OVERLAY_CHANNEL_DMA_V0_NTFY_UEVENT 0x00
+#endif
diff --git a/nvif/cl826e.h b/nvif/cl826e.h
new file mode 100644
index 0000000..1a87509
--- /dev/null
+++ b/nvif/cl826e.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __NVIF_CL826E_H__
+#define __NVIF_CL826E_H__
+
+struct g82_channel_dma_v0 {
+ __u8 version;
+ __u8 chid;
+ __u8 pad02[6];
+ __u64 vmm;
+ __u64 pushbuf;
+ __u64 offset;
+};
+
+#define NV826E_V0_NTFY_NON_STALL_INTERRUPT 0x00
+#endif
diff --git a/nvif/cl826f.h b/nvif/cl826f.h
new file mode 100644
index 0000000..e4e50cf
--- /dev/null
+++ b/nvif/cl826f.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __NVIF_CL826F_H__
+#define __NVIF_CL826F_H__
+
+struct g82_channel_gpfifo_v0 {
+ __u8 version;
+ __u8 chid;
+ __u8 pad02[2];
+ __u32 ilength;
+ __u64 ioffset;
+ __u64 pushbuf;
+ __u64 vmm;
+};
+
+#define NV826F_V0_NTFY_NON_STALL_INTERRUPT 0x00
+#endif
diff --git a/nvif/cl906f.h b/nvif/cl906f.h
new file mode 100644
index 0000000..ab0fa8a
--- /dev/null
+++ b/nvif/cl906f.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __NVIF_CL906F_H__
+#define __NVIF_CL906F_H__
+
+struct fermi_channel_gpfifo_v0 {
+ __u8 version;
+ __u8 chid;
+ __u8 pad02[2];
+ __u32 ilength;
+ __u64 ioffset;
+ __u64 vmm;
+};
+
+#define NV906F_V0_NTFY_NON_STALL_INTERRUPT 0x00
+#define NV906F_V0_NTFY_KILLED 0x01
+#endif
diff --git a/nvif/cl9097.h b/nvif/cl9097.h
new file mode 100644
index 0000000..e4c8de6
--- /dev/null
+++ b/nvif/cl9097.h
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __NVIF_CL9097_H__
+#define __NVIF_CL9097_H__
+
+#define FERMI_A_ZBC_COLOR 0x00
+#define FERMI_A_ZBC_DEPTH 0x01
+
+struct fermi_a_zbc_color_v0 {
+ __u8 version;
+#define FERMI_A_ZBC_COLOR_V0_FMT_ZERO 0x01
+#define FERMI_A_ZBC_COLOR_V0_FMT_UNORM_ONE 0x02
+#define FERMI_A_ZBC_COLOR_V0_FMT_RF32_GF32_BF32_AF32 0x04
+#define FERMI_A_ZBC_COLOR_V0_FMT_R16_G16_B16_A16 0x08
+#define FERMI_A_ZBC_COLOR_V0_FMT_RN16_GN16_BN16_AN16 0x0c
+#define FERMI_A_ZBC_COLOR_V0_FMT_RS16_GS16_BS16_AS16 0x10
+#define FERMI_A_ZBC_COLOR_V0_FMT_RU16_GU16_BU16_AU16 0x14
+#define FERMI_A_ZBC_COLOR_V0_FMT_RF16_GF16_BF16_AF16 0x16
+#define FERMI_A_ZBC_COLOR_V0_FMT_A8R8G8B8 0x18
+#define FERMI_A_ZBC_COLOR_V0_FMT_A8RL8GL8BL8 0x1c
+#define FERMI_A_ZBC_COLOR_V0_FMT_A2B10G10R10 0x20
+#define FERMI_A_ZBC_COLOR_V0_FMT_AU2BU10GU10RU10 0x24
+#define FERMI_A_ZBC_COLOR_V0_FMT_A8B8G8R8 0x28
+#define FERMI_A_ZBC_COLOR_V0_FMT_A8BL8GL8RL8 0x2c
+#define FERMI_A_ZBC_COLOR_V0_FMT_AN8BN8GN8RN8 0x30
+#define FERMI_A_ZBC_COLOR_V0_FMT_AS8BS8GS8RS8 0x34
+#define FERMI_A_ZBC_COLOR_V0_FMT_AU8BU8GU8RU8 0x38
+#define FERMI_A_ZBC_COLOR_V0_FMT_A2R10G10B10 0x3c
+#define FERMI_A_ZBC_COLOR_V0_FMT_BF10GF11RF11 0x40
+ __u8 format;
+ __u8 index;
+ __u8 pad03[5];
+ __u32 ds[4];
+ __u32 l2[4];
+};
+
+struct fermi_a_zbc_depth_v0 {
+ __u8 version;
+#define FERMI_A_ZBC_DEPTH_V0_FMT_FP32 0x01
+ __u8 format;
+ __u8 index;
+ __u8 pad03[5];
+ __u32 ds;
+ __u32 l2;
+};
+#endif
diff --git a/nvif/cla06f.h b/nvif/cla06f.h
new file mode 100644
index 0000000..56f5bd8
--- /dev/null
+++ b/nvif/cla06f.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __NVIF_CLA06F_H__
+#define __NVIF_CLA06F_H__
+
+struct kepler_channel_gpfifo_a_v0 {
+ __u8 version;
+ __u8 pad01[5];
+ __u16 chid;
+#define NVA06F_V0_ENGINE_SW 0x00000001
+#define NVA06F_V0_ENGINE_GR 0x00000002
+#define NVA06F_V0_ENGINE_SEC 0x00000004
+#define NVA06F_V0_ENGINE_MSVLD 0x00000010
+#define NVA06F_V0_ENGINE_MSPDEC 0x00000020
+#define NVA06F_V0_ENGINE_MSPPP 0x00000040
+#define NVA06F_V0_ENGINE_MSENC 0x00000080
+#define NVA06F_V0_ENGINE_VIC 0x00000100
+#define NVA06F_V0_ENGINE_NVDEC 0x00000200
+#define NVA06F_V0_ENGINE_NVENC0 0x00000400
+#define NVA06F_V0_ENGINE_NVENC1 0x00000800
+#define NVA06F_V0_ENGINE_CE0 0x00010000
+#define NVA06F_V0_ENGINE_CE1 0x00020000
+#define NVA06F_V0_ENGINE_CE2 0x00040000
+ __u32 engines;
+ __u32 ilength;
+ __u64 ioffset;
+ __u64 vmm;
+};
+
+#define NVA06F_V0_NTFY_NON_STALL_INTERRUPT 0x00
+#define NVA06F_V0_NTFY_KILLED 0x01
+#endif
diff --git a/nvif/class.h b/nvif/class.h
new file mode 100644
index 0000000..a7c5bf5
--- /dev/null
+++ b/nvif/class.h
@@ -0,0 +1,188 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __NVIF_CLASS_H__
+#define __NVIF_CLASS_H__
+
+/* these class numbers are made up by us, and not nvidia-assigned */
+#define NVIF_CLASS_CLIENT /* if0000.h */ -0x00000000
+
+#define NVIF_CLASS_CONTROL /* if0001.h */ -0x00000001
+
+#define NVIF_CLASS_PERFMON /* if0002.h */ -0x00000002
+#define NVIF_CLASS_PERFDOM /* if0003.h */ -0x00000003
+
+#define NVIF_CLASS_SW_NV04 /* if0004.h */ -0x00000004
+#define NVIF_CLASS_SW_NV10 /* if0005.h */ -0x00000005
+#define NVIF_CLASS_SW_NV50 /* if0005.h */ -0x00000006
+#define NVIF_CLASS_SW_GF100 /* if0005.h */ -0x00000007
+
+#define NVIF_CLASS_MMU /* if0008.h */ 0x80000008
+#define NVIF_CLASS_MMU_NV04 /* if0008.h */ 0x80000009
+#define NVIF_CLASS_MMU_NV50 /* if0008.h */ 0x80005009
+#define NVIF_CLASS_MMU_GF100 /* if0008.h */ 0x80009009
+
+#define NVIF_CLASS_MEM /* if000a.h */ 0x8000000a
+#define NVIF_CLASS_MEM_NV04 /* if000b.h */ 0x8000000b
+#define NVIF_CLASS_MEM_NV50 /* if500b.h */ 0x8000500b
+#define NVIF_CLASS_MEM_GF100 /* if900b.h */ 0x8000900b
+
+#define NVIF_CLASS_VMM /* if000c.h */ 0x8000000c
+#define NVIF_CLASS_VMM_NV04 /* if000d.h */ 0x8000000d
+#define NVIF_CLASS_VMM_NV50 /* if500d.h */ 0x8000500d
+#define NVIF_CLASS_VMM_GF100 /* if900d.h */ 0x8000900d
+#define NVIF_CLASS_VMM_GM200 /* ifb00d.h */ 0x8000b00d
+#define NVIF_CLASS_VMM_GP100 /* ifc00d.h */ 0x8000c00d
+
+/* the below match nvidia-assigned (either in hw, or sw) class numbers */
+#define NV_NULL_CLASS 0x00000030
+
+#define NV_DEVICE /* cl0080.h */ 0x00000080
+
+#define NV_DMA_FROM_MEMORY /* cl0002.h */ 0x00000002
+#define NV_DMA_TO_MEMORY /* cl0002.h */ 0x00000003
+#define NV_DMA_IN_MEMORY /* cl0002.h */ 0x0000003d
+
+#define NV50_TWOD 0x0000502d
+#define FERMI_TWOD_A 0x0000902d
+
+#define NV50_MEMORY_TO_MEMORY_FORMAT 0x00005039
+#define FERMI_MEMORY_TO_MEMORY_FORMAT_A 0x00009039
+
+#define KEPLER_INLINE_TO_MEMORY_A 0x0000a040
+#define KEPLER_INLINE_TO_MEMORY_B 0x0000a140
+
+#define NV04_DISP /* cl0046.h */ 0x00000046
+
+#define NV03_CHANNEL_DMA /* cl506b.h */ 0x0000006b
+#define NV10_CHANNEL_DMA /* cl506b.h */ 0x0000006e
+#define NV17_CHANNEL_DMA /* cl506b.h */ 0x0000176e
+#define NV40_CHANNEL_DMA /* cl506b.h */ 0x0000406e
+#define NV50_CHANNEL_DMA /* cl506e.h */ 0x0000506e
+#define G82_CHANNEL_DMA /* cl826e.h */ 0x0000826e
+
+#define NV50_CHANNEL_GPFIFO /* cl506f.h */ 0x0000506f
+#define G82_CHANNEL_GPFIFO /* cl826f.h */ 0x0000826f
+#define FERMI_CHANNEL_GPFIFO /* cl906f.h */ 0x0000906f
+#define KEPLER_CHANNEL_GPFIFO_A /* cla06f.h */ 0x0000a06f
+#define KEPLER_CHANNEL_GPFIFO_B /* cla06f.h */ 0x0000a16f
+#define MAXWELL_CHANNEL_GPFIFO_A /* cla06f.h */ 0x0000b06f
+#define PASCAL_CHANNEL_GPFIFO_A /* cla06f.h */ 0x0000c06f
+
+#define NV50_DISP /* cl5070.h */ 0x00005070
+#define G82_DISP /* cl5070.h */ 0x00008270
+#define GT200_DISP /* cl5070.h */ 0x00008370
+#define GT214_DISP /* cl5070.h */ 0x00008570
+#define GT206_DISP /* cl5070.h */ 0x00008870
+#define GF110_DISP /* cl5070.h */ 0x00009070
+#define GK104_DISP /* cl5070.h */ 0x00009170
+#define GK110_DISP /* cl5070.h */ 0x00009270
+#define GM107_DISP /* cl5070.h */ 0x00009470
+#define GM200_DISP /* cl5070.h */ 0x00009570
+#define GP100_DISP /* cl5070.h */ 0x00009770
+#define GP102_DISP /* cl5070.h */ 0x00009870
+
+#define NV31_MPEG 0x00003174
+#define G82_MPEG 0x00008274
+
+#define NV74_VP2 0x00007476
+
+#define NV50_DISP_CURSOR /* cl507a.h */ 0x0000507a
+#define G82_DISP_CURSOR /* cl507a.h */ 0x0000827a
+#define GT214_DISP_CURSOR /* cl507a.h */ 0x0000857a
+#define GF110_DISP_CURSOR /* cl507a.h */ 0x0000907a
+#define GK104_DISP_CURSOR /* cl507a.h */ 0x0000917a
+
+#define NV50_DISP_OVERLAY /* cl507b.h */ 0x0000507b
+#define G82_DISP_OVERLAY /* cl507b.h */ 0x0000827b
+#define GT214_DISP_OVERLAY /* cl507b.h */ 0x0000857b
+#define GF110_DISP_OVERLAY /* cl507b.h */ 0x0000907b
+#define GK104_DISP_OVERLAY /* cl507b.h */ 0x0000917b
+
+#define NV50_DISP_BASE_CHANNEL_DMA /* cl507c.h */ 0x0000507c
+#define G82_DISP_BASE_CHANNEL_DMA /* cl507c.h */ 0x0000827c
+#define GT200_DISP_BASE_CHANNEL_DMA /* cl507c.h */ 0x0000837c
+#define GT214_DISP_BASE_CHANNEL_DMA /* cl507c.h */ 0x0000857c
+#define GF110_DISP_BASE_CHANNEL_DMA /* cl507c.h */ 0x0000907c
+#define GK104_DISP_BASE_CHANNEL_DMA /* cl507c.h */ 0x0000917c
+#define GK110_DISP_BASE_CHANNEL_DMA /* cl507c.h */ 0x0000927c
+
+#define NV50_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000507d
+#define G82_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000827d
+#define GT200_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000837d
+#define GT214_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000857d
+#define GT206_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000887d
+#define GF110_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000907d
+#define GK104_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000917d
+#define GK110_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000927d
+#define GM107_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000947d
+#define GM200_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000957d
+#define GP100_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000977d
+#define GP102_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000987d
+
+#define NV50_DISP_OVERLAY_CHANNEL_DMA /* cl507e.h */ 0x0000507e
+#define G82_DISP_OVERLAY_CHANNEL_DMA /* cl507e.h */ 0x0000827e
+#define GT200_DISP_OVERLAY_CHANNEL_DMA /* cl507e.h */ 0x0000837e
+#define GT214_DISP_OVERLAY_CHANNEL_DMA /* cl507e.h */ 0x0000857e
+#define GF110_DISP_OVERLAY_CONTROL_DMA /* cl507e.h */ 0x0000907e
+#define GK104_DISP_OVERLAY_CONTROL_DMA /* cl507e.h */ 0x0000917e
+
+#define NV50_TESLA 0x00005097
+#define G82_TESLA 0x00008297
+#define GT200_TESLA 0x00008397
+#define GT214_TESLA 0x00008597
+#define GT21A_TESLA 0x00008697
+
+#define FERMI_A /* cl9097.h */ 0x00009097
+#define FERMI_B /* cl9097.h */ 0x00009197
+#define FERMI_C /* cl9097.h */ 0x00009297
+
+#define KEPLER_A /* cl9097.h */ 0x0000a097
+#define KEPLER_B /* cl9097.h */ 0x0000a197
+#define KEPLER_C /* cl9097.h */ 0x0000a297
+
+#define MAXWELL_A /* cl9097.h */ 0x0000b097
+#define MAXWELL_B /* cl9097.h */ 0x0000b197
+
+#define PASCAL_A /* cl9097.h */ 0x0000c097
+#define PASCAL_B /* cl9097.h */ 0x0000c197
+
+#define NV74_BSP 0x000074b0
+
+#define GT212_MSVLD 0x000085b1
+#define IGT21A_MSVLD 0x000086b1
+#define G98_MSVLD 0x000088b1
+#define GF100_MSVLD 0x000090b1
+#define GK104_MSVLD 0x000095b1
+
+#define GT212_MSPDEC 0x000085b2
+#define G98_MSPDEC 0x000088b2
+#define GF100_MSPDEC 0x000090b2
+#define GK104_MSPDEC 0x000095b2
+
+#define GT212_MSPPP 0x000085b3
+#define G98_MSPPP 0x000088b3
+#define GF100_MSPPP 0x000090b3
+
+#define G98_SEC 0x000088b4
+
+#define GT212_DMA 0x000085b5
+#define FERMI_DMA 0x000090b5
+#define KEPLER_DMA_COPY_A 0x0000a0b5
+#define MAXWELL_DMA_COPY_A 0x0000b0b5
+#define PASCAL_DMA_COPY_A 0x0000c0b5
+#define PASCAL_DMA_COPY_B 0x0000c1b5
+
+#define FERMI_DECOMPRESS 0x000090b8
+
+#define NV50_COMPUTE 0x000050c0
+#define GT214_COMPUTE 0x000085c0
+#define FERMI_COMPUTE_A 0x000090c0
+#define FERMI_COMPUTE_B 0x000091c0
+#define KEPLER_COMPUTE_A 0x0000a0c0
+#define KEPLER_COMPUTE_B 0x0000a1c0
+#define MAXWELL_COMPUTE_A 0x0000b0c0
+#define MAXWELL_COMPUTE_B 0x0000b1c0
+#define PASCAL_COMPUTE_A 0x0000c0c0
+#define PASCAL_COMPUTE_B 0x0000c1c0
+
+#define NV74_CIPHER 0x000074c1
+#endif
diff --git a/nvif/client.h b/nvif/client.h
new file mode 100644
index 0000000..f5df8b3
--- /dev/null
+++ b/nvif/client.h
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __NVIF_CLIENT_H__
+#define __NVIF_CLIENT_H__
+
+#include <nvif/object.h>
+
+struct nvif_client {
+ struct nvif_object object;
+ const struct nvif_driver *driver;
+ u64 version;
+ u8 route;
+ bool super;
+};
+
+int nvif_client_init(struct nvif_client *parent, const char *name, u64 device,
+ struct nvif_client *);
+void nvif_client_fini(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 nvxx_client(a) ({ \
+ struct nvif_client *_client = (a); \
+ (struct nvkm_client *)_client->object.priv; \
+})
+#endif
diff --git a/nvif/device.h b/nvif/device.h
new file mode 100644
index 0000000..6edb626
--- /dev/null
+++ b/nvif/device.h
@@ -0,0 +1,72 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __NVIF_DEVICE_H__
+#define __NVIF_DEVICE_H__
+
+#include <nvif/object.h>
+#include <nvif/cl0080.h>
+
+struct nvif_device {
+ struct nvif_object object;
+ struct nv_device_info_v0 info;
+};
+
+int nvif_device_init(struct nvif_object *, u32 handle, s32 oclass, void *, u32,
+ struct nvif_device *);
+void nvif_device_fini(struct nvif_device *);
+u64 nvif_device_time(struct nvif_device *);
+
+/* Delay based on GPU time (ie. PTIMER).
+ *
+ * Will return -ETIMEDOUT unless the loop was terminated with 'break',
+ * where it will return the number of nanoseconds taken instead.
+ */
+#define nvif_nsec(d,n,cond...) ({ \
+ struct nvif_device *_device = (d); \
+ u64 _nsecs = (n), _time0 = nvif_device_time(_device); \
+ s64 _taken = 0; \
+ \
+ do { \
+ cond \
+ } while (_taken = nvif_device_time(_device) - _time0, _taken < _nsecs);\
+ \
+ if (_taken >= _nsecs) \
+ _taken = -ETIMEDOUT; \
+ _taken; \
+})
+#define nvif_usec(d,u,cond...) nvif_nsec((d), (u) * 1000, ##cond)
+#define nvif_msec(d,m,cond...) nvif_usec((d), (m) * 1000, ##cond)
+
+/*XXX*/
+#include <subdev/bios.h>
+#include <subdev/fb.h>
+#include <subdev/bar.h>
+#include <subdev/gpio.h>
+#include <subdev/clk.h>
+#include <subdev/i2c.h>
+#include <subdev/timer.h>
+#include <subdev/therm.h>
+#include <subdev/pci.h>
+
+#define nvxx_device(a) ({ \
+ struct nvif_device *_device = (a); \
+ struct { \
+ struct nvkm_object object; \
+ struct nvkm_device *device; \
+ } *_udevice = _device->object.priv; \
+ _udevice->device; \
+})
+#define nvxx_bios(a) nvxx_device(a)->bios
+#define nvxx_fb(a) nvxx_device(a)->fb
+#define nvxx_gpio(a) nvxx_device(a)->gpio
+#define nvxx_clk(a) nvxx_device(a)->clk
+#define nvxx_i2c(a) nvxx_device(a)->i2c
+#define nvxx_iccsense(a) nvxx_device(a)->iccsense
+#define nvxx_therm(a) nvxx_device(a)->therm
+#define nvxx_volt(a) nvxx_device(a)->volt
+
+#include <engine/fifo.h>
+#include <engine/gr.h>
+
+#define nvxx_fifo(a) nvxx_device(a)->fifo
+#define nvxx_gr(a) nvxx_device(a)->gr
+#endif
diff --git a/nvif/driver.h b/nvif/driver.h
new file mode 100644
index 0000000..93bccd4
--- /dev/null
+++ b/nvif/driver.h
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __NVIF_DRIVER_H__
+#define __NVIF_DRIVER_H__
+#include <nvif/os.h>
+struct nvif_client;
+
+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 __iomem *(*map)(void *priv, u64 handle, u32 size);
+ void (*unmap)(void *priv, void __iomem *ptr, u32 size);
+ bool keep;
+};
+
+int nvif_driver_init(const char *drv, const char *cfg, const char *dbg,
+ const char *name, u64 device, struct nvif_client *);
+
+extern const struct nvif_driver nvif_driver_nvkm;
+extern const struct nvif_driver nvif_driver_drm;
+extern const struct nvif_driver nvif_driver_lib;
+extern const struct nvif_driver nvif_driver_null;
+#endif
diff --git a/nvif/event.h b/nvif/event.h
new file mode 100644
index 0000000..ec5c924
--- /dev/null
+++ b/nvif/event.h
@@ -0,0 +1,63 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __NVIF_EVENT_H__
+#define __NVIF_EVENT_H__
+
+struct nvif_notify_req_v0 {
+ __u8 version;
+ __u8 reply;
+ __u8 pad02[5];
+#define NVIF_NOTIFY_V0_ROUTE_NVIF 0x00
+ __u8 route;
+ __u64 token; /* must be unique */
+ __u8 data[]; /* request data (below) */
+};
+
+struct nvif_notify_rep_v0 {
+ __u8 version;
+ __u8 pad01[6];
+ __u8 route;
+ __u64 token;
+ __u8 data[]; /* reply data (below) */
+};
+
+struct nvif_notify_head_req_v0 {
+ /* nvif_notify_req ... */
+ __u8 version;
+ __u8 head;
+ __u8 pad02[6];
+};
+
+struct nvif_notify_head_rep_v0 {
+ /* nvif_notify_rep ... */
+ __u8 version;
+ __u8 pad01[7];
+};
+
+struct nvif_notify_conn_req_v0 {
+ /* nvif_notify_req ... */
+ __u8 version;
+#define NVIF_NOTIFY_CONN_V0_PLUG 0x01
+#define NVIF_NOTIFY_CONN_V0_UNPLUG 0x02
+#define NVIF_NOTIFY_CONN_V0_IRQ 0x04
+#define NVIF_NOTIFY_CONN_V0_ANY 0x07
+ __u8 mask;
+ __u8 conn;
+ __u8 pad03[5];
+};
+
+struct nvif_notify_conn_rep_v0 {
+ /* nvif_notify_rep ... */
+ __u8 version;
+ __u8 mask;
+ __u8 pad02[6];
+};
+
+struct nvif_notify_uevent_req {
+ /* nvif_notify_req ... */
+};
+
+struct nvif_notify_uevent_rep {
+ /* nvif_notify_rep ... */
+};
+
+#endif
diff --git a/nvif/if0000.h b/nvif/if0000.h
new file mode 100644
index 0000000..30ecd31
--- /dev/null
+++ b/nvif/if0000.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __NVIF_IF0000_H__
+#define __NVIF_IF0000_H__
+
+struct nvif_client_v0 {
+ __u8 version;
+ __u8 pad01[7];
+ __u64 device;
+ char name[32];
+};
+
+#define NVIF_CLIENT_V0_DEVLIST 0x00
+
+struct nvif_client_devlist_v0 {
+ __u8 version;
+ __u8 count;
+ __u8 pad02[6];
+ __u64 device[];
+};
+#endif
diff --git a/nvif/if0001.h b/nvif/if0001.h
new file mode 100644
index 0000000..ca92152
--- /dev/null
+++ b/nvif/if0001.h
@@ -0,0 +1,47 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __NVIF_IF0001_H__
+#define __NVIF_IF0001_H__
+
+#define NVIF_CONTROL_PSTATE_INFO 0x00
+#define NVIF_CONTROL_PSTATE_ATTR 0x01
+#define NVIF_CONTROL_PSTATE_USER 0x02
+
+struct nvif_control_pstate_info_v0 {
+ __u8 version;
+ __u8 count; /* out: number of power states */
+#define NVIF_CONTROL_PSTATE_INFO_V0_USTATE_DISABLE (-1)
+#define NVIF_CONTROL_PSTATE_INFO_V0_USTATE_PERFMON (-2)
+ __s8 ustate_ac; /* out: target pstate index */
+ __s8 ustate_dc; /* out: target pstate index */
+ __s8 pwrsrc; /* out: current power source */
+#define NVIF_CONTROL_PSTATE_INFO_V0_PSTATE_UNKNOWN (-1)
+#define NVIF_CONTROL_PSTATE_INFO_V0_PSTATE_PERFMON (-2)
+ __s8 pstate; /* out: current pstate index */
+ __u8 pad06[2];
+};
+
+struct nvif_control_pstate_attr_v0 {
+ __u8 version;
+#define NVIF_CONTROL_PSTATE_ATTR_V0_STATE_CURRENT (-1)
+ __s8 state; /* in: index of pstate to query
+ * out: pstate identifier
+ */
+ __u8 index; /* in: index of attribute to query
+ * out: index of next attribute, or 0 if no more
+ */
+ __u8 pad03[5];
+ __u32 min;
+ __u32 max;
+ char name[32];
+ char unit[16];
+};
+
+struct nvif_control_pstate_user_v0 {
+ __u8 version;
+#define NVIF_CONTROL_PSTATE_USER_V0_STATE_UNKNOWN (-1)
+#define NVIF_CONTROL_PSTATE_USER_V0_STATE_PERFMON (-2)
+ __s8 ustate; /* in: pstate identifier */
+ __s8 pwrsrc; /* in: target power source */
+ __u8 pad03[5];
+};
+#endif
diff --git a/nvif/if0002.h b/nvif/if0002.h
new file mode 100644
index 0000000..d9235c0
--- /dev/null
+++ b/nvif/if0002.h
@@ -0,0 +1,39 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __NVIF_IF0002_H__
+#define __NVIF_IF0002_H__
+
+#define NVIF_PERFMON_V0_QUERY_DOMAIN 0x00
+#define NVIF_PERFMON_V0_QUERY_SIGNAL 0x01
+#define NVIF_PERFMON_V0_QUERY_SOURCE 0x02
+
+struct nvif_perfmon_query_domain_v0 {
+ __u8 version;
+ __u8 id;
+ __u8 counter_nr;
+ __u8 iter;
+ __u16 signal_nr;
+ __u8 pad05[2];
+ char name[64];
+};
+
+struct nvif_perfmon_query_signal_v0 {
+ __u8 version;
+ __u8 domain;
+ __u16 iter;
+ __u8 signal;
+ __u8 source_nr;
+ __u8 pad05[2];
+ char name[64];
+};
+
+struct nvif_perfmon_query_source_v0 {
+ __u8 version;
+ __u8 domain;
+ __u8 signal;
+ __u8 iter;
+ __u8 pad04[4];
+ __u32 source;
+ __u32 mask;
+ char name[64];
+};
+#endif
diff --git a/nvif/if0003.h b/nvif/if0003.h
new file mode 100644
index 0000000..ae30b82
--- /dev/null
+++ b/nvif/if0003.h
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __NVIF_IF0003_H__
+#define __NVIF_IF0003_H__
+
+struct nvif_perfdom_v0 {
+ __u8 version;
+ __u8 domain;
+ __u8 mode;
+ __u8 pad03[1];
+ struct {
+ __u8 signal[4];
+ __u64 source[4][8];
+ __u16 logic_op;
+ } ctr[4];
+};
+
+#define NVIF_PERFDOM_V0_INIT 0x00
+#define NVIF_PERFDOM_V0_SAMPLE 0x01
+#define NVIF_PERFDOM_V0_READ 0x02
+
+struct nvif_perfdom_init {
+};
+
+struct nvif_perfdom_sample {
+};
+
+struct nvif_perfdom_read_v0 {
+ __u8 version;
+ __u8 pad01[7];
+ __u32 ctr[4];
+ __u32 clk;
+ __u8 pad04[4];
+};
+#endif
diff --git a/nvif/if0004.h b/nvif/if0004.h
new file mode 100644
index 0000000..b35547c
--- /dev/null
+++ b/nvif/if0004.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __NVIF_IF0004_H__
+#define __NVIF_IF0004_H__
+
+#define NV04_NVSW_NTFY_UEVENT 0x00
+
+#define NV04_NVSW_GET_REF 0x00
+
+struct nv04_nvsw_get_ref_v0 {
+ __u8 version;
+ __u8 pad01[3];
+ __u32 ref;
+};
+#endif
diff --git a/nvif/if0005.h b/nvif/if0005.h
new file mode 100644
index 0000000..8ed0ae1
--- /dev/null
+++ b/nvif/if0005.h
@@ -0,0 +1,5 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __NVIF_IF0005_H__
+#define __NVIF_IF0005_H__
+#define NV10_NVSW_NTFY_UEVENT 0x00
+#endif
diff --git a/nvif/if0008.h b/nvif/if0008.h
new file mode 100644
index 0000000..8450127
--- /dev/null
+++ b/nvif/if0008.h
@@ -0,0 +1,42 @@
+#ifndef __NVIF_IF0008_H__
+#define __NVIF_IF0008_H__
+struct nvif_mmu_v0 {
+ __u8 version;
+ __u8 dmabits;
+ __u8 heap_nr;
+ __u8 type_nr;
+ __u16 kind_nr;
+};
+
+#define NVIF_MMU_V0_HEAP 0x00
+#define NVIF_MMU_V0_TYPE 0x01
+#define NVIF_MMU_V0_KIND 0x02
+
+struct nvif_mmu_heap_v0 {
+ __u8 version;
+ __u8 index;
+ __u8 pad02[6];
+ __u64 size;
+};
+
+struct nvif_mmu_type_v0 {
+ __u8 version;
+ __u8 index;
+ __u8 heap;
+ __u8 vram;
+ __u8 host;
+ __u8 comp;
+ __u8 disp;
+ __u8 kind;
+ __u8 mappable;
+ __u8 coherent;
+ __u8 uncached;
+};
+
+struct nvif_mmu_kind_v0 {
+ __u8 version;
+ __u8 pad01[1];
+ __u16 count;
+ __u8 data[];
+};
+#endif
diff --git a/nvif/if000a.h b/nvif/if000a.h
new file mode 100644
index 0000000..88d0938
--- /dev/null
+++ b/nvif/if000a.h
@@ -0,0 +1,22 @@
+#ifndef __NVIF_IF000A_H__
+#define __NVIF_IF000A_H__
+struct nvif_mem_v0 {
+ __u8 version;
+ __u8 type;
+ __u8 page;
+ __u8 pad03[5];
+ __u64 size;
+ __u64 addr;
+ __u8 data[];
+};
+
+struct nvif_mem_ram_vn {
+};
+
+struct nvif_mem_ram_v0 {
+ __u8 version;
+ __u8 pad01[7];
+ dma_addr_t *dma;
+ struct scatterlist *sgl;
+};
+#endif
diff --git a/nvif/if000b.h b/nvif/if000b.h
new file mode 100644
index 0000000..c677fb0
--- /dev/null
+++ b/nvif/if000b.h
@@ -0,0 +1,11 @@
+#ifndef __NVIF_IF000B_H__
+#define __NVIF_IF000B_H__
+#include "if000a.h"
+
+struct nv04_mem_vn {
+ /* nvkm_mem_vX ... */
+};
+
+struct nv04_mem_map_vn {
+};
+#endif
diff --git a/nvif/if000c.h b/nvif/if000c.h
new file mode 100644
index 0000000..e784291
--- /dev/null
+++ b/nvif/if000c.h
@@ -0,0 +1,72 @@
+#ifndef __NVIF_IF000C_H__
+#define __NVIF_IF000C_H__
+struct nvif_vmm_v0 {
+ __u8 version;
+ __u8 page_nr;
+ __u8 pad02[6];
+ __u64 addr;
+ __u64 size;
+ __u8 data[];
+};
+
+#define NVIF_VMM_V0_PAGE 0x00
+#define NVIF_VMM_V0_GET 0x01
+#define NVIF_VMM_V0_PUT 0x02
+#define NVIF_VMM_V0_MAP 0x03
+#define NVIF_VMM_V0_UNMAP 0x04
+#define NVIF_VMM_V0_HMM 0x05
+
+struct nvif_vmm_page_v0 {
+ __u8 version;
+ __u8 index;
+ __u8 shift;
+ __u8 sparse;
+ __u8 vram;
+ __u8 host;
+ __u8 comp;
+ __u8 pad07[1];
+};
+
+struct nvif_vmm_get_v0 {
+ __u8 version;
+#define NVIF_VMM_GET_V0_ADDR 0x00
+#define NVIF_VMM_GET_V0_PTES 0x01
+#define NVIF_VMM_GET_V0_LAZY 0x02
+ __u8 type;
+ __u8 sparse;
+ __u8 page;
+ __u8 align;
+ __u8 pad05[3];
+ __u64 size;
+ __u64 addr;
+};
+
+struct nvif_vmm_put_v0 {
+ __u8 version;
+ __u8 pad01[7];
+ __u64 addr;
+};
+
+struct nvif_vmm_map_v0 {
+ __u8 version;
+ __u8 pad01[7];
+ __u64 addr;
+ __u64 size;
+ __u64 memory;
+ __u64 offset;
+ __u8 data[];
+};
+
+struct nvif_vmm_unmap_v0 {
+ __u8 version;
+ __u8 pad01[7];
+ __u64 addr;
+};
+
+struct nvif_vmm_hmm_v0 {
+ __u8 version;
+ __u8 pad01[7];
+ __u64 addr;
+ __u64 size;
+};
+#endif
diff --git a/nvif/if000d.h b/nvif/if000d.h
new file mode 100644
index 0000000..516ec94
--- /dev/null
+++ b/nvif/if000d.h
@@ -0,0 +1,12 @@
+#ifndef __NVIF_IF000D_H__
+#define __NVIF_IF000D_H__
+#include "if000c.h"
+
+struct nv04_vmm_vn {
+ /* nvif_vmm_vX ... */
+};
+
+struct nv04_vmm_map_vn {
+ /* nvif_vmm_map_vX ... */
+};
+#endif
diff --git a/nvif/if500b.h b/nvif/if500b.h
new file mode 100644
index 0000000..c7c8431
--- /dev/null
+++ b/nvif/if500b.h
@@ -0,0 +1,25 @@
+#ifndef __NVIF_IF500B_H__
+#define __NVIF_IF500B_H__
+#include "if000a.h"
+
+struct nv50_mem_vn {
+ /* nvif_mem_vX ... */
+};
+
+struct nv50_mem_v0 {
+ /* nvif_mem_vX ... */
+ __u8 version;
+ __u8 bankswz;
+ __u8 contig;
+};
+
+struct nv50_mem_map_vn {
+};
+
+struct nv50_mem_map_v0 {
+ __u8 version;
+ __u8 ro;
+ __u8 kind;
+ __u8 comp;
+};
+#endif
diff --git a/nvif/if500d.h b/nvif/if500d.h
new file mode 100644
index 0000000..c29a782
--- /dev/null
+++ b/nvif/if500d.h
@@ -0,0 +1,21 @@
+#ifndef __NVIF_IF500D_H__
+#define __NVIF_IF500D_H__
+#include "if000c.h"
+
+struct nv50_vmm_vn {
+ /* nvif_vmm_vX ... */
+};
+
+struct nv50_vmm_map_vn {
+ /* nvif_vmm_map_vX ... */
+};
+
+struct nv50_vmm_map_v0 {
+ /* nvif_vmm_map_vX ... */
+ __u8 version;
+ __u8 ro;
+ __u8 priv;
+ __u8 kind;
+ __u8 comp;
+};
+#endif
diff --git a/nvif/if900b.h b/nvif/if900b.h
new file mode 100644
index 0000000..9b16454
--- /dev/null
+++ b/nvif/if900b.h
@@ -0,0 +1,23 @@
+#ifndef __NVIF_IF900B_H__
+#define __NVIF_IF900B_H__
+#include "if000a.h"
+
+struct gf100_mem_vn {
+ /* nvif_mem_vX ... */
+};
+
+struct gf100_mem_v0 {
+ /* nvif_mem_vX ... */
+ __u8 version;
+ __u8 contig;
+};
+
+struct gf100_mem_map_vn {
+};
+
+struct gf100_mem_map_v0 {
+ __u8 version;
+ __u8 ro;
+ __u8 kind;
+};
+#endif
diff --git a/nvif/if900d.h b/nvif/if900d.h
new file mode 100644
index 0000000..49aa505
--- /dev/null
+++ b/nvif/if900d.h
@@ -0,0 +1,21 @@
+#ifndef __NVIF_IF900D_H__
+#define __NVIF_IF900D_H__
+#include "if000c.h"
+
+struct gf100_vmm_vn {
+ /* nvif_vmm_vX ... */
+};
+
+struct gf100_vmm_map_vn {
+ /* nvif_vmm_map_vX ... */
+};
+
+struct gf100_vmm_map_v0 {
+ /* nvif_vmm_map_vX ... */
+ __u8 version;
+ __u8 vol;
+ __u8 ro;
+ __u8 priv;
+ __u8 kind;
+};
+#endif
diff --git a/nvif/ifb00d.h b/nvif/ifb00d.h
new file mode 100644
index 0000000..a0e4198
--- /dev/null
+++ b/nvif/ifb00d.h
@@ -0,0 +1,27 @@
+#ifndef __NVIF_IFB00D_H__
+#define __NVIF_IFB00D_H__
+#include "if000c.h"
+
+struct gm200_vmm_vn {
+ /* nvif_vmm_vX ... */
+};
+
+struct gm200_vmm_v0 {
+ /* nvif_vmm_vX ... */
+ __u8 version;
+ __u8 bigpage;
+};
+
+struct gm200_vmm_map_vn {
+ /* nvif_vmm_map_vX ... */
+};
+
+struct gm200_vmm_map_v0 {
+ /* nvif_vmm_map_vX ... */
+ __u8 version;
+ __u8 vol;
+ __u8 ro;
+ __u8 priv;
+ __u8 kind;
+};
+#endif
diff --git a/nvif/ifc00d.h b/nvif/ifc00d.h
new file mode 100644
index 0000000..1d9c637
--- /dev/null
+++ b/nvif/ifc00d.h
@@ -0,0 +1,21 @@
+#ifndef __NVIF_IFC00D_H__
+#define __NVIF_IFC00D_H__
+#include "if000c.h"
+
+struct gp100_vmm_vn {
+ /* nvif_vmm_vX ... */
+};
+
+struct gp100_vmm_map_vn {
+ /* nvif_vmm_map_vX ... */
+};
+
+struct gp100_vmm_map_v0 {
+ /* nvif_vmm_map_vX ... */
+ __u8 version;
+ __u8 vol;
+ __u8 ro;
+ __u8 priv;
+ __u8 kind;
+};
+#endif
diff --git a/nvif/ioctl.h b/nvif/ioctl.h
new file mode 100644
index 0000000..b93d586
--- /dev/null
+++ b/nvif/ioctl.h
@@ -0,0 +1,137 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __NVIF_IOCTL_H__
+#define __NVIF_IOCTL_H__
+
+#define NVIF_VERSION_LATEST 0x0000000000000100ULL
+
+struct nvif_ioctl_v0 {
+ __u8 version;
+#define NVIF_IOCTL_V0_NOP 0x00
+#define NVIF_IOCTL_V0_SCLASS 0x01
+#define NVIF_IOCTL_V0_NEW 0x02
+#define NVIF_IOCTL_V0_DEL 0x03
+#define NVIF_IOCTL_V0_MTHD 0x04
+#define NVIF_IOCTL_V0_RD 0x05
+#define NVIF_IOCTL_V0_WR 0x06
+#define NVIF_IOCTL_V0_MAP 0x07
+#define NVIF_IOCTL_V0_UNMAP 0x08
+#define NVIF_IOCTL_V0_NTFY_NEW 0x09
+#define NVIF_IOCTL_V0_NTFY_DEL 0x0a
+#define NVIF_IOCTL_V0_NTFY_GET 0x0b
+#define NVIF_IOCTL_V0_NTFY_PUT 0x0c
+ __u8 type;
+ __u8 pad02[4];
+#define NVIF_IOCTL_V0_OWNER_NVIF 0x00
+#define NVIF_IOCTL_V0_OWNER_ANY 0xff
+ __u8 owner;
+#define NVIF_IOCTL_V0_ROUTE_NVIF 0x00
+#define NVIF_IOCTL_V0_ROUTE_HIDDEN 0xff
+ __u8 route;
+ __u64 token;
+ __u64 object;
+ __u8 data[]; /* ioctl data (below) */
+};
+
+struct nvif_ioctl_nop_v0 {
+ __u64 version;
+};
+
+struct nvif_ioctl_sclass_v0 {
+ /* nvif_ioctl ... */
+ __u8 version;
+ __u8 count;
+ __u8 pad02[6];
+ struct nvif_ioctl_sclass_oclass_v0 {
+ __s32 oclass;
+ __s16 minver;
+ __s16 maxver;
+ } oclass[];
+};
+
+struct nvif_ioctl_new_v0 {
+ /* nvif_ioctl ... */
+ __u8 version;
+ __u8 pad01[6];
+ __u8 route;
+ __u64 token;
+ __u64 object;
+ __u32 handle;
+ __s32 oclass;
+ __u8 data[]; /* class data (class.h) */
+};
+
+struct nvif_ioctl_del {
+};
+
+struct nvif_ioctl_rd_v0 {
+ /* nvif_ioctl ... */
+ __u8 version;
+ __u8 size;
+ __u8 pad02[2];
+ __u32 data;
+ __u64 addr;
+};
+
+struct nvif_ioctl_wr_v0 {
+ /* nvif_ioctl ... */
+ __u8 version;
+ __u8 size;
+ __u8 pad02[2];
+ __u32 data;
+ __u64 addr;
+};
+
+struct nvif_ioctl_map_v0 {
+ /* nvif_ioctl ... */
+ __u8 version;
+#define NVIF_IOCTL_MAP_V0_IO 0x00
+#define NVIF_IOCTL_MAP_V0_VA 0x01
+ __u8 type;
+ __u8 pad02[6];
+ __u64 handle;
+ __u64 length;
+ __u8 data[];
+};
+
+struct nvif_ioctl_unmap {
+};
+
+struct nvif_ioctl_ntfy_new_v0 {
+ /* nvif_ioctl ... */
+ __u8 version;
+ __u8 event;
+ __u8 index;
+ __u8 pad03[5];
+ __u8 data[]; /* event request data (event.h) */
+};
+
+struct nvif_ioctl_ntfy_del_v0 {
+ /* nvif_ioctl ... */
+ __u8 version;
+ __u8 index;
+ __u8 pad02[6];
+};
+
+struct nvif_ioctl_ntfy_get_v0 {
+ /* nvif_ioctl ... */
+ __u8 version;
+ __u8 index;
+ __u8 pad02[6];
+};
+
+struct nvif_ioctl_ntfy_put_v0 {
+ /* nvif_ioctl ... */
+ __u8 version;
+ __u8 index;
+ __u8 pad02[6];
+};
+
+struct nvif_ioctl_mthd_v0 {
+ /* nvif_ioctl ... */
+ __u8 version;
+ __u8 method;
+ __u8 pad02[6];
+ __u8 data[]; /* method data (class.h) */
+};
+
+#endif
diff --git a/nvif/list.h b/nvif/list.h
new file mode 100644
index 0000000..8af5d14
--- /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/mem.h b/nvif/mem.h
new file mode 100644
index 0000000..b542fe3
--- /dev/null
+++ b/nvif/mem.h
@@ -0,0 +1,18 @@
+#ifndef __NVIF_MEM_H__
+#define __NVIF_MEM_H__
+#include "mmu.h"
+
+struct nvif_mem {
+ struct nvif_object object;
+ u8 type;
+ u8 page;
+ u64 addr;
+ u64 size;
+};
+
+int nvif_mem_init_type(struct nvif_mmu *mmu, s32 oclass, int type, u8 page,
+ u64 size, void *argv, u32 argc, struct nvif_mem *);
+int nvif_mem_init(struct nvif_mmu *mmu, s32 oclass, u8 type, u8 page,
+ u64 size, void *argv, u32 argc, struct nvif_mem *);
+void nvif_mem_fini(struct nvif_mem *);
+#endif
diff --git a/nvif/mmu.h b/nvif/mmu.h
new file mode 100644
index 0000000..c8cd5b5
--- /dev/null
+++ b/nvif/mmu.h
@@ -0,0 +1,56 @@
+#ifndef __NVIF_MMU_H__
+#define __NVIF_MMU_H__
+#include <nvif/object.h>
+
+struct nvif_mmu {
+ struct nvif_object object;
+ u8 dmabits;
+ u8 heap_nr;
+ u8 type_nr;
+ u16 kind_nr;
+
+ struct {
+ u64 size;
+ } *heap;
+
+ struct {
+#define NVIF_MEM_VRAM 0x01
+#define NVIF_MEM_HOST 0x02
+#define NVIF_MEM_COMP 0x04
+#define NVIF_MEM_DISP 0x08
+#define NVIF_MEM_KIND 0x10
+#define NVIF_MEM_MAPPABLE 0x20
+#define NVIF_MEM_COHERENT 0x40
+#define NVIF_MEM_UNCACHED 0x80
+ u8 type;
+ u8 heap;
+ } *type;
+
+ u8 *kind;
+};
+
+int nvif_mmu_init(struct nvif_object *, s32 oclass, struct nvif_mmu *);
+void nvif_mmu_fini(struct nvif_mmu *);
+
+static inline bool
+nvif_mmu_kind_valid(struct nvif_mmu *mmu, u8 kind)
+{
+ const u8 invalid = mmu->kind_nr - 1;
+ if (kind) {
+ if (kind >= mmu->kind_nr || mmu->kind[kind] == invalid)
+ return false;
+ }
+ return true;
+}
+
+static inline int
+nvif_mmu_type(struct nvif_mmu *mmu, u8 mask)
+{
+ int i;
+ for (i = 0; i < mmu->type_nr; i++) {
+ if ((mmu->type[i].type & mask) == mask)
+ return i;
+ }
+ return -EINVAL;
+}
+#endif
diff --git a/nvif/notify.h b/nvif/notify.h
new file mode 100644
index 0000000..4ed1692
--- /dev/null
+++ b/nvif/notify.h
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#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 *, 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);
+#endif
diff --git a/nvif/object.h b/nvif/object.h
new file mode 100644
index 0000000..a2d5244
--- /dev/null
+++ b/nvif/object.h
@@ -0,0 +1,108 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __NVIF_OBJECT_H__
+#define __NVIF_OBJECT_H__
+
+#include <nvif/os.h>
+
+struct nvif_sclass {
+ s32 oclass;
+ int minver;
+ int maxver;
+};
+
+struct nvif_object {
+ struct nvif_client *client;
+ u32 handle;
+ s32 oclass;
+ void *priv; /*XXX: hack */
+ struct {
+ void __iomem *ptr;
+ u64 size;
+ } map;
+};
+
+int nvif_object_init(struct nvif_object *, u32 handle, s32 oclass, void *, u32,
+ struct nvif_object *);
+void nvif_object_fini(struct nvif_object *);
+int nvif_object_ioctl(struct nvif_object *, void *, u32, void **);
+int nvif_object_sclass_get(struct nvif_object *, struct nvif_sclass **);
+void nvif_object_sclass_put(struct nvif_sclass **);
+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_handle(struct nvif_object *, void *, u32,
+ u64 *handle, u64 *length);
+void nvif_object_unmap_handle(struct nvif_object *);
+int nvif_object_map(struct nvif_object *, void *, u32);
+void nvif_object_unmap(struct nvif_object *);
+
+#define nvif_handle(a) (unsigned long)(void *)(a)
+#define nvif_object(a) (a)->object
+
+#define nvif_rd(a,f,b,c) ({ \
+ struct nvif_object *_object = (a); \
+ u32 _data; \
+ if (likely(_object->map.ptr)) \
+ _data = f((u8 __iomem *)_object->map.ptr + (c)); \
+ else \
+ _data = nvif_object_rd(_object, (b), (c)); \
+ _data; \
+})
+#define nvif_wr(a,f,b,c,d) ({ \
+ struct nvif_object *_object = (a); \
+ if (likely(_object->map.ptr)) \
+ f((d), (u8 __iomem *)_object->map.ptr + (c)); \
+ else \
+ nvif_object_wr(_object, (b), (c), (d)); \
+})
+#define nvif_rd08(a,b) ({ ((u8)nvif_rd((a), ioread8, 1, (b))); })
+#define nvif_rd16(a,b) ({ ((u16)nvif_rd((a), ioread16_native, 2, (b))); })
+#define nvif_rd32(a,b) ({ ((u32)nvif_rd((a), ioread32_native, 4, (b))); })
+#define nvif_wr08(a,b,c) nvif_wr((a), iowrite8, 1, (b), (u8)(c))
+#define nvif_wr16(a,b,c) nvif_wr((a), iowrite16_native, 2, (b), (u16)(c))
+#define nvif_wr32(a,b,c) nvif_wr((a), iowrite32_native, 4, (b), (u32)(c))
+#define nvif_mask(a,b,c,d) ({ \
+ struct nvif_object *__object = (a); \
+ u32 _addr = (b), _data = nvif_rd32(__object, _addr); \
+ nvif_wr32(__object, _addr, (_data & ~(c)) | (d)); \
+ _data; \
+})
+
+#define nvif_mthd(a,b,c,d) nvif_object_mthd((a), (b), (c), (d))
+
+struct nvif_mclass {
+ s32 oclass;
+ int version;
+};
+
+#define nvif_mclass(o,m) ({ \
+ struct nvif_object *object = (o); \
+ struct nvif_sclass *sclass; \
+ const typeof(m[0]) *mclass = (m); \
+ int ret = -ENODEV; \
+ int cnt, i, j; \
+ \
+ cnt = nvif_object_sclass_get(object, &sclass); \
+ if (cnt >= 0) { \
+ for (i = 0; ret < 0 && mclass[i].oclass; i++) { \
+ for (j = 0; j < cnt; j++) { \
+ if (mclass[i].oclass == sclass[j].oclass && \
+ mclass[i].version >= sclass[j].minver && \
+ mclass[i].version <= sclass[j].maxver) { \
+ ret = i; \
+ break; \
+ } \
+ } \
+ } \
+ nvif_object_sclass_put(&sclass); \
+ } \
+ ret; \
+})
+
+/*XXX*/
+#include <core/object.h>
+#define nvxx_object(a) ({ \
+ struct nvif_object *_object = (a); \
+ (struct nvkm_object *)_object->priv; \
+})
+#endif
diff --git a/nvif/os.h b/nvif/os.h
new file mode 100644
index 0000000..fd09b28
--- /dev/null
+++ b/nvif/os.h
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __NOUVEAU_OS_H__
+#define __NOUVEAU_OS_H__
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/mutex.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+#include <linux/printk.h>
+#include <linux/bitops.h>
+#include <linux/firmware.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+#include <linux/delay.h>
+#include <linux/io-mapping.h>
+#include <linux/acpi.h>
+#include <linux/vmalloc.h>
+#include <linux/dmi.h>
+#include <linux/reboot.h>
+#include <linux/interrupt.h>
+#include <linux/log2.h>
+#include <linux/pm_runtime.h>
+#include <linux/power_supply.h>
+#include <linux/clk.h>
+#include <linux/regulator/consumer.h>
+#include <linux/agp_backend.h>
+#include <linux/reset.h>
+#include <linux/iommu.h>
+#include <linux/of_device.h>
+
+#include <asm/unaligned.h>
+
+#include <soc/tegra/fuse.h>
+#include <soc/tegra/pmc.h>
+#endif
diff --git a/nvif/unpack.h b/nvif/unpack.h
new file mode 100644
index 0000000..7f0d9f6
--- /dev/null
+++ b/nvif/unpack.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __NVIF_UNPACK_H__
+#define __NVIF_UNPACK_H__
+
+#define nvif_unvers(r,d,s,m) ({ \
+ void **_data = (d); __u32 *_size = (s); int _ret = (r); \
+ if (_ret == -ENOSYS && *_size == sizeof(m)) { \
+ *_data = NULL; \
+ *_size = _ret = 0; \
+ } \
+ _ret; \
+})
+
+#define nvif_unpack(r,d,s,m,vl,vh,x) ({ \
+ void **_data = (d); __u32 *_size = (s); \
+ int _ret = (r), _vl = (vl), _vh = (vh); \
+ if (_ret == -ENOSYS && *_size >= sizeof(m) && \
+ (m).version >= _vl && (m).version <= _vh) { \
+ *_data = (__u8 *)*_data + sizeof(m); \
+ *_size = *_size - sizeof(m); \
+ if (_ret = 0, !(x)) { \
+ _ret = *_size ? -E2BIG : 0; \
+ *_data = NULL; \
+ *_size = 0; \
+ } \
+ } \
+ _ret; \
+})
+#endif
diff --git a/nvif/vmm.h b/nvif/vmm.h
new file mode 100644
index 0000000..c5db8a2
--- /dev/null
+++ b/nvif/vmm.h
@@ -0,0 +1,42 @@
+#ifndef __NVIF_VMM_H__
+#define __NVIF_VMM_H__
+#include <nvif/object.h>
+struct nvif_mem;
+struct nvif_mmu;
+
+enum nvif_vmm_get {
+ ADDR,
+ PTES,
+ LAZY
+};
+
+struct nvif_vma {
+ u64 addr;
+ u64 size;
+};
+
+struct nvif_vmm {
+ struct nvif_object object;
+ u64 start;
+ u64 limit;
+
+ struct {
+ u8 shift;
+ bool sparse:1;
+ bool vram:1;
+ bool host:1;
+ bool comp:1;
+ } *page;
+ int page_nr;
+};
+
+int nvif_vmm_init(struct nvif_mmu *, s32 oclass, u64 addr, u64 size,
+ void *argv, u32 argc, struct nvif_vmm *);
+void nvif_vmm_fini(struct nvif_vmm *);
+int nvif_vmm_get(struct nvif_vmm *, enum nvif_vmm_get, bool sparse,
+ u8 page, u8 align, u64 size, struct nvif_vma *);
+void nvif_vmm_put(struct nvif_vmm *, struct nvif_vma *);
+int nvif_vmm_map(struct nvif_vmm *, u64 addr, u64 size, void *argv, u32 argc,
+ struct nvif_mem *, u64 offset);
+int nvif_vmm_unmap(struct nvif_vmm *, u64);
+#endif