aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Skeggs2011-12-09 00:11:06 -0600
committerBen Skeggs2012-04-13 11:47:23 -0500
commit292da616fe1f936ca78a3fa8e1b1b19883e343b6 (patch)
treecbe346a327238bb77f697beb9bd06f96f7632b28 /nouveau
parent0d6350002d74848dd3d1e4d28d514a7ac9d580c9 (diff)
downloadlibdrm-292da616fe1f936ca78a3fa8e1b1b19883e343b6.tar.gz
libdrm-292da616fe1f936ca78a3fa8e1b1b19883e343b6.tar.xz
libdrm-292da616fe1f936ca78a3fa8e1b1b19883e343b6.zip
nouveau: pull in major libdrm rewrite
Redesigned primarily to allow us to better take advantage of BO's having fixed GPU virtual addresses on GeForce 8 and up, and to reduce the overhead of handling relocations on earlier chipsets. Signed-off-by: Ben Skeggs <bskeggs@redhat.com> Signed-off-by: Christoph Bumiller <e0425955@student.tuwien.ac.at>
Diffstat (limited to 'nouveau')
-rw-r--r--nouveau/Makefile.am36
-rw-r--r--nouveau/abi16.c197
-rw-r--r--nouveau/bufctx.c170
-rw-r--r--nouveau/libdrm_nouveau.pc.in2
-rw-r--r--nouveau/nouveau.c489
-rw-r--r--nouveau/nouveau.h211
-rw-r--r--nouveau/nouveau_bo.c549
-rw-r--r--nouveau/nouveau_bo.h104
-rw-r--r--nouveau/nouveau_channel.c142
-rw-r--r--nouveau/nouveau_channel.h57
-rw-r--r--nouveau/nouveau_device.c198
-rw-r--r--nouveau/nouveau_device.h33
-rw-r--r--nouveau/nouveau_drmif.h58
-rw-r--r--nouveau/nouveau_grobj.c148
-rw-r--r--nouveau/nouveau_grobj.h48
-rw-r--r--nouveau/nouveau_notifier.c148
-rw-r--r--nouveau/nouveau_notifier.h63
-rw-r--r--nouveau/nouveau_private.h136
-rw-r--r--nouveau/nouveau_pushbuf.c344
-rw-r--r--nouveau/nouveau_pushbuf.h162
-rw-r--r--nouveau/nouveau_reloc.c154
-rw-r--r--nouveau/nouveau_reloc.h32
-rw-r--r--nouveau/nouveau_resource.c124
-rw-r--r--nouveau/nouveau_resource.h51
-rw-r--r--nouveau/nv04_pushbuf.h66
-rw-r--r--nouveau/nvc0_pushbuf.h92
-rw-r--r--nouveau/private.h122
-rw-r--r--nouveau/pushbuf.c774
28 files changed, 1973 insertions, 2737 deletions
diff --git a/nouveau/Makefile.am b/nouveau/Makefile.am
index 8b899164..206e892e 100644
--- a/nouveau/Makefile.am
+++ b/nouveau/Makefile.am
@@ -3,41 +3,23 @@ AM_CFLAGS = \
3 -I$(top_srcdir) \ 3 -I$(top_srcdir) \
4 -I$(top_srcdir)/nouveau \ 4 -I$(top_srcdir)/nouveau \
5 $(PTHREADSTUBS_CFLAGS) \ 5 $(PTHREADSTUBS_CFLAGS) \
6 -I$(top_srcdir)/include/drm 6 -I$(top_srcdir)/include/drm \
7 -DDEBUG
7 8
8libdrm_nouveau_la_LTLIBRARIES = libdrm_nouveau.la 9libdrm_nouveau_la_LTLIBRARIES = libdrm_nouveau.la
9libdrm_nouveau_ladir = $(libdir) 10libdrm_nouveau_ladir = $(libdir)
10libdrm_nouveau_la_LDFLAGS = -version-number 1:0:0 -no-undefined 11libdrm_nouveau_la_LDFLAGS = -version-number 2:0:0 -no-undefined
11libdrm_nouveau_la_LIBADD = ../libdrm.la @PTHREADSTUBS_LIBS@ 12libdrm_nouveau_la_LIBADD = ../libdrm.la @PTHREADSTUBS_LIBS@
12 13
13libdrm_nouveau_la_SOURCES = \ 14libdrm_nouveau_la_SOURCES = nouveau.c \
14 nouveau_device.c \ 15 pushbuf.c \
15 nouveau_channel.c \ 16 bufctx.c \
16 nouveau_pushbuf.c \ 17 abi16.c \
17 nouveau_grobj.c \ 18 private.h
18 nouveau_notifier.c \
19 nouveau_bo.c \
20 nouveau_resource.c \
21 nouveau_private.h \
22 nouveau_reloc.c
23
24libdrm_nouveaucommonincludedir = ${includedir}/nouveau
25libdrm_nouveaucommoninclude_HEADERS = \
26 nouveau_device.h \
27 nouveau_channel.h \
28 nouveau_grobj.h \
29 nouveau_notifier.h \
30 nouveau_pushbuf.h \
31 nv04_pushbuf.h \
32 nvc0_pushbuf.h \
33 nouveau_bo.h \
34 nouveau_resource.h \
35 nouveau_reloc.h
36 19
37 20
38libdrm_nouveauincludedir = ${includedir}/libdrm 21libdrm_nouveauincludedir = ${includedir}/libdrm
39libdrm_nouveauinclude_HEADERS = \ 22libdrm_nouveauinclude_HEADERS = nouveau.h
40 nouveau_drmif.h
41 23
42pkgconfigdir = @pkgconfigdir@ 24pkgconfigdir = @pkgconfigdir@
43pkgconfig_DATA = libdrm_nouveau.pc 25pkgconfig_DATA = libdrm_nouveau.pc
diff --git a/nouveau/abi16.c b/nouveau/abi16.c
new file mode 100644
index 00000000..688a9ac6
--- /dev/null
+++ b/nouveau/abi16.c
@@ -0,0 +1,197 @@
1/*
2 * Copyright 2012 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Ben Skeggs
23 */
24
25#include <stdlib.h>
26#include <stdint.h>
27
28#include "private.h"
29
30int
31abi16_chan_nv04(struct nouveau_object *obj)
32{
33 struct nouveau_device *dev = (struct nouveau_device *)obj->parent;
34 struct drm_nouveau_channel_alloc req;
35 struct nv04_fifo *nv04 = obj->data;
36 int ret;
37
38 req.fb_ctxdma_handle = nv04->vram;
39 req.tt_ctxdma_handle = nv04->gart;
40
41 ret = drmCommandWriteRead(dev->fd, DRM_NOUVEAU_CHANNEL_ALLOC,
42 &req, sizeof(req));
43 if (ret)
44 return ret;
45
46 nv04->base.channel = req.channel;
47 nv04->base.pushbuf = req.pushbuf_domains;
48 nv04->notify = req.notifier_handle;
49 nv04->base.object->handle = req.channel;
50 nv04->base.object->length = sizeof(*nv04);
51 return 0;
52}
53
54int
55abi16_chan_nvc0(struct nouveau_object *obj)
56{
57 struct nouveau_device *dev = (struct nouveau_device *)obj->parent;
58 struct drm_nouveau_channel_alloc req;
59 struct nvc0_fifo *nvc0 = obj->data;
60 int ret;
61
62 ret = drmCommandWriteRead(dev->fd, DRM_NOUVEAU_CHANNEL_ALLOC,
63 &req, sizeof(req));
64 if (ret)
65 return ret;
66
67 nvc0->base.channel = req.channel;
68 nvc0->base.pushbuf = req.pushbuf_domains;
69 nvc0->base.object->handle = req.channel;
70 nvc0->base.object->length = sizeof(*nvc0);
71 return 0;
72}
73
74int
75abi16_engobj(struct nouveau_object *obj)
76{
77 struct drm_nouveau_grobj_alloc req = {
78 obj->parent->handle, obj->handle, obj->oclass
79 };
80 struct nouveau_device *dev;
81 int ret;
82
83 dev = nouveau_object_find(obj, NOUVEAU_DEVICE_CLASS);
84 ret = drmCommandWrite(dev->fd, DRM_NOUVEAU_GROBJ_ALLOC,
85 &req, sizeof(req));
86 if (ret)
87 return ret;
88
89 obj->length = sizeof(struct nouveau_object *);
90 return 0;
91}
92
93int
94abi16_ntfy(struct nouveau_object *obj)
95{
96 struct nv04_notify *ntfy = obj->data;
97 struct drm_nouveau_notifierobj_alloc req = {
98 obj->parent->handle, ntfy->object->handle, ntfy->length
99 };
100 struct nouveau_device *dev;
101 int ret;
102
103 dev = nouveau_object_find(obj, NOUVEAU_DEVICE_CLASS);
104 ret = drmCommandWriteRead(dev->fd, DRM_NOUVEAU_NOTIFIEROBJ_ALLOC,
105 &req, sizeof(req));
106 if (ret)
107 return ret;
108
109 ntfy->offset = req.offset;
110 ntfy->object->length = sizeof(*ntfy);
111 return 0;
112}
113
114void
115abi16_bo_info(struct nouveau_bo *bo, struct drm_nouveau_gem_info *info)
116{
117 struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
118
119 nvbo->map_handle = info->map_handle;
120 bo->handle = info->handle;
121 bo->size = info->size;
122 bo->offset = info->offset;
123
124 bo->flags = 0;
125 if (info->domain & NOUVEAU_GEM_DOMAIN_VRAM)
126 bo->flags |= NOUVEAU_BO_VRAM;
127 if (info->domain & NOUVEAU_GEM_DOMAIN_GART)
128 bo->flags |= NOUVEAU_BO_GART;
129 if (!(info->tile_flags & NOUVEAU_GEM_TILE_NONCONTIG))
130 bo->flags |= NOUVEAU_BO_CONTIG;
131 if (nvbo->map_handle)
132 bo->flags |= NOUVEAU_BO_MAP;
133
134 if (bo->device->chipset >= 0xc0) {
135 bo->config.nvc0.memtype = (info->tile_flags & 0xff00) >> 8;
136 bo->config.nvc0.tile_mode = info->tile_mode;
137 } else
138 if (bo->device->chipset >= 0x80 || bo->device->chipset == 0x50) {
139 bo->config.nv50.memtype = (info->tile_flags & 0x07f00) >> 8 |
140 (info->tile_flags & 0x30000) >> 9;
141 bo->config.nv50.tile_mode = info->tile_mode << 4;
142 } else {
143 bo->config.nv04.surf_flags = info->tile_flags & 7;
144 bo->config.nv04.surf_pitch = info->tile_mode;
145 }
146}
147
148int
149abi16_bo_init(struct nouveau_bo *bo, uint32_t alignment,
150 union nouveau_bo_config *config)
151{
152 struct nouveau_device *dev = bo->device;
153 struct drm_nouveau_gem_new req = {};
154 struct drm_nouveau_gem_info *info = &req.info;
155 int ret;
156
157 if (bo->flags & NOUVEAU_BO_VRAM)
158 info->domain |= NOUVEAU_GEM_DOMAIN_VRAM;
159 if (bo->flags & NOUVEAU_BO_GART)
160 info->domain |= NOUVEAU_GEM_DOMAIN_GART;
161 if (!info->domain)
162 info->domain |= NOUVEAU_GEM_DOMAIN_VRAM |
163 NOUVEAU_GEM_DOMAIN_GART;
164
165 if (bo->flags & NOUVEAU_BO_MAP)
166 info->domain |= NOUVEAU_GEM_DOMAIN_MAPPABLE;
167
168 if (!(bo->flags & NOUVEAU_BO_CONTIG))
169 info->tile_flags = NOUVEAU_GEM_TILE_NONCONTIG;
170
171 info->size = bo->size;
172 req.align = alignment;
173
174 if (config) {
175 if (dev->chipset >= 0xc0) {
176 info->tile_flags = (config->nvc0.memtype & 0xff) << 8;
177 info->tile_mode = config->nvc0.tile_mode;
178 } else
179 if (dev->chipset >= 0x80 || dev->chipset == 0x50) {
180 info->tile_flags = (config->nv50.memtype & 0x07f) << 8 |
181 (config->nv50.memtype & 0x180) << 9;
182 info->tile_mode = config->nv50.tile_mode >> 4;
183 } else {
184 info->tile_flags = config->nv04.surf_flags & 7;
185 info->tile_mode = config->nv04.surf_pitch;
186 }
187 }
188
189 if (!nouveau_device(dev)->have_bo_usage)
190 info->tile_flags &= 0x0000ff00;
191
192 ret = drmCommandWriteRead(dev->fd, DRM_NOUVEAU_GEM_NEW,
193 &req, sizeof(req));
194 if (ret == 0)
195 abi16_bo_info(bo, &req.info);
196 return ret;
197}
diff --git a/nouveau/bufctx.c b/nouveau/bufctx.c
new file mode 100644
index 00000000..23d6f096
--- /dev/null
+++ b/nouveau/bufctx.c
@@ -0,0 +1,170 @@
1/*
2 * Copyright 2012 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Ben Skeggs
23 */
24
25#ifdef HAVE_CONFIG_H
26#include <config.h>
27#endif
28
29#include <stdio.h>
30#include <stdlib.h>
31#include <stdint.h>
32#include <stdbool.h>
33#include <assert.h>
34#include <errno.h>
35
36#include "libdrm_lists.h"
37
38#include "nouveau.h"
39#include "private.h"
40
41struct nouveau_bufref_priv {
42 struct nouveau_bufref base;
43 struct nouveau_bufref_priv *next;
44 struct nouveau_bufctx *bufctx;
45};
46
47static inline struct nouveau_bufref_priv *
48nouveau_bufref(struct nouveau_bufref *bctx)
49{
50 return (struct nouveau_bufref_priv *)bctx;
51}
52
53struct nouveau_bufbin_priv {
54 struct nouveau_bufref_priv *list;
55 int relocs;
56};
57
58struct nouveau_bufctx_priv {
59 struct nouveau_bufctx base;
60 struct nouveau_bufref_priv *free;
61 int nr_bins;
62 struct nouveau_bufbin_priv bins[];
63};
64
65static inline struct nouveau_bufctx_priv *
66nouveau_bufctx(struct nouveau_bufctx *bctx)
67{
68 return (struct nouveau_bufctx_priv *)bctx;
69}
70
71int
72nouveau_bufctx_new(struct nouveau_client *client, int bins,
73 struct nouveau_bufctx **pbctx)
74{
75 struct nouveau_bufctx_priv *priv;
76
77 priv = calloc(1, sizeof(*priv) + sizeof(priv->bins[0]) * bins);
78 if (priv) {
79 DRMINITLISTHEAD(&priv->base.head);
80 DRMINITLISTHEAD(&priv->base.pending);
81 DRMINITLISTHEAD(&priv->base.current);
82 priv->base.client = client;
83 priv->nr_bins = bins;
84 *pbctx = &priv->base;
85 return 0;
86 }
87
88 return -ENOMEM;
89}
90
91void
92nouveau_bufctx_del(struct nouveau_bufctx **pbctx)
93{
94 struct nouveau_bufctx_priv *pctx = nouveau_bufctx(*pbctx);
95 struct nouveau_bufref_priv *pref;
96 if (pctx) {
97 while (pctx->nr_bins--)
98 nouveau_bufctx_reset(&pctx->base, pctx->nr_bins);
99 while ((pref = pctx->free)) {
100 pctx->free = pref->next;
101 free(pref);
102 }
103 free(pctx);
104 *pbctx = NULL;
105 }
106}
107
108void
109nouveau_bufctx_reset(struct nouveau_bufctx *bctx, int bin)
110{
111 struct nouveau_bufctx_priv *pctx = nouveau_bufctx(bctx);
112 struct nouveau_bufbin_priv *pbin = &pctx->bins[bin];
113 struct nouveau_bufref_priv *pref;
114
115 while ((pref = pbin->list)) {
116 DRMLISTDELINIT(&pref->base.thead);
117 pbin->list = pref->next;
118 pref->next = pctx->free;
119 pctx->free = pref;
120 }
121
122 bctx->relocs -= pbin->relocs;
123 pbin->relocs = 0;
124}
125
126struct nouveau_bufref *
127nouveau_bufctx_refn(struct nouveau_bufctx *bctx, int bin,
128 struct nouveau_bo *bo, uint32_t flags)
129{
130 struct nouveau_bufctx_priv *pctx = nouveau_bufctx(bctx);
131 struct nouveau_bufbin_priv *pbin = &pctx->bins[bin];
132 struct nouveau_bufref_priv *pref = pctx->free;
133
134 if (!pref)
135 pref = malloc(sizeof(*pref));
136 else
137 pctx->free = pref->next;
138
139 if (pref) {
140 pref->base.bo = bo;
141 pref->base.flags = flags;
142 pref->base.packet = 0;
143
144 DRMLISTADDTAIL(&pref->base.thead, &bctx->pending);
145 pref->bufctx = bctx;
146 pref->next = pbin->list;
147 pbin->list = pref;
148 }
149
150 return &pref->base;
151}
152
153struct nouveau_bufref *
154nouveau_bufctx_mthd(struct nouveau_bufctx *bctx, int bin, uint32_t packet,
155 struct nouveau_bo *bo, uint64_t data, uint32_t flags,
156 uint32_t vor, uint32_t tor)
157{
158 struct nouveau_bufctx_priv *pctx = nouveau_bufctx(bctx);
159 struct nouveau_bufbin_priv *pbin = &pctx->bins[bin];
160 struct nouveau_bufref *bref = nouveau_bufctx_refn(bctx, bin, bo, flags);
161 if (bref) {
162 bref->packet = packet;
163 bref->data = data;
164 bref->vor = vor;
165 bref->tor = tor;
166 pbin->relocs++;
167 bctx->relocs++;
168 }
169 return bref;
170}
diff --git a/nouveau/libdrm_nouveau.pc.in b/nouveau/libdrm_nouveau.pc.in
index c78a28a7..6170613d 100644
--- a/nouveau/libdrm_nouveau.pc.in
+++ b/nouveau/libdrm_nouveau.pc.in
@@ -5,7 +5,7 @@ includedir=@includedir@
5 5
6Name: libdrm_nouveau 6Name: libdrm_nouveau
7Description: Userspace interface to nouveau kernel DRM services 7Description: Userspace interface to nouveau kernel DRM services
8Version: 0.6 8Version: 2.4.33
9Libs: -L${libdir} -ldrm_nouveau 9Libs: -L${libdir} -ldrm_nouveau
10Cflags: -I${includedir} -I${includedir}/libdrm -I${includedir}/nouveau 10Cflags: -I${includedir} -I${includedir}/libdrm -I${includedir}/nouveau
11Requires.private: libdrm 11Requires.private: libdrm
diff --git a/nouveau/nouveau.c b/nouveau/nouveau.c
new file mode 100644
index 00000000..699b9b76
--- /dev/null
+++ b/nouveau/nouveau.c
@@ -0,0 +1,489 @@
1/*
2 * Copyright 2012 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Ben Skeggs
23 */
24
25#ifdef HAVE_CONFIG_H
26#include <config.h>
27#endif
28
29#include <stdio.h>
30#include <stdlib.h>
31#include <stdint.h>
32#include <string.h>
33#include <stdbool.h>
34#include <assert.h>
35#include <errno.h>
36#include <sys/mman.h>
37
38#include <xf86drm.h>
39#include <xf86atomic.h>
40#include "libdrm_lists.h"
41#include "nouveau_drm.h"
42
43#include "nouveau.h"
44#include "private.h"
45
46#ifdef DEBUG
47uint32_t nouveau_debug = 0;
48
49static void
50debug_init(char *args)
51{
52 if (args) {
53 int n = strtol(args, NULL, 0);
54 if (n >= 0)
55 nouveau_debug = n;
56 }
57}
58#endif
59
60/* this is the old libdrm's version of nouveau_device_wrap(), the symbol
61 * is kept here to prevent AIGLX from crashing if the DDX is linked against
62 * the new libdrm, but the DRI driver against the old
63 */
64int
65nouveau_device_open_existing(struct nouveau_device **pdev, int close, int fd,
66 drm_context_t ctx)
67{
68 return -EACCES;
69}
70
71int
72nouveau_device_wrap(int fd, int close, struct nouveau_device **pdev)
73{
74 struct nouveau_device_priv *nvdev = calloc(1, sizeof(*nvdev));
75 struct nouveau_device *dev = &nvdev->base;
76 uint64_t chipset, vram, gart, bousage;
77 drmVersionPtr ver;
78 int ret;
79
80#ifdef DEBUG
81 debug_init(getenv("NOUVEAU_LIBDRM_DEBUG"));
82#endif
83
84 if (!nvdev)
85 return -ENOMEM;
86 nvdev->base.fd = fd;
87
88 ver = drmGetVersion(fd);
89 if (ver) dev->drm_version = (ver->version_major << 24) |
90 (ver->version_minor << 8) |
91 ver->version_patchlevel;
92 drmFreeVersion(ver);
93
94 if ( dev->drm_version != 0x00000010 &&
95 (dev->drm_version < 0x01000000 ||
96 dev->drm_version >= 0x02000000)) {
97 nouveau_device_del(&dev);
98 return -EINVAL;
99 }
100
101 ret = nouveau_getparam(dev, NOUVEAU_GETPARAM_CHIPSET_ID, &chipset);
102 if (ret == 0)
103 ret = nouveau_getparam(dev, NOUVEAU_GETPARAM_FB_SIZE, &vram);
104 if (ret == 0)
105 ret = nouveau_getparam(dev, NOUVEAU_GETPARAM_AGP_SIZE, &gart);
106 if (ret) {
107 nouveau_device_del(&dev);
108 return ret;
109 }
110
111 ret = nouveau_getparam(dev, NOUVEAU_GETPARAM_HAS_BO_USAGE, &bousage);
112 if (ret == 0)
113 nvdev->have_bo_usage = (bousage != 0);
114
115 nvdev->close = close;
116 DRMINITLISTHEAD(&nvdev->bo_list);
117 nvdev->base.object.oclass = NOUVEAU_DEVICE_CLASS;
118 nvdev->base.lib_version = 0x01000000;
119 nvdev->base.chipset = chipset;
120 nvdev->base.vram_size = vram;
121 nvdev->base.gart_size = gart;
122 nvdev->base.vram_limit = (nvdev->base.vram_size * 80) / 100;
123 nvdev->base.gart_limit = (nvdev->base.gart_size * 80) / 100;
124
125 *pdev = &nvdev->base;
126 return 0;
127}
128
129int
130nouveau_device_open(const char *busid, struct nouveau_device **pdev)
131{
132 int ret = -ENODEV, fd = drmOpen("nouveau", busid);
133 if (fd >= 0) {
134 ret = nouveau_device_wrap(fd, 1, pdev);
135 if (ret)
136 drmClose(fd);
137 }
138 return ret;
139}
140
141void
142nouveau_device_del(struct nouveau_device **pdev)
143{
144 struct nouveau_device_priv *nvdev = nouveau_device(*pdev);
145 if (nvdev) {
146 if (nvdev->close)
147 drmClose(nvdev->base.fd);
148 free(nvdev->client);
149 free(nvdev);
150 *pdev = NULL;
151 }
152}
153
154int
155nouveau_getparam(struct nouveau_device *dev, uint64_t param, uint64_t *value)
156{
157 struct drm_nouveau_getparam r = { param, 0 };
158 int fd = dev->fd, ret =
159 drmCommandWriteRead(fd, DRM_NOUVEAU_GETPARAM, &r, sizeof(r));
160 *value = r.value;
161 return ret;
162}
163
164int
165nouveau_setparam(struct nouveau_device *dev, uint64_t param, uint64_t value)
166{
167 struct drm_nouveau_setparam r = { param, value };
168 return drmCommandWrite(dev->fd, DRM_NOUVEAU_SETPARAM, &r, sizeof(r));
169}
170
171int
172nouveau_client_new(struct nouveau_device *dev, struct nouveau_client **pclient)
173{
174 struct nouveau_device_priv *nvdev = nouveau_device(dev);
175 struct nouveau_client_priv *pcli;
176 int id = 0, i, ret = -ENOMEM;
177 uint32_t *clients;
178
179 for (i = 0; i < nvdev->nr_client; i++) {
180 id = ffs(nvdev->client[i]) - 1;
181 if (id >= 0)
182 goto out;
183 }
184
185 clients = realloc(nvdev->client, sizeof(uint32_t) * (i + 1));
186 if (!clients)
187 return ret;
188 nvdev->client = clients;
189 nvdev->client[i] = 0;
190 nvdev->nr_client++;
191
192out:
193 pcli = calloc(1, sizeof(*pcli));
194 if (pcli) {
195 nvdev->client[i] |= (1 << id);
196 pcli->base.device = dev;
197 pcli->base.id = (i * 32) + id;
198 ret = 0;
199 }
200
201 *pclient = &pcli->base;
202 return ret;
203}
204
205void
206nouveau_client_del(struct nouveau_client **pclient)
207{
208 struct nouveau_client_priv *pcli = nouveau_client(*pclient);
209 struct nouveau_device_priv *nvdev;
210 if (pcli) {
211 int id = pcli->base.id;
212 nvdev = nouveau_device(pcli->base.device);
213 nvdev->client[id / 32] &= ~(1 << (id % 32));
214 free(pcli->kref);
215 free(pcli);
216 }
217}
218
219int
220nouveau_object_new(struct nouveau_object *parent, uint64_t handle,
221 uint32_t oclass, void *data, uint32_t length,
222 struct nouveau_object **pobj)
223{
224 struct nouveau_device *dev;
225 struct nouveau_object *obj;
226 int ret = -EINVAL;
227
228 if (length == 0)
229 length = sizeof(struct nouveau_object *);
230 obj = malloc(sizeof(*obj) + length);
231 obj->parent = parent;
232 obj->handle = handle;
233 obj->oclass = oclass;
234 obj->length = length;
235 obj->data = obj + 1;
236 if (data)
237 memcpy(obj->data, data, length);
238 *(struct nouveau_object **)obj->data = obj;
239
240 dev = nouveau_object_find(obj, NOUVEAU_DEVICE_CLASS);
241 switch (parent->oclass) {
242 case NOUVEAU_DEVICE_CLASS:
243 switch (obj->oclass) {
244 case NOUVEAU_FIFO_CHANNEL_CLASS:
245 {
246 if (dev->chipset < 0xc0)
247 ret = abi16_chan_nv04(obj);
248 else
249 ret = abi16_chan_nvc0(obj);
250 }
251 break;
252 default:
253 break;
254 }
255 break;
256 case NOUVEAU_FIFO_CHANNEL_CLASS:
257 switch (obj->oclass) {
258 case NOUVEAU_NOTIFIER_CLASS:
259 ret = abi16_ntfy(obj);
260 break;
261 default:
262 ret = abi16_engobj(obj);
263 break;
264 }
265 default:
266 break;
267 }
268
269 if (ret) {
270 free(obj);
271 return ret;
272 }
273
274 *pobj = obj;
275 return 0;
276}
277
278void
279nouveau_object_del(struct nouveau_object **pobj)
280{
281 struct drm_nouveau_gpuobj_free req;
282 struct nouveau_object *obj = *pobj;
283 struct nouveau_device *dev;
284 if (obj) {
285 dev = nouveau_object_find(obj, NOUVEAU_DEVICE_CLASS);
286 req.channel = obj->parent->handle;
287 req.handle = obj->handle;
288 drmCommandWrite(dev->fd, DRM_NOUVEAU_GPUOBJ_FREE,
289 &req, sizeof(req));
290 }
291 free(obj);
292 *pobj = NULL;
293}
294
295void *
296nouveau_object_find(struct nouveau_object *obj, uint32_t pclass)
297{
298 while (obj && obj->oclass != pclass) {
299 obj = obj->parent;
300 if (pclass == NOUVEAU_PARENT_CLASS)
301 break;
302 }
303 return obj;
304}
305
306static void
307nouveau_bo_del(struct nouveau_bo *bo)
308{
309 struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
310 struct drm_gem_close req = { bo->handle };
311 DRMLISTDEL(&nvbo->head);
312 if (bo->map)
313 munmap(bo->map, bo->size);
314 drmIoctl(bo->device->fd, DRM_IOCTL_GEM_CLOSE, &req);
315 free(nvbo);
316}
317
318int
319nouveau_bo_new(struct nouveau_device *dev, uint32_t flags, uint32_t align,
320 uint64_t size, union nouveau_bo_config *config,
321 struct nouveau_bo **pbo)
322{
323 struct nouveau_device_priv *nvdev = nouveau_device(dev);
324 struct nouveau_bo_priv *nvbo = calloc(1, sizeof(*nvbo));
325 struct nouveau_bo *bo = &nvbo->base;
326 int ret;
327
328 if (!nvbo)
329 return -ENOMEM;
330 atomic_set(&nvbo->refcnt, 1);
331 bo->device = dev;
332 bo->flags = flags;
333 bo->size = size;
334
335 ret = abi16_bo_init(bo, align, config);
336 if (ret) {
337 free(nvbo);
338 return ret;
339 }
340
341 DRMLISTADD(&nvbo->head, &nvdev->bo_list);
342
343 *pbo = bo;
344 return 0;
345}
346
347int
348nouveau_bo_wrap(struct nouveau_device *dev, uint32_t handle,
349 struct nouveau_bo **pbo)
350{
351 struct nouveau_device_priv *nvdev = nouveau_device(dev);
352 struct drm_nouveau_gem_info req = { .handle = handle };
353 struct nouveau_bo_priv *nvbo;
354 int ret;
355
356 DRMLISTFOREACHENTRY(nvbo, &nvdev->bo_list, head) {
357 if (nvbo->base.handle == handle) {
358 *pbo = NULL;
359 nouveau_bo_ref(&nvbo->base, pbo);
360 return 0;
361 }
362 }
363
364 ret = drmCommandWriteRead(dev->fd, DRM_NOUVEAU_GEM_INFO,
365 &req, sizeof(req));
366 if (ret)
367 return ret;
368
369 nvbo = calloc(1, sizeof(*nvbo));
370 if (nvbo) {
371 atomic_set(&nvbo->refcnt, 1);
372 nvbo->base.device = dev;
373 abi16_bo_info(&nvbo->base, &req);
374 DRMLISTADD(&nvbo->head, &nvdev->bo_list);
375 *pbo = &nvbo->base;
376 return 0;
377 }
378
379 return -ENOMEM;
380}
381
382int
383nouveau_bo_name_ref(struct nouveau_device *dev, uint32_t name,
384 struct nouveau_bo **pbo)
385{
386 struct nouveau_device_priv *nvdev = nouveau_device(dev);
387 struct nouveau_bo_priv *nvbo;
388 struct drm_gem_open req = { .name = name };
389 int ret;
390
391 DRMLISTFOREACHENTRY(nvbo, &nvdev->bo_list, head) {
392 if (nvbo->name == name) {
393 *pbo = NULL;
394 nouveau_bo_ref(&nvbo->base, pbo);
395 return 0;
396 }
397 }
398
399 ret = drmIoctl(dev->fd, DRM_IOCTL_GEM_OPEN, &req);
400 if (ret == 0) {
401 ret = nouveau_bo_wrap(dev, req.handle, pbo);
402 nouveau_bo((*pbo))->name = name;
403 }
404
405 return ret;
406}
407
408int
409nouveau_bo_name_get(struct nouveau_bo *bo, uint32_t *name)
410{
411 struct drm_gem_flink req = { .handle = bo->handle };
412 struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
413 if (!nvbo->name) {
414 int ret = drmIoctl(bo->device->fd, DRM_IOCTL_GEM_FLINK, &req);
415 if (ret)
416 return ret;
417 nvbo->name = req.name;
418 }
419 *name = nvbo->name;
420 return 0;
421}
422
423void
424nouveau_bo_ref(struct nouveau_bo *bo, struct nouveau_bo **pref)
425{
426 struct nouveau_bo *ref = *pref;
427 if (bo) {
428 atomic_inc(&nouveau_bo(bo)->refcnt);
429 }
430 if (ref) {
431 if (atomic_dec_and_test(&nouveau_bo(ref)->refcnt))
432 nouveau_bo_del(ref);
433 }
434 *pref = bo;
435}
436
437int
438nouveau_bo_wait(struct nouveau_bo *bo, uint32_t access,
439 struct nouveau_client *client)
440{
441 struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
442 struct drm_nouveau_gem_cpu_prep req;
443 struct nouveau_pushbuf *push;
444 int ret = 0;
445
446 if (!(access & NOUVEAU_BO_RDWR))
447 return 0;
448
449 push = cli_push_get(client, bo);
450 if (push && push->channel)
451 nouveau_pushbuf_kick(push, push->channel);
452
453 if (!nvbo->name && !(nvbo->access & NOUVEAU_BO_WR) &&
454 !( access & NOUVEAU_BO_WR))
455 return 0;
456
457 req.handle = bo->handle;
458 req.flags = 0;
459 if (access & NOUVEAU_BO_WR)
460 req.flags |= NOUVEAU_GEM_CPU_PREP_WRITE;
461 if (access & NOUVEAU_BO_NOBLOCK)
462 req.flags |= NOUVEAU_GEM_CPU_PREP_NOWAIT;
463
464 do {
465 ret = drmCommandWrite(bo->device->fd,
466 DRM_NOUVEAU_GEM_CPU_PREP,
467 &req, sizeof(req));
468 } while (ret == -EAGAIN);
469
470 if (ret == 0)
471 nvbo->access = 0;
472 return ret;
473}
474
475int
476nouveau_bo_map(struct nouveau_bo *bo, uint32_t access,
477 struct nouveau_client *client)
478{
479 struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
480 if (bo->map == NULL) {
481 bo->map = mmap(0, bo->size, PROT_READ | PROT_WRITE,
482 MAP_SHARED, bo->device->fd, nvbo->map_handle);
483 if (bo->map == MAP_FAILED) {
484 bo->map = NULL;
485 return -errno;
486 }
487 }
488 return nouveau_bo_wait(bo, access, client);
489}
diff --git a/nouveau/nouveau.h b/nouveau/nouveau.h
new file mode 100644
index 00000000..d7954cf4
--- /dev/null
+++ b/nouveau/nouveau.h
@@ -0,0 +1,211 @@
1#ifndef __NOUVEAU_H__
2#define __NOUVEAU_H__
3
4#include <stdint.h>
5#include <stdbool.h>
6
7#define NOUVEAU_DEVICE_CLASS 0x80000000
8#define NOUVEAU_FIFO_CHANNEL_CLASS 0x80000001
9#define NOUVEAU_NOTIFIER_CLASS 0x80000002
10#define NOUVEAU_PARENT_CLASS 0xffffffff
11
12struct nouveau_list {
13 struct nouveau_list *prev;
14 struct nouveau_list *next;
15};
16
17struct nouveau_object {
18 struct nouveau_object *parent;
19 uint64_t handle;
20 uint32_t oclass;
21 uint32_t length;
22 void *data;
23};
24
25struct nouveau_fifo {
26 struct nouveau_object *object;
27 uint32_t channel;
28 uint32_t pushbuf;
29 uint64_t unused1[3];
30};
31
32struct nv04_fifo {
33 struct nouveau_fifo base;
34 uint32_t vram;
35 uint32_t gart;
36 uint32_t notify;
37};
38
39struct nvc0_fifo {
40 struct nouveau_fifo base;
41};
42
43struct nv04_notify {
44 struct nouveau_object *object;
45 uint32_t offset;
46 uint32_t length;
47};
48
49int nouveau_object_new(struct nouveau_object *parent, uint64_t handle,
50 uint32_t oclass, void *data, uint32_t length,
51 struct nouveau_object **);
52void nouveau_object_del(struct nouveau_object **);
53void *nouveau_object_find(struct nouveau_object *, uint32_t parent_class);
54
55struct nouveau_device {
56 struct nouveau_object object;
57 int fd;
58 uint32_t lib_version;
59 uint32_t drm_version;
60 uint32_t chipset;
61 uint64_t vram_size;
62 uint64_t gart_size;
63 uint64_t vram_limit;
64 uint64_t gart_limit;
65};
66
67int nouveau_device_wrap(int fd, int close, struct nouveau_device **);
68int nouveau_device_open(const char *busid, struct nouveau_device **);
69void nouveau_device_del(struct nouveau_device **);
70int nouveau_getparam(struct nouveau_device *, uint64_t param, uint64_t *value);
71int nouveau_setparam(struct nouveau_device *, uint64_t param, uint64_t value);
72
73struct nouveau_client {
74 struct nouveau_device *device;
75 int id;
76};
77
78int nouveau_client_new(struct nouveau_device *, struct nouveau_client **);
79void nouveau_client_del(struct nouveau_client **);
80
81union nouveau_bo_config {
82 struct {
83#define NV04_BO_16BPP 0x00000001
84#define NV04_BO_32BPP 0x00000002
85#define NV04_BO_ZETA 0x00000004
86 uint32_t surf_flags;
87 uint32_t surf_pitch;
88 } nv04;
89 struct {
90 uint32_t memtype;
91 uint32_t tile_mode;
92 } nv50;
93 struct {
94 uint32_t memtype;
95 uint32_t tile_mode;
96 } nvc0;
97 uint32_t data[8];
98};
99
100#define NOUVEAU_BO_VRAM 0x00000001
101#define NOUVEAU_BO_GART 0x00000002
102#define NOUVEAU_BO_APER (NOUVEAU_BO_VRAM | NOUVEAU_BO_GART)
103#define NOUVEAU_BO_RD 0x00000100
104#define NOUVEAU_BO_WR 0x00000200
105#define NOUVEAU_BO_RDWR (NOUVEAU_BO_RD | NOUVEAU_BO_WR)
106#define NOUVEAU_BO_NOBLOCK 0x00000400
107#define NOUVEAU_BO_LOW 0x00001000
108#define NOUVEAU_BO_HIGH 0x00002000
109#define NOUVEAU_BO_OR 0x00004000
110#define NOUVEAU_BO_MAP 0x80000000
111#define NOUVEAU_BO_CONTIG 0x40000000
112#define NOUVEAU_BO_NOSNOOP 0x20000000
113
114struct nouveau_bo {
115 struct nouveau_device *device;
116 uint32_t handle;
117 uint64_t size;
118 uint32_t flags;
119 uint64_t offset;
120 void *map;
121 union nouveau_bo_config config;
122};
123
124int nouveau_bo_new(struct nouveau_device *, uint32_t flags, uint32_t align,
125 uint64_t size, union nouveau_bo_config *,
126 struct nouveau_bo **);
127int nouveau_bo_wrap(struct nouveau_device *, uint32_t handle,
128 struct nouveau_bo **);
129int nouveau_bo_name_ref(struct nouveau_device *dev, uint32_t name,
130 struct nouveau_bo **);
131int nouveau_bo_name_get(struct nouveau_bo *, uint32_t *name);
132void nouveau_bo_ref(struct nouveau_bo *, struct nouveau_bo **);
133int nouveau_bo_map(struct nouveau_bo *, uint32_t access,
134 struct nouveau_client *);
135int nouveau_bo_wait(struct nouveau_bo *, uint32_t access,
136 struct nouveau_client *);
137
138struct nouveau_bufref {
139 struct nouveau_list thead;
140 struct nouveau_bo *bo;
141 uint32_t packet;
142 uint32_t flags;
143 uint32_t data;
144 uint32_t vor;
145 uint32_t tor;
146 uint32_t priv_data;
147 void *priv;
148};
149
150struct nouveau_bufctx {
151 struct nouveau_client *client;
152 struct nouveau_list head;
153 struct nouveau_list pending;
154 struct nouveau_list current;
155 int relocs;
156};
157
158int nouveau_bufctx_new(struct nouveau_client *, int bins,
159 struct nouveau_bufctx **);
160void nouveau_bufctx_del(struct nouveau_bufctx **);
161struct nouveau_bufref *
162nouveau_bufctx_refn(struct nouveau_bufctx *, int bin,
163 struct nouveau_bo *, uint32_t flags);
164struct nouveau_bufref *
165nouveau_bufctx_mthd(struct nouveau_bufctx *, int bin, uint32_t packet,
166 struct nouveau_bo *, uint64_t data, uint32_t flags,
167 uint32_t vor, uint32_t tor);
168void nouveau_bufctx_reset(struct nouveau_bufctx *, int bin);
169
170struct nouveau_pushbuf_krec;
171struct nouveau_pushbuf {
172 struct nouveau_client *client;
173 struct nouveau_object *channel;
174 struct nouveau_bufctx *bufctx;
175 void (*kick_notify)(struct nouveau_pushbuf *);
176 void *user_priv;
177 uint32_t rsvd_kick;
178 uint32_t flags;
179 uint32_t *cur;
180 uint32_t *end;
181};
182
183struct nouveau_pushbuf_refn {
184 struct nouveau_bo *bo;
185 uint32_t flags;
186};
187
188int nouveau_pushbuf_new(struct nouveau_client *, struct nouveau_object *channel,
189 int nr, uint32_t size, bool immediate,
190 struct nouveau_pushbuf **);
191void nouveau_pushbuf_del(struct nouveau_pushbuf **);
192int nouveau_pushbuf_space(struct nouveau_pushbuf *, uint32_t dwords,
193 uint32_t relocs, uint32_t pushes);
194void nouveau_pushbuf_data(struct nouveau_pushbuf *, struct nouveau_bo *,
195 uint64_t offset, uint64_t length);
196int nouveau_pushbuf_refn(struct nouveau_pushbuf *,
197 struct nouveau_pushbuf_refn *, int nr);
198/* Emits a reloc into the push buffer at the current position, you *must*
199 * have previously added the referenced buffer to a buffer context, and
200 * validated it against the current push buffer.
201 */
202void nouveau_pushbuf_reloc(struct nouveau_pushbuf *, struct nouveau_bo *,
203 uint32_t data, uint32_t flags,
204 uint32_t vor, uint32_t tor);
205int nouveau_pushbuf_validate(struct nouveau_pushbuf *);
206uint32_t nouveau_pushbuf_refd(struct nouveau_pushbuf *, struct nouveau_bo *);
207int nouveau_pushbuf_kick(struct nouveau_pushbuf *, struct nouveau_object *channel);
208struct nouveau_bufctx *
209nouveau_pushbuf_bufctx(struct nouveau_pushbuf *, struct nouveau_bufctx *);
210
211#endif
diff --git a/nouveau/nouveau_bo.c b/nouveau/nouveau_bo.c
deleted file mode 100644
index d6bb22de..00000000
--- a/nouveau/nouveau_bo.c
+++ /dev/null
@@ -1,549 +0,0 @@
1/*
2 * Copyright 2007 Nouveau Project
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
23#ifdef HAVE_CONFIG_H
24#include <config.h>
25#endif
26#include <stdint.h>
27#include <stdlib.h>
28#include <errno.h>
29#include <assert.h>
30
31#include <sys/mman.h>
32
33#include "nouveau_private.h"
34
35int
36nouveau_bo_init(struct nouveau_device *dev)
37{
38 return 0;
39}
40
41void
42nouveau_bo_takedown(struct nouveau_device *dev)
43{
44}
45
46static int
47nouveau_bo_info(struct nouveau_bo_priv *nvbo, struct drm_nouveau_gem_info *arg)
48{
49 nvbo->handle = nvbo->base.handle = arg->handle;
50 nvbo->domain = arg->domain;
51 nvbo->size = arg->size;
52 nvbo->offset = arg->offset;
53 nvbo->map_handle = arg->map_handle;
54 nvbo->base.tile_mode = arg->tile_mode;
55 /* XXX - flag inverted for backwards compatibility */
56 nvbo->base.tile_flags = arg->tile_flags ^ NOUVEAU_GEM_TILE_NONCONTIG;
57 return 0;
58}
59
60static int
61nouveau_bo_allocated(struct nouveau_bo_priv *nvbo)
62{
63 if (nvbo->sysmem || nvbo->handle)
64 return 1;
65 return 0;
66}
67
68static int
69nouveau_bo_ualloc(struct nouveau_bo_priv *nvbo)
70{
71 if (nvbo->user || nvbo->sysmem) {
72 assert(nvbo->sysmem);
73 return 0;
74 }
75
76 nvbo->sysmem = malloc(nvbo->size);
77 if (!nvbo->sysmem)
78 return -ENOMEM;
79
80 return 0;
81}
82
83static void
84nouveau_bo_ufree(struct nouveau_bo_priv *nvbo)
85{
86 if (nvbo->sysmem) {
87 if (!nvbo->user)
88 free(nvbo->sysmem);
89 nvbo->sysmem = NULL;
90 }
91}
92
93static void
94nouveau_bo_kfree(struct nouveau_bo_priv *nvbo)
95{
96 struct nouveau_device_priv *nvdev = nouveau_device(nvbo->base.device);
97 struct drm_gem_close req;
98
99 if (!nvbo->handle)
100 return;
101
102 if (nvbo->map) {
103 munmap(nvbo->map, nvbo->size);
104 nvbo->map = NULL;
105 }
106
107 req.handle = nvbo->handle;
108 nvbo->handle = 0;
109 drmIoctl(nvdev->fd, DRM_IOCTL_GEM_CLOSE, &req);
110}
111
112static int
113nouveau_bo_kalloc(struct nouveau_bo_priv *nvbo, struct nouveau_channel *chan)
114{
115 struct nouveau_device_priv *nvdev = nouveau_device(nvbo->base.device);
116 struct drm_nouveau_gem_new req;
117 struct drm_nouveau_gem_info *info = &req.info;
118 int ret;
119
120 if (nvbo->handle)
121 return 0;
122
123 req.channel_hint = chan ? chan->id : 0;
124 req.align = nvbo->align;
125
126
127 info->size = nvbo->size;
128 info->domain = 0;
129
130 if (nvbo->flags & NOUVEAU_BO_VRAM)
131 info->domain |= NOUVEAU_GEM_DOMAIN_VRAM;
132 if (nvbo->flags & NOUVEAU_BO_GART)
133 info->domain |= NOUVEAU_GEM_DOMAIN_GART;
134 if (!info->domain) {
135 info->domain |= (NOUVEAU_GEM_DOMAIN_VRAM |
136 NOUVEAU_GEM_DOMAIN_GART);
137 }
138
139 if (nvbo->flags & NOUVEAU_BO_MAP)
140 info->domain |= NOUVEAU_GEM_DOMAIN_MAPPABLE;
141
142 info->tile_mode = nvbo->base.tile_mode;
143 info->tile_flags = nvbo->base.tile_flags;
144 /* XXX - flag inverted for backwards compatibility */
145 info->tile_flags ^= NOUVEAU_GEM_TILE_NONCONTIG;
146 if (!nvdev->has_bo_usage)
147 info->tile_flags &= NOUVEAU_GEM_TILE_LAYOUT_MASK;
148
149 ret = drmCommandWriteRead(nvdev->fd, DRM_NOUVEAU_GEM_NEW,
150 &req, sizeof(req));
151 if (ret)
152 return ret;
153
154 nouveau_bo_info(nvbo, &req.info);
155 return 0;
156}
157
158static int
159nouveau_bo_kmap(struct nouveau_bo_priv *nvbo)
160{
161 struct nouveau_device_priv *nvdev = nouveau_device(nvbo->base.device);
162
163 if (nvbo->map)
164 return 0;
165
166 if (!nvbo->map_handle)
167 return -EINVAL;
168
169 nvbo->map = mmap(0, nvbo->size, PROT_READ | PROT_WRITE,
170 MAP_SHARED, nvdev->fd, nvbo->map_handle);
171 if (nvbo->map == MAP_FAILED) {
172 nvbo->map = NULL;
173 return -errno;
174 }
175
176 return 0;
177}
178
179int
180nouveau_bo_new_tile(struct nouveau_device *dev, uint32_t flags, int align,
181 int size, uint32_t tile_mode, uint32_t tile_flags,
182 struct nouveau_bo **bo)
183{
184 struct nouveau_bo_priv *nvbo;
185 int ret;
186
187 if (!dev || !bo || *bo)
188 return -EINVAL;
189
190 nvbo = calloc(1, sizeof(struct nouveau_bo_priv));
191 if (!nvbo)
192 return -ENOMEM;
193 nvbo->base.device = dev;
194 nvbo->base.size = size;
195 nvbo->base.tile_mode = tile_mode;
196 nvbo->base.tile_flags = tile_flags;
197
198 nvbo->refcount = 1;
199 nvbo->flags = flags;
200 nvbo->size = size;
201 nvbo->align = align;
202
203 if (flags & (NOUVEAU_BO_VRAM | NOUVEAU_BO_GART)) {
204 ret = nouveau_bo_kalloc(nvbo, NULL);
205 if (ret) {
206 nouveau_bo_ref(NULL, (void *)&nvbo);
207 return ret;
208 }
209 }
210
211 *bo = &nvbo->base;
212 return 0;
213}
214
215int
216nouveau_bo_new(struct nouveau_device *dev, uint32_t flags, int align,
217 int size, struct nouveau_bo **bo)
218{
219 return nouveau_bo_new_tile(dev, flags, align, size, 0, 0, bo);
220}
221
222int
223nouveau_bo_user(struct nouveau_device *dev, void *ptr, int size,
224 struct nouveau_bo **bo)
225{
226 struct nouveau_bo_priv *nvbo;
227 int ret;
228
229 ret = nouveau_bo_new(dev, NOUVEAU_BO_MAP, 0, size, bo);
230 if (ret)
231 return ret;
232 nvbo = nouveau_bo(*bo);
233
234 nvbo->sysmem = ptr;
235 nvbo->user = 1;
236 return 0;
237}
238
239int
240nouveau_bo_wrap(struct nouveau_device *dev, uint32_t handle,
241 struct nouveau_bo **bo)
242{
243 struct nouveau_device_priv *nvdev = nouveau_device(dev);
244 struct drm_nouveau_gem_info req;
245 struct nouveau_bo_priv *nvbo;
246 int ret;
247
248 ret = nouveau_bo_new(dev, 0, 0, 0, bo);
249 if (ret)
250 return ret;
251 nvbo = nouveau_bo(*bo);
252
253 req.handle = handle;
254 ret = drmCommandWriteRead(nvdev->fd, DRM_NOUVEAU_GEM_INFO,
255 &req, sizeof(req));
256 if (ret) {
257 nouveau_bo_ref(NULL, bo);
258 return ret;
259 }
260
261 nouveau_bo_info(nvbo, &req);
262 nvbo->base.size = nvbo->size;
263 return 0;
264}
265
266int
267nouveau_bo_handle_get(struct nouveau_bo *bo, uint32_t *handle)
268{
269 struct nouveau_device_priv *nvdev = nouveau_device(bo->device);
270 struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
271 int ret;
272
273 if (!bo || !handle)
274 return -EINVAL;
275
276 if (!nvbo->global_handle) {
277 struct drm_gem_flink req;
278
279 ret = nouveau_bo_kalloc(nvbo, NULL);
280 if (ret)
281 return ret;
282
283 req.handle = nvbo->handle;
284 ret = drmIoctl(nvdev->fd, DRM_IOCTL_GEM_FLINK, &req);
285 if (ret) {
286 nouveau_bo_kfree(nvbo);
287 return ret;
288 }
289
290 nvbo->global_handle = req.name;
291 }
292
293 *handle = nvbo->global_handle;
294 return 0;
295}
296
297int
298nouveau_bo_handle_ref(struct nouveau_device *dev, uint32_t handle,
299 struct nouveau_bo **bo)
300{
301 struct nouveau_device_priv *nvdev = nouveau_device(dev);
302 struct nouveau_bo_priv *nvbo;
303 struct drm_gem_open req;
304 int ret;
305
306 req.name = handle;
307 ret = drmIoctl(nvdev->fd, DRM_IOCTL_GEM_OPEN, &req);
308 if (ret) {
309 nouveau_bo_ref(NULL, bo);
310 return ret;
311 }
312
313 ret = nouveau_bo_wrap(dev, req.handle, bo);
314 if (ret) {
315 nouveau_bo_ref(NULL, bo);
316 return ret;
317 }
318
319 nvbo = nouveau_bo(*bo);
320 nvbo->base.handle = nvbo->handle;
321 return 0;
322}
323
324static void
325nouveau_bo_del(struct nouveau_bo **bo)
326{
327 struct nouveau_bo_priv *nvbo;
328
329 if (!bo || !*bo)
330 return;
331 nvbo = nouveau_bo(*bo);
332 *bo = NULL;
333
334 if (--nvbo->refcount)
335 return;
336
337 if (nvbo->pending) {
338 nvbo->pending = NULL;
339 nouveau_pushbuf_flush(nvbo->pending_channel, 0);
340 }
341
342 nouveau_bo_ufree(nvbo);
343 nouveau_bo_kfree(nvbo);
344 free(nvbo);
345}
346
347int
348nouveau_bo_ref(struct nouveau_bo *ref, struct nouveau_bo **pbo)
349{
350 if (!pbo)
351 return -EINVAL;
352
353 if (ref)
354 nouveau_bo(ref)->refcount++;
355
356 if (*pbo)
357 nouveau_bo_del(pbo);
358
359 *pbo = ref;
360 return 0;
361}
362
363static int
364nouveau_bo_wait(struct nouveau_bo *bo, int cpu_write, int no_wait, int no_block)
365{
366 struct nouveau_device_priv *nvdev = nouveau_device(bo->device);
367 struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
368 struct drm_nouveau_gem_cpu_prep req;
369 int ret;
370
371 if (!nvbo->global_handle && !nvbo->write_marker && !cpu_write)
372 return 0;
373
374 if (nvbo->pending &&
375 (nvbo->pending->write_domains || cpu_write)) {
376 nvbo->pending = NULL;
377 nouveau_pushbuf_flush(nvbo->pending_channel, 0);
378 }
379
380 req.handle = nvbo->handle;
381 req.flags = 0;
382 if (cpu_write)
383 req.flags |= NOUVEAU_GEM_CPU_PREP_WRITE;
384 if (no_wait)
385 req.flags |= NOUVEAU_GEM_CPU_PREP_NOWAIT;
386 if (no_block)
387 req.flags |= NOUVEAU_GEM_CPU_PREP_NOBLOCK;
388
389 do {
390 ret = drmCommandWrite(nvdev->fd, DRM_NOUVEAU_GEM_CPU_PREP,
391 &req, sizeof(req));
392 } while (ret == -EAGAIN);
393 if (ret)
394 return ret;
395
396 if (ret == 0)
397 nvbo->write_marker = 0;
398 return 0;
399}
400
401int
402nouveau_bo_map_range(struct nouveau_bo *bo, uint32_t delta, uint32_t size,
403 uint32_t flags)
404{
405 struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
406 int ret;
407
408 if (!nvbo || bo->map)
409 return -EINVAL;
410
411 if (!nouveau_bo_allocated(nvbo)) {
412 if (nvbo->flags & (NOUVEAU_BO_VRAM | NOUVEAU_BO_GART)) {
413 ret = nouveau_bo_kalloc(nvbo, NULL);
414 if (ret)
415 return ret;
416 }
417
418 if (!nouveau_bo_allocated(nvbo)) {
419 ret = nouveau_bo_ualloc(nvbo);
420 if (ret)
421 return ret;
422 }
423 }
424
425 if (nvbo->sysmem) {
426 bo->map = (char *)nvbo->sysmem + delta;
427 } else {
428 ret = nouveau_bo_kmap(nvbo);
429 if (ret)
430 return ret;
431
432 if (!(flags & NOUVEAU_BO_NOSYNC)) {
433 ret = nouveau_bo_wait(bo, (flags & NOUVEAU_BO_WR),
434 (flags & NOUVEAU_BO_NOWAIT), 0);
435 if (ret)
436 return ret;
437
438 nvbo->map_refcnt++;
439 }
440
441 bo->map = (char *)nvbo->map + delta;
442 }
443
444 return 0;
445}
446
447void
448nouveau_bo_map_flush(struct nouveau_bo *bo, uint32_t delta, uint32_t size)
449{
450}
451
452int
453nouveau_bo_map(struct nouveau_bo *bo, uint32_t flags)
454{
455 return nouveau_bo_map_range(bo, 0, bo->size, flags);
456}
457
458void
459nouveau_bo_unmap(struct nouveau_bo *bo)
460{
461 struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
462
463 if (bo->map && !nvbo->sysmem && nvbo->map_refcnt) {
464 struct nouveau_device_priv *nvdev = nouveau_device(bo->device);
465 struct drm_nouveau_gem_cpu_fini req;
466
467 req.handle = nvbo->handle;
468 drmCommandWrite(nvdev->fd, DRM_NOUVEAU_GEM_CPU_FINI,
469 &req, sizeof(req));
470 nvbo->map_refcnt--;
471 }
472
473 bo->map = NULL;
474}
475
476int
477nouveau_bo_busy(struct nouveau_bo *bo, uint32_t access)
478{
479 return nouveau_bo_wait(bo, (access & NOUVEAU_BO_WR), 1, 1);
480}
481
482uint32_t
483nouveau_bo_pending(struct nouveau_bo *bo)
484{
485 struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
486 uint32_t flags;
487
488 if (!nvbo->pending)
489 return 0;
490
491 flags = 0;
492 if (nvbo->pending->read_domains)
493 flags |= NOUVEAU_BO_RD;
494 if (nvbo->pending->write_domains)
495 flags |= NOUVEAU_BO_WR;
496
497 return flags;
498}
499
500struct drm_nouveau_gem_pushbuf_bo *
501nouveau_bo_emit_buffer(struct nouveau_channel *chan, struct nouveau_bo *bo)
502{
503 struct nouveau_pushbuf_priv *nvpb = &nouveau_channel(chan)->pb;
504 struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
505 struct drm_nouveau_gem_pushbuf_bo *pbbo;
506 struct nouveau_bo *ref = NULL;
507 int ret;
508
509 if (nvbo->pending)
510 return nvbo->pending;
511
512 if (!nvbo->handle) {
513 ret = nouveau_bo_kalloc(nvbo, chan);
514 if (ret)
515 return NULL;
516
517 if (nvbo->sysmem) {
518 void *sysmem_tmp = nvbo->sysmem;
519
520 nvbo->sysmem = NULL;
521 ret = nouveau_bo_map(bo, NOUVEAU_BO_WR);
522 if (ret)
523 return NULL;
524 nvbo->sysmem = sysmem_tmp;
525
526 memcpy(bo->map, nvbo->sysmem, nvbo->base.size);
527 nouveau_bo_ufree(nvbo);
528 nouveau_bo_unmap(bo);
529 }
530 }
531
532 if (nvpb->nr_buffers >= NOUVEAU_GEM_MAX_BUFFERS)
533 return NULL;
534 pbbo = nvpb->buffers + nvpb->nr_buffers++;
535 nvbo->pending = pbbo;
536 nvbo->pending_channel = chan;
537 nvbo->pending_refcnt = 0;
538
539 nouveau_bo_ref(bo, &ref);
540 pbbo->user_priv = (uint64_t)(unsigned long)ref;
541 pbbo->handle = nvbo->handle;
542 pbbo->valid_domains = NOUVEAU_GEM_DOMAIN_VRAM | NOUVEAU_GEM_DOMAIN_GART;
543 pbbo->read_domains = 0;
544 pbbo->write_domains = 0;
545 pbbo->presumed.domain = nvbo->domain;
546 pbbo->presumed.offset = nvbo->offset;
547 pbbo->presumed.valid = 1;
548 return pbbo;
549}
diff --git a/nouveau/nouveau_bo.h b/nouveau/nouveau_bo.h
deleted file mode 100644
index 3a1f2d4a..00000000
--- a/nouveau/nouveau_bo.h
+++ /dev/null
@@ -1,104 +0,0 @@
1/*
2 * Copyright 2007 Nouveau Project
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
23#ifndef __NOUVEAU_BO_H__
24#define __NOUVEAU_BO_H__
25
26/* Relocation/Buffer type flags */
27#define NOUVEAU_BO_VRAM (1 << 0)
28#define NOUVEAU_BO_GART (1 << 1)
29#define NOUVEAU_BO_RD (1 << 2)
30#define NOUVEAU_BO_WR (1 << 3)
31#define NOUVEAU_BO_RDWR (NOUVEAU_BO_RD | NOUVEAU_BO_WR)
32#define NOUVEAU_BO_MAP (1 << 4)
33#define NOUVEAU_BO_LOW (1 << 6)
34#define NOUVEAU_BO_HIGH (1 << 7)
35#define NOUVEAU_BO_OR (1 << 8)
36#define NOUVEAU_BO_INVAL (1 << 12)
37#define NOUVEAU_BO_NOSYNC (1 << 13)
38#define NOUVEAU_BO_NOWAIT (1 << 14)
39#define NOUVEAU_BO_IFLUSH (1 << 15)
40#define NOUVEAU_BO_DUMMY (1 << 31)
41
42#define NOUVEAU_BO_TILE_LAYOUT_MASK 0x0000ff00
43#define NOUVEAU_BO_TILE_16BPP 0x00000001
44#define NOUVEAU_BO_TILE_32BPP 0x00000002
45#define NOUVEAU_BO_TILE_ZETA 0x00000004
46#define NOUVEAU_BO_TILE_SCANOUT 0x00000008
47
48struct nouveau_bo {
49 struct nouveau_device *device;
50 uint32_t handle;
51
52 uint64_t size;
53 void *map;
54
55 uint32_t tile_mode;
56 uint32_t tile_flags;
57};
58
59int
60nouveau_bo_new(struct nouveau_device *, uint32_t flags, int align, int size,
61 struct nouveau_bo **);
62
63int
64nouveau_bo_new_tile(struct nouveau_device *, uint32_t flags, int align,
65 int size, uint32_t tile_mode, uint32_t tile_flags,
66 struct nouveau_bo **);
67
68int
69nouveau_bo_user(struct nouveau_device *, void *ptr, int size,
70 struct nouveau_bo **);
71
72int
73nouveau_bo_wrap(struct nouveau_device *, uint32_t handle, struct nouveau_bo **);
74
75int
76nouveau_bo_handle_get(struct nouveau_bo *, uint32_t *);
77
78int
79nouveau_bo_handle_ref(struct nouveau_device *, uint32_t handle,
80 struct nouveau_bo **);
81
82int
83nouveau_bo_ref(struct nouveau_bo *, struct nouveau_bo **);
84
85int
86nouveau_bo_map_range(struct nouveau_bo *, uint32_t delta, uint32_t size,
87 uint32_t flags);
88
89void
90nouveau_bo_map_flush(struct nouveau_bo *, uint32_t delta, uint32_t size);
91
92int
93nouveau_bo_map(struct nouveau_bo *, uint32_t flags);
94
95void
96nouveau_bo_unmap(struct nouveau_bo *);
97
98int
99nouveau_bo_busy(struct nouveau_bo *, uint32_t access);
100
101uint32_t
102nouveau_bo_pending(struct nouveau_bo *);
103
104#endif
diff --git a/nouveau/nouveau_channel.c b/nouveau/nouveau_channel.c
deleted file mode 100644
index 96fa03bd..00000000
--- a/nouveau/nouveau_channel.c
+++ /dev/null
@@ -1,142 +0,0 @@
1/*
2 * Copyright 2007 Nouveau Project
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
23#include <stdlib.h>
24#include <string.h>
25#include <errno.h>
26
27#include "nouveau_private.h"
28
29int
30nouveau_channel_alloc(struct nouveau_device *dev, uint32_t fb_ctxdma,
31 uint32_t tt_ctxdma, int pushbuf_size,
32 struct nouveau_channel **chan)
33{
34 struct nouveau_device_priv *nvdev = nouveau_device(dev);
35 struct nouveau_channel_priv *nvchan;
36 unsigned i;
37 int ret;
38
39 if (!nvdev || !chan || *chan)
40 return -EINVAL;
41
42 nvchan = calloc(1, sizeof(struct nouveau_channel_priv));
43 if (!nvchan)
44 return -ENOMEM;
45 nvchan->base.device = dev;
46
47 nvchan->drm.fb_ctxdma_handle = fb_ctxdma;
48 nvchan->drm.tt_ctxdma_handle = tt_ctxdma;
49 ret = drmCommandWriteRead(nvdev->fd, DRM_NOUVEAU_CHANNEL_ALLOC,
50 &nvchan->drm, sizeof(nvchan->drm));
51 if (ret) {
52 free(nvchan);
53 return ret;
54 }
55
56 nvchan->base.id = nvchan->drm.channel;
57 if (nouveau_grobj_ref(&nvchan->base, nvchan->drm.fb_ctxdma_handle,
58 &nvchan->base.vram) ||
59 nouveau_grobj_ref(&nvchan->base, nvchan->drm.tt_ctxdma_handle,
60 &nvchan->base.gart)) {
61 nouveau_channel_free((void *)&nvchan);
62 return -EINVAL;
63 }
64
65 /* Mark all DRM-assigned subchannels as in-use */
66 for (i = 0; i < nvchan->drm.nr_subchan; i++) {
67 struct nouveau_grobj_priv *gr = calloc(1, sizeof(*gr));
68
69 gr->base.bound = NOUVEAU_GROBJ_BOUND_EXPLICIT;
70 gr->base.subc = i;
71 gr->base.handle = nvchan->drm.subchan[i].handle;
72 gr->base.grclass = nvchan->drm.subchan[i].grclass;
73 gr->base.channel = &nvchan->base;
74
75 nvchan->base.subc[i].gr = &gr->base;
76 }
77
78 if (dev->chipset < 0xc0) {
79 ret = nouveau_bo_wrap(dev, nvchan->drm.notifier_handle,
80 &nvchan->notifier_bo);
81 if (!ret)
82 ret = nouveau_bo_map(nvchan->notifier_bo,
83 NOUVEAU_BO_RDWR);
84 if (ret) {
85 nouveau_channel_free((void *)&nvchan);
86 return ret;
87 }
88
89 ret = nouveau_grobj_alloc(&nvchan->base, 0x00000000, 0x0030,
90 &nvchan->base.nullobj);
91 if (ret) {
92 nouveau_channel_free((void *)&nvchan);
93 return ret;
94 }
95 }
96
97 ret = nouveau_pushbuf_init(&nvchan->base, pushbuf_size);
98 if (ret) {
99 nouveau_channel_free((void *)&nvchan);
100 return ret;
101 }
102
103 *chan = &nvchan->base;
104 return 0;
105}
106
107void
108nouveau_channel_free(struct nouveau_channel **chan)
109{
110 struct nouveau_channel_priv *nvchan;
111 struct nouveau_device_priv *nvdev;
112 struct drm_nouveau_channel_free cf;
113 unsigned i;
114
115 if (!chan || !*chan)
116 return;
117 nvchan = nouveau_channel(*chan);
118 (*chan)->flush_notify = NULL;
119 *chan = NULL;
120 nvdev = nouveau_device(nvchan->base.device);
121
122 FIRE_RING(&nvchan->base);
123
124 nouveau_pushbuf_fini(&nvchan->base);
125 if (nvchan->notifier_bo) {
126 nouveau_bo_unmap(nvchan->notifier_bo);
127 nouveau_bo_ref(NULL, &nvchan->notifier_bo);
128 }
129
130 for (i = 0; i < nvchan->drm.nr_subchan; i++)
131 free(nvchan->base.subc[i].gr);
132
133 nouveau_grobj_free(&nvchan->base.vram);
134 nouveau_grobj_free(&nvchan->base.gart);
135 nouveau_grobj_free(&nvchan->base.nullobj);
136
137 cf.channel = nvchan->drm.channel;
138 drmCommandWrite(nvdev->fd, DRM_NOUVEAU_CHANNEL_FREE, &cf, sizeof(cf));
139 free(nvchan);
140}
141
142
diff --git a/nouveau/nouveau_channel.h b/nouveau/nouveau_channel.h
deleted file mode 100644
index d61a4c0d..00000000
--- a/nouveau/nouveau_channel.h
+++ /dev/null
@@ -1,57 +0,0 @@
1/*
2 * Copyright 2007 Nouveau Project
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
23#ifndef __NOUVEAU_CHANNEL_H__
24#define __NOUVEAU_CHANNEL_H__
25
26struct nouveau_subchannel {
27 struct nouveau_grobj *gr;
28 unsigned sequence;
29};
30
31struct nouveau_channel {
32 uint32_t *cur;
33 uint32_t *end;
34
35 struct nouveau_device *device;
36 int id;
37
38 struct nouveau_grobj *nullobj;
39 struct nouveau_grobj *vram;
40 struct nouveau_grobj *gart;
41
42 void *user_private;
43 void (*hang_notify)(struct nouveau_channel *);
44 void (*flush_notify)(struct nouveau_channel *);
45
46 struct nouveau_subchannel subc[8];
47 unsigned subc_sequence;
48};
49
50int
51nouveau_channel_alloc(struct nouveau_device *, uint32_t fb, uint32_t tt,
52 int pushbuf_size, struct nouveau_channel **);
53
54void
55nouveau_channel_free(struct nouveau_channel **);
56
57#endif
diff --git a/nouveau/nouveau_device.c b/nouveau/nouveau_device.c
deleted file mode 100644
index 425c5d29..00000000
--- a/nouveau/nouveau_device.c
+++ /dev/null
@@ -1,198 +0,0 @@
1/*
2 * Copyright 2007 Nouveau Project
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <errno.h>
26
27#include "nouveau_private.h"
28
29int
30nouveau_device_open_existing(struct nouveau_device **dev, int close,
31 int fd, drm_context_t ctx)
32{
33 struct nouveau_device_priv *nvdev;
34 drmVersionPtr ver;
35 uint64_t value;
36 int ret;
37
38 if (!dev || *dev)
39 return -EINVAL;
40
41 nvdev = calloc(1, sizeof(*nvdev));
42 if (!nvdev)
43 return -ENOMEM;
44 nvdev->fd = fd;
45 nvdev->ctx = ctx;
46 nvdev->needs_close = close;
47
48 ver = drmGetVersion(fd);
49 if (!ver) {
50 nouveau_device_close((void *)&nvdev);
51 return -EINVAL;
52 }
53
54 if ((ver->version_major == 0 && ver->version_patchlevel != 16) ||
55 ver->version_major > 1) {
56 nouveau_device_close((void *)&nvdev);
57 return -EINVAL;
58 }
59
60 drmFreeVersion(ver);
61
62 ret = nouveau_device_get_param(&nvdev->base,
63 NOUVEAU_GETPARAM_VM_VRAM_BASE, &value);
64 if (ret) {
65 nouveau_device_close((void *)&nvdev);
66 return ret;
67 }
68 nvdev->base.vm_vram_base = value;
69
70 ret = nouveau_device_get_param(&nvdev->base,
71 NOUVEAU_GETPARAM_FB_SIZE, &value);
72 if (ret) {
73 nouveau_device_close((void *)&nvdev);
74 return ret;
75 }
76 nvdev->base.vm_vram_size = value;
77
78 ret = nouveau_device_get_param(&nvdev->base,
79 NOUVEAU_GETPARAM_AGP_SIZE, &value);
80 if (ret) {
81 nouveau_device_close((void *)&nvdev);
82 return ret;
83 }
84 nvdev->base.vm_gart_size = value;
85
86 ret = nouveau_bo_init(&nvdev->base);
87 if (ret) {
88 nouveau_device_close((void *)&nvdev);
89 return ret;
90 }
91
92 ret = nouveau_device_get_param(&nvdev->base,
93 NOUVEAU_GETPARAM_CHIPSET_ID, &value);
94 if (ret) {
95 nouveau_device_close((void *)&nvdev);
96 return ret;
97 }
98 nvdev->base.chipset = value;
99
100 ret = nouveau_device_get_param(&nvdev->base,
101 NOUVEAU_GETPARAM_HAS_BO_USAGE, &value);
102 if (!ret)
103 nvdev->has_bo_usage = value;
104
105 *dev = &nvdev->base;
106 return 0;
107}
108
109int
110nouveau_device_open(struct nouveau_device **dev, const char *busid)
111{
112 drm_context_t ctx;
113 int fd, ret;
114
115 if (!dev || *dev)
116 return -EINVAL;
117
118 fd = drmOpen("nouveau", busid);
119 if (fd < 0)
120 return -EINVAL;
121
122 ret = drmCreateContext(fd, &ctx);
123 if (ret) {
124 drmClose(fd);
125 return ret;
126 }
127
128 ret = nouveau_device_open_existing(dev, 1, fd, ctx);
129 if (ret) {
130 drmDestroyContext(fd, ctx);
131 drmClose(fd);
132 return ret;
133 }
134
135 return 0;
136}
137
138void
139nouveau_device_close(struct nouveau_device **dev)
140{
141 struct nouveau_device_priv *nvdev;
142
143 if (!dev || !*dev)
144 return;
145 nvdev = nouveau_device(*dev);
146 *dev = NULL;
147
148 nouveau_bo_takedown(&nvdev->base);
149
150 if (nvdev->needs_close) {
151 drmDestroyContext(nvdev->fd, nvdev->ctx);
152 drmClose(nvdev->fd);
153 }
154 free(nvdev);
155}
156
157int
158nouveau_device_get_param(struct nouveau_device *dev,
159 uint64_t param, uint64_t *value)
160{
161 struct nouveau_device_priv *nvdev = nouveau_device(dev);
162 struct drm_nouveau_getparam g;
163 int ret;
164
165 if (!nvdev || !value)
166 return -EINVAL;
167
168 g.param = param;
169 ret = drmCommandWriteRead(nvdev->fd, DRM_NOUVEAU_GETPARAM,
170 &g, sizeof(g));
171 if (ret)
172 return ret;
173
174 *value = g.value;
175 return 0;
176}
177
178int
179nouveau_device_set_param(struct nouveau_device *dev,
180 uint64_t param, uint64_t value)
181{
182 struct nouveau_device_priv *nvdev = nouveau_device(dev);
183 struct drm_nouveau_setparam s;
184 int ret;
185
186 if (!nvdev)
187 return -EINVAL;
188
189 s.param = param;
190 s.value = value;
191 ret = drmCommandWriteRead(nvdev->fd, DRM_NOUVEAU_SETPARAM,
192 &s, sizeof(s));
193 if (ret)
194 return ret;
195
196 return 0;
197}
198
diff --git a/nouveau/nouveau_device.h b/nouveau/nouveau_device.h
deleted file mode 100644
index c0d93335..00000000
--- a/nouveau/nouveau_device.h
+++ /dev/null
@@ -1,33 +0,0 @@
1/*
2 * Copyright 2007 Nouveau Project
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
23#ifndef __NOUVEAU_DEVICE_H__
24#define __NOUVEAU_DEVICE_H__
25
26struct nouveau_device {
27 unsigned chipset;
28 uint64_t vm_vram_base;
29 uint64_t vm_vram_size;
30 uint64_t vm_gart_size;
31};
32
33#endif
diff --git a/nouveau/nouveau_drmif.h b/nouveau/nouveau_drmif.h
deleted file mode 100644
index ec226a22..00000000
--- a/nouveau/nouveau_drmif.h
+++ /dev/null
@@ -1,58 +0,0 @@
1/*
2 * Copyright 2008 Nouveau Project
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
23#ifndef __NOUVEAU_DRMIF_H__
24#define __NOUVEAU_DRMIF_H__
25
26#include <stdint.h>
27#include <xf86drm.h>
28
29#include "nouveau_device.h"
30
31struct nouveau_device_priv {
32 struct nouveau_device base;
33
34 int fd;
35 drm_context_t ctx;
36 drmLock *lock;
37 int needs_close;
38 int has_bo_usage;
39};
40#define nouveau_device(n) ((struct nouveau_device_priv *)(n))
41
42int
43nouveau_device_open_existing(struct nouveau_device **, int close,
44 int fd, drm_context_t ctx);
45
46int
47nouveau_device_open(struct nouveau_device **, const char *busid);
48
49void
50nouveau_device_close(struct nouveau_device **);
51
52int
53nouveau_device_get_param(struct nouveau_device *, uint64_t param, uint64_t *v);
54
55int
56nouveau_device_set_param(struct nouveau_device *, uint64_t param, uint64_t val);
57
58#endif
diff --git a/nouveau/nouveau_grobj.c b/nouveau/nouveau_grobj.c
deleted file mode 100644
index 36344b99..00000000
--- a/nouveau/nouveau_grobj.c
+++ /dev/null
@@ -1,148 +0,0 @@
1/*
2 * Copyright 2007 Nouveau Project
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
23#include <stdlib.h>
24#include <errno.h>
25
26#include "nouveau_private.h"
27
28int
29nouveau_grobj_alloc(struct nouveau_channel *chan, uint32_t handle,
30 int class, struct nouveau_grobj **grobj)
31{
32 struct nouveau_device_priv *nvdev = nouveau_device(chan->device);
33 struct nouveau_grobj_priv *nvgrobj;
34 struct drm_nouveau_grobj_alloc g;
35 int ret;
36
37 if (!nvdev || !grobj || *grobj)
38 return -EINVAL;
39
40 nvgrobj = calloc(1, sizeof(*nvgrobj));
41 if (!nvgrobj)
42 return -ENOMEM;
43 nvgrobj->base.channel = chan;
44 nvgrobj->base.handle = handle;
45 nvgrobj->base.grclass = class;
46 nvgrobj->base.bound = NOUVEAU_GROBJ_UNBOUND;
47 nvgrobj->base.subc = -1;
48
49 g.channel = chan->id;
50 g.handle = handle;
51 g.class = class;
52 ret = drmCommandWrite(nvdev->fd, DRM_NOUVEAU_GROBJ_ALLOC,
53 &g, sizeof(g));
54 if (ret) {
55 nouveau_grobj_free((void *)&nvgrobj);
56 return ret;
57 }
58
59 *grobj = &nvgrobj->base;
60 return 0;
61}
62
63int
64nouveau_grobj_ref(struct nouveau_channel *chan, uint32_t handle,
65 struct nouveau_grobj **grobj)
66{
67 struct nouveau_grobj_priv *nvgrobj;
68
69 if (!chan || !grobj || *grobj)
70 return -EINVAL;
71
72 nvgrobj = calloc(1, sizeof(struct nouveau_grobj_priv));
73 if (!nvgrobj)
74 return -ENOMEM;
75 nvgrobj->base.channel = chan;
76 nvgrobj->base.handle = handle;
77 nvgrobj->base.grclass = 0;
78
79 *grobj = &nvgrobj->base;
80 return 0;
81}
82
83void
84nouveau_grobj_free(struct nouveau_grobj **grobj)
85{
86 struct nouveau_device_priv *nvdev;
87 struct nouveau_channel_priv *chan;
88 struct nouveau_grobj_priv *nvgrobj;
89
90 if (!grobj || !*grobj)
91 return;
92 nvgrobj = nouveau_grobj(*grobj);
93 *grobj = NULL;
94
95
96 chan = nouveau_channel(nvgrobj->base.channel);
97 nvdev = nouveau_device(chan->base.device);
98
99 if (nvgrobj->base.grclass) {
100 struct drm_nouveau_gpuobj_free f;
101
102 FIRE_RING(&chan->base);
103 f.channel = chan->drm.channel;
104 f.handle = nvgrobj->base.handle;
105 drmCommandWrite(nvdev->fd, DRM_NOUVEAU_GPUOBJ_FREE,
106 &f, sizeof(f));
107 }
108 if (nvgrobj->base.bound != NOUVEAU_GROBJ_UNBOUND)
109 chan->base.subc[nvgrobj->base.subc].gr = NULL;
110 free(nvgrobj);
111}
112
113void
114nouveau_grobj_autobind(struct nouveau_grobj *grobj)
115{
116 struct nouveau_channel *chan = grobj->channel;
117 struct nouveau_subchannel *subc = NULL;
118 int i;
119
120 for (i = 0; i < 8; i++) {
121 struct nouveau_subchannel *scc = &grobj->channel->subc[i];
122
123 if (scc->gr && scc->gr->bound == NOUVEAU_GROBJ_BOUND_EXPLICIT)
124 continue;
125
126 if (!subc || scc->sequence < subc->sequence)
127 subc = scc;
128 }
129
130 if (subc->gr) {
131 subc->gr->bound = NOUVEAU_GROBJ_UNBOUND;
132 subc->gr->subc = -1;
133 }
134
135 subc->gr = grobj;
136 subc->gr->bound = NOUVEAU_GROBJ_BOUND;
137 subc->gr->subc = subc - &grobj->channel->subc[0];
138
139 WAIT_RING(chan, 2);
140 if (chan->device->chipset < 0xc0) {
141 OUT_RING (chan, (1 << 18) | (grobj->subc << 13));
142 OUT_RING (chan, grobj->handle);
143 } else {
144 OUT_RING (chan, (2 << 28) | (1 << 16) | (grobj->subc << 13));
145 OUT_RING (chan, grobj->grclass);
146 }
147}
148
diff --git a/nouveau/nouveau_grobj.h b/nouveau/nouveau_grobj.h
deleted file mode 100644
index 51ac7d9b..00000000
--- a/nouveau/nouveau_grobj.h
+++ /dev/null
@@ -1,48 +0,0 @@
1/*
2 * Copyright 2007 Nouveau Project
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
23#ifndef __NOUVEAU_GROBJ_H__
24#define __NOUVEAU_GROBJ_H__
25
26#include "nouveau_channel.h"
27
28struct nouveau_grobj {
29 struct nouveau_channel *channel;
30 int grclass;
31 uint32_t handle;
32
33 enum {
34 NOUVEAU_GROBJ_UNBOUND = 0,
35 NOUVEAU_GROBJ_BOUND = 1,
36 NOUVEAU_GROBJ_BOUND_EXPLICIT = 2
37 } bound;
38 int subc;
39};
40
41int nouveau_grobj_alloc(struct nouveau_channel *, uint32_t handle,
42 int class, struct nouveau_grobj **);
43int nouveau_grobj_ref(struct nouveau_channel *, uint32_t handle,
44 struct nouveau_grobj **);
45void nouveau_grobj_free(struct nouveau_grobj **);
46void nouveau_grobj_autobind(struct nouveau_grobj *);
47
48#endif
diff --git a/nouveau/nouveau_notifier.c b/nouveau/nouveau_notifier.c
deleted file mode 100644
index 513fa635..00000000
--- a/nouveau/nouveau_notifier.c
+++ /dev/null
@@ -1,148 +0,0 @@
1/*
2 * Copyright 2007 Nouveau Project
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
23#include <stdlib.h>
24#include <errno.h>
25#include <sys/time.h>
26
27#include "nouveau_private.h"
28
29#define NOTIFIER(__v) \
30 struct nouveau_notifier_priv *nvnotify = nouveau_notifier(notifier); \
31 volatile uint32_t *__v = (uint32_t *)((char *)nvnotify->map + (id * 32))
32
33int
34nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle,
35 int count, struct nouveau_notifier **notifier)
36{
37 struct nouveau_notifier_priv *nvnotify;
38 int ret;
39
40 if (!chan || !notifier || *notifier)
41 return -EINVAL;
42
43 nvnotify = calloc(1, sizeof(struct nouveau_notifier_priv));
44 if (!nvnotify)
45 return -ENOMEM;
46 nvnotify->base.channel = chan;
47 nvnotify->base.handle = handle;
48
49 nvnotify->drm.channel = chan->id;
50 nvnotify->drm.handle = handle;
51 nvnotify->drm.size = (count * 32);
52 if ((ret = drmCommandWriteRead(nouveau_device(chan->device)->fd,
53 DRM_NOUVEAU_NOTIFIEROBJ_ALLOC,
54 &nvnotify->drm,
55 sizeof(nvnotify->drm)))) {
56 nouveau_notifier_free((void *)&nvnotify);
57 return ret;
58 }
59
60 nvnotify->map = (char *)nouveau_channel(chan)->notifier_bo->map +
61 nvnotify->drm.offset;
62 *notifier = &nvnotify->base;
63 return 0;
64}
65
66void
67nouveau_notifier_free(struct nouveau_notifier **notifier)
68{
69
70 struct nouveau_notifier_priv *nvnotify;
71 struct nouveau_channel_priv *nvchan;
72 struct nouveau_device_priv *nvdev;
73 struct drm_nouveau_gpuobj_free f;
74
75 if (!notifier || !*notifier)
76 return;
77 nvnotify = nouveau_notifier(*notifier);
78 *notifier = NULL;
79
80 nvchan = nouveau_channel(nvnotify->base.channel);
81 nvdev = nouveau_device(nvchan->base.device);
82
83 FIRE_RING(&nvchan->base);
84
85 f.channel = nvchan->drm.channel;
86 f.handle = nvnotify->base.handle;
87 drmCommandWrite(nvdev->fd, DRM_NOUVEAU_GPUOBJ_FREE, &f, sizeof(f));
88 free(nvnotify);
89}
90
91void
92nouveau_notifier_reset(struct nouveau_notifier *notifier, int id)
93{
94 NOTIFIER(n);
95
96 n[NV_NOTIFY_TIME_0 /4] = 0x00000000;
97 n[NV_NOTIFY_TIME_1 /4] = 0x00000000;
98 n[NV_NOTIFY_RETURN_VALUE/4] = 0x00000000;
99 n[NV_NOTIFY_STATE /4] = (NV_NOTIFY_STATE_STATUS_IN_PROCESS <<
100 NV_NOTIFY_STATE_STATUS_SHIFT);
101}
102
103uint32_t
104nouveau_notifier_status(struct nouveau_notifier *notifier, int id)
105{
106 NOTIFIER(n);
107
108 return n[NV_NOTIFY_STATE/4] >> NV_NOTIFY_STATE_STATUS_SHIFT;
109}
110
111uint32_t
112nouveau_notifier_return_val(struct nouveau_notifier *notifier, int id)
113{
114 NOTIFIER(n);
115
116 return n[NV_NOTIFY_RETURN_VALUE/4];
117}
118
119static inline double
120gettime(void)
121{
122 struct timeval tv;
123
124 gettimeofday(&tv, NULL);
125 return (double)tv.tv_sec + tv.tv_usec / 1000000.0;
126}
127
128int
129nouveau_notifier_wait_status(struct nouveau_notifier *notifier, int id,
130 uint32_t status, double timeout)
131{
132 NOTIFIER(n);
133 double time = 0, t_start = gettime();
134
135 while (time <= timeout) {
136 uint32_t v;
137
138 v = n[NV_NOTIFY_STATE/4] >> NV_NOTIFY_STATE_STATUS_SHIFT;
139 if (v == status)
140 return 0;
141
142 if (timeout)
143 time = gettime() - t_start;
144 }
145
146 return -EBUSY;
147}
148
diff --git a/nouveau/nouveau_notifier.h b/nouveau/nouveau_notifier.h
deleted file mode 100644
index dbc6a3b8..00000000
--- a/nouveau/nouveau_notifier.h
+++ /dev/null
@@ -1,63 +0,0 @@
1/*
2 * Copyright 2007 Nouveau Project
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
23#ifndef __NOUVEAU_NOTIFIER_H__
24#define __NOUVEAU_NOTIFIER_H__
25
26#define NV_NOTIFIER_SIZE 32
27#define NV_NOTIFY_TIME_0 0x00000000
28#define NV_NOTIFY_TIME_1 0x00000004
29#define NV_NOTIFY_RETURN_VALUE 0x00000008
30#define NV_NOTIFY_STATE 0x0000000C
31#define NV_NOTIFY_STATE_STATUS_MASK 0xFF000000
32#define NV_NOTIFY_STATE_STATUS_SHIFT 24
33#define NV_NOTIFY_STATE_STATUS_COMPLETED 0x00
34#define NV_NOTIFY_STATE_STATUS_IN_PROCESS 0x01
35#define NV_NOTIFY_STATE_ERROR_CODE_MASK 0x0000FFFF
36#define NV_NOTIFY_STATE_ERROR_CODE_SHIFT 0
37
38struct nouveau_notifier {
39 struct nouveau_channel *channel;
40 uint32_t handle;
41};
42
43int
44nouveau_notifier_alloc(struct nouveau_channel *, uint32_t handle, int count,
45 struct nouveau_notifier **);
46
47void
48nouveau_notifier_free(struct nouveau_notifier **);
49
50void
51nouveau_notifier_reset(struct nouveau_notifier *, int id);
52
53uint32_t
54nouveau_notifier_status(struct nouveau_notifier *, int id);
55
56uint32_t
57nouveau_notifier_return_val(struct nouveau_notifier *, int id);
58
59int
60nouveau_notifier_wait_status(struct nouveau_notifier *, int id, uint32_t status,
61 double timeout);
62
63#endif
diff --git a/nouveau/nouveau_private.h b/nouveau/nouveau_private.h
deleted file mode 100644
index 124fe870..00000000
--- a/nouveau/nouveau_private.h
+++ /dev/null
@@ -1,136 +0,0 @@
1/*
2 * Copyright 2007 Nouveau Project
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
23#ifndef __NOUVEAU_PRIVATE_H__
24#define __NOUVEAU_PRIVATE_H__
25
26#include <stdint.h>
27#include <xf86drm.h>
28#include <nouveau_drm.h>
29
30#include "nouveau_drmif.h"
31#include "nouveau_device.h"
32#include "nouveau_channel.h"
33#include "nouveau_grobj.h"
34#include "nouveau_notifier.h"
35#include "nouveau_bo.h"
36#include "nouveau_resource.h"
37#include "nouveau_pushbuf.h"
38#include "nouveau_reloc.h"
39
40#define CALPB_BUFFERS 3
41
42struct nouveau_pushbuf_priv {
43 uint32_t cal_suffix0;
44 uint32_t cal_suffix1;
45 struct nouveau_bo *buffer[CALPB_BUFFERS];
46 int current;
47 int current_offset;
48
49 unsigned *pushbuf;
50 unsigned size;
51
52 uint32_t *marker;
53 unsigned marker_offset;
54 unsigned marker_relocs;
55 unsigned marker_push;
56
57 struct drm_nouveau_gem_pushbuf_bo *buffers;
58 unsigned nr_buffers;
59 struct drm_nouveau_gem_pushbuf_reloc *relocs;
60 unsigned nr_relocs;
61 struct drm_nouveau_gem_pushbuf_push push[NOUVEAU_GEM_MAX_PUSH];
62 unsigned nr_push;
63};
64#define nouveau_pushbuf(n) ((struct nouveau_pushbuf_priv *)(n))
65
66int
67nouveau_pushbuf_init(struct nouveau_channel *, int buf_size);
68void
69nouveau_pushbuf_fini(struct nouveau_channel *);
70
71struct nouveau_channel_priv {
72 struct nouveau_channel base;
73
74 struct drm_nouveau_channel_alloc drm;
75
76 struct nouveau_bo *notifier_bo;
77
78 struct nouveau_pushbuf_priv pb;
79};
80#define nouveau_channel(n) ((struct nouveau_channel_priv *)(n))
81
82struct nouveau_grobj_priv {
83 struct nouveau_grobj base;
84};
85#define nouveau_grobj(n) ((struct nouveau_grobj_priv *)(n))
86
87struct nouveau_notifier_priv {
88 struct nouveau_notifier base;
89
90 struct drm_nouveau_notifierobj_alloc drm;
91 volatile void *map;
92};
93#define nouveau_notifier(n) ((struct nouveau_notifier_priv *)(n))
94
95struct nouveau_bo_priv {
96 struct nouveau_bo base;
97 int refcount;
98
99 /* Buffer configuration + usage hints */
100 unsigned flags;
101 unsigned size;
102 unsigned align;
103 int user;
104
105 /* Tracking */
106 struct drm_nouveau_gem_pushbuf_bo *pending;
107 struct nouveau_channel *pending_channel;
108 int pending_refcnt;
109 int write_marker;
110
111 /* Userspace object */
112 void *sysmem;
113
114 /* Kernel object */
115 uint32_t global_handle;
116 drm_handle_t handle;
117 uint64_t map_handle;
118 int map_refcnt;
119 void *map;
120
121 /* Last known information from kernel on buffer status */
122 uint64_t offset;
123 uint32_t domain;
124};
125#define nouveau_bo(n) ((struct nouveau_bo_priv *)(n))
126
127int
128nouveau_bo_init(struct nouveau_device *);
129
130void
131nouveau_bo_takedown(struct nouveau_device *);
132
133struct drm_nouveau_gem_pushbuf_bo *
134nouveau_bo_emit_buffer(struct nouveau_channel *, struct nouveau_bo *);
135
136#endif
diff --git a/nouveau/nouveau_pushbuf.c b/nouveau/nouveau_pushbuf.c
deleted file mode 100644
index 59f60d9f..00000000
--- a/nouveau/nouveau_pushbuf.c
+++ /dev/null
@@ -1,344 +0,0 @@
1/*
2 * Copyright 2007 Nouveau Project
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <errno.h>
26#include <assert.h>
27
28#include "nouveau_private.h"
29
30#define PB_BUFMGR_DWORDS (4096 / 2)
31#define PB_MIN_USER_DWORDS 2048
32
33static int
34nouveau_pushbuf_space(struct nouveau_channel *chan, unsigned min)
35{
36 struct nouveau_channel_priv *nvchan = nouveau_channel(chan);
37 struct nouveau_pushbuf_priv *nvpb = &nvchan->pb;
38 struct nouveau_bo *bo;
39 int ret;
40
41 if (min < PB_MIN_USER_DWORDS)
42 min = PB_MIN_USER_DWORDS;
43
44 nvpb->current_offset = chan->cur - nvpb->pushbuf;
45 if (chan->cur + min + 2 <= chan->end)
46 return 0;
47
48 nvpb->current++;
49 if (nvpb->current == CALPB_BUFFERS)
50 nvpb->current = 0;
51 bo = nvpb->buffer[nvpb->current];
52
53 ret = nouveau_bo_map(bo, NOUVEAU_BO_WR);
54 if (ret)
55 return ret;
56
57 nvpb->size = (bo->size - 8) / 4;
58 nvpb->pushbuf = bo->map;
59 nvpb->current_offset = 0;
60
61 chan->cur = nvpb->pushbuf;
62 chan->end = nvpb->pushbuf + nvpb->size;
63
64 nouveau_bo_unmap(bo);
65 return 0;
66}
67
68static void
69nouveau_pushbuf_fini_call(struct nouveau_channel *chan)
70{
71 struct nouveau_channel_priv *nvchan = nouveau_channel(chan);
72 struct nouveau_pushbuf_priv *nvpb = &nvchan->pb;
73 int i;
74
75 for (i = 0; i < CALPB_BUFFERS; i++)
76 nouveau_bo_ref(NULL, &nvpb->buffer[i]);
77 nvpb->pushbuf = NULL;
78}
79
80static int
81nouveau_pushbuf_init_call(struct nouveau_channel *chan, int buf_size)
82{
83 struct drm_nouveau_gem_pushbuf req;
84 struct nouveau_channel_priv *nvchan = nouveau_channel(chan);
85 struct nouveau_pushbuf_priv *nvpb = &nvchan->pb;
86 struct nouveau_device *dev = chan->device;
87 uint32_t flags = 0;
88 int i, ret;
89
90 if (nvchan->drm.pushbuf_domains & NOUVEAU_GEM_DOMAIN_GART)
91 flags |= NOUVEAU_BO_GART;
92 else
93 flags |= NOUVEAU_BO_VRAM;
94
95 req.channel = chan->id;
96 req.nr_push = 0;
97 ret = drmCommandWriteRead(nouveau_device(dev)->fd,
98 DRM_NOUVEAU_GEM_PUSHBUF, &req, sizeof(req));
99 if (ret)
100 return ret;
101
102 for (i = 0; i < CALPB_BUFFERS; i++) {
103 ret = nouveau_bo_new(dev, flags | NOUVEAU_BO_MAP,
104 0, buf_size, &nvpb->buffer[i]);
105 if (ret) {
106 nouveau_pushbuf_fini_call(chan);
107 return ret;
108 }
109 }
110
111 nvpb->cal_suffix0 = req.suffix0;
112 nvpb->cal_suffix1 = req.suffix1;
113 return 0;
114}
115
116int
117nouveau_pushbuf_init(struct nouveau_channel *chan, int buf_size)
118{
119 struct nouveau_channel_priv *nvchan = nouveau_channel(chan);
120 struct nouveau_pushbuf_priv *nvpb = &nvchan->pb;
121 int ret;
122
123 ret = nouveau_pushbuf_init_call(chan, buf_size);
124 if (ret)
125 return ret;
126
127 ret = nouveau_pushbuf_space(chan, 0);
128 if (ret)
129 return ret;
130
131 nvpb->buffers = calloc(NOUVEAU_GEM_MAX_BUFFERS,
132 sizeof(struct drm_nouveau_gem_pushbuf_bo));
133 nvpb->relocs = calloc(NOUVEAU_GEM_MAX_RELOCS,
134 sizeof(struct drm_nouveau_gem_pushbuf_reloc));
135 return 0;
136}
137
138void
139nouveau_pushbuf_fini(struct nouveau_channel *chan)
140{
141 struct nouveau_channel_priv *nvchan = nouveau_channel(chan);
142 struct nouveau_pushbuf_priv *nvpb = &nvchan->pb;
143 nouveau_pushbuf_fini_call(chan);
144 free(nvpb->buffers);
145 free(nvpb->relocs);
146}
147
148static int
149nouveau_pushbuf_bo_add(struct nouveau_channel *chan, struct nouveau_bo *bo,
150 unsigned offset, unsigned length)
151{
152 struct nouveau_channel_priv *nvchan = nouveau_channel(chan);
153 struct nouveau_pushbuf_priv *nvpb = &nvchan->pb;
154 struct drm_nouveau_gem_pushbuf_push *p = &nvpb->push[nvpb->nr_push++];
155 struct drm_nouveau_gem_pushbuf_bo *pbbo;
156 struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
157
158 pbbo = nouveau_bo_emit_buffer(chan, bo);
159 if (!pbbo)
160 return -ENOMEM;
161 pbbo->valid_domains &= nvchan->drm.pushbuf_domains;
162 pbbo->read_domains |= nvchan->drm.pushbuf_domains;
163 nvbo->pending_refcnt++;
164
165 p->bo_index = pbbo - nvpb->buffers;
166 p->offset = offset;
167 p->length = length;
168 return 0;
169}
170
171int
172nouveau_pushbuf_submit(struct nouveau_channel *chan, struct nouveau_bo *bo,
173 unsigned offset, unsigned length)
174{
175 struct nouveau_pushbuf_priv *nvpb = &nouveau_channel(chan)->pb;
176 int ret, len;
177
178 if ((AVAIL_RING(chan) + nvpb->current_offset) != nvpb->size) {
179 if (nvpb->cal_suffix0 || nvpb->cal_suffix1) {
180 *(chan->cur++) = nvpb->cal_suffix0;
181 *(chan->cur++) = nvpb->cal_suffix1;
182 }
183
184 len = (chan->cur - nvpb->pushbuf) - nvpb->current_offset;
185
186 ret = nouveau_pushbuf_bo_add(chan, nvpb->buffer[nvpb->current],
187 nvpb->current_offset * 4, len * 4);
188 if (ret)
189 return ret;
190
191 nvpb->current_offset += len;
192 }
193
194 return bo ? nouveau_pushbuf_bo_add(chan, bo, offset, length) : 0;
195}
196
197static void
198nouveau_pushbuf_bo_unref(struct nouveau_pushbuf_priv *nvpb, int index)
199{
200 struct drm_nouveau_gem_pushbuf_bo *pbbo = &nvpb->buffers[index];
201 struct nouveau_bo *bo = (void *)(unsigned long)pbbo->user_priv;
202 struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
203
204 if (--nvbo->pending_refcnt)
205 return;
206
207 if (pbbo->presumed.valid == 0) {
208 nvbo->domain = pbbo->presumed.domain;
209 nvbo->offset = pbbo->presumed.offset;
210 }
211
212 nvbo->pending = NULL;
213 nouveau_bo_ref(NULL, &bo);
214
215 /* we only ever remove from the tail of the pending lists,
216 * so this is safe.
217 */
218 nvpb->nr_buffers--;
219}
220
221int
222nouveau_pushbuf_flush(struct nouveau_channel *chan, unsigned min)
223{
224 struct nouveau_device_priv *nvdev = nouveau_device(chan->device);
225 struct nouveau_channel_priv *nvchan = nouveau_channel(chan);
226 struct nouveau_pushbuf_priv *nvpb = &nvchan->pb;
227 struct drm_nouveau_gem_pushbuf req;
228 unsigned i;
229 int ret;
230
231 ret = nouveau_pushbuf_submit(chan, NULL, 0, 0);
232 if (ret)
233 return ret;
234
235 if (!nvpb->nr_push)
236 return 0;
237
238 req.channel = chan->id;
239 req.nr_push = nvpb->nr_push;
240 req.push = (uint64_t)(unsigned long)nvpb->push;
241 req.nr_buffers = nvpb->nr_buffers;
242 req.buffers = (uint64_t)(unsigned long)nvpb->buffers;
243 req.nr_relocs = nvpb->nr_relocs;
244 req.relocs = (uint64_t)(unsigned long)nvpb->relocs;
245 req.suffix0 = nvpb->cal_suffix0;
246 req.suffix1 = nvpb->cal_suffix1;
247
248 do {
249 ret = drmCommandWriteRead(nvdev->fd, DRM_NOUVEAU_GEM_PUSHBUF,
250 &req, sizeof(req));
251 } while (ret == -EAGAIN);
252 nvpb->cal_suffix0 = req.suffix0;
253 nvpb->cal_suffix1 = req.suffix1;
254 nvdev->base.vm_vram_size = req.vram_available;
255 nvdev->base.vm_gart_size = req.gart_available;
256
257 /* Update presumed offset/domain for any buffers that moved.
258 * Dereference all buffers on validate list
259 */
260 for (i = 0; i < nvpb->nr_relocs; i++) {
261 nouveau_pushbuf_bo_unref(nvpb, nvpb->relocs[i].bo_index);
262 nouveau_pushbuf_bo_unref(nvpb, nvpb->relocs[i].reloc_bo_index);
263 }
264
265 for (i = 0; i < nvpb->nr_push; i++)
266 nouveau_pushbuf_bo_unref(nvpb, nvpb->push[i].bo_index);
267
268 nvpb->nr_buffers = 0;
269 nvpb->nr_relocs = 0;
270 nvpb->nr_push = 0;
271
272 /* Allocate space for next push buffer */
273 if (nouveau_pushbuf_space(chan, min))
274 assert(0);
275
276 if (chan->flush_notify)
277 chan->flush_notify(chan);
278
279 nvpb->marker = NULL;
280 return ret;
281}
282
283int
284nouveau_pushbuf_marker_emit(struct nouveau_channel *chan,
285 unsigned wait_dwords, unsigned wait_relocs)
286{
287 struct nouveau_pushbuf_priv *nvpb = &nouveau_channel(chan)->pb;
288
289 if (AVAIL_RING(chan) < wait_dwords)
290 return nouveau_pushbuf_flush(chan, wait_dwords);
291
292 if (nvpb->nr_relocs + wait_relocs >= NOUVEAU_GEM_MAX_RELOCS)
293 return nouveau_pushbuf_flush(chan, wait_dwords);
294
295 nvpb->marker = chan->cur;
296 nvpb->marker_offset = nvpb->current_offset;
297 nvpb->marker_push = nvpb->nr_push;
298 nvpb->marker_relocs = nvpb->nr_relocs;
299 return 0;
300}
301
302void
303nouveau_pushbuf_marker_undo(struct nouveau_channel *chan)
304{
305 struct nouveau_pushbuf_priv *nvpb = &nouveau_channel(chan)->pb;
306 unsigned i;
307
308 if (!nvpb->marker)
309 return;
310
311 /* undo any relocs/buffers added to the list since last marker */
312 for (i = nvpb->marker_relocs; i < nvpb->nr_relocs; i++) {
313 nouveau_pushbuf_bo_unref(nvpb, nvpb->relocs[i].bo_index);
314 nouveau_pushbuf_bo_unref(nvpb, nvpb->relocs[i].reloc_bo_index);
315 }
316 nvpb->nr_relocs = nvpb->marker_relocs;
317
318 for (i = nvpb->marker_push; i < nvpb->nr_push; i++)
319 nouveau_pushbuf_bo_unref(nvpb, nvpb->push[i].bo_index);
320 nvpb->nr_push = nvpb->marker_push;
321
322 /* reset pushbuf back to last marker */
323 chan->cur = nvpb->marker;
324 nvpb->current_offset = nvpb->marker_offset;
325 nvpb->marker = NULL;
326}
327
328int
329nouveau_pushbuf_emit_reloc(struct nouveau_channel *chan, void *ptr,
330 struct nouveau_bo *bo, uint32_t data, uint32_t data2,
331 uint32_t flags, uint32_t vor, uint32_t tor)
332{
333 struct nouveau_pushbuf_priv *nvpb = &nouveau_channel(chan)->pb;
334 int ret;
335
336 ret = nouveau_reloc_emit(chan, nvpb->buffer[nvpb->current],
337 (char *)ptr - (char *)nvpb->pushbuf, ptr,
338 bo, data, data2, flags, vor, tor);
339 if (ret)
340 return ret;
341
342 return 0;
343}
344
diff --git a/nouveau/nouveau_pushbuf.h b/nouveau/nouveau_pushbuf.h
deleted file mode 100644
index 2a98789c..00000000
--- a/nouveau/nouveau_pushbuf.h
+++ /dev/null
@@ -1,162 +0,0 @@
1/*
2 * Copyright 2007 Nouveau Project
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
23#ifndef __NOUVEAU_PUSHBUF_H__
24#define __NOUVEAU_PUSHBUF_H__
25
26#include <assert.h>
27#include <string.h>
28
29#include "nouveau_bo.h"
30#include "nouveau_grobj.h"
31
32int
33nouveau_pushbuf_flush(struct nouveau_channel *, unsigned min);
34
35int
36nouveau_pushbuf_marker_emit(struct nouveau_channel *chan,
37 unsigned wait_dwords, unsigned wait_relocs);
38
39void
40nouveau_pushbuf_marker_undo(struct nouveau_channel *chan);
41
42int
43nouveau_pushbuf_emit_reloc(struct nouveau_channel *, void *ptr,
44 struct nouveau_bo *, uint32_t data, uint32_t data2,
45 uint32_t flags, uint32_t vor, uint32_t tor);
46
47int
48nouveau_pushbuf_submit(struct nouveau_channel *chan, struct nouveau_bo *bo,
49 unsigned offset, unsigned length);
50
51/* Push buffer access macros */
52static __inline__ int
53MARK_RING(struct nouveau_channel *chan, unsigned dwords, unsigned relocs)
54{
55 return nouveau_pushbuf_marker_emit(chan, dwords, relocs);
56}
57
58static __inline__ void
59MARK_UNDO(struct nouveau_channel *chan)
60{
61 nouveau_pushbuf_marker_undo(chan);
62}
63
64static __inline__ void
65OUT_RING(struct nouveau_channel *chan, unsigned data)
66{
67 *(chan->cur++) = (data);
68}
69
70static __inline__ void
71OUT_RINGp(struct nouveau_channel *chan, const void *data, unsigned size)
72{
73 memcpy(chan->cur, data, size * 4);
74 chan->cur += size;
75}
76
77static __inline__ void
78OUT_RINGf(struct nouveau_channel *chan, float f)
79{
80 union { uint32_t i; float f; } c;
81 c.f = f;
82 OUT_RING(chan, c.i);
83}
84
85static __inline__ unsigned
86AVAIL_RING(struct nouveau_channel *chan)
87{
88 return chan->end - chan->cur;
89}
90
91static __inline__ void
92WAIT_RING(struct nouveau_channel *chan, unsigned size)
93{
94 if (chan->cur + size > chan->end)
95 nouveau_pushbuf_flush(chan, size);
96}
97
98static __inline__ void
99FIRE_RING(struct nouveau_channel *chan)
100{
101 nouveau_pushbuf_flush(chan, 0);
102}
103
104static __inline__ int
105OUT_RELOC(struct nouveau_channel *chan, struct nouveau_bo *bo,
106 unsigned data, unsigned flags, unsigned vor, unsigned tor)
107{
108 return nouveau_pushbuf_emit_reloc(chan, chan->cur++, bo,
109 data, 0, flags, vor, tor);
110}
111
112static __inline__ int
113OUT_RELOC2(struct nouveau_channel *chan, struct nouveau_bo *bo,
114 unsigned data, unsigned data2, unsigned flags,
115 unsigned vor, unsigned tor)
116{
117 return nouveau_pushbuf_emit_reloc(chan, chan->cur++, bo,
118 data, data2, flags, vor, tor);
119}
120
121/* Raw data + flags depending on FB/TT buffer */
122static __inline__ int
123OUT_RELOCd(struct nouveau_channel *chan, struct nouveau_bo *bo,
124 unsigned data, unsigned flags, unsigned vor, unsigned tor)
125{
126 return OUT_RELOC(chan, bo, data, flags | NOUVEAU_BO_OR, vor, tor);
127}
128
129/* FB/TT object handle */
130static __inline__ int
131OUT_RELOCo(struct nouveau_channel *chan, struct nouveau_bo *bo,
132 unsigned flags)
133{
134 return OUT_RELOC(chan, bo, 0, flags | NOUVEAU_BO_OR,
135 chan->vram->handle, chan->gart->handle);
136}
137
138/* Low 32-bits of offset */
139static __inline__ int
140OUT_RELOCl(struct nouveau_channel *chan, struct nouveau_bo *bo,
141 unsigned delta, unsigned flags)
142{
143 return OUT_RELOC(chan, bo, delta, flags | NOUVEAU_BO_LOW, 0, 0);
144}
145
146/* Low 32-bits of offset + GPU linear access range info */
147static __inline__ int
148OUT_RELOCr(struct nouveau_channel *chan, struct nouveau_bo *bo,
149 unsigned delta, unsigned size, unsigned flags)
150{
151 return OUT_RELOC2(chan, bo, delta, size, flags | NOUVEAU_BO_LOW, 0, 0);
152}
153
154/* High 32-bits of offset */
155static __inline__ int
156OUT_RELOCh(struct nouveau_channel *chan, struct nouveau_bo *bo,
157 unsigned delta, unsigned flags)
158{
159 return OUT_RELOC(chan, bo, delta, flags | NOUVEAU_BO_HIGH, 0, 0);
160}
161
162#endif
diff --git a/nouveau/nouveau_reloc.c b/nouveau/nouveau_reloc.c
deleted file mode 100644
index cd219db4..00000000
--- a/nouveau/nouveau_reloc.c
+++ /dev/null
@@ -1,154 +0,0 @@
1/*
2 * Copyright 2010 Nouveau Project
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <errno.h>
26#include <assert.h>
27
28#include "nouveau_private.h"
29
30static uint32_t
31nouveau_reloc_calc(struct drm_nouveau_gem_pushbuf_bo *pbbo,
32 struct drm_nouveau_gem_pushbuf_reloc *r)
33{
34 uint32_t push = 0;
35
36 if (r->flags & NOUVEAU_GEM_RELOC_LOW)
37 push = (pbbo->presumed.offset + r->data);
38 else
39 if (r->flags & NOUVEAU_GEM_RELOC_HIGH)
40 push = (pbbo->presumed.offset + r->data) >> 32;
41 else
42 push = r->data;
43
44 if (r->flags & NOUVEAU_GEM_RELOC_OR) {
45 if (pbbo->presumed.domain & NOUVEAU_GEM_DOMAIN_VRAM)
46 push |= r->vor;
47 else
48 push |= r->tor;
49 }
50
51 return push;
52}
53
54int
55nouveau_reloc_emit(struct nouveau_channel *chan, struct nouveau_bo *reloc_bo,
56 uint32_t reloc_offset, uint32_t *reloc_ptr,
57 struct nouveau_bo *bo, uint32_t data, uint32_t data2,
58 uint32_t flags, uint32_t vor, uint32_t tor)
59{
60 struct nouveau_pushbuf_priv *nvpb = &nouveau_channel(chan)->pb;
61 struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
62 struct drm_nouveau_gem_pushbuf_reloc *r;
63 struct drm_nouveau_gem_pushbuf_bo *pbbo, *rpbbo;
64 uint32_t domains = 0;
65
66 if (nvpb->nr_relocs >= NOUVEAU_GEM_MAX_RELOCS) {
67 fprintf(stderr, "too many relocs!!\n");
68 return -ENOMEM;
69 }
70
71 if (nvbo->user && (flags & NOUVEAU_BO_WR)) {
72 fprintf(stderr, "write to user buffer!!\n");
73 return -EINVAL;
74 }
75
76 /* We're about to reloc a user buffer, better make sure we don't cause
77 * a double migration.
78 */
79 if (!(nvbo->flags & (NOUVEAU_BO_GART | NOUVEAU_BO_VRAM)))
80 nvbo->flags |= (flags & (NOUVEAU_BO_GART | NOUVEAU_BO_VRAM));
81
82 /* add buffer to validation list */
83 pbbo = nouveau_bo_emit_buffer(chan, bo);
84 if (!pbbo) {
85 fprintf(stderr, "buffer emit fail :(\n");
86 return -ENOMEM;
87 }
88 nouveau_bo(bo)->pending_refcnt++;
89
90 if (flags & (NOUVEAU_BO_VRAM | NOUVEAU_BO_GART)) {
91 if (flags & NOUVEAU_BO_VRAM)
92 domains |= NOUVEAU_GEM_DOMAIN_VRAM;
93 if (flags & NOUVEAU_BO_GART)
94 domains |= NOUVEAU_GEM_DOMAIN_GART;
95 } else
96 domains |= nvbo->domain;
97
98 if (!(pbbo->valid_domains & domains)) {
99 fprintf(stderr, "no valid domains remain!\n");
100 return -EINVAL;
101 }
102 pbbo->valid_domains &= domains;
103
104 assert(flags & NOUVEAU_BO_RDWR);
105 if (flags & NOUVEAU_BO_RD) {
106 pbbo->read_domains |= domains;
107 }
108 if (flags & NOUVEAU_BO_WR) {
109 pbbo->write_domains |= domains;
110 nvbo->write_marker = 1;
111 }
112
113 /* nvc0 gallium driver uses reloc_emit() with NULL target buffer
114 * to inform bufmgr of a buffer's use - however, we need something
115 * to track, so create a reloc for now, and hope it never triggers
116 * (it shouldn't, constant virtual address..)..
117 */
118 if (!reloc_bo) {
119 reloc_bo = nvpb->buffer[nvpb->current];
120 reloc_offset = 0;
121 reloc_ptr = NULL;
122 }
123
124 /* add reloc target bo to validation list, and create the reloc */
125 rpbbo = nouveau_bo_emit_buffer(chan, reloc_bo);
126 if (!rpbbo)
127 return -ENOMEM;
128 nouveau_bo(reloc_bo)->pending_refcnt++;
129
130 r = nvpb->relocs + nvpb->nr_relocs++;
131 r->reloc_bo_index = rpbbo - nvpb->buffers;
132 r->reloc_bo_offset = reloc_offset;
133 r->bo_index = pbbo - nvpb->buffers;
134 r->flags = 0;
135 if (flags & NOUVEAU_BO_LOW)
136 r->flags |= NOUVEAU_GEM_RELOC_LOW;
137 if (flags & NOUVEAU_BO_HIGH)
138 r->flags |= NOUVEAU_GEM_RELOC_HIGH;
139 if (flags & NOUVEAU_BO_OR)
140 r->flags |= NOUVEAU_GEM_RELOC_OR;
141 r->data = data;
142 r->vor = vor;
143 r->tor = tor;
144
145 if (reloc_ptr) {
146 if (flags & NOUVEAU_BO_DUMMY)
147 *reloc_ptr = 0;
148 else
149 *reloc_ptr = nouveau_reloc_calc(pbbo, r);
150 }
151
152 return 0;
153}
154
diff --git a/nouveau/nouveau_reloc.h b/nouveau/nouveau_reloc.h
deleted file mode 100644
index 24ddb52e..00000000
--- a/nouveau/nouveau_reloc.h
+++ /dev/null
@@ -1,32 +0,0 @@
1/*
2 * Copyright 2010 Nouveau Project
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
23#ifndef __NOUVEAU_RELOC_H__
24#define __NOUVEAU_RELOC_H__
25
26int
27nouveau_reloc_emit(struct nouveau_channel *chan, struct nouveau_bo *reloc_bo,
28 uint32_t reloc_offset, uint32_t *reloc_ptr,
29 struct nouveau_bo *bo, uint32_t data, uint32_t data2,
30 uint32_t flags, uint32_t vor, uint32_t tor);
31
32#endif
diff --git a/nouveau/nouveau_resource.c b/nouveau/nouveau_resource.c
deleted file mode 100644
index 7acaf7db..00000000
--- a/nouveau/nouveau_resource.c
+++ /dev/null
@@ -1,124 +0,0 @@
1/*
2 * Copyright 2007 Nouveau Project
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
23#include <stdlib.h>
24#include <errno.h>
25
26#include "nouveau_private.h"
27
28int
29nouveau_resource_init(struct nouveau_resource **heap,
30 unsigned start, unsigned size)
31{
32 struct nouveau_resource *r;
33
34 r = calloc(1, sizeof(struct nouveau_resource));
35 if (!r)
36 return 1;
37
38 r->start = start;
39 r->size = size;
40 *heap = r;
41 return 0;
42}
43
44void
45nouveau_resource_destroy(struct nouveau_resource **heap)
46{
47 if (!*heap)
48 return;
49 free(*heap);
50 *heap = NULL;
51}
52
53int
54nouveau_resource_alloc(struct nouveau_resource *heap, unsigned size, void *priv,
55 struct nouveau_resource **res)
56{
57 struct nouveau_resource *r;
58
59 if (!heap || !size || !res || *res)
60 return 1;
61
62 while (heap) {
63 if (!heap->in_use && heap->size >= size) {
64 r = calloc(1, sizeof(struct nouveau_resource));
65 if (!r)
66 return 1;
67
68 r->start = (heap->start + heap->size) - size;
69 r->size = size;
70 r->in_use = 1;
71 r->priv = priv;
72
73 heap->size -= size;
74
75 r->next = heap->next;
76 if (heap->next)
77 heap->next->prev = r;
78 r->prev = heap;
79 heap->next = r;
80
81 *res = r;
82 return 0;
83 }
84
85 heap = heap->next;
86 }
87
88 return 1;
89}
90
91void
92nouveau_resource_free(struct nouveau_resource **res)
93{
94 struct nouveau_resource *r;
95
96 if (!res || !*res)
97 return;
98 r = *res;
99 *res = NULL;
100
101 r->in_use = 0;
102
103 if (r->next && !r->next->in_use) {
104 struct nouveau_resource *new = r->next;
105
106 new->prev = r->prev;
107 if (r->prev)
108 r->prev->next = new;
109 new->size += r->size;
110 new->start = r->start;
111
112 free(r);
113 r = new;
114 }
115
116 if (r->prev && !r->prev->in_use) {
117 r->prev->next = r->next;
118 if (r->next)
119 r->next->prev = r->prev;
120 r->prev->size += r->size;
121 free(r);
122 }
123
124}
diff --git a/nouveau/nouveau_resource.h b/nouveau/nouveau_resource.h
deleted file mode 100644
index b760dfbb..00000000
--- a/nouveau/nouveau_resource.h
+++ /dev/null
@@ -1,51 +0,0 @@
1/*
2 * Copyright 2007 Nouveau Project
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
23#ifndef __NOUVEAU_RESOURCE_H__
24#define __NOUVEAU_RESOURCE_H__
25
26struct nouveau_resource {
27 struct nouveau_resource *prev;
28 struct nouveau_resource *next;
29
30 int in_use;
31 void *priv;
32
33 unsigned int start;
34 unsigned int size;
35};
36
37int
38nouveau_resource_init(struct nouveau_resource **heap, unsigned start,
39 unsigned size);
40
41void
42nouveau_resource_destroy(struct nouveau_resource **heap);
43
44int
45nouveau_resource_alloc(struct nouveau_resource *heap, unsigned size, void *priv,
46 struct nouveau_resource **);
47
48void
49nouveau_resource_free(struct nouveau_resource **);
50
51#endif
diff --git a/nouveau/nv04_pushbuf.h b/nouveau/nv04_pushbuf.h
deleted file mode 100644
index 586b2847..00000000
--- a/nouveau/nv04_pushbuf.h
+++ /dev/null
@@ -1,66 +0,0 @@
1/*
2 * Copyright 2007 Nouveau Project
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
23#ifndef __NV04_PUSHBUF_H__
24#define __NV04_PUSHBUF_H__
25
26#include "nouveau_pushbuf.h"
27
28static __inline__ void
29BEGIN_RING(struct nouveau_channel *chan, struct nouveau_grobj *gr,
30 unsigned mthd, unsigned size)
31{
32 if (gr->bound == NOUVEAU_GROBJ_UNBOUND)
33 nouveau_grobj_autobind(gr);
34 chan->subc[gr->subc].sequence = chan->subc_sequence++;
35
36 WAIT_RING(chan, size + 1);
37 OUT_RING(chan, (gr->subc << 13) | (size << 18) | mthd);
38}
39
40/* non-incrementing BEGIN_RING */
41static __inline__ void
42BEGIN_RING_NI(struct nouveau_channel *chan, struct nouveau_grobj *gr,
43 unsigned mthd, unsigned size)
44{
45 BEGIN_RING(chan, gr, mthd | 0x40000000, size);
46}
47
48static __inline__ void
49BIND_RING(struct nouveau_channel *chan, struct nouveau_grobj *gr, unsigned sc)
50{
51 struct nouveau_subchannel *subc = &gr->channel->subc[sc];
52
53 if (subc->gr) {
54 if (subc->gr->bound == NOUVEAU_GROBJ_BOUND_EXPLICIT)
55 assert(0);
56 subc->gr->bound = NOUVEAU_GROBJ_UNBOUND;
57 }
58 subc->gr = gr;
59 subc->gr->subc = sc;
60 subc->gr->bound = NOUVEAU_GROBJ_BOUND_EXPLICIT;
61
62 BEGIN_RING(chan, gr, 0x0000, 1);
63 OUT_RING (chan, gr->handle);
64}
65
66#endif
diff --git a/nouveau/nvc0_pushbuf.h b/nouveau/nvc0_pushbuf.h
deleted file mode 100644
index 40dc7e67..00000000
--- a/nouveau/nvc0_pushbuf.h
+++ /dev/null
@@ -1,92 +0,0 @@
1/*
2 * Copyright 2010 Nouveau Project
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
23#ifndef __NVC0_PUSHBUF_H__
24#define __NVC0_PUSHBUF_H__
25
26#include "nouveau_pushbuf.h"
27
28#define SUBC_BIND(chan, gr) do { \
29 if (gr->bound == NOUVEAU_GROBJ_UNBOUND) \
30 nouveau_grobj_autobind(gr); \
31 chan->subc[gr->subc].sequence = chan->subc_sequence++; \
32} while (0)
33
34/* incremental methods */
35static __inline__ void
36BEGIN_RING(struct nouveau_channel *chan, struct nouveau_grobj *gr,
37 unsigned mthd, unsigned size)
38{
39 SUBC_BIND(chan, gr);
40 WAIT_RING(chan, size + 1);
41 OUT_RING (chan, (0x2 << 28) | (size << 16) | (gr->subc << 13) | (mthd >> 2));
42}
43
44/* non-incremental */
45static __inline__ void
46BEGIN_RING_NI(struct nouveau_channel *chan, struct nouveau_grobj *gr,
47 unsigned mthd, unsigned size)
48{
49 SUBC_BIND(chan, gr);
50 WAIT_RING(chan, size + 1);
51 OUT_RING (chan, (0x6 << 28) | (size << 16) | (gr->subc << 13) | (mthd >> 2));
52}
53
54/* increment-once */
55static __inline__ void
56BEGIN_RING_1I(struct nouveau_channel *chan, struct nouveau_grobj *gr,
57 unsigned mthd, unsigned size)
58{
59 SUBC_BIND(chan, gr);
60 WAIT_RING(chan, size + 1);
61 OUT_RING (chan, (0xa << 28) | (size << 16) | (gr->subc << 13) | (mthd >> 2));
62}
63
64/* inline-data */
65static __inline__ void
66IMMED_RING(struct nouveau_channel *chan, struct nouveau_grobj *gr,
67 unsigned mthd, unsigned data)
68{
69 SUBC_BIND(chan, gr);
70 WAIT_RING(chan, 1);
71 OUT_RING (chan, (0x8 << 28) | (data << 16) | (gr->subc << 13) | (mthd >> 2));
72}
73
74static __inline__ void
75BIND_RING(struct nouveau_channel *chan, struct nouveau_grobj *gr, unsigned sc)
76{
77 struct nouveau_subchannel *subc = &gr->channel->subc[sc];
78
79 if (subc->gr) {
80 if (subc->gr->bound == NOUVEAU_GROBJ_BOUND_EXPLICIT)
81 assert(0);
82 subc->gr->bound = NOUVEAU_GROBJ_UNBOUND;
83 }
84 subc->gr = gr;
85 subc->gr->subc = sc;
86 subc->gr->bound = NOUVEAU_GROBJ_BOUND_EXPLICIT;
87
88 BEGIN_RING(chan, gr, 0x0000, 1);
89 OUT_RING (chan, gr->grclass);
90}
91
92#endif
diff --git a/nouveau/private.h b/nouveau/private.h
new file mode 100644
index 00000000..b409cc8d
--- /dev/null
+++ b/nouveau/private.h
@@ -0,0 +1,122 @@
1#ifndef __NOUVEAU_LIBDRM_PRIVATE_H__
2#define __NOUVEAU_LIBDRM_PRIVATE_H__
3
4#include <xf86drm.h>
5#include <xf86atomic.h>
6#include "nouveau_drm.h"
7
8#include "nouveau.h"
9
10#ifdef DEBUG
11uint32_t nouveau_debug;
12#define dbg_on(lvl) (nouveau_debug & (1 << lvl))
13#define dbg(lvl, fmt, args...) do { \
14 if (dbg_on((lvl))) \
15 fprintf(stderr, "nouveau: "fmt, ##args); \
16} while(0)
17#else
18#define dbg_on(lvl) (0)
19#define dbg(lvl, fmt, args...)
20#endif
21#define err(fmt, args...) fprintf(stderr, "nouveau: "fmt, ##args)
22
23struct nouveau_client_kref {
24 struct drm_nouveau_gem_pushbuf_bo *kref;
25 struct nouveau_pushbuf *push;
26};
27
28struct nouveau_client_priv {
29 struct nouveau_client base;
30 struct nouveau_client_kref *kref;
31 unsigned kref_nr;
32};
33
34static inline struct nouveau_client_priv *
35nouveau_client(struct nouveau_client *client)
36{
37 return (struct nouveau_client_priv *)client;
38}
39
40static inline struct drm_nouveau_gem_pushbuf_bo *
41cli_kref_get(struct nouveau_client *client, struct nouveau_bo *bo)
42{
43 struct nouveau_client_priv *pcli = nouveau_client(client);
44 struct drm_nouveau_gem_pushbuf_bo *kref = NULL;
45 if (pcli->kref_nr > bo->handle)
46 kref = pcli->kref[bo->handle].kref;
47 return kref;
48}
49
50static inline struct nouveau_pushbuf *
51cli_push_get(struct nouveau_client *client, struct nouveau_bo *bo)
52{
53 struct nouveau_client_priv *pcli = nouveau_client(client);
54 struct nouveau_pushbuf *push = NULL;
55 if (pcli->kref_nr > bo->handle)
56 push = pcli->kref[bo->handle].push;
57 return push;
58}
59
60static inline void
61cli_kref_set(struct nouveau_client *client, struct nouveau_bo *bo,
62 struct drm_nouveau_gem_pushbuf_bo *kref,
63 struct nouveau_pushbuf *push)
64{
65 struct nouveau_client_priv *pcli = nouveau_client(client);
66 if (pcli->kref_nr <= bo->handle) {
67 pcli->kref = realloc(pcli->kref,
68 sizeof(*pcli->kref) * bo->handle * 2);
69 while (pcli->kref_nr < bo->handle * 2) {
70 pcli->kref[pcli->kref_nr].kref = NULL;
71 pcli->kref[pcli->kref_nr].push = NULL;
72 pcli->kref_nr++;
73 }
74 }
75 pcli->kref[bo->handle].kref = kref;
76 pcli->kref[bo->handle].push = push;
77}
78
79struct nouveau_bo_priv {
80 struct nouveau_bo base;
81 struct nouveau_list head;
82 atomic_t refcnt;
83 uint64_t map_handle;
84 uint32_t name;
85 uint32_t access;
86};
87
88static inline struct nouveau_bo_priv *
89nouveau_bo(struct nouveau_bo *bo)
90{
91 return (struct nouveau_bo_priv *)bo;
92}
93
94struct nouveau_device_priv {
95 struct nouveau_device base;
96 int close;
97 atomic_t lock;
98 struct nouveau_list bo_list;
99 uint32_t *client;
100 int nr_client;
101 bool have_bo_usage;
102};
103
104static inline struct nouveau_device_priv *
105nouveau_device(struct nouveau_device *dev)
106{
107 return (struct nouveau_device_priv *)dev;
108}
109
110int
111nouveau_device_open_existing(struct nouveau_device **, int, int, drm_context_t);
112
113/* abi16.c */
114int abi16_chan_nv04(struct nouveau_object *);
115int abi16_chan_nvc0(struct nouveau_object *);
116int abi16_engobj(struct nouveau_object *);
117int abi16_ntfy(struct nouveau_object *);
118void abi16_bo_info(struct nouveau_bo *, struct drm_nouveau_gem_info *);
119int abi16_bo_init(struct nouveau_bo *, uint32_t alignment,
120 union nouveau_bo_config *);
121
122#endif
diff --git a/nouveau/pushbuf.c b/nouveau/pushbuf.c
new file mode 100644
index 00000000..103737e6
--- /dev/null
+++ b/nouveau/pushbuf.c
@@ -0,0 +1,774 @@
1/*
2 * Copyright 2012 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in