2 * Copyright 2007 Nouveau Project
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 #ifndef __NOUVEAU_DMA_H__
24 #define __NOUVEAU_DMA_H__
27 #include "nouveau_drmif.h"
28 #include "nouveau_local.h"
32 extern int nouveau_dma_wait(struct nouveau_channel
*chan
, int size
);
33 extern void nouveau_dma_subc_bind(struct nouveau_grobj
*);
34 extern void nouveau_dma_channel_init(struct nouveau_channel
*);
35 extern void nouveau_dma_kickoff(struct nouveau_channel
*);
37 #ifdef NOUVEAU_DMA_DEBUG
38 static char faulty
[1024];
42 nouveau_dma_out(struct nouveau_channel
*chan
, uint32_t data
)
44 struct nouveau_channel_priv
*nvchan
= nouveau_channel(chan
);
45 struct nouveau_dma_priv
*dma
= nvchan
->dma
;
47 #ifdef NOUVEAU_DMA_DEBUG
48 if (dma
->push_free
== 0) {
49 NOUVEAU_ERR("No space left in packet at %s\n", faulty
);
54 #ifdef NOUVEAU_DMA_TRACE
56 uint32_t offset
= (dma
->cur
<< 2) + dma
->base
;
57 NOUVEAU_MSG("\tOUT_RING %d/0x%08x -> 0x%08x\n",
58 nvchan
->drm
.channel
, offset
, data
);
61 nvchan
->pushbuf
[dma
->cur
+ (dma
->base
- nvchan
->drm
.put_base
)/4] = data
;
66 nouveau_dma_outp(struct nouveau_channel
*chan
, uint32_t *ptr
, int size
)
68 struct nouveau_channel_priv
*nvchan
= nouveau_channel(chan
);
69 struct nouveau_dma_priv
*dma
= nvchan
->dma
;
72 #ifdef NOUVEAU_DMA_DEBUG
73 if (dma
->push_free
< size
) {
74 NOUVEAU_ERR("Packet too small. Free=%d, Need=%d\n",
75 dma
->push_free
, size
);
79 #ifdef NOUVEAU_DMA_TRACE
81 nouveau_dma_out(chan
, *ptr
);
85 memcpy(&nvchan
->pushbuf
[dma
->cur
], ptr
, size
<< 2);
86 #ifdef NOUVEAU_DMA_DEBUG
87 dma
->push_free
-= size
;
94 nouveau_dma_space(struct nouveau_channel
*chan
, int size
)
96 struct nouveau_channel_priv
*nvchan
= nouveau_channel(chan
);
97 struct nouveau_dma_priv
*dma
= nvchan
->dma
;
99 if (dma
->free
< size
) {
100 if (nouveau_dma_wait(chan
, size
) && chan
->hang_notify
)
101 chan
->hang_notify(chan
);
104 #ifdef NOUVEAU_DMA_DEBUG
105 dma
->push_free
= size
;
110 nouveau_dma_begin(struct nouveau_channel
*chan
, struct nouveau_grobj
*grobj
,
111 int method
, int size
, const char* file
, int line
)
113 struct nouveau_channel_priv
*nvchan
= nouveau_channel(chan
);
114 struct nouveau_dma_priv
*dma
= nvchan
->dma
;
117 #ifdef NOUVEAU_DMA_TRACE
118 NOUVEAU_MSG("BEGIN_RING %d/%08x/%d/0x%04x/%d\n", nvchan
->drm
.channel
,
119 grobj
->handle
, grobj
->subc
, method
, size
);
122 #ifdef NOUVEAU_DMA_DEBUG
123 if (dma
->push_free
) {
124 NOUVEAU_ERR("Previous packet incomplete: %d left at %s\n",
125 dma
->push_free
, faulty
);
128 sprintf(faulty
,"%s:%d",file
,line
);
131 nouveau_dma_space(chan
, (size
+ 1));
132 nouveau_dma_out(chan
, (size
<< 18) | (grobj
->subc
<< 13) | method
);
135 #define RING_SPACE_CH(ch,sz) nouveau_dma_space((ch), (sz))
136 #define BEGIN_RING_CH(ch,gr,m,sz) nouveau_dma_begin((ch), (gr), (m), (sz), __FUNCTION__, __LINE__ )
137 #define OUT_RING_CH(ch, data) nouveau_dma_out((ch), (data))
138 #define OUT_RINGp_CH(ch,ptr,dwords) nouveau_dma_outp((ch), (void*)(ptr), \
140 #define FIRE_RING_CH(ch) nouveau_dma_kickoff((ch))
141 #define WAIT_RING_CH(ch,sz) nouveau_dma_wait((ch), (sz))