2 #include "nv_include.h"
5 CARD32 NVDmaCreateDMAObject(NVPtr pNv, int target, CARD32 base_address, CARD32 size, int access)
7 drm_nouveau_dma_object_init_t dma;
10 dma.instance = &object;
14 dma.offset = base_address;
15 if (target == NV_DMA_TARGET_AGP)
16 dma.offset += pNv->agpPhysical;
17 drmCommandWriteRead(pNv->drm_fd, DRM_NOUVEAU_DMA_OBJECT_INIT, &dma, sizeof(dma));
23 A DMA notifier is a DMA object that references a small (32 byte it
24 seems, we use 256 for saftey) memory area that will be used by the HW to give feedback
25 about a DMA operation.
27 CARD32 NVDmaCreateNotifier(NVPtr pNv, int target, CARD32 base_address)
29 return NVDmaCreateDMAObject(pNv, target, base_address, 0x100, NV_DMA_ACCES_RW);
33 How do we wait for DMA completion (by notifiers) ?
35 Either repeatedly read the notifier address and wait until it changes,
36 or enable a 'wakeup' interrupt by writing NOTIFY_WRITE_LE_AWAKEN into
37 the 'notify' field of the object in the channel. My guess is that
38 this causes an interrupt in PGRAPH/NOTIFY as soon as the transfer is
39 completed. Clients probably can use poll on the nv* devices to get this
40 event. All this is a guess. I don't know any details, and I have not
41 tested is. Also, I have no idea how the 'nvdriver' reacts if it gets
42 notify events that are not registered.
44 Writing NV_NOTIFY_WRITE_LE_AWAKEN into the 'Notify' field of an object
45 in a channel really causes an interrupt in the PGRAPH engine. Thus
46 we can determine whether a DMA transfer has finished in the interrupt
49 We can't use interrupts in user land, so we do the simple polling approach.
50 The method returns FALSE in case of an error.
52 Bool NVDmaWaitForNotifier(NVPtr pNv, int target, CARD32 base_address)
55 unsigned char *notifier = (target == NV_DMA_TARGET_AGP)
58 notifier += base_address;
59 n = (volatile U032 *)notifier;
60 NVDEBUG("NVDmaWaitForNotifier @%p", n);
66 NVDEBUG("status: n[0]=%x, n[1]=%x, n[2]=%x, n[3]=%x\n", a, b, c, status);
67 if (status == 0xffffffff)
77 void NVDmaCreateContextObject(NVPtr pNv, int handle, int class, CARD32 flags,
78 CARD32 dma_in, CARD32 dma_out, CARD32 dma_notifier)
80 drm_nouveau_object_init_t cto;
81 CARD32 nv_flags0 = 0, nv_flags1 = 0, nv_flags2 = 0;
83 if (pNv->Architecture >= NV_ARCH_40) {
84 if (flags & NV_DMA_CONTEXT_FLAGS_PATCH_ROP_AND)
85 nv_flags0 |= 0x02080000;
86 else if (flags & NV_DMA_CONTEXT_FLAGS_PATCH_SRCCOPY)
87 nv_flags0 |= 0x02080000;
88 if (flags & NV_DMA_CONTEXT_FLAGS_CLIP_ENABLE)
89 nv_flags0 |= 0x00020000;
90 #if X_BYTE_ORDER == X_BIG_ENDIAN
91 if (flags & NV_DMA_CONTEXT_FLAGS_MONO)
92 nv_flags1 |= 0x01000000;
93 nv_flags2 |= 0x01000000;
95 if (flags & NV_DMA_CONTEXT_FLAGS_MONO)
96 nv_flags1 |= 0x02000000;
99 if (flags & NV_DMA_CONTEXT_FLAGS_PATCH_ROP_AND)
100 nv_flags0 |= 0x01008000;
101 else if (flags & NV_DMA_CONTEXT_FLAGS_PATCH_SRCCOPY)
102 nv_flags0 |= 0x01018000;
103 if (flags & NV_DMA_CONTEXT_FLAGS_CLIP_ENABLE)
104 nv_flags0 |= 0x00002000;
105 #if X_BYTE_ORDER == X_BIG_ENDIAN
106 nv_flags0 |= 0x00080000;
107 if (flags & NV_DMA_CONTEXT_FLAGS_MONO)
108 nv_flags1 |= 0x00000001;
110 if (flags & NV_DMA_CONTEXT_FLAGS_MONO)
111 nv_flags1 |= 0x00000002;
117 cto.flags0 = nv_flags0;
118 cto.flags1 = nv_flags1;
119 cto.flags2 = nv_flags2;
121 cto.dma_out = dma_out;
122 cto.dma_notifier = dma_notifier;
123 drmCommandWrite(pNv->drm_fd, DRM_NOUVEAU_OBJECT_INIT, &cto, sizeof(cto));
126 Bool NVInitDma(ScrnInfoPtr pScrn)
128 NVPtr pNv = NVPTR(pScrn);
134 drm_nouveau_fifo_init_t fifo_init;
135 unsigned int *fifo_regs, *fifo_cmdbuf;
139 if (!NVDRIScreenInit(pScrn))
142 fifo_init.fifo_num = &fifo;
143 if (drmCommandWriteRead(pNv->drm_fd, DRM_NOUVEAU_FIFO_INIT, &fifo_init, sizeof(fifo_init)) != 0) {
144 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Could not initialise kernel module\n");
148 dma_fb = NVDmaCreateDMAObject(pNv, NV_DMA_TARGET_VIDMEM, 0, pNv->FbMapSize, NV_DMA_ACCES_RW);
150 NVDmaCreateContextObject (pNv, NvContextSurfaces,
151 (pNv->Architecture >= NV_ARCH_10) ? NV10_CONTEXT_SURFACES_2D : NV4_SURFACE,
152 NV_DMA_CONTEXT_FLAGS_PATCH_ROP_AND,
154 NVDmaCreateContextObject (pNv, NvRop,
156 NV_DMA_CONTEXT_FLAGS_PATCH_ROP_AND,
158 NVDmaCreateContextObject (pNv, NvImagePattern,
160 NV_DMA_CONTEXT_FLAGS_PATCH_ROP_AND|NV_DMA_CONTEXT_FLAGS_MONO,
162 NVDmaCreateContextObject (pNv, NvClipRectangle,
163 NV_IMAGE_BLACK_RECTANGLE,
164 NV_DMA_CONTEXT_FLAGS_PATCH_ROP_AND,
166 NVDmaCreateContextObject (pNv, NvSolidLine,
167 NV4_RENDER_SOLID_LIN,
168 NV_DMA_CONTEXT_FLAGS_PATCH_ROP_AND|NV_DMA_CONTEXT_FLAGS_CLIP_ENABLE,
170 NVDmaCreateContextObject (pNv, NvImageBlit,
171 pNv->WaitVSyncPossible ? NV12_IMAGE_BLIT : NV_IMAGE_BLIT,
172 NV_DMA_CONTEXT_FLAGS_PATCH_ROP_AND,
174 NVDmaCreateContextObject (pNv, NvRectangle,
175 NV4_GDI_RECTANGLE_TEXT,
176 NV_DMA_CONTEXT_FLAGS_PATCH_ROP_AND|NV_DMA_CONTEXT_FLAGS_MONO,
178 NVDmaCreateContextObject (pNv, NvScaledImage,
179 NV_SCALED_IMAGE_FROM_MEMORY,
180 NV_DMA_CONTEXT_FLAGS_PATCH_SRCCOPY,
184 if (NVInitAGP(pScrn) && pNv->agpMemory) {
186 dma_agp = NVDmaCreateDMAObject(pNv, NV_DMA_TARGET_AGP, 0x10000, pNv->agpSize - 0x10000,
188 dma_notifier = NVDmaCreateNotifier(pNv, NV_DMA_TARGET_AGP, 0);
190 NVDmaCreateContextObject (pNv, NvGraphicsToAGP,
191 NV_MEMORY_TO_MEMORY_FORMAT,
193 dma_fb, dma_agp, dma_notifier);
195 NVDmaCreateContextObject (pNv, NvAGPToGraphics,
196 NV_MEMORY_TO_MEMORY_FORMAT,
198 dma_agp, dma_fb, dma_notifier);
202 fifo_regs = pNv->FIFO;
203 fifo_cmdbuf = pNv->dmaBase;
205 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using FIFO %d\n", fifo);
206 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "FIFO control registers: %p\n", fifo_regs);
207 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "DMA command buffer : %p\n", fifo_cmdbuf);