2 #include "nv_include.h"
5 void NVDmaKickoff(NVPtr pNv)
7 if(pNv->dmaCurrent != pNv->dmaPut) {
8 pNv->dmaPut = pNv->dmaCurrent;
9 WRITE_PUT(pNv, pNv->dmaPut);
13 void NVDmaKickoffCallback(NVPtr pNv)
16 pNv->DMAKickoffCallback = NULL;
19 static uint32_t subchannels[8];
21 void NVDmaStart(NVPtr pNv, uint32_t object, uint32_t tag, int size)
27 ScrnInfoPtr pScrn = xf86Screens[0];
29 /* look for a subchannel already bound to that object */
32 if (subchannels[i]==object)
39 /* add 2 for the potential subchannel binding */
40 if((pNv)->dmaFree <= (size + 2))
41 NVDmaWait(pScrn, size + 2);
47 subchannels[subchannel]=object;
48 NVDEBUG("Bind object %x on subchannel %d\n", (object), (subchannel));
49 NVDmaNext(pNv, (1<<18) | (subchannel<<13));
50 NVDmaNext(pNv,object);
53 NVDEBUG("NVDmaStart: subc=%d, cmd=%x, num=%d\n", (subchannel), (tag), (size));
54 NVDmaNext(pNv, ((size) << 18) | ((subchannel) << 13) | (tag));
55 pNv->dmaFree -= ((size) + 1);
59 /* There is a HW race condition with videoram command buffers.
60 * You can't jump to the location of your put offset. We write put
61 * at the jump offset + SKIPS dwords with noop padding in between
62 * to solve this problem
66 void NVDmaWait (ScrnInfoPtr pScrn, int size)
68 NVPtr pNv = NVPTR(pScrn);
74 t_start = GetTimeInMillis();
75 while(pNv->dmaFree < size) {
76 dmaGet = READ_GET(pNv);
78 if(pNv->dmaPut >= dmaGet) {
79 pNv->dmaFree = pNv->dmaMax - pNv->dmaCurrent;
80 if(pNv->dmaFree < size) {
81 NVDmaNext(pNv, (0x20000000|pNv->fifo.put_base));
83 if(pNv->dmaPut <= SKIPS) /* corner case - will be idle */
84 WRITE_PUT(pNv, SKIPS + 1);
86 if (GetTimeInMillis() - t_start > 2000)
88 dmaGet = READ_GET(pNv);
89 } while(dmaGet <= SKIPS);
91 WRITE_PUT(pNv, SKIPS);
92 pNv->dmaCurrent = pNv->dmaPut = SKIPS;
93 pNv->dmaFree = dmaGet - (SKIPS + 1);
96 pNv->dmaFree = dmaGet - pNv->dmaCurrent - 1;
98 if (GetTimeInMillis() - t_start > 2000)
103 static void NVDumpLockupInfo(NVPtr pNv)
106 start=READ_GET(pNv)-20;
107 if (start<0) start=0;
108 xf86DrvMsg(0, X_INFO, "Fifo dump (lockup 0x%04x,0x%04x):\n",READ_GET(pNv),pNv->dmaPut);
109 for(i=start;i<pNv->dmaPut+10;i++)
110 xf86DrvMsg(0, X_INFO, "[0x%04x] 0x%08x\n", i, pNv->dmaBase[i]);
111 xf86DrvMsg(0, X_INFO, "End of fifo dump\n");
115 NVLockedUp(ScrnInfoPtr pScrn)
117 NVPtr pNv = NVPTR(pScrn);
119 /* avoid re-entering FatalError on shutdown */
122 pNv->LockedUp = TRUE;
124 NVDumpLockupInfo(pNv);
126 FatalError("DMA queue hang: dmaPut=%x, current=%x, status=%x\n",
127 pNv->dmaPut, READ_GET(pNv), pNv->PGRAPH[NV_PGRAPH_STATUS/4]);
130 void NVSync(ScrnInfoPtr pScrn)
132 NVPtr pNv = NVPTR(pScrn);
133 int t_start, timeout = 2000;
134 int grobj = pNv->Architecture < NV_ARCH_50 ? NvImageBlit : Nv2D;
139 if(pNv->DMAKickoffCallback)
140 (*pNv->DMAKickoffCallback)(pNv);
142 /* Wait for entire FIFO to be processed */
143 t_start = GetTimeInMillis();
144 while((GetTimeInMillis() - t_start) < timeout &&
145 (READ_GET(pNv) != pNv->dmaPut));
146 if ((GetTimeInMillis() - t_start) >= timeout) {
151 /* Wait for channel to go completely idle */
152 NVNotifierReset(pScrn, pNv->Notifier0);
153 NVDmaStart(pNv, grobj, 0x104, 1);
155 NVDmaStart(pNv, grobj, 0x100, 1);
158 if (!NVNotifierWaitStatus(pScrn, pNv->Notifier0, 0, timeout))
162 void NVResetGraphics(ScrnInfoPtr pScrn)
164 NVPtr pNv = NVPTR(pScrn);
167 pNv->dmaPut = pNv->dmaCurrent = READ_GET(pNv);
168 pNv->dmaMax = (pNv->fifo.cmdbuf_size >> 2) - 2;
169 pNv->dmaFree = pNv->dmaMax - pNv->dmaCurrent;
171 /* assert there's enough room for the skips */
172 if(pNv->dmaFree <= SKIPS)
173 NVDmaWait(pScrn, SKIPS);
174 for (i=0; i<SKIPS; i++) {
178 pNv->dmaFree -= SKIPS;
183 NVAccelCommonInit(pScrn);
186 Bool NVDmaCreateContextObject(NVPtr pNv, int handle, int class)
188 struct drm_nouveau_grobj_alloc cto;
191 cto.channel = pNv->fifo.channel;
194 ret = drmCommandWrite(pNv->drm_fd, DRM_NOUVEAU_GROBJ_ALLOC,
199 static void NVInitDmaCB(ScrnInfoPtr pScrn)
201 NVPtr pNv = NVPTR(pScrn);
202 unsigned int cb_location;
206 /* I'm not bothering to check for failures here, the DRM will fall back
207 * on defaults if anything's wrong (ie. out of AGP, invalid sizes)
210 if (pNv->GARTScratch)
211 cb_location = NOUVEAU_MEM_AGP | NOUVEAU_MEM_PCI_ACCEPTABLE;
214 cb_location = NOUVEAU_MEM_FB;
215 if((s = (char *)xf86GetOptValString(pNv->Options, OPTION_CMDBUF_LOCATION))) {
216 if(!xf86NameCmp(s, "AGP"))
217 cb_location = NOUVEAU_MEM_AGP;
218 else if (!xf86NameCmp(s, "VRAM"))
219 cb_location = NOUVEAU_MEM_FB;
220 else if (!xf86NameCmp(s, "PCI"))
221 cb_location = NOUVEAU_MEM_PCI;
223 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Invalid value \"%s\" for CBLocation\n", s);
225 NVDRMSetParam(pNv, NOUVEAU_SETPARAM_CMDBUF_LOCATION, cb_location);
227 /* CBSize == size of space reserved for *all* FIFOs in MiB */
228 if (xf86GetOptValInteger(pNv->Options, OPTION_CMDBUF_SIZE, &cb_size))
229 NVDRMSetParam(pNv, NOUVEAU_SETPARAM_CMDBUF_SIZE, (cb_size<<20));
232 Bool NVInitDma(ScrnInfoPtr pScrn)
234 NVPtr pNv = NVPTR(pScrn);
242 pNv->fifo.fb_ctxdma_handle = NvDmaFB;
243 pNv->fifo.tt_ctxdma_handle = NvDmaTT;
244 ret = drmCommandWriteRead(pNv->drm_fd, DRM_NOUVEAU_CHANNEL_ALLOC,
245 &pNv->fifo, sizeof(pNv->fifo));
247 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
248 "Could not allocate GPU channel: %d\n", ret);
252 ret = drmMap(pNv->drm_fd, pNv->fifo.cmdbuf, pNv->fifo.cmdbuf_size,
253 (drmAddressPtr)&pNv->dmaBase);
255 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
256 "Failed to map DMA push buffer: %d\n", ret);
260 ret = drmMap(pNv->drm_fd, pNv->fifo.ctrl, pNv->fifo.ctrl_size,
261 (drmAddressPtr)&pNv->FIFO);
263 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
264 "Failed to map FIFO control regs: %d\n", ret);
268 ret = drmMap(pNv->drm_fd, pNv->fifo.notifier, pNv->fifo.notifier_size,
269 (drmAddressPtr)&pNv->NotifierBlock);
271 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
272 "Failed to map notifier block: %d\n", ret);
276 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
277 "Using FIFO channel %d\n", pNv->fifo.channel);
278 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
279 " Control registers : %p (0x%08x)\n",
280 pNv->FIFO, pNv->fifo.ctrl);
281 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
282 " DMA command buffer: %p (0x%08x)\n",
283 pNv->dmaBase, pNv->fifo.cmdbuf);
284 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
285 " DMA cmdbuf length : %d KiB\n",
286 pNv->fifo.cmdbuf_size / 1024);
287 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
288 " DMA base PUT : 0x%08x\n", pNv->fifo.put_base);
290 pNv->dmaPut = pNv->dmaCurrent = READ_GET(pNv);
291 pNv->dmaMax = (pNv->fifo.cmdbuf_size >> 2) - 2;
292 pNv->dmaFree = pNv->dmaMax - pNv->dmaCurrent;
294 for (i=0; i<SKIPS; i++)
296 pNv->dmaFree -= SKIPS;