2 * Copyright (C) 2007 Ben Skeggs.
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial
16 * portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
22 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 #include "vblank.h" /* for DO_USLEEP */
30 #include "nouveau_context.h"
31 #include "nouveau_buffers.h"
32 #include "nouveau_object.h"
33 #include "nouveau_fifo.h"
34 #include "nouveau_reg.h"
35 #include "nouveau_msg.h"
36 #include "nouveau_sync.h"
39 nouveau_notifier_new(GLcontext
*ctx
, GLuint handle
, GLuint count
)
41 nouveauContextPtr nmesa
= NOUVEAU_CONTEXT(ctx
);
42 nouveau_notifier
*notifier
;
44 #ifdef NOUVEAU_RING_DEBUG
48 notifier
= CALLOC_STRUCT(nouveau_notifier_t
);
52 notifier
->mem
= nouveau_mem_alloc(ctx
,
53 NOUVEAU_MEM_FB
| NOUVEAU_MEM_MAPPED
,
54 count
* NV_NOTIFIER_SIZE
,
61 if (!nouveauCreateDmaObjectFromMem(nmesa
, handle
, NV_DMA_IN_MEMORY
,
63 NOUVEAU_MEM_ACCESS_RW
)) {
64 nouveau_mem_free(ctx
, notifier
->mem
);
69 notifier
->handle
= handle
;
74 nouveau_notifier_destroy(GLcontext
*ctx
, nouveau_notifier
*notifier
)
76 /*XXX: free DMA object.. */
77 nouveau_mem_free(ctx
, notifier
->mem
);
82 nouveau_notifier_reset(nouveau_notifier
*notifier
, GLuint id
)
84 volatile GLuint
*n
= notifier
->mem
->map
+ (id
* NV_NOTIFIER_SIZE
);
86 #ifdef NOUVEAU_RING_DEBUG
90 n
[NV_NOTIFY_TIME_0
/4] = 0x00000000;
91 n
[NV_NOTIFY_TIME_1
/4] = 0x00000000;
92 n
[NV_NOTIFY_RETURN_VALUE
/4] = 0x00000000;
93 n
[NV_NOTIFY_STATE
/4] = (NV_NOTIFY_STATE_STATUS_IN_PROCESS
<<
94 NV_NOTIFY_STATE_STATUS_SHIFT
);
98 nouveau_notifier_status(nouveau_notifier
*notifier
, GLuint id
)
100 volatile GLuint
*n
= notifier
->mem
->map
+ (id
* NV_NOTIFIER_SIZE
);
102 return n
[NV_NOTIFY_STATE
/4] >> NV_NOTIFY_STATE_STATUS_SHIFT
;
106 nouveau_notifier_return_val(nouveau_notifier
*notifier
, GLuint id
)
108 volatile GLuint
*n
= notifier
->mem
->map
+ (id
* NV_NOTIFIER_SIZE
);
110 return n
[NV_NOTIFY_RETURN_VALUE
/4];
114 nouveau_notifier_wait_status(nouveau_notifier
*notifier
, GLuint id
,
115 GLuint status
, GLuint timeout
)
117 volatile GLuint
*n
= notifier
->mem
->map
+ (id
* NV_NOTIFIER_SIZE
);
118 unsigned int time
= 0;
120 #ifdef NOUVEAU_RING_DEBUG
124 while (time
<= timeout
) {
125 if (n
[NV_NOTIFY_STATE
/4] & NV_NOTIFY_STATE_ERROR_CODE_MASK
) {
126 MESSAGE("Notifier returned error: 0x%04x\n",
128 NV_NOTIFY_STATE_ERROR_CODE_MASK
);
132 if (((n
[NV_NOTIFY_STATE
/4] & NV_NOTIFY_STATE_STATUS_MASK
) >>
133 NV_NOTIFY_STATE_STATUS_SHIFT
) == status
)
142 MESSAGE("Notifier timed out\n");
147 nouveau_notifier_wait_nop(GLcontext
*ctx
, nouveau_notifier
*notifier
,
150 nouveauContextPtr nmesa
= NOUVEAU_CONTEXT(ctx
);
153 nouveau_notifier_reset(notifier
, 0);
155 BEGIN_RING_SIZE(subc
, NV_NOTIFY
, 1);
156 OUT_RING (NV_NOTIFY_STYLE_WRITE_ONLY
);
157 BEGIN_RING_SIZE(subc
, NV_NOP
, 1);
161 ret
= nouveau_notifier_wait_status(notifier
, 0,
162 NV_NOTIFY_STATE_STATUS_COMPLETED
,
164 if (ret
== GL_FALSE
) MESSAGE("wait on notifier failed\n");
167 GLboolean
nouveauSyncInitFuncs(GLcontext
*ctx
)
169 nouveauContextPtr nmesa
= NOUVEAU_CONTEXT(ctx
);
171 #ifdef NOUVEAU_RING_DEBUG
175 nmesa
->syncNotifier
= nouveau_notifier_new(ctx
, NvSyncNotify
, 1);
176 if (!nmesa
->syncNotifier
) {
177 MESSAGE("Failed to create channel sync notifier\n");
181 /* 0x180 is SET_DMA_NOTIFY, should be correct for all supported 3D
184 BEGIN_RING_CACHE(NvSub3D
, 0x180, 1);
185 OUT_RING_CACHE (NvSyncNotify
);
186 #ifdef ALLOW_MULTI_SUBCHANNEL
187 BEGIN_RING_SIZE(NvSubMemFormat
,
188 NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY
, 1);
189 OUT_RING (NvSyncNotify
);