No empty .Rs/.Re
[netbsd-mini2440.git] / sys / external / bsd / drm / dist / bsd-core / nouveau_sgdma.c
blob99f854fed4a293846d180d44d422a7fecc8d961e
1 #include "drmP.h"
2 #include "nouveau_drv.h"
4 #define NV_CTXDMA_PAGE_SHIFT 12
5 #define NV_CTXDMA_PAGE_SIZE (1 << NV_CTXDMA_PAGE_SHIFT)
6 #define NV_CTXDMA_PAGE_MASK (NV_CTXDMA_PAGE_SIZE - 1)
8 #if 0
9 struct nouveau_sgdma_be {
10 struct drm_ttm_backend backend;
11 struct drm_device *dev;
13 int pages;
14 int pages_populated;
15 dma_addr_t *pagelist;
16 int is_bound;
18 unsigned int pte_start;
21 static int
22 nouveau_sgdma_needs_ub_cache_adjust(struct drm_ttm_backend *be)
24 return ((be->flags & DRM_BE_FLAG_BOUND_CACHED) ? 0 : 1);
27 static int
28 nouveau_sgdma_populate(struct drm_ttm_backend *be, unsigned long num_pages,
29 struct page **pages, struct page *dummy_read_page)
31 struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
32 int p, d, o;
34 DRM_DEBUG("num_pages = %ld\n", num_pages);
36 if (nvbe->pagelist)
37 return -EINVAL;
38 nvbe->pages = (num_pages << PAGE_SHIFT) >> NV_CTXDMA_PAGE_SHIFT;
39 nvbe->pagelist = drm_alloc(nvbe->pages*sizeof(dma_addr_t),
40 DRM_MEM_PAGES);
42 nvbe->pages_populated = d = 0;
43 for (p = 0; p < num_pages; p++) {
44 for (o = 0; o < PAGE_SIZE; o += NV_CTXDMA_PAGE_SIZE) {
45 struct page *page = pages[p];
46 if (!page)
47 page = dummy_read_page;
48 #ifdef __linux__
49 nvbe->pagelist[d] = pci_map_page(nvbe->dev->pdev,
50 page, o,
51 NV_CTXDMA_PAGE_SIZE,
52 PCI_DMA_BIDIRECTIONAL);
53 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))
54 if (pci_dma_mapping_error(nvbe->dev->pdev, nvbe->pagelist[d])) {
55 #else
56 if (pci_dma_mapping_error(nvbe->pagelist[d])) {
57 #endif
58 be->func->clear(be);
59 DRM_ERROR("pci_map_page failed\n");
60 return -EINVAL;
62 #endif
63 nvbe->pages_populated = ++d;
67 return 0;
70 static void
71 nouveau_sgdma_clear(struct drm_ttm_backend *be)
73 struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
74 #ifdef __linux__
75 int d;
76 #endif
77 DRM_DEBUG("\n");
79 if (nvbe && nvbe->pagelist) {
80 if (nvbe->is_bound)
81 be->func->unbind(be);
82 #ifdef __linux__
83 for (d = 0; d < nvbe->pages_populated; d++) {
84 pci_unmap_page(nvbe->dev->pdev, nvbe->pagelist[d],
85 NV_CTXDMA_PAGE_SIZE,
86 PCI_DMA_BIDIRECTIONAL);
88 #endif
89 drm_free(nvbe->pagelist, nvbe->pages*sizeof(dma_addr_t),
90 DRM_MEM_PAGES);
94 static int
95 nouveau_sgdma_bind(struct drm_ttm_backend *be, struct drm_bo_mem_reg *mem)
97 struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
98 struct drm_nouveau_private *dev_priv = nvbe->dev->dev_private;
99 struct nouveau_gpuobj *gpuobj = dev_priv->gart_info.sg_ctxdma;
100 uint64_t offset = (mem->mm_node->start << PAGE_SHIFT);
101 uint32_t i;
103 DRM_DEBUG("pg=0x%lx (0x%llx), cached=%d\n", mem->mm_node->start,
104 (unsigned long long)offset,
105 (mem->flags & DRM_BO_FLAG_CACHED) == 1);
107 if (offset & NV_CTXDMA_PAGE_MASK)
108 return -EINVAL;
109 nvbe->pte_start = (offset >> NV_CTXDMA_PAGE_SHIFT);
110 if (dev_priv->card_type < NV_50)
111 nvbe->pte_start += 2; /* skip ctxdma header */
113 for (i = nvbe->pte_start; i < nvbe->pte_start + nvbe->pages; i++) {
114 uint64_t pteval = nvbe->pagelist[i - nvbe->pte_start];
116 if (pteval & NV_CTXDMA_PAGE_MASK) {
117 DRM_ERROR("Bad pteval 0x%llx\n",
118 (unsigned long long)pteval);
119 return -EINVAL;
122 if (dev_priv->card_type < NV_50) {
123 INSTANCE_WR(gpuobj, i, pteval | 3);
124 } else {
125 INSTANCE_WR(gpuobj, (i<<1)+0, pteval | 0x21);
126 INSTANCE_WR(gpuobj, (i<<1)+1, 0x00000000);
130 nvbe->is_bound = 1;
131 return 0;
134 static int
135 nouveau_sgdma_unbind(struct drm_ttm_backend *be)
137 struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
138 struct drm_nouveau_private *dev_priv = nvbe->dev->dev_private;
140 DRM_DEBUG("\n");
142 if (nvbe->is_bound) {
143 struct nouveau_gpuobj *gpuobj = dev_priv->gart_info.sg_ctxdma;
144 unsigned int pte;
146 pte = nvbe->pte_start;
147 while (pte < (nvbe->pte_start + nvbe->pages)) {
148 uint64_t pteval = dev_priv->gart_info.sg_dummy_bus;
150 if (dev_priv->card_type < NV_50) {
151 INSTANCE_WR(gpuobj, pte, pteval | 3);
152 } else {
153 INSTANCE_WR(gpuobj, (pte<<1)+0, pteval | 0x21);
154 INSTANCE_WR(gpuobj, (pte<<1)+1, 0x00000000);
157 pte++;
160 nvbe->is_bound = 0;
163 return 0;
166 static void
167 nouveau_sgdma_destroy(struct drm_ttm_backend *be)
169 DRM_DEBUG("\n");
170 if (be) {
171 struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
172 if (nvbe) {
173 if (nvbe->pagelist)
174 be->func->clear(be);
175 drm_ctl_free(nvbe, sizeof(*nvbe), DRM_MEM_TTM);
180 static struct drm_ttm_backend_func nouveau_sgdma_backend = {
181 .needs_ub_cache_adjust = nouveau_sgdma_needs_ub_cache_adjust,
182 .populate = nouveau_sgdma_populate,
183 .clear = nouveau_sgdma_clear,
184 .bind = nouveau_sgdma_bind,
185 .unbind = nouveau_sgdma_unbind,
186 .destroy = nouveau_sgdma_destroy
189 struct drm_ttm_backend *
190 nouveau_sgdma_init_ttm(struct drm_device *dev)
192 struct drm_nouveau_private *dev_priv = dev->dev_private;
193 struct nouveau_sgdma_be *nvbe;
195 if (!dev_priv->gart_info.sg_ctxdma)
196 return NULL;
198 nvbe = drm_ctl_calloc(1, sizeof(*nvbe), DRM_MEM_TTM);
199 if (!nvbe)
200 return NULL;
202 nvbe->dev = dev;
204 nvbe->backend.func = &nouveau_sgdma_backend;
206 return &nvbe->backend;
208 #endif
211 nouveau_sgdma_init(struct drm_device *dev)
213 struct drm_nouveau_private *dev_priv = dev->dev_private;
214 struct nouveau_gpuobj *gpuobj = NULL;
215 uint32_t aper_size, obj_size;
216 int i, ret;
218 if (dev_priv->card_type < NV_50) {
219 aper_size = (64 * 1024 * 1024);
220 obj_size = (aper_size >> NV_CTXDMA_PAGE_SHIFT) * 4;
221 obj_size += 8; /* ctxdma header */
222 } else {
223 /* 1 entire VM page table */
224 aper_size = (512 * 1024 * 1024);
225 obj_size = (aper_size >> NV_CTXDMA_PAGE_SHIFT) * 8;
228 if ((ret = nouveau_gpuobj_new(dev, NULL, obj_size, 16,
229 NVOBJ_FLAG_ALLOW_NO_REFS |
230 NVOBJ_FLAG_ZERO_ALLOC |
231 NVOBJ_FLAG_ZERO_FREE, &gpuobj))) {
232 DRM_ERROR("Error creating sgdma object: %d\n", ret);
233 return ret;
235 #ifdef __linux__
236 dev_priv->gart_info.sg_dummy_page =
237 alloc_page(GFP_KERNEL|__GFP_DMA32);
238 set_page_locked(dev_priv->gart_info.sg_dummy_page);
239 dev_priv->gart_info.sg_dummy_bus =
240 pci_map_page(dev->pdev, dev_priv->gart_info.sg_dummy_page, 0,
241 PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
242 #endif
243 if (dev_priv->card_type < NV_50) {
244 /* Maybe use NV_DMA_TARGET_AGP for PCIE? NVIDIA do this, and
245 * confirmed to work on c51. Perhaps means NV_DMA_TARGET_PCIE
246 * on those cards? */
247 INSTANCE_WR(gpuobj, 0, NV_CLASS_DMA_IN_MEMORY |
248 (1 << 12) /* PT present */ |
249 (0 << 13) /* PT *not* linear */ |
250 (NV_DMA_ACCESS_RW << 14) |
251 (NV_DMA_TARGET_PCI << 16));
252 INSTANCE_WR(gpuobj, 1, aper_size - 1);
253 for (i=2; i<2+(aper_size>>12); i++) {
254 INSTANCE_WR(gpuobj, i,
255 dev_priv->gart_info.sg_dummy_bus | 3);
257 } else {
258 for (i=0; i<obj_size; i+=8) {
259 INSTANCE_WR(gpuobj, (i+0)/4,
260 dev_priv->gart_info.sg_dummy_bus | 0x21);
261 INSTANCE_WR(gpuobj, (i+4)/4, 0);
265 dev_priv->gart_info.type = NOUVEAU_GART_SGDMA;
266 dev_priv->gart_info.aper_base = 0;
267 dev_priv->gart_info.aper_size = aper_size;
268 dev_priv->gart_info.sg_ctxdma = gpuobj;
269 return 0;
272 void
273 nouveau_sgdma_takedown(struct drm_device *dev)
275 struct drm_nouveau_private *dev_priv = dev->dev_private;
277 if (dev_priv->gart_info.sg_dummy_page) {
278 #ifdef __linux__
279 pci_unmap_page(dev->pdev, dev_priv->gart_info.sg_dummy_bus,
280 NV_CTXDMA_PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
281 unlock_page(dev_priv->gart_info.sg_dummy_page);
282 __free_page(dev_priv->gart_info.sg_dummy_page);
283 #endif
284 dev_priv->gart_info.sg_dummy_page = NULL;
285 dev_priv->gart_info.sg_dummy_bus = 0;
288 nouveau_gpuobj_del(dev, &dev_priv->gart_info.sg_ctxdma);
291 #if 0
293 nouveau_sgdma_nottm_hack_init(struct drm_device *dev)
295 struct drm_nouveau_private *dev_priv = dev->dev_private;
296 struct drm_ttm_backend *be;
297 struct drm_scatter_gather sgreq;
298 struct drm_mm_node mm_node;
299 struct drm_bo_mem_reg mem;
300 int ret;
302 dev_priv->gart_info.sg_be = nouveau_sgdma_init_ttm(dev);
303 if (!dev_priv->gart_info.sg_be)
304 return -ENOMEM;
305 be = dev_priv->gart_info.sg_be;
307 /* Hack the aperture size down to the amount of system memory
308 * we're going to bind into it.
310 if (dev_priv->gart_info.aper_size > 32*1024*1024)
311 dev_priv->gart_info.aper_size = 32*1024*1024;
313 sgreq.size = dev_priv->gart_info.aper_size;
314 if ((ret = drm_sg_alloc(dev, &sgreq))) {
315 DRM_ERROR("drm_sg_alloc failed: %d\n", ret);
316 return ret;
318 dev_priv->gart_info.sg_handle = sgreq.handle;
320 if ((ret = be->func->populate(be, dev->sg->pages, dev->sg->pagelist, dev->bm.dummy_read_page))) {
321 DRM_ERROR("failed populate: %d\n", ret);
322 return ret;
325 mm_node.start = 0;
326 mem.mm_node = &mm_node;
328 if ((ret = be->func->bind(be, &mem))) {
329 DRM_ERROR("failed bind: %d\n", ret);
330 return ret;
333 return 0;
336 void
337 nouveau_sgdma_nottm_hack_takedown(struct drm_device *dev)
340 #endif
343 nouveau_sgdma_get_page(struct drm_device *dev, uint32_t offset, uint32_t *page)
345 struct drm_nouveau_private *dev_priv = dev->dev_private;
346 struct nouveau_gpuobj *gpuobj = dev_priv->gart_info.sg_ctxdma;
347 int pte;
349 pte = (offset >> NV_CTXDMA_PAGE_SHIFT);
350 if (dev_priv->card_type < NV_50) {
351 *page = INSTANCE_RD(gpuobj, (pte + 2)) & ~NV_CTXDMA_PAGE_MASK;
352 return 0;
355 DRM_ERROR("Unimplemented on NV50\n");
356 return -EINVAL;