2 * Copyright 2012 Red Hat Inc.
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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
25 #include <core/gpuobj.h>
26 #include <core/option.h>
28 #include <subdev/timer.h>
29 #include <subdev/vm.h>
33 #define NV44_GART_SIZE (512 * 1024 * 1024)
34 #define NV44_GART_PAGE ( 4 * 1024)
36 /*******************************************************************************
37 * VM map/unmap callbacks
38 ******************************************************************************/
41 nv44_vm_fill(struct nouveau_gpuobj
*pgt
, dma_addr_t null
,
42 dma_addr_t
*list
, u32 pte
, u32 cnt
)
44 u32 base
= (pte
<< 2) & ~0x0000000f;
47 tmp
[0] = nv_ro32(pgt
, base
+ 0x0);
48 tmp
[1] = nv_ro32(pgt
, base
+ 0x4);
49 tmp
[2] = nv_ro32(pgt
, base
+ 0x8);
50 tmp
[3] = nv_ro32(pgt
, base
+ 0xc);
53 u32 addr
= list
? (*list
++ >> 12) : (null
>> 12);
54 switch (pte
++ & 0x3) {
56 tmp
[0] &= ~0x07ffffff;
60 tmp
[0] &= ~0xf8000000;
62 tmp
[1] &= ~0x003fffff;
66 tmp
[1] &= ~0xffc00000;
68 tmp
[2] &= ~0x0001ffff;
72 tmp
[2] &= ~0xfffe0000;
74 tmp
[3] &= ~0x00000fff;
80 nv_wo32(pgt
, base
+ 0x0, tmp
[0]);
81 nv_wo32(pgt
, base
+ 0x4, tmp
[1]);
82 nv_wo32(pgt
, base
+ 0x8, tmp
[2]);
83 nv_wo32(pgt
, base
+ 0xc, tmp
[3] | 0x40000000);
87 nv44_vm_map_sg(struct nouveau_vma
*vma
, struct nouveau_gpuobj
*pgt
,
88 struct nouveau_mem
*mem
, u32 pte
, u32 cnt
, dma_addr_t
*list
)
90 struct nv04_vmmgr_priv
*priv
= (void *)vma
->vm
->vmm
;
95 u32 max
= 4 - (pte
& 3);
96 u32 part
= (cnt
> max
) ? max
: cnt
;
97 nv44_vm_fill(pgt
, priv
->null
, list
, pte
, part
);
104 for (i
= 0; i
< 4; i
++)
105 tmp
[i
] = *list
++ >> 12;
106 nv_wo32(pgt
, pte
++ * 4, tmp
[0] >> 0 | tmp
[1] << 27);
107 nv_wo32(pgt
, pte
++ * 4, tmp
[1] >> 5 | tmp
[2] << 22);
108 nv_wo32(pgt
, pte
++ * 4, tmp
[2] >> 10 | tmp
[3] << 17);
109 nv_wo32(pgt
, pte
++ * 4, tmp
[3] >> 15 | 0x40000000);
114 nv44_vm_fill(pgt
, priv
->null
, list
, pte
, cnt
);
118 nv44_vm_unmap(struct nouveau_gpuobj
*pgt
, u32 pte
, u32 cnt
)
120 struct nv04_vmmgr_priv
*priv
= (void *)nouveau_vmmgr(pgt
);
123 u32 max
= 4 - (pte
& 3);
124 u32 part
= (cnt
> max
) ? max
: cnt
;
125 nv44_vm_fill(pgt
, priv
->null
, NULL
, pte
, part
);
131 nv_wo32(pgt
, pte
++ * 4, 0x00000000);
132 nv_wo32(pgt
, pte
++ * 4, 0x00000000);
133 nv_wo32(pgt
, pte
++ * 4, 0x00000000);
134 nv_wo32(pgt
, pte
++ * 4, 0x00000000);
139 nv44_vm_fill(pgt
, priv
->null
, NULL
, pte
, cnt
);
143 nv44_vm_flush(struct nouveau_vm
*vm
)
145 struct nv04_vmmgr_priv
*priv
= (void *)vm
->vmm
;
146 nv_wr32(priv
, 0x100814, priv
->base
.limit
- NV44_GART_PAGE
);
147 nv_wr32(priv
, 0x100808, 0x00000020);
148 if (!nv_wait(priv
, 0x100808, 0x00000001, 0x00000001))
149 nv_error(priv
, "timeout: 0x%08x\n", nv_rd32(priv
, 0x100808));
150 nv_wr32(priv
, 0x100808, 0x00000000);
153 /*******************************************************************************
155 ******************************************************************************/
158 nv44_vmmgr_ctor(struct nouveau_object
*parent
, struct nouveau_object
*engine
,
159 struct nouveau_oclass
*oclass
, void *data
, u32 size
,
160 struct nouveau_object
**pobject
)
162 struct nouveau_device
*device
= nv_device(parent
);
163 struct nv04_vmmgr_priv
*priv
;
166 if (pci_find_capability(device
->pdev
, PCI_CAP_ID_AGP
) ||
167 !nouveau_boolopt(device
->cfgopt
, "NvPCIE", true)) {
168 return nouveau_object_ctor(parent
, engine
, &nv04_vmmgr_oclass
,
169 data
, size
, pobject
);
172 ret
= nouveau_vmmgr_create(parent
, engine
, oclass
, "PCIEGART",
174 *pobject
= nv_object(priv
);
178 priv
->base
.create
= nv04_vm_create
;
179 priv
->base
.limit
= NV44_GART_SIZE
;
180 priv
->base
.dma_bits
= 39;
181 priv
->base
.pgt_bits
= 32 - 12;
182 priv
->base
.spg_shift
= 12;
183 priv
->base
.lpg_shift
= 12;
184 priv
->base
.map_sg
= nv44_vm_map_sg
;
185 priv
->base
.unmap
= nv44_vm_unmap
;
186 priv
->base
.flush
= nv44_vm_flush
;
188 priv
->nullp
= pci_alloc_consistent(device
->pdev
, 16 * 1024, &priv
->null
);
190 nv_error(priv
, "unable to allocate dummy pages\n");
194 ret
= nouveau_vm_create(&priv
->base
, 0, NV44_GART_SIZE
, 0, 4096,
199 ret
= nouveau_gpuobj_new(nv_object(priv
), NULL
,
200 (NV44_GART_SIZE
/ NV44_GART_PAGE
) * 4,
201 512 * 1024, NVOBJ_FLAG_ZERO_ALLOC
,
202 &priv
->vm
->pgt
[0].obj
[0]);
203 priv
->vm
->pgt
[0].refcount
[0] = 1;
211 nv44_vmmgr_init(struct nouveau_object
*object
)
213 struct nv04_vmmgr_priv
*priv
= (void *)object
;
214 struct nouveau_gpuobj
*gart
= priv
->vm
->pgt
[0].obj
[0];
218 ret
= nouveau_vmmgr_init(&priv
->base
);
222 /* calculate vram address of this PRAMIN block, object must be
223 * allocated on 512KiB alignment, and not exceed a total size
224 * of 512KiB for this to work correctly
226 addr
= nv_rd32(priv
, 0x10020c);
227 addr
-= ((gart
->addr
>> 19) + 1) << 19;
229 nv_wr32(priv
, 0x100850, 0x80000000);
230 nv_wr32(priv
, 0x100818, priv
->null
);
231 nv_wr32(priv
, 0x100804, NV44_GART_SIZE
);
232 nv_wr32(priv
, 0x100850, 0x00008000);
233 nv_mask(priv
, 0x10008c, 0x00000200, 0x00000200);
234 nv_wr32(priv
, 0x100820, 0x00000000);
235 nv_wr32(priv
, 0x10082c, 0x00000001);
236 nv_wr32(priv
, 0x100800, addr
| 0x00000010);
240 struct nouveau_oclass
241 nv44_vmmgr_oclass
= {
242 .handle
= NV_SUBDEV(VM
, 0x44),
243 .ofuncs
= &(struct nouveau_ofuncs
) {
244 .ctor
= nv44_vmmgr_ctor
,
245 .dtor
= nv04_vmmgr_dtor
,
246 .init
= nv44_vmmgr_init
,
247 .fini
= _nouveau_vmmgr_fini
,
This page took 0.132351 seconds and 5 git commands to generate.