Update patches
[ubuntu-omap:libdrm.git] / debian / patches / 04_libdrm-2.4.37-nouveau-1.diff
1 Index: libdrm/Makefile.am
2 ===================================================================
3 --- libdrm.orig/Makefile.am     2013-03-06 16:18:44.979937481 +0100
4 +++ libdrm/Makefile.am  2013-03-06 16:27:49.803925019 +0100
5 @@ -34,7 +34,7 @@
6  endif
7  
8  if HAVE_NOUVEAU
9 -NOUVEAU_SUBDIR = nouveau
10 +NOUVEAU_SUBDIR = nouveau-1 nouveau
11  endif
12  
13  if HAVE_RADEON
14 Index: libdrm/configure.ac
15 ===================================================================
16 --- libdrm.orig/configure.ac    2013-03-06 16:18:44.979937481 +0100
17 +++ libdrm/configure.ac 2013-03-06 16:27:49.803925019 +0100
18 @@ -334,6 +334,8 @@
19         intel/libdrm_intel.pc
20         radeon/Makefile
21         radeon/libdrm_radeon.pc
22 +       nouveau-1/Makefile
23 +       nouveau-1/libdrm_nouveau1.pc
24         nouveau/Makefile
25         nouveau/libdrm_nouveau.pc
26         omap/Makefile
27 Index: libdrm/nouveau-1/Makefile.am
28 ===================================================================
29 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
30 +++ libdrm/nouveau-1/Makefile.am        2013-03-06 16:27:49.807925019 +0100
31 @@ -0,0 +1,43 @@
32 +AM_CFLAGS = \
33 +       $(WARN_CFLAGS) \
34 +       -I$(top_srcdir) \
35 +       -I$(top_srcdir)/nouveau-1 \
36 +       $(PTHREADSTUBS_CFLAGS) \
37 +       -I$(top_srcdir)/include/drm
38 +
39 +libdrm_nouveau_la_LTLIBRARIES = libdrm_nouveau.la
40 +libdrm_nouveau_ladir = $(libdir)
41 +libdrm_nouveau_la_LDFLAGS = -version-number 1:0:0 -no-undefined
42 +libdrm_nouveau_la_LIBADD = ../libdrm.la @PTHREADSTUBS_LIBS@
43 +
44 +libdrm_nouveau_la_SOURCES = \
45 +                           nouveau_device.c \
46 +                           nouveau_channel.c \
47 +                           nouveau_pushbuf.c \
48 +                           nouveau_grobj.c \
49 +                           nouveau_notifier.c \
50 +                           nouveau_bo.c \
51 +                           nouveau_resource.c \
52 +                           nouveau_private.h \
53 +                           nouveau_reloc.c
54 +
55 +libdrm_nouveaucommonincludedir = ${includedir}/nouveau
56 +libdrm_nouveaucommoninclude_HEADERS = \
57 +                               nouveau_device.h \
58 +                               nouveau_channel.h \
59 +                               nouveau_grobj.h \
60 +                               nouveau_notifier.h \
61 +                               nouveau_pushbuf.h \
62 +                               nv04_pushbuf.h \
63 +                               nvc0_pushbuf.h \
64 +                               nouveau_bo.h \
65 +                               nouveau_resource.h \
66 +                               nouveau_reloc.h
67 +
68 +
69 +libdrm_nouveauincludedir = ${includedir}/libdrm
70 +libdrm_nouveauinclude_HEADERS = \
71 +                               nouveau_drmif.h
72 +
73 +pkgconfigdir = @pkgconfigdir@
74 +pkgconfig_DATA = libdrm_nouveau1.pc
75 Index: libdrm/nouveau-1/libdrm_nouveau1.pc.in
76 ===================================================================
77 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
78 +++ libdrm/nouveau-1/libdrm_nouveau1.pc.in      2013-03-06 16:27:49.807925019 +0100
79 @@ -0,0 +1,11 @@
80 +prefix=@prefix@
81 +exec_prefix=@exec_prefix@
82 +libdir=@libdir@
83 +includedir=@includedir@
84 +
85 +Name: libdrm_nouveau
86 +Description: Userspace interface to nouveau kernel DRM services
87 +Version: 0.6
88 +Libs: -L${libdir} -ldrm_nouveau1
89 +Cflags: -I${includedir} -I${includedir}/libdrm -I${includedir}/nouveau
90 +Requires.private: libdrm
91 Index: libdrm/nouveau-1/nouveau_bo.c
92 ===================================================================
93 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
94 +++ libdrm/nouveau-1/nouveau_bo.c       2013-03-06 16:27:49.807925019 +0100
95 @@ -0,0 +1,549 @@
96 +/*
97 + * Copyright 2007 Nouveau Project
98 + *
99 + * Permission is hereby granted, free of charge, to any person obtaining a
100 + * copy of this software and associated documentation files (the "Software"),
101 + * to deal in the Software without restriction, including without limitation
102 + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
103 + * and/or sell copies of the Software, and to permit persons to whom the
104 + * Software is furnished to do so, subject to the following conditions:
105 + *
106 + * The above copyright notice and this permission notice shall be included in
107 + * all copies or substantial portions of the Software.
108 + *
109 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
110 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
111 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
112 + * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
113 + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
114 + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
115 + * SOFTWARE.
116 + */
117 +
118 +#ifdef HAVE_CONFIG_H
119 +#include <config.h>
120 +#endif
121 +#include <stdint.h>
122 +#include <stdlib.h>
123 +#include <errno.h>
124 +#include <assert.h>
125 +
126 +#include <sys/mman.h>
127 +
128 +#include "nouveau_private.h"
129 +
130 +int
131 +nouveau_bo_init(struct nouveau_device *dev)
132 +{
133 +       return 0;
134 +}
135 +
136 +void
137 +nouveau_bo_takedown(struct nouveau_device *dev)
138 +{
139 +}
140 +
141 +static int
142 +nouveau_bo_info(struct nouveau_bo_priv *nvbo, struct drm_nouveau_gem_info *arg)
143 +{
144 +       nvbo->handle = nvbo->base.handle = arg->handle;
145 +       nvbo->domain = arg->domain;
146 +       nvbo->size = arg->size;
147 +       nvbo->offset = arg->offset;
148 +       nvbo->map_handle = arg->map_handle;
149 +       nvbo->base.tile_mode = arg->tile_mode;
150 +       /* XXX - flag inverted for backwards compatibility */
151 +       nvbo->base.tile_flags = arg->tile_flags ^ NOUVEAU_GEM_TILE_NONCONTIG;
152 +       return 0;
153 +}
154 +
155 +static int
156 +nouveau_bo_allocated(struct nouveau_bo_priv *nvbo)
157 +{
158 +       if (nvbo->sysmem || nvbo->handle)
159 +               return 1;
160 +       return 0;
161 +}
162 +
163 +static int
164 +nouveau_bo_ualloc(struct nouveau_bo_priv *nvbo)
165 +{
166 +       if (nvbo->user || nvbo->sysmem) {
167 +               assert(nvbo->sysmem);
168 +               return 0;
169 +       }
170 +
171 +       nvbo->sysmem = malloc(nvbo->size);
172 +       if (!nvbo->sysmem)
173 +               return -ENOMEM;
174 +
175 +       return 0;
176 +}
177 +
178 +static void
179 +nouveau_bo_ufree(struct nouveau_bo_priv *nvbo)
180 +{
181 +       if (nvbo->sysmem) {
182 +               if (!nvbo->user)
183 +                       free(nvbo->sysmem);
184 +               nvbo->sysmem = NULL;
185 +       }
186 +}
187 +
188 +static void
189 +nouveau_bo_kfree(struct nouveau_bo_priv *nvbo)
190 +{
191 +       struct nouveau_device_priv *nvdev = nouveau_device(nvbo->base.device);
192 +       struct drm_gem_close req;
193 +
194 +       if (!nvbo->handle)
195 +               return;
196 +
197 +       if (nvbo->map) {
198 +               munmap(nvbo->map, nvbo->size);
199 +               nvbo->map = NULL;
200 +       }
201 +
202 +       req.handle = nvbo->handle;
203 +       nvbo->handle = 0;
204 +       drmIoctl(nvdev->fd, DRM_IOCTL_GEM_CLOSE, &req);
205 +}
206 +
207 +static int
208 +nouveau_bo_kalloc(struct nouveau_bo_priv *nvbo, struct nouveau_channel *chan)
209 +{
210 +       struct nouveau_device_priv *nvdev = nouveau_device(nvbo->base.device);
211 +       struct drm_nouveau_gem_new req;
212 +       struct drm_nouveau_gem_info *info = &req.info;
213 +       int ret;
214 +
215 +       if (nvbo->handle)
216 +               return 0;
217 +
218 +       req.channel_hint = chan ? chan->id : 0;
219 +       req.align = nvbo->align;
220 +
221 +
222 +       info->size = nvbo->size;
223 +       info->domain = 0;
224 +
225 +       if (nvbo->flags & NOUVEAU_BO_VRAM)
226 +               info->domain |= NOUVEAU_GEM_DOMAIN_VRAM;
227 +       if (nvbo->flags & NOUVEAU_BO_GART)
228 +               info->domain |= NOUVEAU_GEM_DOMAIN_GART;
229 +       if (!info->domain) {
230 +               info->domain |= (NOUVEAU_GEM_DOMAIN_VRAM |
231 +                                NOUVEAU_GEM_DOMAIN_GART);
232 +       }
233 +
234 +       if (nvbo->flags & NOUVEAU_BO_MAP)
235 +               info->domain |= NOUVEAU_GEM_DOMAIN_MAPPABLE;
236 +
237 +       info->tile_mode = nvbo->base.tile_mode;
238 +       info->tile_flags = nvbo->base.tile_flags;
239 +       /* XXX - flag inverted for backwards compatibility */
240 +       info->tile_flags ^= NOUVEAU_GEM_TILE_NONCONTIG;
241 +       if (!nvdev->has_bo_usage)
242 +               info->tile_flags &= NOUVEAU_GEM_TILE_LAYOUT_MASK;
243 +
244 +       ret = drmCommandWriteRead(nvdev->fd, DRM_NOUVEAU_GEM_NEW,
245 +                                 &req, sizeof(req));
246 +       if (ret)
247 +               return ret;
248 +
249 +       nouveau_bo_info(nvbo, &req.info);
250 +       return 0;
251 +}
252 +
253 +static int
254 +nouveau_bo_kmap(struct nouveau_bo_priv *nvbo)
255 +{
256 +       struct nouveau_device_priv *nvdev = nouveau_device(nvbo->base.device);
257 +
258 +       if (nvbo->map)
259 +               return 0;
260 +
261 +       if (!nvbo->map_handle)
262 +               return -EINVAL;
263 +
264 +       nvbo->map = mmap(0, nvbo->size, PROT_READ | PROT_WRITE,
265 +                        MAP_SHARED, nvdev->fd, nvbo->map_handle);
266 +       if (nvbo->map == MAP_FAILED) {
267 +               nvbo->map = NULL;
268 +               return -errno;
269 +       }
270 +
271 +       return 0;
272 +}
273 +
274 +int
275 +nouveau_bo_new_tile(struct nouveau_device *dev, uint32_t flags, int align,
276 +                   int size, uint32_t tile_mode, uint32_t tile_flags,
277 +                   struct nouveau_bo **bo)
278 +{
279 +       struct nouveau_bo_priv *nvbo;
280 +       int ret;
281 +
282 +       if (!dev || !bo || *bo)
283 +               return -EINVAL;
284 +
285 +       nvbo = calloc(1, sizeof(struct nouveau_bo_priv));
286 +       if (!nvbo)
287 +               return -ENOMEM;
288 +       nvbo->base.device = dev;
289 +       nvbo->base.size = size;
290 +       nvbo->base.tile_mode = tile_mode;
291 +       nvbo->base.tile_flags = tile_flags;
292 +
293 +       nvbo->refcount = 1;
294 +       nvbo->flags = flags;
295 +       nvbo->size = size;
296 +       nvbo->align = align;
297 +
298 +       if (flags & (NOUVEAU_BO_VRAM | NOUVEAU_BO_GART)) {
299 +               ret = nouveau_bo_kalloc(nvbo, NULL);
300 +               if (ret) {
301 +                       nouveau_bo_ref(NULL, (void *)&nvbo);
302 +                       return ret;
303 +               }
304 +       }
305 +
306 +       *bo = &nvbo->base;
307 +       return 0;
308 +}
309 +
310 +int
311 +nouveau_bo_new(struct nouveau_device *dev, uint32_t flags, int align,
312 +              int size, struct nouveau_bo **bo)
313 +{
314 +       return nouveau_bo_new_tile(dev, flags, align, size, 0, 0, bo);
315 +}
316 +
317 +int
318 +nouveau_bo_user(struct nouveau_device *dev, void *ptr, int size,
319 +               struct nouveau_bo **bo)
320 +{
321 +       struct nouveau_bo_priv *nvbo;
322 +       int ret;
323 +
324 +       ret = nouveau_bo_new(dev, NOUVEAU_BO_MAP, 0, size, bo);
325 +       if (ret)
326 +               return ret;
327 +       nvbo = nouveau_bo(*bo);
328 +
329 +       nvbo->sysmem = ptr;
330 +       nvbo->user = 1;
331 +       return 0;
332 +}
333 +
334 +int
335 +nouveau_bo_wrap(struct nouveau_device *dev, uint32_t handle,
336 +               struct nouveau_bo **bo)
337 +{
338 +       struct nouveau_device_priv *nvdev = nouveau_device(dev);
339 +       struct drm_nouveau_gem_info req;
340 +       struct nouveau_bo_priv *nvbo;
341 +       int ret;
342 +
343 +       ret = nouveau_bo_new(dev, 0, 0, 0, bo);
344 +       if (ret)
345 +               return ret;
346 +       nvbo = nouveau_bo(*bo);
347 +
348 +       req.handle = handle;
349 +       ret = drmCommandWriteRead(nvdev->fd, DRM_NOUVEAU_GEM_INFO,
350 +                                 &req, sizeof(req));
351 +       if (ret) {
352 +               nouveau_bo_ref(NULL, bo);
353 +               return ret;
354 +       }
355 +
356 +       nouveau_bo_info(nvbo, &req);
357 +       nvbo->base.size = nvbo->size;
358 +       return 0;
359 +}
360 +
361 +int
362 +nouveau_bo_handle_get(struct nouveau_bo *bo, uint32_t *handle)
363 +{
364 +       struct nouveau_device_priv *nvdev = nouveau_device(bo->device);
365 +       struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
366 +       int ret;
367
368 +       if (!bo || !handle)
369 +               return -EINVAL;
370 +
371 +       if (!nvbo->global_handle) {
372 +               struct drm_gem_flink req;
373
374 +               ret = nouveau_bo_kalloc(nvbo, NULL);
375 +               if (ret)
376 +                       return ret;
377 +
378 +               req.handle = nvbo->handle;
379 +               ret = drmIoctl(nvdev->fd, DRM_IOCTL_GEM_FLINK, &req);
380 +               if (ret) {
381 +                       nouveau_bo_kfree(nvbo);
382 +                       return ret;
383 +               }
384 +
385 +               nvbo->global_handle = req.name;
386 +       }
387
388 +       *handle = nvbo->global_handle;
389 +       return 0;
390 +}
391
392 +int
393 +nouveau_bo_handle_ref(struct nouveau_device *dev, uint32_t handle,
394 +                     struct nouveau_bo **bo)
395 +{
396 +       struct nouveau_device_priv *nvdev = nouveau_device(dev);
397 +       struct nouveau_bo_priv *nvbo;
398 +       struct drm_gem_open req;
399 +       int ret;
400 +
401 +       req.name = handle;
402 +       ret = drmIoctl(nvdev->fd, DRM_IOCTL_GEM_OPEN, &req);
403 +       if (ret) {
404 +               nouveau_bo_ref(NULL, bo);
405 +               return ret;
406 +       }
407 +
408 +       ret = nouveau_bo_wrap(dev, req.handle, bo);
409 +       if (ret) {
410 +               nouveau_bo_ref(NULL, bo);
411 +               return ret;
412 +       }
413 +
414 +       nvbo = nouveau_bo(*bo);
415 +       nvbo->base.handle = nvbo->handle;
416 +       return 0;
417 +} 
418 +
419 +static void
420 +nouveau_bo_del(struct nouveau_bo **bo)
421 +{
422 +       struct nouveau_bo_priv *nvbo;
423 +
424 +       if (!bo || !*bo)
425 +               return;
426 +       nvbo = nouveau_bo(*bo);
427 +       *bo = NULL;
428 +
429 +       if (--nvbo->refcount)
430 +               return;
431 +
432 +       if (nvbo->pending) {
433 +               nvbo->pending = NULL;
434 +               nouveau_pushbuf_flush(nvbo->pending_channel, 0);
435 +       }
436 +
437 +       nouveau_bo_ufree(nvbo);
438 +       nouveau_bo_kfree(nvbo);
439 +       free(nvbo);
440 +}
441 +
442 +int
443 +nouveau_bo_ref(struct nouveau_bo *ref, struct nouveau_bo **pbo)
444 +{
445 +       if (!pbo)
446 +               return -EINVAL;
447 +
448 +       if (ref)
449 +               nouveau_bo(ref)->refcount++;
450 +
451 +       if (*pbo)
452 +               nouveau_bo_del(pbo);
453 +
454 +       *pbo = ref;
455 +       return 0;
456 +}
457 +
458 +static int
459 +nouveau_bo_wait(struct nouveau_bo *bo, int cpu_write, int no_wait, int no_block)
460 +{
461 +       struct nouveau_device_priv *nvdev = nouveau_device(bo->device);
462 +       struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
463 +       struct drm_nouveau_gem_cpu_prep req;
464 +       int ret;
465 +
466 +       if (!nvbo->global_handle && !nvbo->write_marker && !cpu_write)
467 +               return 0;
468 +
469 +       if (nvbo->pending &&
470 +           (nvbo->pending->write_domains || cpu_write)) {
471 +               nvbo->pending = NULL;
472 +               nouveau_pushbuf_flush(nvbo->pending_channel, 0);
473 +       }
474 +
475 +       req.handle = nvbo->handle;
476 +       req.flags = 0;
477 +       if (cpu_write)
478 +               req.flags |= NOUVEAU_GEM_CPU_PREP_WRITE;
479 +       if (no_wait)
480 +               req.flags |= NOUVEAU_GEM_CPU_PREP_NOWAIT;
481 +       if (no_block)
482 +               req.flags |= NOUVEAU_GEM_CPU_PREP_NOBLOCK;
483 +
484 +       do {
485 +               ret = drmCommandWrite(nvdev->fd, DRM_NOUVEAU_GEM_CPU_PREP,
486 +                                     &req, sizeof(req));
487 +       } while (ret == -EAGAIN);
488 +       if (ret)
489 +               return ret;
490 +
491 +       if (ret == 0)
492 +               nvbo->write_marker = 0;
493 +       return 0;
494 +}
495 +
496 +int
497 +nouveau_bo_map_range(struct nouveau_bo *bo, uint32_t delta, uint32_t size,
498 +                    uint32_t flags)
499 +{
500 +       struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
501 +       int ret;
502 +
503 +       if (!nvbo || bo->map)
504 +               return -EINVAL;
505 +
506 +       if (!nouveau_bo_allocated(nvbo)) {
507 +               if (nvbo->flags & (NOUVEAU_BO_VRAM | NOUVEAU_BO_GART)) {
508 +                       ret = nouveau_bo_kalloc(nvbo, NULL);
509 +                       if (ret)
510 +                               return ret;
511 +               }
512 +
513 +               if (!nouveau_bo_allocated(nvbo)) {
514 +                       ret = nouveau_bo_ualloc(nvbo);
515 +                       if (ret)
516 +                               return ret;
517 +               }
518 +       }
519 +
520 +       if (nvbo->sysmem) {
521 +               bo->map = (char *)nvbo->sysmem + delta;
522 +       } else {
523 +               ret = nouveau_bo_kmap(nvbo);
524 +               if (ret)
525 +                       return ret;
526 +
527 +               if (!(flags & NOUVEAU_BO_NOSYNC)) {
528 +                       ret = nouveau_bo_wait(bo, (flags & NOUVEAU_BO_WR),
529 +                                             (flags & NOUVEAU_BO_NOWAIT), 0);
530 +                       if (ret)
531 +                               return ret;
532 +
533 +                       nvbo->map_refcnt++;
534 +               }
535 +
536 +               bo->map = (char *)nvbo->map + delta;
537 +       }
538 +
539 +       return 0;
540 +}
541 +
542 +void
543 +nouveau_bo_map_flush(struct nouveau_bo *bo, uint32_t delta, uint32_t size)
544 +{
545 +}
546 +
547 +int
548 +nouveau_bo_map(struct nouveau_bo *bo, uint32_t flags)
549 +{
550 +       return nouveau_bo_map_range(bo, 0, bo->size, flags);
551 +}
552 +
553 +void
554 +nouveau_bo_unmap(struct nouveau_bo *bo)
555 +{
556 +       struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
557 +
558 +       if (bo->map && !nvbo->sysmem && nvbo->map_refcnt) {
559 +               struct nouveau_device_priv *nvdev = nouveau_device(bo->device);
560 +               struct drm_nouveau_gem_cpu_fini req;
561 +
562 +               req.handle = nvbo->handle;
563 +               drmCommandWrite(nvdev->fd, DRM_NOUVEAU_GEM_CPU_FINI,
564 +                               &req, sizeof(req));
565 +               nvbo->map_refcnt--;
566 +       }
567 +
568 +       bo->map = NULL;
569 +}
570 +
571 +int
572 +nouveau_bo_busy(struct nouveau_bo *bo, uint32_t access)
573 +{
574 +       return nouveau_bo_wait(bo, (access & NOUVEAU_BO_WR), 1, 1);
575 +}
576 +
577 +uint32_t
578 +nouveau_bo_pending(struct nouveau_bo *bo)
579 +{
580 +       struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
581 +       uint32_t flags;
582 +
583 +       if (!nvbo->pending)
584 +               return 0;
585 +
586 +       flags = 0;
587 +       if (nvbo->pending->read_domains)
588 +               flags |= NOUVEAU_BO_RD;
589 +       if (nvbo->pending->write_domains)
590 +               flags |= NOUVEAU_BO_WR;
591 +
592 +       return flags;
593 +}
594 +
595 +struct drm_nouveau_gem_pushbuf_bo *
596 +nouveau_bo_emit_buffer(struct nouveau_channel *chan, struct nouveau_bo *bo)
597 +{
598 +       struct nouveau_pushbuf_priv *nvpb = &nouveau_channel(chan)->pb;
599 +       struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
600 +       struct drm_nouveau_gem_pushbuf_bo *pbbo;
601 +       struct nouveau_bo *ref = NULL;
602 +       int ret;
603 +
604 +       if (nvbo->pending)
605 +               return nvbo->pending;
606 +
607 +       if (!nvbo->handle) {
608 +               ret = nouveau_bo_kalloc(nvbo, chan);
609 +               if (ret)
610 +                       return NULL;
611 +
612 +               if (nvbo->sysmem) {
613 +                       void *sysmem_tmp = nvbo->sysmem;
614 +
615 +                       nvbo->sysmem = NULL;
616 +                       ret = nouveau_bo_map(bo, NOUVEAU_BO_WR);
617 +                       if (ret)
618 +                               return NULL;
619 +                       nvbo->sysmem = sysmem_tmp;
620 +
621 +                       memcpy(bo->map, nvbo->sysmem, nvbo->base.size);
622 +                       nouveau_bo_ufree(nvbo);
623 +                       nouveau_bo_unmap(bo);
624 +               }
625 +       }
626 +
627 +       if (nvpb->nr_buffers >= NOUVEAU_GEM_MAX_BUFFERS)
628 +               return NULL;
629 +       pbbo = nvpb->buffers + nvpb->nr_buffers++;
630 +       nvbo->pending = pbbo;
631 +       nvbo->pending_channel = chan;
632 +       nvbo->pending_refcnt = 0;
633 +
634 +       nouveau_bo_ref(bo, &ref);
635 +       pbbo->user_priv = (uint64_t)(unsigned long)ref;
636 +       pbbo->handle = nvbo->handle;
637 +       pbbo->valid_domains = NOUVEAU_GEM_DOMAIN_VRAM | NOUVEAU_GEM_DOMAIN_GART;
638 +       pbbo->read_domains = 0;
639 +       pbbo->write_domains = 0;
640 +       pbbo->presumed.domain = nvbo->domain;
641 +       pbbo->presumed.offset = nvbo->offset;
642 +       pbbo->presumed.valid = 1;
643 +       return pbbo;
644 +}
645 Index: libdrm/nouveau-1/nouveau_bo.h
646 ===================================================================
647 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
648 +++ libdrm/nouveau-1/nouveau_bo.h       2013-03-06 16:27:49.807925019 +0100
649 @@ -0,0 +1,104 @@
650 +/*
651 + * Copyright 2007 Nouveau Project
652 + *
653 + * Permission is hereby granted, free of charge, to any person obtaining a
654 + * copy of this software and associated documentation files (the "Software"),
655 + * to deal in the Software without restriction, including without limitation
656 + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
657 + * and/or sell copies of the Software, and to permit persons to whom the
658 + * Software is furnished to do so, subject to the following conditions:
659 + *
660 + * The above copyright notice and this permission notice shall be included in
661 + * all copies or substantial portions of the Software.
662 + *
663 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
664 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
665 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
666 + * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
667 + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
668 + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
669 + * SOFTWARE.
670 + */
671 +
672 +#ifndef __NOUVEAU_BO_H__
673 +#define __NOUVEAU_BO_H__
674 +
675 +/* Relocation/Buffer type flags */
676 +#define NOUVEAU_BO_VRAM   (1 << 0)
677 +#define NOUVEAU_BO_GART   (1 << 1)
678 +#define NOUVEAU_BO_RD     (1 << 2)
679 +#define NOUVEAU_BO_WR     (1 << 3)
680 +#define NOUVEAU_BO_RDWR   (NOUVEAU_BO_RD | NOUVEAU_BO_WR)
681 +#define NOUVEAU_BO_MAP    (1 << 4)
682 +#define NOUVEAU_BO_LOW    (1 << 6)
683 +#define NOUVEAU_BO_HIGH   (1 << 7)
684 +#define NOUVEAU_BO_OR     (1 << 8)
685 +#define NOUVEAU_BO_INVAL  (1 << 12)
686 +#define NOUVEAU_BO_NOSYNC (1 << 13)
687 +#define NOUVEAU_BO_NOWAIT (1 << 14)
688 +#define NOUVEAU_BO_IFLUSH (1 << 15)
689 +#define NOUVEAU_BO_DUMMY  (1 << 31)
690 +
691 +#define NOUVEAU_BO_TILE_LAYOUT_MASK 0x0000ff00
692 +#define NOUVEAU_BO_TILE_16BPP       0x00000001
693 +#define NOUVEAU_BO_TILE_32BPP       0x00000002
694 +#define NOUVEAU_BO_TILE_ZETA        0x00000004
695 +#define NOUVEAU_BO_TILE_SCANOUT     0x00000008
696 +
697 +struct nouveau_bo {
698 +       struct nouveau_device *device;
699 +       uint32_t handle;
700 +
701 +       uint64_t size;
702 +       void *map;
703 +
704 +       uint32_t tile_mode;
705 +       uint32_t tile_flags;
706 +};
707 +
708 +int
709 +nouveau_bo_new(struct nouveau_device *, uint32_t flags, int align, int size,
710 +              struct nouveau_bo **);
711 +
712 +int
713 +nouveau_bo_new_tile(struct nouveau_device *, uint32_t flags, int align,
714 +                   int size, uint32_t tile_mode, uint32_t tile_flags,
715 +                   struct nouveau_bo **);
716 +
717 +int
718 +nouveau_bo_user(struct nouveau_device *, void *ptr, int size,
719 +               struct nouveau_bo **);
720 +
721 +int
722 +nouveau_bo_wrap(struct nouveau_device *, uint32_t handle, struct nouveau_bo **);
723 +
724 +int
725 +nouveau_bo_handle_get(struct nouveau_bo *, uint32_t *);
726 +
727 +int
728 +nouveau_bo_handle_ref(struct nouveau_device *, uint32_t handle,
729 +                     struct nouveau_bo **);
730 +
731 +int
732 +nouveau_bo_ref(struct nouveau_bo *, struct nouveau_bo **);
733 +
734 +int
735 +nouveau_bo_map_range(struct nouveau_bo *, uint32_t delta, uint32_t size,
736 +                    uint32_t flags);
737 +
738 +void
739 +nouveau_bo_map_flush(struct nouveau_bo *, uint32_t delta, uint32_t size);
740 +
741 +int
742 +nouveau_bo_map(struct nouveau_bo *, uint32_t flags);
743 +
744 +void
745 +nouveau_bo_unmap(struct nouveau_bo *);
746 +
747 +int
748 +nouveau_bo_busy(struct nouveau_bo *, uint32_t access);
749 +
750 +uint32_t
751 +nouveau_bo_pending(struct nouveau_bo *);
752 +
753 +#endif
754 Index: libdrm/nouveau-1/nouveau_channel.c
755 ===================================================================
756 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
757 +++ libdrm/nouveau-1/nouveau_channel.c  2013-03-06 16:27:49.807925019 +0100
758 @@ -0,0 +1,142 @@
759 +/*
760 + * Copyright 2007 Nouveau Project
761 + *
762 + * Permission is hereby granted, free of charge, to any person obtaining a
763 + * copy of this software and associated documentation files (the "Software"),
764 + * to deal in the Software without restriction, including without limitation
765 + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
766 + * and/or sell copies of the Software, and to permit persons to whom the
767 + * Software is furnished to do so, subject to the following conditions:
768 + *
769 + * The above copyright notice and this permission notice shall be included in
770 + * all copies or substantial portions of the Software.
771 + *
772 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
773 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
774 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
775 + * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
776 + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
777 + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
778 + * SOFTWARE.
779 + */
780 +
781 +#include <stdlib.h>
782 +#include <string.h>
783 +#include <errno.h>
784 +
785 +#include "nouveau_private.h"
786 +
787 +int
788 +nouveau_channel_alloc(struct nouveau_device *dev, uint32_t fb_ctxdma,
789 +                     uint32_t tt_ctxdma, int pushbuf_size,
790 +                     struct nouveau_channel **chan)
791 +{
792 +       struct nouveau_device_priv *nvdev = nouveau_device(dev);
793 +       struct nouveau_channel_priv *nvchan;
794 +       unsigned i;
795 +       int ret;
796 +
797 +       if (!nvdev || !chan || *chan)
798 +           return -EINVAL;
799 +
800 +       nvchan = calloc(1, sizeof(struct nouveau_channel_priv));
801 +       if (!nvchan)
802 +               return -ENOMEM;
803 +       nvchan->base.device = dev;
804 +
805 +       nvchan->drm.fb_ctxdma_handle = fb_ctxdma;
806 +       nvchan->drm.tt_ctxdma_handle = tt_ctxdma;
807 +       ret = drmCommandWriteRead(nvdev->fd, DRM_NOUVEAU_CHANNEL_ALLOC,
808 +                                 &nvchan->drm, sizeof(nvchan->drm));
809 +       if (ret) {
810 +               free(nvchan);
811 +               return ret;
812 +       }
813 +
814 +       nvchan->base.id = nvchan->drm.channel;
815 +       if (nouveau_grobj_ref(&nvchan->base, nvchan->drm.fb_ctxdma_handle,
816 +                             &nvchan->base.vram) ||
817 +           nouveau_grobj_ref(&nvchan->base, nvchan->drm.tt_ctxdma_handle,
818 +                             &nvchan->base.gart)) {
819 +               nouveau_channel_free((void *)&nvchan);
820 +               return -EINVAL;
821 +       }
822 +
823 +       /* Mark all DRM-assigned subchannels as in-use */
824 +       for (i = 0; i < nvchan->drm.nr_subchan; i++) {
825 +               struct nouveau_grobj_priv *gr = calloc(1, sizeof(*gr));
826 +
827 +               gr->base.bound = NOUVEAU_GROBJ_BOUND_EXPLICIT;
828 +               gr->base.subc = i;
829 +               gr->base.handle = nvchan->drm.subchan[i].handle;
830 +               gr->base.grclass = nvchan->drm.subchan[i].grclass;
831 +               gr->base.channel = &nvchan->base;
832 +
833 +               nvchan->base.subc[i].gr = &gr->base;
834 +       }
835 +
836 +       if (dev->chipset < 0xc0) {
837 +               ret = nouveau_bo_wrap(dev, nvchan->drm.notifier_handle,
838 +                                     &nvchan->notifier_bo);
839 +               if (!ret)
840 +                       ret = nouveau_bo_map(nvchan->notifier_bo,
841 +                                            NOUVEAU_BO_RDWR);
842 +               if (ret) {
843 +                       nouveau_channel_free((void *)&nvchan);
844 +                       return ret;
845 +               }
846 +
847 +               ret = nouveau_grobj_alloc(&nvchan->base, 0x00000000, 0x0030,
848 +                                         &nvchan->base.nullobj);
849 +               if (ret) {
850 +                       nouveau_channel_free((void *)&nvchan);
851 +                       return ret;
852 +               }
853 +       }
854 +
855 +       ret = nouveau_pushbuf_init(&nvchan->base, pushbuf_size);
856 +       if (ret) {
857 +               nouveau_channel_free((void *)&nvchan);
858 +               return ret;
859 +       }
860 +
861 +       *chan = &nvchan->base;
862 +       return 0;
863 +}
864 +
865 +void
866 +nouveau_channel_free(struct nouveau_channel **chan)
867 +{
868 +       struct nouveau_channel_priv *nvchan;
869 +       struct nouveau_device_priv *nvdev;
870 +       struct drm_nouveau_channel_free cf;
871 +       unsigned i;
872 +
873 +       if (!chan || !*chan)
874 +               return;
875 +       nvchan = nouveau_channel(*chan);
876 +       (*chan)->flush_notify = NULL;
877 +       *chan = NULL;
878 +       nvdev = nouveau_device(nvchan->base.device);
879 +
880 +       FIRE_RING(&nvchan->base);
881 +
882 +       nouveau_pushbuf_fini(&nvchan->base);
883 +       if (nvchan->notifier_bo) {
884 +               nouveau_bo_unmap(nvchan->notifier_bo);
885 +               nouveau_bo_ref(NULL, &nvchan->notifier_bo);
886 +       }
887 +
888 +       for (i = 0; i < nvchan->drm.nr_subchan; i++)
889 +               free(nvchan->base.subc[i].gr);
890 +
891 +       nouveau_grobj_free(&nvchan->base.vram);
892 +       nouveau_grobj_free(&nvchan->base.gart);
893 +       nouveau_grobj_free(&nvchan->base.nullobj);
894 +
895 +       cf.channel = nvchan->drm.channel;
896 +       drmCommandWrite(nvdev->fd, DRM_NOUVEAU_CHANNEL_FREE, &cf, sizeof(cf));
897 +       free(nvchan);
898 +}
899 +
900 +
901 Index: libdrm/nouveau-1/nouveau_channel.h
902 ===================================================================
903 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
904 +++ libdrm/nouveau-1/nouveau_channel.h  2013-03-06 16:27:49.807925019 +0100
905 @@ -0,0 +1,57 @@
906 +/*
907 + * Copyright 2007 Nouveau Project
908 + *
909 + * Permission is hereby granted, free of charge, to any person obtaining a
910 + * copy of this software and associated documentation files (the "Software"),
911 + * to deal in the Software without restriction, including without limitation
912 + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
913 + * and/or sell copies of the Software, and to permit persons to whom the
914 + * Software is furnished to do so, subject to the following conditions:
915 + *
916 + * The above copyright notice and this permission notice shall be included in
917 + * all copies or substantial portions of the Software.
918 + *
919 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
920 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
921 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
922 + * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
923 + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
924 + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
925 + * SOFTWARE.
926 + */
927 +
928 +#ifndef __NOUVEAU_CHANNEL_H__
929 +#define __NOUVEAU_CHANNEL_H__
930 +
931 +struct nouveau_subchannel {
932 +       struct nouveau_grobj *gr;
933 +       unsigned sequence;
934 +};
935 +
936 +struct nouveau_channel {
937 +       uint32_t *cur;
938 +       uint32_t *end;
939 +
940 +       struct nouveau_device *device;
941 +       int id;
942 +
943 +       struct nouveau_grobj *nullobj;
944 +       struct nouveau_grobj *vram;
945 +       struct nouveau_grobj *gart;
946 +
947 +       void *user_private;
948 +       void (*hang_notify)(struct nouveau_channel *);
949 +       void (*flush_notify)(struct nouveau_channel *);
950 +
951 +       struct nouveau_subchannel subc[8];
952 +       unsigned subc_sequence;
953 +};
954 +
955 +int
956 +nouveau_channel_alloc(struct nouveau_device *, uint32_t fb, uint32_t tt,
957 +                     int pushbuf_size, struct nouveau_channel **);
958 +
959 +void
960 +nouveau_channel_free(struct nouveau_channel **);
961 +
962 +#endif
963 Index: libdrm/nouveau-1/nouveau_device.c
964 ===================================================================
965 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
966 +++ libdrm/nouveau-1/nouveau_device.c   2013-03-06 16:27:49.807925019 +0100
967 @@ -0,0 +1,198 @@
968 +/*
969 + * Copyright 2007 Nouveau Project
970 + *
971 + * Permission is hereby granted, free of charge, to any person obtaining a
972 + * copy of this software and associated documentation files (the "Software"),
973 + * to deal in the Software without restriction, including without limitation
974 + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
975 + * and/or sell copies of the Software, and to permit persons to whom the
976 + * Software is furnished to do so, subject to the following conditions:
977 + *
978 + * The above copyright notice and this permission notice shall be included in
979 + * all copies or substantial portions of the Software.
980 + *
981 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
982 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
983 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
984 + * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
985 + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
986 + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
987 + * SOFTWARE.
988 + */
989 +
990 +#include <stdio.h>
991 +#include <stdlib.h>
992 +#include <errno.h>
993 +
994 +#include "nouveau_private.h"
995 +
996 +int
997 +nouveau_device_open_existing(struct nouveau_device **dev, int close,
998 +                            int fd, drm_context_t ctx)
999 +{
1000 +       struct nouveau_device_priv *nvdev;
1001 +       drmVersionPtr ver;
1002 +       uint64_t value;
1003 +       int ret;
1004 +
1005 +       if (!dev || *dev)
1006 +           return -EINVAL;
1007 +
1008 +       nvdev = calloc(1, sizeof(*nvdev));
1009 +       if (!nvdev)
1010 +           return -ENOMEM;
1011 +       nvdev->fd = fd;
1012 +       nvdev->ctx = ctx;
1013 +       nvdev->needs_close = close;
1014 +
1015 +       ver = drmGetVersion(fd);
1016 +       if (!ver) {
1017 +               nouveau_device_close((void *)&nvdev);
1018 +               return -EINVAL;
1019 +       }
1020 +
1021 +       if ((ver->version_major == 0 && ver->version_patchlevel != 16) ||
1022 +            ver->version_major > 1) {
1023 +               nouveau_device_close((void *)&nvdev);
1024 +               return -EINVAL;
1025 +       }
1026 +
1027 +       drmFreeVersion(ver);
1028 +
1029 +       ret = nouveau_device_get_param(&nvdev->base,
1030 +                                      NOUVEAU_GETPARAM_VM_VRAM_BASE, &value);
1031 +       if (ret) {
1032 +               nouveau_device_close((void *)&nvdev);
1033 +               return ret;
1034 +       }
1035 +       nvdev->base.vm_vram_base = value;
1036 +
1037 +       ret = nouveau_device_get_param(&nvdev->base,
1038 +                                      NOUVEAU_GETPARAM_FB_SIZE, &value);
1039 +       if (ret) {
1040 +               nouveau_device_close((void *)&nvdev);
1041 +               return ret;
1042 +       }
1043 +       nvdev->base.vm_vram_size = value;
1044 +
1045 +       ret = nouveau_device_get_param(&nvdev->base,
1046 +                                      NOUVEAU_GETPARAM_AGP_SIZE, &value);
1047 +       if (ret) {
1048 +               nouveau_device_close((void *)&nvdev);
1049 +               return ret;
1050 +       }
1051 +       nvdev->base.vm_gart_size = value;
1052 +
1053 +       ret = nouveau_bo_init(&nvdev->base);
1054 +       if (ret) {
1055 +               nouveau_device_close((void *)&nvdev);
1056 +               return ret;
1057 +       }
1058 +
1059 +       ret = nouveau_device_get_param(&nvdev->base,
1060 +                                      NOUVEAU_GETPARAM_CHIPSET_ID, &value);
1061 +       if (ret) {
1062 +               nouveau_device_close((void *)&nvdev);
1063 +               return ret;
1064 +       }
1065 +       nvdev->base.chipset = value;
1066 +
1067 +       ret = nouveau_device_get_param(&nvdev->base,
1068 +                                      NOUVEAU_GETPARAM_HAS_BO_USAGE, &value);
1069 +       if (!ret)
1070 +               nvdev->has_bo_usage = value;
1071 +
1072 +       *dev = &nvdev->base;
1073 +       return 0;
1074 +}
1075 +
1076 +int
1077 +nouveau_device_open(struct nouveau_device **dev, const char *busid)
1078 +{
1079 +       drm_context_t ctx;
1080 +       int fd, ret;
1081 +
1082 +       if (!dev || *dev)
1083 +               return -EINVAL;
1084 +
1085 +       fd = drmOpen("nouveau", busid);
1086 +       if (fd < 0)
1087 +               return -EINVAL;
1088 +
1089 +       ret = drmCreateContext(fd, &ctx);
1090 +       if (ret) {
1091 +               drmClose(fd);
1092 +               return ret;
1093 +       }
1094 +
1095 +       ret = nouveau_device_open_existing(dev, 1, fd, ctx);
1096 +       if (ret) {
1097 +           drmDestroyContext(fd, ctx);
1098 +           drmClose(fd);
1099 +           return ret;
1100 +       }
1101 +
1102 +       return 0;
1103 +}
1104 +
1105 +void
1106 +nouveau_device_close(struct nouveau_device **dev)
1107 +{
1108 +       struct nouveau_device_priv *nvdev;
1109 +
1110 +       if (!dev || !*dev)
1111 +               return;
1112 +       nvdev = nouveau_device(*dev);
1113 +       *dev = NULL;
1114 +
1115 +       nouveau_bo_takedown(&nvdev->base);
1116 +
1117 +       if (nvdev->needs_close) {
1118 +               drmDestroyContext(nvdev->fd, nvdev->ctx);
1119 +               drmClose(nvdev->fd);
1120 +       }
1121 +       free(nvdev);
1122 +}
1123 +
1124 +int
1125 +nouveau_device_get_param(struct nouveau_device *dev,
1126 +                        uint64_t param, uint64_t *value)
1127 +{
1128 +       struct nouveau_device_priv *nvdev = nouveau_device(dev);
1129 +       struct drm_nouveau_getparam g;
1130 +       int ret;
1131 +
1132 +       if (!nvdev || !value)
1133 +               return -EINVAL;
1134 +
1135 +       g.param = param;
1136 +       ret = drmCommandWriteRead(nvdev->fd, DRM_NOUVEAU_GETPARAM,
1137 +                                 &g, sizeof(g));
1138 +       if (ret)
1139 +               return ret;
1140 +
1141 +       *value = g.value;
1142 +       return 0;
1143 +}
1144 +
1145 +int
1146 +nouveau_device_set_param(struct nouveau_device *dev,
1147 +                        uint64_t param, uint64_t value)
1148 +{
1149 +       struct nouveau_device_priv *nvdev = nouveau_device(dev);
1150 +       struct drm_nouveau_setparam s;
1151 +       int ret;
1152 +
1153 +       if (!nvdev)
1154 +               return -EINVAL;
1155 +
1156 +       s.param = param;
1157 +       s.value = value;
1158 +       ret = drmCommandWriteRead(nvdev->fd, DRM_NOUVEAU_SETPARAM,
1159 +                                 &s, sizeof(s));
1160 +       if (ret)
1161 +               return ret;
1162 +
1163 +       return 0;
1164 +}
1165 +
1166 Index: libdrm/nouveau-1/nouveau_device.h
1167 ===================================================================
1168 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
1169 +++ libdrm/nouveau-1/nouveau_device.h   2013-03-06 16:27:49.807925019 +0100
1170 @@ -0,0 +1,33 @@
1171 +/*
1172 + * Copyright 2007 Nouveau Project
1173 + *
1174 + * Permission is hereby granted, free of charge, to any person obtaining a
1175 + * copy of this software and associated documentation files (the "Software"),
1176 + * to deal in the Software without restriction, including without limitation
1177 + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
1178 + * and/or sell copies of the Software, and to permit persons to whom the
1179 + * Software is furnished to do so, subject to the following conditions:
1180 + *
1181 + * The above copyright notice and this permission notice shall be included in
1182 + * all copies or substantial portions of the Software.
1183 + *
1184 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1185 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1186 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1187 + * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
1188 + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
1189 + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1190 + * SOFTWARE.
1191 + */
1192 +
1193 +#ifndef __NOUVEAU_DEVICE_H__
1194 +#define __NOUVEAU_DEVICE_H__
1195 +
1196 +struct nouveau_device {
1197 +       unsigned chipset;
1198 +       uint64_t vm_vram_base;
1199 +       uint64_t vm_vram_size;
1200 +       uint64_t vm_gart_size;
1201 +};
1202 +
1203 +#endif
1204 Index: libdrm/nouveau-1/nouveau_drmif.h
1205 ===================================================================
1206 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
1207 +++ libdrm/nouveau-1/nouveau_drmif.h    2013-03-06 16:27:49.811925019 +0100
1208 @@ -0,0 +1,58 @@
1209 +/*
1210 + * Copyright 2008 Nouveau Project
1211 + *
1212 + * Permission is hereby granted, free of charge, to any person obtaining a
1213 + * copy of this software and associated documentation files (the "Software"),
1214 + * to deal in the Software without restriction, including without limitation
1215 + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
1216 + * and/or sell copies of the Software, and to permit persons to whom the
1217 + * Software is furnished to do so, subject to the following conditions:
1218 + *
1219 + * The above copyright notice and this permission notice shall be included in
1220 + * all copies or substantial portions of the Software.
1221 + *
1222 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1223 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1224 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1225 + * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
1226 + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
1227 + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1228 + * SOFTWARE.
1229 + */
1230 +
1231 +#ifndef __NOUVEAU_DRMIF_H__
1232 +#define __NOUVEAU_DRMIF_H__
1233 +
1234 +#include <stdint.h>
1235 +#include <xf86drm.h>
1236 +
1237 +#include "nouveau_device.h"
1238 +
1239 +struct nouveau_device_priv {
1240 +       struct nouveau_device base;
1241 +
1242 +       int fd;
1243 +       drm_context_t ctx;
1244 +       drmLock *lock;
1245 +       int needs_close;
1246 +       int has_bo_usage;
1247 +};
1248 +#define nouveau_device(n) ((struct nouveau_device_priv *)(n))
1249 +
1250 +int
1251 +nouveau_device_open_existing(struct nouveau_device **, int close,
1252 +                            int fd, drm_context_t ctx);
1253 +
1254 +int
1255 +nouveau_device_open(struct nouveau_device **, const char *busid);
1256 +
1257 +void
1258 +nouveau_device_close(struct nouveau_device **);
1259 +
1260 +int
1261 +nouveau_device_get_param(struct nouveau_device *, uint64_t param, uint64_t *v);
1262 +
1263 +int
1264 +nouveau_device_set_param(struct nouveau_device *, uint64_t param, uint64_t val);
1265 +
1266 +#endif
1267 Index: libdrm/nouveau-1/nouveau_grobj.c
1268 ===================================================================
1269 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
1270 +++ libdrm/nouveau-1/nouveau_grobj.c    2013-03-06 16:27:49.811925019 +0100
1271 @@ -0,0 +1,148 @@
1272 +/*
1273 + * Copyright 2007 Nouveau Project
1274 + *
1275 + * Permission is hereby granted, free of charge, to any person obtaining a
1276 + * copy of this software and associated documentation files (the "Software"),
1277 + * to deal in the Software without restriction, including without limitation
1278 + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
1279 + * and/or sell copies of the Software, and to permit persons to whom the
1280 + * Software is furnished to do so, subject to the following conditions:
1281 + *
1282 + * The above copyright notice and this permission notice shall be included in
1283 + * all copies or substantial portions of the Software.
1284 + *
1285 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1286 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1287 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1288 + * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
1289 + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
1290 + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1291 + * SOFTWARE.
1292 + */
1293 +
1294 +#include <stdlib.h>
1295 +#include <errno.h>
1296 +
1297 +#include "nouveau_private.h"
1298 +
1299 +int
1300 +nouveau_grobj_alloc(struct nouveau_channel *chan, uint32_t handle,
1301 +                   int class, struct nouveau_grobj **grobj)
1302 +{
1303 +       struct nouveau_device_priv *nvdev = nouveau_device(chan->device);
1304 +       struct nouveau_grobj_priv *nvgrobj;
1305 +       struct drm_nouveau_grobj_alloc g;
1306 +       int ret;
1307 +
1308 +       if (!nvdev || !grobj || *grobj)
1309 +               return -EINVAL;
1310 +
1311 +       nvgrobj = calloc(1, sizeof(*nvgrobj));
1312 +       if (!nvgrobj)
1313 +               return -ENOMEM;
1314 +       nvgrobj->base.channel = chan;
1315 +       nvgrobj->base.handle  = handle;
1316 +       nvgrobj->base.grclass = class;
1317 +       nvgrobj->base.bound   = NOUVEAU_GROBJ_UNBOUND;
1318 +       nvgrobj->base.subc    = -1;
1319 +
1320 +       g.channel = chan->id;
1321 +       g.handle  = handle;
1322 +       g.class   = class;
1323 +       ret = drmCommandWrite(nvdev->fd, DRM_NOUVEAU_GROBJ_ALLOC,
1324 +                             &g, sizeof(g));
1325 +       if (ret) {
1326 +               nouveau_grobj_free((void *)&nvgrobj);
1327 +               return ret;
1328 +       }
1329 +
1330 +       *grobj = &nvgrobj->base;
1331 +       return 0;
1332 +}
1333 +
1334 +int
1335 +nouveau_grobj_ref(struct nouveau_channel *chan, uint32_t handle,
1336 +                 struct nouveau_grobj **grobj)
1337 +{
1338 +       struct nouveau_grobj_priv *nvgrobj;
1339 +
1340 +       if (!chan || !grobj || *grobj)
1341 +               return -EINVAL;
1342 +
1343 +       nvgrobj = calloc(1, sizeof(struct nouveau_grobj_priv));
1344 +       if (!nvgrobj)
1345 +               return -ENOMEM;
1346 +       nvgrobj->base.channel = chan;
1347 +       nvgrobj->base.handle = handle;
1348 +       nvgrobj->base.grclass = 0;
1349 +
1350 +       *grobj = &nvgrobj->base;
1351 +       return 0;
1352 +}
1353 +
1354 +void
1355 +nouveau_grobj_free(struct nouveau_grobj **grobj)
1356 +{
1357 +       struct nouveau_device_priv *nvdev;
1358 +       struct nouveau_channel_priv *chan;
1359 +       struct nouveau_grobj_priv *nvgrobj;
1360 +
1361 +       if (!grobj || !*grobj)
1362 +               return;
1363 +       nvgrobj = nouveau_grobj(*grobj);
1364 +       *grobj = NULL;
1365 +
1366 +
1367 +       chan = nouveau_channel(nvgrobj->base.channel);
1368 +       nvdev = nouveau_device(chan->base.device);
1369 +
1370 +       if (nvgrobj->base.grclass) {
1371 +               struct drm_nouveau_gpuobj_free f;
1372 +
1373 +               FIRE_RING(&chan->base);
1374 +               f.channel = chan->drm.channel;
1375 +               f.handle  = nvgrobj->base.handle;
1376 +               drmCommandWrite(nvdev->fd, DRM_NOUVEAU_GPUOBJ_FREE,
1377 +                               &f, sizeof(f)); 
1378 +       }
1379 +       if (nvgrobj->base.bound != NOUVEAU_GROBJ_UNBOUND)
1380 +               chan->base.subc[nvgrobj->base.subc].gr = NULL;
1381 +       free(nvgrobj);
1382 +}
1383 +
1384 +void
1385 +nouveau_grobj_autobind(struct nouveau_grobj *grobj)
1386 +{
1387 +       struct nouveau_channel *chan = grobj->channel;
1388 +       struct nouveau_subchannel *subc = NULL;
1389 +       int i;
1390 +
1391 +       for (i = 0; i < 8; i++) {
1392 +               struct nouveau_subchannel *scc = &grobj->channel->subc[i];
1393 +
1394 +               if (scc->gr && scc->gr->bound == NOUVEAU_GROBJ_BOUND_EXPLICIT)
1395 +                       continue;
1396 +
1397 +               if (!subc || scc->sequence < subc->sequence)
1398 +                       subc = scc;
1399 +       }
1400 +
1401 +       if (subc->gr) {
1402 +               subc->gr->bound = NOUVEAU_GROBJ_UNBOUND;
1403 +               subc->gr->subc  = -1;
1404 +       }
1405 +
1406 +       subc->gr = grobj;
1407 +       subc->gr->bound = NOUVEAU_GROBJ_BOUND;
1408 +       subc->gr->subc  = subc - &grobj->channel->subc[0];
1409 +
1410 +       WAIT_RING(chan, 2);
1411 +       if (chan->device->chipset < 0xc0) {
1412 +               OUT_RING (chan, (1 << 18) | (grobj->subc << 13));
1413 +               OUT_RING (chan, grobj->handle);
1414 +       } else {
1415 +               OUT_RING (chan, (2 << 28) | (1 << 16) | (grobj->subc << 13));
1416 +               OUT_RING (chan, grobj->grclass);
1417 +       }
1418 +}
1419 +
1420 Index: libdrm/nouveau-1/nouveau_grobj.h
1421 ===================================================================
1422 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
1423 +++ libdrm/nouveau-1/nouveau_grobj.h    2013-03-06 16:27:49.811925019 +0100
1424 @@ -0,0 +1,48 @@
1425 +/*
1426 + * Copyright 2007 Nouveau Project
1427 + *
1428 + * Permission is hereby granted, free of charge, to any person obtaining a
1429 + * copy of this software and associated documentation files (the "Software"),
1430 + * to deal in the Software without restriction, including without limitation
1431 + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
1432 + * and/or sell copies of the Software, and to permit persons to whom the
1433 + * Software is furnished to do so, subject to the following conditions:
1434 + *
1435 + * The above copyright notice and this permission notice shall be included in
1436 + * all copies or substantial portions of the Software.
1437 + *
1438 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1439 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1440 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1441 + * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
1442 + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
1443 + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1444 + * SOFTWARE.
1445 + */
1446 +
1447 +#ifndef __NOUVEAU_GROBJ_H__
1448 +#define __NOUVEAU_GROBJ_H__
1449 +
1450 +#include "nouveau_channel.h"
1451 +
1452 +struct nouveau_grobj {
1453 +       struct nouveau_channel *channel;
1454 +       int grclass;
1455 +       uint32_t handle;
1456 +
1457 +       enum {
1458 +               NOUVEAU_GROBJ_UNBOUND = 0,
1459 +               NOUVEAU_GROBJ_BOUND = 1,
1460 +               NOUVEAU_GROBJ_BOUND_EXPLICIT = 2
1461 +       } bound;
1462 +       int subc;
1463 +};
1464 +
1465 +int nouveau_grobj_alloc(struct nouveau_channel *, uint32_t handle,
1466 +                              int class, struct nouveau_grobj **);
1467 +int nouveau_grobj_ref(struct nouveau_channel *, uint32_t handle,
1468 +                            struct nouveau_grobj **);
1469 +void nouveau_grobj_free(struct nouveau_grobj **);
1470 +void nouveau_grobj_autobind(struct nouveau_grobj *);
1471 +
1472 +#endif
1473 Index: libdrm/nouveau-1/nouveau_notifier.c
1474 ===================================================================
1475 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
1476 +++ libdrm/nouveau-1/nouveau_notifier.c 2013-03-06 16:27:49.811925019 +0100
1477 @@ -0,0 +1,148 @@
1478 +/*
1479 + * Copyright 2007 Nouveau Project
1480 + *
1481 + * Permission is hereby granted, free of charge, to any person obtaining a
1482 + * copy of this software and associated documentation files (the "Software"),
1483 + * to deal in the Software without restriction, including without limitation
1484 + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
1485 + * and/or sell copies of the Software, and to permit persons to whom the
1486 + * Software is furnished to do so, subject to the following conditions:
1487 + *
1488 + * The above copyright notice and this permission notice shall be included in
1489 + * all copies or substantial portions of the Software.
1490 + *
1491 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1492 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1493 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1494 + * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
1495 + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
1496 + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1497 + * SOFTWARE.
1498 + */
1499 +
1500 +#include <stdlib.h>
1501 +#include <errno.h>
1502 +#include <sys/time.h>
1503 +
1504 +#include "nouveau_private.h"
1505 +
1506 +#define NOTIFIER(__v)                                                          \
1507 +       struct nouveau_notifier_priv *nvnotify = nouveau_notifier(notifier);   \
1508 +       volatile uint32_t *__v = (uint32_t *)((char *)nvnotify->map + (id * 32))
1509 +
1510 +int
1511 +nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle,
1512 +                      int count, struct nouveau_notifier **notifier)
1513 +{
1514 +       struct nouveau_notifier_priv *nvnotify;
1515 +       int ret;
1516 +
1517 +       if (!chan || !notifier || *notifier)
1518 +               return -EINVAL;
1519 +
1520 +       nvnotify = calloc(1, sizeof(struct nouveau_notifier_priv));
1521 +       if (!nvnotify)
1522 +               return -ENOMEM;
1523 +       nvnotify->base.channel = chan;
1524 +       nvnotify->base.handle  = handle;
1525 +
1526 +       nvnotify->drm.channel = chan->id;
1527 +       nvnotify->drm.handle  = handle;
1528 +       nvnotify->drm.size    = (count * 32);
1529 +       if ((ret = drmCommandWriteRead(nouveau_device(chan->device)->fd,
1530 +                                      DRM_NOUVEAU_NOTIFIEROBJ_ALLOC,
1531 +                                      &nvnotify->drm,
1532 +                                      sizeof(nvnotify->drm)))) {
1533 +               nouveau_notifier_free((void *)&nvnotify);
1534 +               return ret;
1535 +       }
1536 +
1537 +       nvnotify->map = (char *)nouveau_channel(chan)->notifier_bo->map +
1538 +                               nvnotify->drm.offset;
1539 +       *notifier = &nvnotify->base;
1540 +       return 0;
1541 +}
1542 +
1543 +void
1544 +nouveau_notifier_free(struct nouveau_notifier **notifier)
1545 +{
1546 +
1547 +       struct nouveau_notifier_priv *nvnotify;
1548 +       struct nouveau_channel_priv *nvchan;
1549 +       struct nouveau_device_priv *nvdev;
1550 +       struct drm_nouveau_gpuobj_free f;
1551 +
1552 +       if (!notifier || !*notifier)
1553 +               return;
1554 +       nvnotify = nouveau_notifier(*notifier);
1555 +       *notifier = NULL;
1556 +
1557 +       nvchan = nouveau_channel(nvnotify->base.channel);
1558 +       nvdev   = nouveau_device(nvchan->base.device);
1559 +
1560 +       FIRE_RING(&nvchan->base);
1561 +
1562 +       f.channel = nvchan->drm.channel;
1563 +       f.handle  = nvnotify->base.handle;
1564 +       drmCommandWrite(nvdev->fd, DRM_NOUVEAU_GPUOBJ_FREE, &f, sizeof(f));             
1565 +       free(nvnotify);
1566 +}
1567 +
1568 +void
1569 +nouveau_notifier_reset(struct nouveau_notifier *notifier, int id)
1570 +{
1571 +       NOTIFIER(n);
1572 +
1573 +       n[NV_NOTIFY_TIME_0      /4] = 0x00000000;
1574 +       n[NV_NOTIFY_TIME_1      /4] = 0x00000000;
1575 +       n[NV_NOTIFY_RETURN_VALUE/4] = 0x00000000;
1576 +       n[NV_NOTIFY_STATE       /4] = (NV_NOTIFY_STATE_STATUS_IN_PROCESS <<
1577 +                                      NV_NOTIFY_STATE_STATUS_SHIFT);
1578 +}
1579 +
1580 +uint32_t
1581 +nouveau_notifier_status(struct nouveau_notifier *notifier, int id)
1582 +{
1583 +       NOTIFIER(n);
1584 +
1585 +       return n[NV_NOTIFY_STATE/4] >> NV_NOTIFY_STATE_STATUS_SHIFT;
1586 +}
1587 +
1588 +uint32_t
1589 +nouveau_notifier_return_val(struct nouveau_notifier *notifier, int id)
1590 +{
1591 +       NOTIFIER(n);
1592 +
1593 +       return n[NV_NOTIFY_RETURN_VALUE/4];
1594 +}
1595 +
1596 +static inline double
1597 +gettime(void)
1598 +{
1599 +       struct timeval tv;
1600 +
1601 +       gettimeofday(&tv, NULL);
1602 +       return (double)tv.tv_sec + tv.tv_usec / 1000000.0;
1603 +}
1604 +
1605 +int
1606 +nouveau_notifier_wait_status(struct nouveau_notifier *notifier, int id,
1607 +                            uint32_t status, double timeout)
1608 +{
1609 +       NOTIFIER(n);
1610 +       double time = 0, t_start = gettime();
1611 +
1612 +       while (time <= timeout) {
1613 +               uint32_t v;
1614 +
1615 +               v = n[NV_NOTIFY_STATE/4] >> NV_NOTIFY_STATE_STATUS_SHIFT;
1616 +               if (v == status)
1617 +                       return 0;
1618 +
1619 +               if (timeout)
1620 +                       time = gettime() - t_start;
1621 +       }
1622 +
1623 +       return -EBUSY;
1624 +}
1625 +
1626 Index: libdrm/nouveau-1/nouveau_notifier.h
1627 ===================================================================
1628 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
1629 +++ libdrm/nouveau-1/nouveau_notifier.h 2013-03-06 16:27:49.811925019 +0100
1630 @@ -0,0 +1,63 @@
1631 +/*
1632 + * Copyright 2007 Nouveau Project
1633 + *
1634 + * Permission is hereby granted, free of charge, to any person obtaining a
1635 + * copy of this software and associated documentation files (the "Software"),
1636 + * to deal in the Software without restriction, including without limitation
1637 + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
1638 + * and/or sell copies of the Software, and to permit persons to whom the
1639 + * Software is furnished to do so, subject to the following conditions:
1640 + *
1641 + * The above copyright notice and this permission notice shall be included in
1642 + * all copies or substantial portions of the Software.
1643 + *
1644 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1645 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1646 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1647 + * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
1648 + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
1649 + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1650 + * SOFTWARE.
1651 + */
1652 +
1653 +#ifndef __NOUVEAU_NOTIFIER_H__
1654 +#define __NOUVEAU_NOTIFIER_H__
1655 +
1656 +#define NV_NOTIFIER_SIZE                                                      32
1657 +#define NV_NOTIFY_TIME_0                                              0x00000000
1658 +#define NV_NOTIFY_TIME_1                                              0x00000004
1659 +#define NV_NOTIFY_RETURN_VALUE                                        0x00000008
1660 +#define NV_NOTIFY_STATE                                               0x0000000C
1661 +#define NV_NOTIFY_STATE_STATUS_MASK                                   0xFF000000
1662 +#define NV_NOTIFY_STATE_STATUS_SHIFT                                          24
1663 +#define NV_NOTIFY_STATE_STATUS_COMPLETED                                    0x00
1664 +#define NV_NOTIFY_STATE_STATUS_IN_PROCESS                                   0x01
1665 +#define NV_NOTIFY_STATE_ERROR_CODE_MASK                               0x0000FFFF
1666 +#define NV_NOTIFY_STATE_ERROR_CODE_SHIFT                                       0
1667 +
1668 +struct nouveau_notifier {
1669 +       struct nouveau_channel *channel;
1670 +       uint32_t handle;
1671 +};
1672 +
1673 +int
1674 +nouveau_notifier_alloc(struct nouveau_channel *, uint32_t handle, int count,
1675 +                      struct nouveau_notifier **);
1676 +
1677 +void
1678 +nouveau_notifier_free(struct nouveau_notifier **);
1679 +
1680 +void
1681 +nouveau_notifier_reset(struct nouveau_notifier *, int id);
1682 +
1683 +uint32_t
1684 +nouveau_notifier_status(struct nouveau_notifier *, int id);
1685 +
1686 +uint32_t
1687 +nouveau_notifier_return_val(struct nouveau_notifier *, int id);
1688 +
1689 +int
1690 +nouveau_notifier_wait_status(struct nouveau_notifier *, int id, uint32_t status,
1691 +                            double timeout);
1692 +
1693 +#endif
1694 Index: libdrm/nouveau-1/nouveau_private.h
1695 ===================================================================
1696 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
1697 +++ libdrm/nouveau-1/nouveau_private.h  2013-03-06 16:27:49.823925019 +0100
1698 @@ -0,0 +1,136 @@
1699 +/*
1700 + * Copyright 2007 Nouveau Project
1701 + *
1702 + * Permission is hereby granted, free of charge, to any person obtaining a
1703 + * copy of this software and associated documentation files (the "Software"),
1704 + * to deal in the Software without restriction, including without limitation
1705 + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
1706 + * and/or sell copies of the Software, and to permit persons to whom the
1707 + * Software is furnished to do so, subject to the following conditions:
1708 + *
1709 + * The above copyright notice and this permission notice shall be included in
1710 + * all copies or substantial portions of the Software.
1711 + *
1712 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1713 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1714 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1715 + * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
1716 + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
1717 + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1718 + * SOFTWARE.
1719 + */
1720 +
1721 +#ifndef __NOUVEAU_PRIVATE_H__
1722 +#define __NOUVEAU_PRIVATE_H__
1723 +
1724 +#include <stdint.h>
1725 +#include <xf86drm.h>
1726 +#include <nouveau_drm.h>
1727 +
1728 +#include "nouveau_drmif.h"
1729 +#include "nouveau_device.h"
1730 +#include "nouveau_channel.h"
1731 +#include "nouveau_grobj.h"
1732 +#include "nouveau_notifier.h"
1733 +#include "nouveau_bo.h"
1734 +#include "nouveau_resource.h"
1735 +#include "nouveau_pushbuf.h"
1736 +#include "nouveau_reloc.h"
1737 +
1738 +#define CALPB_BUFFERS 3
1739 +
1740 +struct nouveau_pushbuf_priv {
1741 +       uint32_t cal_suffix0;
1742 +       uint32_t cal_suffix1;
1743 +       struct nouveau_bo *buffer[CALPB_BUFFERS];
1744 +       int current;
1745 +       int current_offset;
1746 +
1747 +       unsigned *pushbuf;
1748 +       unsigned size;
1749 +
1750 +       uint32_t *marker;
1751 +       unsigned marker_offset;
1752 +       unsigned marker_relocs;
1753 +       unsigned marker_push;
1754 +
1755 +       struct drm_nouveau_gem_pushbuf_bo *buffers;
1756 +       unsigned nr_buffers;
1757 +       struct drm_nouveau_gem_pushbuf_reloc *relocs;
1758 +       unsigned nr_relocs;
1759 +       struct drm_nouveau_gem_pushbuf_push push[NOUVEAU_GEM_MAX_PUSH];
1760 +       unsigned nr_push;
1761 +};
1762 +#define nouveau_pushbuf(n) ((struct nouveau_pushbuf_priv *)(n))
1763 +
1764 +int
1765 +nouveau_pushbuf_init(struct nouveau_channel *, int buf_size);
1766 +void
1767 +nouveau_pushbuf_fini(struct nouveau_channel *);
1768 +
1769 +struct nouveau_channel_priv {
1770 +       struct nouveau_channel base;
1771 +
1772 +       struct drm_nouveau_channel_alloc drm;
1773 +
1774 +       struct nouveau_bo *notifier_bo;
1775 +
1776 +       struct nouveau_pushbuf_priv pb;
1777 +};
1778 +#define nouveau_channel(n) ((struct nouveau_channel_priv *)(n))
1779 +
1780 +struct nouveau_grobj_priv {
1781 +       struct nouveau_grobj base;
1782 +};
1783 +#define nouveau_grobj(n) ((struct nouveau_grobj_priv *)(n))
1784 +
1785 +struct nouveau_notifier_priv {
1786 +       struct nouveau_notifier base;
1787 +
1788 +       struct drm_nouveau_notifierobj_alloc drm;
1789 +       volatile void *map;
1790 +};
1791 +#define nouveau_notifier(n) ((struct nouveau_notifier_priv *)(n))
1792 +
1793 +struct nouveau_bo_priv {
1794 +       struct nouveau_bo base;
1795 +       int refcount;
1796 +
1797 +       /* Buffer configuration + usage hints */
1798 +       unsigned flags;
1799 +       unsigned size;
1800 +       unsigned align;
1801 +       int user;
1802 +
1803 +       /* Tracking */
1804 +       struct drm_nouveau_gem_pushbuf_bo *pending;
1805 +       struct nouveau_channel *pending_channel;
1806 +       int pending_refcnt;
1807 +       int write_marker;
1808 +
1809 +       /* Userspace object */
1810 +       void *sysmem;
1811 +
1812 +       /* Kernel object */
1813 +       uint32_t global_handle;
1814 +       drm_handle_t handle;
1815 +       uint64_t map_handle;
1816 +       int map_refcnt;
1817 +       void *map;
1818 +
1819 +       /* Last known information from kernel on buffer status */
1820 +       uint64_t offset;
1821 +       uint32_t domain;
1822 +};
1823 +#define nouveau_bo(n) ((struct nouveau_bo_priv *)(n))
1824 +
1825 +int
1826 +nouveau_bo_init(struct nouveau_device *);
1827 +
1828 +void
1829 +nouveau_bo_takedown(struct nouveau_device *);
1830 +
1831 +struct drm_nouveau_gem_pushbuf_bo *
1832 +nouveau_bo_emit_buffer(struct nouveau_channel *, struct nouveau_bo *);
1833 +
1834 +#endif
1835 Index: libdrm/nouveau-1/nouveau_pushbuf.c
1836 ===================================================================
1837 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
1838 +++ libdrm/nouveau-1/nouveau_pushbuf.c  2013-03-06 16:27:49.823925019 +0100
1839 @@ -0,0 +1,344 @@
1840 +/*
1841 + * Copyright 2007 Nouveau Project
1842 + *
1843 + * Permission is hereby granted, free of charge, to any person obtaining a
1844 + * copy of this software and associated documentation files (the "Software"),
1845 + * to deal in the Software without restriction, including without limitation
1846 + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
1847 + * and/or sell copies of the Software, and to permit persons to whom the
1848 + * Software is furnished to do so, subject to the following conditions:
1849 + *
1850 + * The above copyright notice and this permission notice shall be included in
1851 + * all copies or substantial portions of the Software.
1852 + *
1853 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1854 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1855 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1856 + * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
1857 + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
1858 + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1859 + * SOFTWARE.
1860 + */
1861 +
1862 +#include <stdio.h>
1863 +#include <stdlib.h>
1864 +#include <errno.h>
1865 +#include <assert.h>
1866 +
1867 +#include "nouveau_private.h"
1868 +
1869 +#define PB_BUFMGR_DWORDS   (4096 / 2)
1870 +#define PB_MIN_USER_DWORDS  2048
1871 +
1872 +static int
1873 +nouveau_pushbuf_space(struct nouveau_channel *chan, unsigned min)
1874 +{
1875 +       struct nouveau_channel_priv *nvchan = nouveau_channel(chan);
1876 +       struct nouveau_pushbuf_priv *nvpb = &nvchan->pb;
1877 +       struct nouveau_bo *bo;
1878 +       int ret;
1879 +
1880 +       if (min < PB_MIN_USER_DWORDS)
1881 +               min = PB_MIN_USER_DWORDS;
1882 +
1883 +       nvpb->current_offset = chan->cur - nvpb->pushbuf;
1884 +       if (chan->cur + min + 2 <= chan->end)
1885 +               return 0;
1886 +
1887 +       nvpb->current++;
1888 +       if (nvpb->current == CALPB_BUFFERS)
1889 +               nvpb->current = 0;
1890 +       bo = nvpb->buffer[nvpb->current];
1891 +
1892 +       ret = nouveau_bo_map(bo, NOUVEAU_BO_WR);
1893 +       if (ret)
1894 +               return ret;
1895 +
1896 +       nvpb->size = (bo->size - 8) / 4;
1897 +       nvpb->pushbuf = bo->map;
1898 +       nvpb->current_offset = 0;
1899 +
1900 +       chan->cur = nvpb->pushbuf;
1901 +       chan->end = nvpb->pushbuf + nvpb->size;
1902 +
1903 +       nouveau_bo_unmap(bo);
1904 +       return 0;
1905 +}
1906 +
1907 +static void
1908 +nouveau_pushbuf_fini_call(struct nouveau_channel *chan)
1909 +{
1910 +       struct nouveau_channel_priv *nvchan = nouveau_channel(chan);
1911 +       struct nouveau_pushbuf_priv *nvpb = &nvchan->pb;
1912 +       int i;
1913 +
1914 +       for (i = 0; i < CALPB_BUFFERS; i++)
1915 +               nouveau_bo_ref(NULL, &nvpb->buffer[i]);
1916 +       nvpb->pushbuf = NULL;
1917 +}
1918 +
1919 +static int
1920 +nouveau_pushbuf_init_call(struct nouveau_channel *chan, int buf_size)
1921 +{
1922 +       struct drm_nouveau_gem_pushbuf req;
1923 +       struct nouveau_channel_priv *nvchan = nouveau_channel(chan);
1924 +       struct nouveau_pushbuf_priv *nvpb = &nvchan->pb;
1925 +       struct nouveau_device *dev = chan->device;
1926 +       uint32_t flags = 0;
1927 +       int i, ret;
1928 +
1929 +       if (nvchan->drm.pushbuf_domains & NOUVEAU_GEM_DOMAIN_GART)
1930 +               flags |= NOUVEAU_BO_GART;
1931 +       else
1932 +               flags |= NOUVEAU_BO_VRAM;
1933 +
1934 +       req.channel = chan->id;
1935 +       req.nr_push = 0;
1936 +       ret = drmCommandWriteRead(nouveau_device(dev)->fd,
1937 +                                 DRM_NOUVEAU_GEM_PUSHBUF, &req, sizeof(req));
1938 +       if (ret)
1939 +               return ret;
1940 +
1941 +       for (i = 0; i < CALPB_BUFFERS; i++) {
1942 +               ret = nouveau_bo_new(dev, flags | NOUVEAU_BO_MAP,
1943 +                                    0, buf_size, &nvpb->buffer[i]);
1944 +               if (ret) {
1945 +                       nouveau_pushbuf_fini_call(chan);
1946 +                       return ret;
1947 +               }
1948 +       }
1949 +
1950 +       nvpb->cal_suffix0 = req.suffix0;
1951 +       nvpb->cal_suffix1 = req.suffix1;
1952 +       return 0;
1953 +}
1954 +
1955 +int
1956 +nouveau_pushbuf_init(struct nouveau_channel *chan, int buf_size)
1957 +{
1958 +       struct nouveau_channel_priv *nvchan = nouveau_channel(chan);
1959 +       struct nouveau_pushbuf_priv *nvpb = &nvchan->pb;
1960 +       int ret;
1961 +
1962 +       ret = nouveau_pushbuf_init_call(chan, buf_size);
1963 +       if (ret)
1964 +               return ret;
1965 +
1966 +       ret = nouveau_pushbuf_space(chan, 0);
1967 +       if (ret)
1968 +               return ret;
1969 +
1970 +       nvpb->buffers = calloc(NOUVEAU_GEM_MAX_BUFFERS,
1971 +                              sizeof(struct drm_nouveau_gem_pushbuf_bo));
1972 +       nvpb->relocs = calloc(NOUVEAU_GEM_MAX_RELOCS,
1973 +                             sizeof(struct drm_nouveau_gem_pushbuf_reloc));
1974 +       return 0;
1975 +}
1976 +
1977 +void
1978 +nouveau_pushbuf_fini(struct nouveau_channel *chan)
1979 +{
1980 +       struct nouveau_channel_priv *nvchan = nouveau_channel(chan);
1981 +       struct nouveau_pushbuf_priv *nvpb = &nvchan->pb;
1982 +       nouveau_pushbuf_fini_call(chan);
1983 +       free(nvpb->buffers);
1984 +       free(nvpb->relocs);
1985 +}
1986 +
1987 +static int
1988 +nouveau_pushbuf_bo_add(struct nouveau_channel *chan, struct nouveau_bo *bo,
1989 +                      unsigned offset, unsigned length)
1990 +{
1991 +       struct nouveau_channel_priv *nvchan = nouveau_channel(chan);
1992 +       struct nouveau_pushbuf_priv *nvpb = &nvchan->pb;
1993 +       struct drm_nouveau_gem_pushbuf_push *p = &nvpb->push[nvpb->nr_push++];
1994 +       struct drm_nouveau_gem_pushbuf_bo *pbbo;
1995 +       struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
1996 +
1997 +       pbbo = nouveau_bo_emit_buffer(chan, bo);
1998 +       if (!pbbo)
1999 +               return -ENOMEM;
2000 +       pbbo->valid_domains &= nvchan->drm.pushbuf_domains;
2001 +       pbbo->read_domains |= nvchan->drm.pushbuf_domains;
2002 +       nvbo->pending_refcnt++;
2003 +
2004 +       p->bo_index = pbbo - nvpb->buffers;
2005 +       p->offset = offset;
2006 +       p->length = length;
2007 +       return 0;
2008 +}
2009 +
2010 +int
2011 +nouveau_pushbuf_submit(struct nouveau_channel *chan, struct nouveau_bo *bo,
2012 +                      unsigned offset, unsigned length)
2013 +{
2014 +       struct nouveau_pushbuf_priv *nvpb = &nouveau_channel(chan)->pb;
2015 +       int ret, len;
2016 +
2017 +       if ((AVAIL_RING(chan) + nvpb->current_offset) != nvpb->size) {
2018 +               if (nvpb->cal_suffix0 || nvpb->cal_suffix1) {
2019 +                       *(chan->cur++) = nvpb->cal_suffix0;
2020 +                       *(chan->cur++) = nvpb->cal_suffix1;
2021 +               }
2022 +
2023 +               len = (chan->cur - nvpb->pushbuf) - nvpb->current_offset;
2024 +
2025 +               ret = nouveau_pushbuf_bo_add(chan, nvpb->buffer[nvpb->current],
2026 +                                            nvpb->current_offset * 4, len * 4);
2027 +               if (ret)
2028 +                       return ret;
2029 +
2030 +               nvpb->current_offset += len;
2031 +       }
2032 +
2033 +       return bo ? nouveau_pushbuf_bo_add(chan, bo, offset, length) : 0;
2034 +}
2035 +
2036 +static void
2037 +nouveau_pushbuf_bo_unref(struct nouveau_pushbuf_priv *nvpb, int index)
2038 +{
2039 +       struct drm_nouveau_gem_pushbuf_bo *pbbo = &nvpb->buffers[index];
2040 +       struct nouveau_bo *bo = (void *)(unsigned long)pbbo->user_priv;
2041 +       struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
2042 +
2043 +       if (--nvbo->pending_refcnt)
2044 +               return;
2045 +
2046 +       if (pbbo->presumed.valid == 0) {
2047 +               nvbo->domain = pbbo->presumed.domain;
2048 +               nvbo->offset = pbbo->presumed.offset;
2049 +       }
2050 +
2051 +       nvbo->pending = NULL;
2052 +       nouveau_bo_ref(NULL, &bo);
2053 +
2054 +       /* we only ever remove from the tail of the pending lists,
2055 +        * so this is safe.
2056 +        */
2057 +       nvpb->nr_buffers--;
2058 +}
2059 +
2060 +int
2061 +nouveau_pushbuf_flush(struct nouveau_channel *chan, unsigned min)
2062 +{
2063 +       struct nouveau_device_priv *nvdev = nouveau_device(chan->device);
2064 +       struct nouveau_channel_priv *nvchan = nouveau_channel(chan);
2065 +       struct nouveau_pushbuf_priv *nvpb = &nvchan->pb;
2066 +       struct drm_nouveau_gem_pushbuf req;
2067 +       unsigned i;
2068 +       int ret;
2069 +
2070 +       ret = nouveau_pushbuf_submit(chan, NULL, 0, 0);
2071 +       if (ret)
2072 +               return ret;
2073 +
2074 +       if (!nvpb->nr_push)
2075 +               return 0;
2076 +
2077 +       req.channel = chan->id;
2078 +       req.nr_push = nvpb->nr_push;
2079 +       req.push = (uint64_t)(unsigned long)nvpb->push;
2080 +       req.nr_buffers = nvpb->nr_buffers;
2081 +       req.buffers = (uint64_t)(unsigned long)nvpb->buffers;
2082 +       req.nr_relocs = nvpb->nr_relocs;
2083 +       req.relocs = (uint64_t)(unsigned long)nvpb->relocs;
2084 +       req.suffix0 = nvpb->cal_suffix0;
2085 +       req.suffix1 = nvpb->cal_suffix1;
2086 +
2087 +       do {
2088 +               ret = drmCommandWriteRead(nvdev->fd, DRM_NOUVEAU_GEM_PUSHBUF,
2089 +                                         &req, sizeof(req));
2090 +       } while (ret == -EAGAIN);
2091 +       nvpb->cal_suffix0 = req.suffix0;
2092 +       nvpb->cal_suffix1 = req.suffix1;
2093 +       nvdev->base.vm_vram_size = req.vram_available;
2094 +       nvdev->base.vm_gart_size = req.gart_available;
2095 +
2096 +       /* Update presumed offset/domain for any buffers that moved.
2097 +        * Dereference all buffers on validate list
2098 +        */
2099 +       for (i = 0; i < nvpb->nr_relocs; i++) {
2100 +               nouveau_pushbuf_bo_unref(nvpb, nvpb->relocs[i].bo_index);
2101 +               nouveau_pushbuf_bo_unref(nvpb, nvpb->relocs[i].reloc_bo_index);
2102 +       }
2103 +
2104 +       for (i = 0; i < nvpb->nr_push; i++)
2105 +               nouveau_pushbuf_bo_unref(nvpb, nvpb->push[i].bo_index);
2106 +
2107 +       nvpb->nr_buffers = 0;
2108 +       nvpb->nr_relocs = 0;
2109 +       nvpb->nr_push = 0;
2110 +
2111 +       /* Allocate space for next push buffer */
2112 +       if (nouveau_pushbuf_space(chan, min))
2113 +               assert(0);
2114 +
2115 +       if (chan->flush_notify)
2116 +               chan->flush_notify(chan);
2117 +
2118 +       nvpb->marker = NULL;
2119 +       return ret;
2120 +}
2121 +
2122 +int
2123 +nouveau_pushbuf_marker_emit(struct nouveau_channel *chan,
2124 +                           unsigned wait_dwords, unsigned wait_relocs)
2125 +{
2126 +       struct nouveau_pushbuf_priv *nvpb = &nouveau_channel(chan)->pb;
2127 +
2128 +       if (AVAIL_RING(chan) < wait_dwords)
2129 +               return nouveau_pushbuf_flush(chan, wait_dwords);
2130 +
2131 +       if (nvpb->nr_relocs + wait_relocs >= NOUVEAU_GEM_MAX_RELOCS)
2132 +               return nouveau_pushbuf_flush(chan, wait_dwords);
2133 +
2134 +       nvpb->marker = chan->cur;
2135 +       nvpb->marker_offset = nvpb->current_offset;
2136 +       nvpb->marker_push = nvpb->nr_push;
2137 +       nvpb->marker_relocs = nvpb->nr_relocs;
2138 +       return 0;
2139 +}
2140 +
2141 +void
2142 +nouveau_pushbuf_marker_undo(struct nouveau_channel *chan)
2143 +{
2144 +       struct nouveau_pushbuf_priv *nvpb = &nouveau_channel(chan)->pb;
2145 +       unsigned i;
2146 +
2147 +       if (!nvpb->marker)
2148 +               return;
2149 +
2150 +       /* undo any relocs/buffers added to the list since last marker */
2151 +       for (i = nvpb->marker_relocs; i < nvpb->nr_relocs; i++) {
2152 +               nouveau_pushbuf_bo_unref(nvpb, nvpb->relocs[i].bo_index);
2153 +               nouveau_pushbuf_bo_unref(nvpb, nvpb->relocs[i].reloc_bo_index);
2154 +       }
2155 +       nvpb->nr_relocs = nvpb->marker_relocs;
2156 +
2157 +       for (i = nvpb->marker_push; i < nvpb->nr_push; i++)
2158 +               nouveau_pushbuf_bo_unref(nvpb, nvpb->push[i].bo_index);
2159 +       nvpb->nr_push = nvpb->marker_push;
2160 +
2161 +       /* reset pushbuf back to last marker */
2162 +       chan->cur = nvpb->marker;
2163 +       nvpb->current_offset = nvpb->marker_offset;
2164 +       nvpb->marker = NULL;
2165 +}
2166 +
2167 +int
2168 +nouveau_pushbuf_emit_reloc(struct nouveau_channel *chan, void *ptr,
2169 +                          struct nouveau_bo *bo, uint32_t data, uint32_t data2,
2170 +                          uint32_t flags, uint32_t vor, uint32_t tor)
2171 +{
2172 +       struct nouveau_pushbuf_priv *nvpb = &nouveau_channel(chan)->pb;
2173 +       int ret;
2174 +
2175 +       ret = nouveau_reloc_emit(chan, nvpb->buffer[nvpb->current],
2176 +                                (char *)ptr - (char *)nvpb->pushbuf, ptr,
2177 +                                bo, data, data2, flags, vor, tor);
2178 +       if (ret)
2179 +               return ret;
2180 +
2181 +       return 0;
2182 +}
2183 +
2184 Index: libdrm/nouveau-1/nouveau_pushbuf.h
2185 ===================================================================
2186 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
2187 +++ libdrm/nouveau-1/nouveau_pushbuf.h  2013-03-06 16:27:49.823925019 +0100
2188 @@ -0,0 +1,162 @@
2189 +/*
2190 + * Copyright 2007 Nouveau Project
2191 + *
2192 + * Permission is hereby granted, free of charge, to any person obtaining a
2193 + * copy of this software and associated documentation files (the "Software"),
2194 + * to deal in the Software without restriction, including without limitation
2195 + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
2196 + * and/or sell copies of the Software, and to permit persons to whom the
2197 + * Software is furnished to do so, subject to the following conditions:
2198 + *
2199 + * The above copyright notice and this permission notice shall be included in
2200 + * all copies or substantial portions of the Software.
2201 + *
2202 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2203 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2204 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
2205 + * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
2206 + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
2207 + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2208 + * SOFTWARE.
2209 + */
2210 +
2211 +#ifndef __NOUVEAU_PUSHBUF_H__
2212 +#define __NOUVEAU_PUSHBUF_H__
2213 +
2214 +#include <assert.h>
2215 +#include <string.h>
2216 +
2217 +#include "nouveau_bo.h"
2218 +#include "nouveau_grobj.h"
2219 +
2220 +int
2221 +nouveau_pushbuf_flush(struct nouveau_channel *, unsigned min);
2222 +
2223 +int
2224 +nouveau_pushbuf_marker_emit(struct nouveau_channel *chan,
2225 +                           unsigned wait_dwords, unsigned wait_relocs);
2226 +
2227 +void
2228 +nouveau_pushbuf_marker_undo(struct nouveau_channel *chan);
2229 +
2230 +int
2231 +nouveau_pushbuf_emit_reloc(struct nouveau_channel *, void *ptr,
2232 +                          struct nouveau_bo *, uint32_t data, uint32_t data2,
2233 +                          uint32_t flags, uint32_t vor, uint32_t tor);
2234 +
2235 +int
2236 +nouveau_pushbuf_submit(struct nouveau_channel *chan, struct nouveau_bo *bo,
2237 +                      unsigned offset, unsigned length);
2238 +
2239 +/* Push buffer access macros */
2240 +static __inline__ int
2241 +MARK_RING(struct nouveau_channel *chan, unsigned dwords, unsigned relocs)
2242 +{
2243 +       return nouveau_pushbuf_marker_emit(chan, dwords, relocs);
2244 +}
2245 +
2246 +static __inline__ void
2247 +MARK_UNDO(struct nouveau_channel *chan)
2248 +{
2249 +       nouveau_pushbuf_marker_undo(chan);
2250 +}
2251 +
2252 +static __inline__ void
2253 +OUT_RING(struct nouveau_channel *chan, unsigned data)
2254 +{
2255 +       *(chan->cur++) = (data);
2256 +}
2257 +
2258 +static __inline__ void
2259 +OUT_RINGp(struct nouveau_channel *chan, const void *data, unsigned size)
2260 +{
2261 +       memcpy(chan->cur, data, size * 4);
2262 +       chan->cur += size;
2263 +}
2264 +
2265 +static __inline__ void
2266 +OUT_RINGf(struct nouveau_channel *chan, float f)
2267 +{
2268 +       union { uint32_t i; float f; } c;
2269 +       c.f = f;
2270 +       OUT_RING(chan, c.i);
2271 +}
2272 +
2273 +static __inline__ unsigned
2274 +AVAIL_RING(struct nouveau_channel *chan)
2275 +{
2276 +       return chan->end - chan->cur;
2277 +}
2278 +
2279 +static __inline__ void
2280 +WAIT_RING(struct nouveau_channel *chan, unsigned size)
2281 +{
2282 +       if (chan->cur + size > chan->end)
2283 +               nouveau_pushbuf_flush(chan, size);
2284 +}
2285 +
2286 +static __inline__ void
2287 +FIRE_RING(struct nouveau_channel *chan)
2288 +{
2289 +       nouveau_pushbuf_flush(chan, 0);
2290 +}
2291 +
2292 +static __inline__ int
2293 +OUT_RELOC(struct nouveau_channel *chan, struct nouveau_bo *bo,
2294 +         unsigned data, unsigned flags, unsigned vor, unsigned tor)
2295 +{
2296 +       return nouveau_pushbuf_emit_reloc(chan, chan->cur++, bo,
2297 +                                         data, 0, flags, vor, tor);
2298 +}
2299 +
2300 +static __inline__ int
2301 +OUT_RELOC2(struct nouveau_channel *chan, struct nouveau_bo *bo,
2302 +          unsigned data, unsigned data2, unsigned flags,
2303 +          unsigned vor, unsigned tor)
2304 +{
2305 +       return nouveau_pushbuf_emit_reloc(chan, chan->cur++, bo,
2306 +                                         data, data2, flags, vor, tor);
2307 +}
2308 +
2309 +/* Raw data + flags depending on FB/TT buffer */
2310 +static __inline__ int
2311 +OUT_RELOCd(struct nouveau_channel *chan, struct nouveau_bo *bo,
2312 +          unsigned data, unsigned flags, unsigned vor, unsigned tor)
2313 +{
2314 +       return OUT_RELOC(chan, bo, data, flags | NOUVEAU_BO_OR, vor, tor);
2315 +}
2316 +
2317 +/* FB/TT object handle */
2318 +static __inline__ int
2319 +OUT_RELOCo(struct nouveau_channel *chan, struct nouveau_bo *bo,
2320 +          unsigned flags)
2321 +{
2322 +       return OUT_RELOC(chan, bo, 0, flags | NOUVEAU_BO_OR,
2323 +                        chan->vram->handle, chan->gart->handle);
2324 +}
2325 +
2326 +/* Low 32-bits of offset */
2327 +static __inline__ int
2328 +OUT_RELOCl(struct nouveau_channel *chan, struct nouveau_bo *bo,
2329 +          unsigned delta, unsigned flags)
2330 +{
2331 +       return OUT_RELOC(chan, bo, delta, flags | NOUVEAU_BO_LOW, 0, 0);
2332 +}
2333 +
2334 +/* Low 32-bits of offset + GPU linear access range info */
2335 +static __inline__ int
2336 +OUT_RELOCr(struct nouveau_channel *chan, struct nouveau_bo *bo,
2337 +          unsigned delta, unsigned size, unsigned flags)
2338 +{
2339 +       return OUT_RELOC2(chan, bo, delta, size, flags | NOUVEAU_BO_LOW, 0, 0);
2340 +}
2341 +
2342 +/* High 32-bits of offset */
2343 +static __inline__ int
2344 +OUT_RELOCh(struct nouveau_channel *chan, struct nouveau_bo *bo,
2345 +          unsigned delta, unsigned flags)
2346 +{
2347 +       return OUT_RELOC(chan, bo, delta, flags | NOUVEAU_BO_HIGH, 0, 0);
2348 +}
2349 +
2350 +#endif
2351 Index: libdrm/nouveau-1/nouveau_reloc.c
2352 ===================================================================
2353 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
2354 +++ libdrm/nouveau-1/nouveau_reloc.c    2013-03-06 16:27:49.823925019 +0100
2355 @@ -0,0 +1,154 @@
2356 +/*
2357 + * Copyright 2010 Nouveau Project
2358 + *
2359 + * Permission is hereby granted, free of charge, to any person obtaining a
2360 + * copy of this software and associated documentation files (the "Software"),
2361 + * to deal in the Software without restriction, including without limitation
2362 + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
2363 + * and/or sell copies of the Software, and to permit persons to whom the
2364 + * Software is furnished to do so, subject to the following conditions:
2365 + *
2366 + * The above copyright notice and this permission notice shall be included in
2367 + * all copies or substantial portions of the Software.
2368 + *
2369 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2370 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2371 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
2372 + * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
2373 + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
2374 + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2375 + * SOFTWARE.
2376 + */
2377 +
2378 +#include <stdio.h>
2379 +#include <stdlib.h>
2380 +#include <errno.h>
2381 +#include <assert.h>
2382 +
2383 +#include "nouveau_private.h"
2384 +
2385 +static uint32_t
2386 +nouveau_reloc_calc(struct drm_nouveau_gem_pushbuf_bo *pbbo,
2387 +                  struct drm_nouveau_gem_pushbuf_reloc *r)
2388 +{
2389 +       uint32_t push = 0;
2390 +
2391 +       if (r->flags & NOUVEAU_GEM_RELOC_LOW)
2392 +               push = (pbbo->presumed.offset + r->data);
2393 +       else
2394 +       if (r->flags & NOUVEAU_GEM_RELOC_HIGH)
2395 +               push = (pbbo->presumed.offset + r->data) >> 32;
2396 +       else
2397 +               push = r->data;
2398 +
2399 +       if (r->flags & NOUVEAU_GEM_RELOC_OR) {
2400 +               if (pbbo->presumed.domain & NOUVEAU_GEM_DOMAIN_VRAM)
2401 +                       push |= r->vor;
2402 +               else
2403 +                       push |= r->tor;
2404 +       }
2405 +
2406 +       return push;
2407 +}
2408 +
2409 +int
2410 +nouveau_reloc_emit(struct nouveau_channel *chan, struct nouveau_bo *reloc_bo,
2411 +                  uint32_t reloc_offset, uint32_t *reloc_ptr,
2412 +                  struct nouveau_bo *bo, uint32_t data, uint32_t data2,
2413 +                  uint32_t flags, uint32_t vor, uint32_t tor)
2414 +{
2415 +       struct nouveau_pushbuf_priv *nvpb = &nouveau_channel(chan)->pb;
2416 +       struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
2417 +       struct drm_nouveau_gem_pushbuf_reloc *r;
2418 +       struct drm_nouveau_gem_pushbuf_bo *pbbo, *rpbbo;
2419 +       uint32_t domains = 0;
2420 +
2421 +       if (nvpb->nr_relocs >= NOUVEAU_GEM_MAX_RELOCS) {
2422 +               fprintf(stderr, "too many relocs!!\n");
2423 +               return -ENOMEM;
2424 +       }
2425 +
2426 +       if (nvbo->user && (flags & NOUVEAU_BO_WR)) {
2427 +               fprintf(stderr, "write to user buffer!!\n");
2428 +               return -EINVAL;
2429 +       }
2430 +
2431 +       /* We're about to reloc a user buffer, better make sure we don't cause
2432 +        * a double migration.
2433 +        */
2434 +       if (!(nvbo->flags & (NOUVEAU_BO_GART | NOUVEAU_BO_VRAM)))
2435 +               nvbo->flags |= (flags & (NOUVEAU_BO_GART | NOUVEAU_BO_VRAM));
2436 +
2437 +       /* add buffer to validation list */
2438 +       pbbo = nouveau_bo_emit_buffer(chan, bo);
2439 +       if (!pbbo) {
2440 +               fprintf(stderr, "buffer emit fail :(\n");
2441 +               return -ENOMEM;
2442 +       }
2443 +       nouveau_bo(bo)->pending_refcnt++;
2444 +
2445 +       if (flags & (NOUVEAU_BO_VRAM | NOUVEAU_BO_GART)) {
2446 +               if (flags & NOUVEAU_BO_VRAM)
2447 +                       domains |= NOUVEAU_GEM_DOMAIN_VRAM;
2448 +               if (flags & NOUVEAU_BO_GART)
2449 +                       domains |= NOUVEAU_GEM_DOMAIN_GART;
2450 +       } else
2451 +               domains |= nvbo->domain;
2452 +
2453 +       if (!(pbbo->valid_domains & domains)) {
2454 +               fprintf(stderr, "no valid domains remain!\n");
2455 +               return -EINVAL;
2456 +       }
2457 +       pbbo->valid_domains &= domains;
2458 +
2459 +       assert(flags & NOUVEAU_BO_RDWR);
2460 +       if (flags & NOUVEAU_BO_RD) {
2461 +               pbbo->read_domains |= domains;
2462 +       }
2463 +       if (flags & NOUVEAU_BO_WR) {
2464 +               pbbo->write_domains |= domains;
2465 +               nvbo->write_marker = 1;
2466 +       }
2467 +
2468 +       /* nvc0 gallium driver uses reloc_emit() with NULL target buffer
2469 +        * to inform bufmgr of a buffer's use - however, we need something
2470 +        * to track, so create a reloc for now, and hope it never triggers
2471 +        * (it shouldn't, constant virtual address..)..
2472 +        */
2473 +       if (!reloc_bo) {
2474 +               reloc_bo  = nvpb->buffer[nvpb->current];
2475 +               reloc_offset = 0;
2476 +               reloc_ptr = NULL;
2477 +       }
2478 +
2479 +       /* add reloc target bo to validation list, and create the reloc */
2480 +       rpbbo = nouveau_bo_emit_buffer(chan, reloc_bo);
2481 +       if (!rpbbo)
2482 +               return -ENOMEM;
2483 +       nouveau_bo(reloc_bo)->pending_refcnt++;
2484 +
2485 +       r = nvpb->relocs + nvpb->nr_relocs++;
2486 +       r->reloc_bo_index = rpbbo - nvpb->buffers;
2487 +       r->reloc_bo_offset = reloc_offset;
2488 +       r->bo_index = pbbo - nvpb->buffers;
2489 +       r->flags = 0;
2490 +       if (flags & NOUVEAU_BO_LOW)
2491 +               r->flags |= NOUVEAU_GEM_RELOC_LOW;
2492 +       if (flags & NOUVEAU_BO_HIGH)
2493 +               r->flags |= NOUVEAU_GEM_RELOC_HIGH;
2494 +       if (flags & NOUVEAU_BO_OR)
2495 +               r->flags |= NOUVEAU_GEM_RELOC_OR;
2496 +       r->data = data;
2497 +       r->vor = vor;
2498 +       r->tor = tor;
2499 +
2500 +       if (reloc_ptr) {
2501 +               if (flags & NOUVEAU_BO_DUMMY)
2502 +                       *reloc_ptr = 0;
2503 +               else
2504 +                       *reloc_ptr = nouveau_reloc_calc(pbbo, r);
2505 +       }
2506 +
2507 +       return 0;
2508 +}
2509 +
2510 Index: libdrm/nouveau-1/nouveau_reloc.h
2511 ===================================================================
2512 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
2513 +++ libdrm/nouveau-1/nouveau_reloc.h    2013-03-06 16:27:49.823925019 +0100
2514 @@ -0,0 +1,32 @@
2515 +/*
2516 + * Copyright 2010 Nouveau Project
2517 + *
2518 + * Permission is hereby granted, free of charge, to any person obtaining a
2519 + * copy of this software and associated documentation files (the "Software"),
2520 + * to deal in the Software without restriction, including without limitation
2521 + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
2522 + * and/or sell copies of the Software, and to permit persons to whom the
2523 + * Software is furnished to do so, subject to the following conditions:
2524 + *
2525 + * The above copyright notice and this permission notice shall be included in
2526 + * all copies or substantial portions of the Software.
2527 + *
2528 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2529 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2530 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
2531 + * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
2532 + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
2533 + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2534 + * SOFTWARE.
2535 + */
2536 +
2537 +#ifndef __NOUVEAU_RELOC_H__
2538 +#define __NOUVEAU_RELOC_H__
2539 +
2540 +int
2541 +nouveau_reloc_emit(struct nouveau_channel *chan, struct nouveau_bo *reloc_bo,
2542 +                  uint32_t reloc_offset, uint32_t *reloc_ptr,
2543 +                  struct nouveau_bo *bo, uint32_t data, uint32_t data2,
2544 +                  uint32_t flags, uint32_t vor, uint32_t tor);
2545 +
2546 +#endif
2547 Index: libdrm/nouveau-1/nouveau_resource.c
2548 ===================================================================
2549 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
2550 +++ libdrm/nouveau-1/nouveau_resource.c 2013-03-06 16:27:49.823925019 +0100
2551 @@ -0,0 +1,124 @@
2552 +/*
2553 + * Copyright 2007 Nouveau Project
2554 + *
2555 + * Permission is hereby granted, free of charge, to any person obtaining a
2556 + * copy of this software and associated documentation files (the "Software"),
2557 + * to deal in the Software without restriction, including without limitation
2558 + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
2559 + * and/or sell copies of the Software, and to permit persons to whom the
2560 + * Software is furnished to do so, subject to the following conditions:
2561 + *
2562 + * The above copyright notice and this permission notice shall be included in
2563 + * all copies or substantial portions of the Software.
2564 + *
2565 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2566 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2567 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
2568 + * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
2569 + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
2570 + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2571 + * SOFTWARE.
2572 + */
2573 +
2574 +#include <stdlib.h>
2575 +#include <errno.h>
2576 +
2577 +#include "nouveau_private.h"
2578 +
2579 +int
2580 +nouveau_resource_init(struct nouveau_resource **heap,
2581 +                     unsigned start, unsigned size)
2582 +{
2583 +       struct nouveau_resource *r;
2584 +
2585 +       r = calloc(1, sizeof(struct nouveau_resource));
2586 +       if (!r)
2587 +               return 1;
2588 +
2589 +       r->start = start;
2590 +       r->size  = size;
2591 +       *heap = r;
2592 +       return 0;
2593 +}
2594 +
2595 +void
2596 +nouveau_resource_destroy(struct nouveau_resource **heap)
2597 +{
2598 +       if (!*heap)
2599 +               return;
2600 +       free(*heap);
2601 +       *heap = NULL;
2602 +}
2603 +
2604 +int
2605 +nouveau_resource_alloc(struct nouveau_resource *heap, unsigned size, void *priv,
2606 +                      struct nouveau_resource **res)
2607 +{
2608 +       struct nouveau_resource *r;
2609 +
2610 +       if (!heap || !size || !res || *res)
2611 +               return 1;
2612 +
2613 +       while (heap) {
2614 +               if (!heap->in_use && heap->size >= size) {
2615 +                       r = calloc(1, sizeof(struct nouveau_resource));
2616 +                       if (!r)
2617 +                               return 1;
2618 +
2619 +                       r->start  = (heap->start + heap->size) - size;
2620 +                       r->size   = size;
2621 +                       r->in_use = 1;
2622 +                       r->priv   = priv;
2623 +
2624 +                       heap->size -= size;
2625 +
2626 +                       r->next = heap->next;
2627 +                       if (heap->next)
2628 +                               heap->next->prev = r;
2629 +                       r->prev = heap;
2630 +                       heap->next = r;
2631 +
2632 +                       *res = r;
2633 +                       return 0;
2634 +               }
2635 +                       
2636 +               heap = heap->next;
2637 +       }
2638 +
2639 +       return 1;
2640 +}
2641 +
2642 +void
2643 +nouveau_resource_free(struct nouveau_resource **res)
2644 +{
2645 +       struct nouveau_resource *r;
2646 +
2647 +       if (!res || !*res)
2648 +               return;
2649 +       r = *res;
2650 +       *res = NULL;
2651 +
2652 +       r->in_use = 0;
2653 +
2654 +       if (r->next && !r->next->in_use) {
2655 +               struct nouveau_resource *new = r->next;
2656 +
2657 +               new->prev = r->prev;
2658 +               if (r->prev)
2659 +                       r->prev->next = new;
2660 +               new->size += r->size;
2661 +               new->start = r->start;
2662 +
2663 +               free(r);
2664 +               r = new;
2665 +       }
2666 +
2667 +       if (r->prev && !r->prev->in_use) {
2668 +               r->prev->next = r->next;
2669 +               if (r->next)
2670 +                       r->next->prev = r->prev;
2671 +               r->prev->size += r->size;
2672 +               free(r);
2673 +       }
2674 +       
2675 +}
2676 Index: libdrm/nouveau-1/nouveau_resource.h
2677 ===================================================================
2678 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
2679 +++ libdrm/nouveau-1/nouveau_resource.h 2013-03-06 16:27:49.823925019 +0100
2680 @@ -0,0 +1,51 @@
2681 +/*
2682 + * Copyright 2007 Nouveau Project
2683 + *
2684 + * Permission is hereby granted, free of charge, to any person obtaining a
2685 + * copy of this software and associated documentation files (the "Software"),
2686 + * to deal in the Software without restriction, including without limitation
2687 + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
2688 + * and/or sell copies of the Software, and to permit persons to whom the
2689 + * Software is furnished to do so, subject to the following conditions:
2690 + *
2691 + * The above copyright notice and this permission notice shall be included in
2692 + * all copies or substantial portions of the Software.
2693 + *
2694 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2695 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2696 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
2697 + * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
2698 + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
2699 + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2700 + * SOFTWARE.
2701 + */
2702 +
2703 +#ifndef __NOUVEAU_RESOURCE_H__
2704 +#define __NOUVEAU_RESOURCE_H__
2705 +
2706 +struct nouveau_resource {
2707 +       struct nouveau_resource *prev;
2708 +       struct nouveau_resource *next;
2709 +
2710 +       int in_use;
2711 +       void *priv;
2712 +
2713 +       unsigned int start;
2714 +       unsigned int size;
2715 +};
2716 +
2717 +int
2718 +nouveau_resource_init(struct nouveau_resource **heap, unsigned start,
2719 +                     unsigned size);