Xv: quick imple of NV04 overlay
[nouveau] / src / nv_notifier.c
1 #include "nv_include.h"
2
3 #define NV_NOTIFIER_SIZE                                                      32
4 #define NV_NOTIFY_TIME_0                                              0x00000000
5 #define NV_NOTIFY_TIME_1                                              0x00000004
6 #define NV_NOTIFY_RETURN_VALUE                                        0x00000008
7 #define NV_NOTIFY_STATE                                               0x0000000C
8 #define NV_NOTIFY_STATE_STATUS_MASK                                   0xFF000000
9 #define NV_NOTIFY_STATE_STATUS_SHIFT                                          24
10 #define NV_NOTIFY_STATE_STATUS_COMPLETED                                    0x00
11 #define NV_NOTIFY_STATE_STATUS_IN_PROCESS                                   0x01
12 #define NV_NOTIFY_STATE_ERROR_CODE_MASK                               0x0000FFFF
13 #define NV_NOTIFY_STATE_ERROR_CODE_SHIFT                                       0
14
15 #define NOTIFIER(__v) \
16         NVPtr pNv = NVPTR(pScrn); \
17         volatile uint32_t *__v = (void*)pNv->NotifierBlock + notifier->offset
18
19 struct drm_nouveau_notifierobj_alloc *
20 NVNotifierAlloc(ScrnInfoPtr pScrn, uint32_t handle)
21 {
22         NVPtr pNv = NVPTR(pScrn);
23         struct drm_nouveau_notifierobj_alloc *notifier;
24         int ret;
25
26         notifier = xcalloc(1, sizeof(*notifier));
27         if (!notifier) {
28                 NVNotifierDestroy(pScrn, notifier);
29                 return NULL;
30         }
31
32         notifier->channel = pNv->fifo.channel;
33         notifier->handle  = handle;
34         notifier->count   = 1;
35         ret = drmCommandWriteRead(pNv->drm_fd, DRM_NOUVEAU_NOTIFIEROBJ_ALLOC,
36                                   notifier, sizeof(*notifier));
37         if (ret) {
38                 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
39                            "Failed to create notifier 0x%08x: %d\n",
40                            handle, ret);
41                 NVNotifierDestroy(pScrn, notifier);
42                 return NULL;
43         }
44
45         return notifier;
46 }
47
48 void
49 NVNotifierDestroy(ScrnInfoPtr pScrn,
50                   struct drm_nouveau_notifierobj_alloc *notifier)
51 {
52         if (notifier) {
53                 /*XXX: destroy notifier object */
54                 xfree(notifier);
55         }
56 }
57
58 void
59 NVNotifierReset(ScrnInfoPtr pScrn,
60                 struct drm_nouveau_notifierobj_alloc *notifier)
61 {
62         NOTIFIER(n);
63
64         n[NV_NOTIFY_TIME_0      /4] =
65         n[NV_NOTIFY_TIME_1      /4] =
66         n[NV_NOTIFY_RETURN_VALUE/4] = 0;
67         n[NV_NOTIFY_STATE       /4] = (NV_NOTIFY_STATE_STATUS_IN_PROCESS <<
68                                        NV_NOTIFY_STATE_STATUS_SHIFT);
69 }
70
71 uint32_t
72 NVNotifierStatus(ScrnInfoPtr pScrn,
73                  struct drm_nouveau_notifierobj_alloc *notifier)
74 {
75         NOTIFIER(n);
76
77         return n[NV_NOTIFY_STATE/4] >> NV_NOTIFY_STATE_STATUS_SHIFT;
78 }
79
80 uint32_t
81 NVNotifierErrorCode(ScrnInfoPtr pScrn,
82                     struct drm_nouveau_notifierobj_alloc *notifier)
83 {
84         NOTIFIER(n);
85
86         return n[NV_NOTIFY_STATE/4] & NV_NOTIFY_STATE_ERROR_CODE_MASK;
87 }
88
89 uint32_t
90 NVNotifierReturnVal(ScrnInfoPtr pScrn,
91                     struct drm_nouveau_notifierobj_alloc *notifier)
92 {
93         NOTIFIER(n);
94
95         return n[NV_NOTIFY_RETURN_VALUE/4];
96 }
97
98 Bool
99 NVNotifierWaitStatus(ScrnInfoPtr pScrn,
100                      struct drm_nouveau_notifierobj_alloc *notifier,
101                      unsigned int status, unsigned int timeout)
102 {
103         NOTIFIER(n);
104         unsigned int t_start, time = 0;
105
106         t_start = GetTimeInMillis();
107         while (time <= timeout) {
108 #if 0
109                 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
110                            "N(0x%08x)/%d = 0x%08x/0x%08x/0x%08x/0x%08x\n",
111                            notifier->handle, time, n[0], n[1], n[2], n[3]);
112 #endif
113                 if (n[NV_NOTIFY_STATE/4] & NV_NOTIFY_STATE_ERROR_CODE_MASK) {
114                         xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
115                                    "Notifier returned error: 0x%04x\n",
116                                    NVNotifierErrorCode(pScrn, notifier));
117                         return FALSE;
118                 }
119
120                 if ((n[NV_NOTIFY_STATE/4] >> NV_NOTIFY_STATE_STATUS_SHIFT)
121                                 == status)
122                         return TRUE;
123
124                 if (timeout)
125                         time = GetTimeInMillis() - t_start;
126         }
127
128         xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
129                    "Notifier (0x%08x) timeout!\n", notifier->handle);
130         return FALSE;
131 }
132