2 * Copyright 2007 Ben Skeggs
3 * Copyright 2007 Stephane Marchesin
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
20 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 #include "nv_include.h"
28 static void NVDumpLockupInfo(NVPtr pNv)
30 struct nouveau_channel_priv *chan = nouveau_channel(pNv->chan);
33 start = ((*chan->get - chan->dma.base) >> 2) - 20;
37 xf86DrvMsg(0, X_INFO, "Fifo dump (lockup 0x%04x,0x%04x):\n",
38 (*chan->get - chan->dma.base) >> 2, chan->dma.put);
39 for(i = start; i < chan->dma.put + 10; i++)
40 xf86DrvMsg(0, X_INFO, "[0x%04x] 0x%08x\n", i, chan->pushbuf[i]);
41 xf86DrvMsg(0, X_INFO, "End of fifo dump\n");
45 NVLockedUp(ScrnInfoPtr pScrn)
47 NVPtr pNv = NVPTR(pScrn);
48 struct nouveau_channel_priv *chan = nouveau_channel(pNv->chan);
50 /* avoid re-entering FatalError on shutdown */
55 NVDumpLockupInfo(pNv);
57 FatalError("DMA queue hang: dmaPut=%x, current=%x, status=%x\n",
58 chan->dma.put, (*chan->get - chan->dma.base) >> 2,
59 pNv->PGRAPH[NV_PGRAPH_STATUS/4]);
63 NVChannelHangNotify(struct nouveau_channel *chan)
65 ScrnInfoPtr pScrn = chan->user_private;
69 void NVSync(ScrnInfoPtr pScrn)
71 NVPtr pNv = NVPTR(pScrn);
72 struct nouveau_channel_priv *chan = nouveau_channel(pNv->chan);
73 int t_start, timeout = 2000;
78 /* Wait for entire FIFO to be processed */
79 t_start = GetTimeInMillis();
80 while((GetTimeInMillis() - t_start) < timeout &&
81 (((*chan->get - chan->dma.base) >> 2)!= chan->dma.put));
82 if ((GetTimeInMillis() - t_start) >= timeout) {
87 /* Wait for channel to go completely idle */
88 nouveau_notifier_reset(pNv->notify0, 0);
89 if (pNv->Architecture < NV_ARCH_50) {
90 BEGIN_RING(NvImageBlit, 0x104, 1);
92 BEGIN_RING(NvImageBlit, 0x100, 1);
95 BEGIN_RING(Nv2D, 0x104, 1);
97 BEGIN_RING(Nv2D, 0x100, 1);
101 if (nouveau_notifier_wait_status(pNv->notify0, 0,
102 NV_NOTIFY_STATE_STATUS_COMPLETED,
107 void NVResetGraphics(ScrnInfoPtr pScrn)
109 NVAccelCommonInit(pScrn);
112 static void NVInitDmaCB(ScrnInfoPtr pScrn)
114 NVPtr pNv = NVPTR(pScrn);
115 unsigned int cb_location;
119 /* I'm not bothering to check for failures here, the DRM will fall back
120 * on defaults if anything's wrong (ie. out of AGP, invalid sizes)
124 cb_location = NOUVEAU_MEM_AGP | NOUVEAU_MEM_PCI_ACCEPTABLE;
127 cb_location = NOUVEAU_MEM_FB;
128 if((s = (char *)xf86GetOptValString(pNv->Options, OPTION_CMDBUF_LOCATION))) {
129 if(!xf86NameCmp(s, "AGP"))
130 cb_location = NOUVEAU_MEM_AGP;
131 else if (!xf86NameCmp(s, "VRAM"))
132 cb_location = NOUVEAU_MEM_FB;
133 else if (!xf86NameCmp(s, "PCI"))
134 cb_location = NOUVEAU_MEM_PCI;
136 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Invalid value \"%s\" for CBLocation\n", s);
138 nouveau_device_set_param(pNv->dev, NOUVEAU_SETPARAM_CMDBUF_LOCATION,
141 /* CBSize == size of space reserved for *all* FIFOs in MiB */
142 if (xf86GetOptValInteger(pNv->Options, OPTION_CMDBUF_SIZE, &cb_size))
143 nouveau_device_set_param(pNv->dev, NOUVEAU_SETPARAM_CMDBUF_SIZE,
148 NVInitDma(ScrnInfoPtr pScrn)
150 NVPtr pNv = NVPTR(pScrn);
155 ret = nouveau_channel_alloc(pNv->dev, NvDmaFB, NvDmaTT, &pNv->chan);
157 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
158 "Error creating GPU channel: %d\n", ret);
161 pNv->chan->user_private = pScrn;
162 pNv->chan->hang_notify = NVChannelHangNotify;
164 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
165 "Opened GPU channel %d\n", pNv->chan->id);