OSDN Git Service

drm: convert drawable handling to use Linux idr
[android-x86/external-libdrm.git] / shared-core / nouveau_object.c
1 /*
2  * Copyright (C) 2006 Ben Skeggs.
3  *
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining
7  * a copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sublicense, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice (including the
15  * next paragraph) shall be included in all copies or substantial
16  * portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21  * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
22  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25  *
26  */
27
28 /*
29  * Authors:
30  *   Ben Skeggs <darktama@iinet.net.au>
31  */
32
33 #include "drmP.h"
34 #include "drm.h"
35 #include "nouveau_drv.h"
36 #include "nouveau_drm.h"
37
38 /* TODO
39  *  - Check object class, deny unsafe objects (add card-specific versioning?)
40  *  - Get rid of DMA object creation, this should be wrapped by MM routines.
41  */
42
43 /* Translate a RAMIN offset into a value the card understands, will be useful
44  * in the future when we can access more instance ram which isn't mapped into
45  * the PRAMIN aperture
46  */
47 uint32_t
48 nouveau_chip_instance_get(drm_device_t *dev, struct mem_block *mem)
49 {
50         uint32_t inst = (uint32_t)mem->start >> 4;
51         DRM_DEBUG("****** on-chip instance for 0x%016llx = 0x%08x\n",
52                         mem->start, inst);
53         return inst;
54 }
55
56 static void
57 nouveau_object_link(drm_device_t *dev, struct nouveau_object *obj)
58 {
59         drm_nouveau_private_t *dev_priv=dev->dev_private;
60         struct nouveau_fifo *chan = &dev_priv->fifos[obj->channel];
61
62         if (!chan->objs) {
63                 chan->objs = obj;
64                 return;
65         }
66
67         obj->prev = NULL;
68         obj->next = chan->objs;
69
70         chan->objs->prev = obj;
71         chan->objs = obj;
72 }
73
74 static void
75 nouveau_object_unlink(drm_device_t *dev, struct nouveau_object *obj)
76 {
77         drm_nouveau_private_t *dev_priv=dev->dev_private;
78         struct nouveau_fifo *chan = &dev_priv->fifos[obj->channel];
79
80         if (obj->prev == NULL) {        
81                 if (obj->next)
82                         obj->next->prev = NULL;
83                 chan->objs = obj->next;
84         } else if (obj->next == NULL) {
85                 if (obj->prev)
86                         obj->prev->next = NULL;
87         } else {
88                 obj->prev->next = obj->next;
89                 obj->next->prev = obj->prev;
90         }
91 }
92
93 static struct nouveau_object *
94 nouveau_object_handle_find(drm_device_t *dev, int channel, uint32_t handle)
95 {
96         drm_nouveau_private_t *dev_priv=dev->dev_private;
97         struct nouveau_fifo *chan = &dev_priv->fifos[channel];
98         struct nouveau_object *obj = chan->objs;
99
100         DRM_DEBUG("Looking for handle 0x%08x\n", handle);
101         while (obj) {
102                 if (obj->handle == handle)
103                         return obj;
104                 obj = obj->next;
105         }
106
107         DRM_DEBUG("...couldn't find handle\n");
108         return NULL;
109 }
110
111 /* NVidia uses context objects to drive drawing operations.
112
113    Context objects can be selected into 8 subchannels in the FIFO,
114    and then used via DMA command buffers.
115
116    A context object is referenced by a user defined handle (CARD32). The HW
117    looks up graphics objects in a hash table in the instance RAM.
118
119    An entry in the hash table consists of 2 CARD32. The first CARD32 contains
120    the handle, the second one a bitfield, that contains the address of the
121    object in instance RAM.
122
123    The format of the second CARD32 seems to be:
124
125    NV4 to NV30:
126
127    15: 0  instance_addr >> 4
128    17:16  engine (here uses 1 = graphics)
129    28:24  channel id (here uses 0)
130    31     valid (use 1)
131
132    NV40:
133
134    15: 0  instance_addr >> 4   (maybe 19-0)
135    21:20  engine (here uses 1 = graphics)
136    I'm unsure about the other bits, but using 0 seems to work.
137
138    The key into the hash table depends on the object handle and channel id and
139    is given as:
140 */
141 static uint32_t
142 nouveau_ht_handle_hash(drm_device_t *dev, int channel, uint32_t handle)
143 {
144         drm_nouveau_private_t *dev_priv=dev->dev_private;
145         uint32_t hash = 0;
146         int i;
147
148         for (i=32;i>0;i-=dev_priv->ramht_bits) {
149                 hash ^= (handle & ((1 << dev_priv->ramht_bits) - 1));
150                 handle >>= dev_priv->ramht_bits;
151         }
152         hash ^= channel << (dev_priv->ramht_bits - 4);
153         return hash << 3;
154 }
155
156 static int
157 nouveau_ht_object_insert(drm_device_t* dev, int channel, uint32_t handle,
158                          struct nouveau_object *obj)
159 {
160         drm_nouveau_private_t *dev_priv=dev->dev_private;
161         int ht_base = NV_RAMIN + dev_priv->ramht_offset;
162         int ht_end  = ht_base + dev_priv->ramht_size;
163         int o_ofs, ofs;
164
165         obj->handle = handle;
166         o_ofs = ofs = nouveau_ht_handle_hash(dev, channel, obj->handle);
167
168         while (NV_READ(ht_base + ofs) || NV_READ(ht_base + ofs + 4)) {
169                 ofs += 8;
170                 if (ofs == ht_end) ofs = ht_base;
171                 if (ofs == o_ofs) {
172                         DRM_ERROR("no free hash table entries\n");
173                         return 1;
174                 }
175         }
176         ofs += ht_base;
177
178         DRM_DEBUG("Channel %d - Handle 0x%08x at 0x%08x\n",
179                 channel, obj->handle, ofs);
180
181         NV_WRITE(NV_RAMHT_HANDLE_OFFSET + ofs, obj->handle);
182         if (dev_priv->card_type >= NV_40)
183                 NV_WRITE(NV_RAMHT_CONTEXT_OFFSET + ofs,
184                         (channel     << NV40_RAMHT_CONTEXT_CHANNEL_SHIFT) |
185                         (obj->engine << NV40_RAMHT_CONTEXT_ENGINE_SHIFT) |
186                         nouveau_chip_instance_get(dev, obj->instance)
187                         );          
188         else
189                 NV_WRITE(NV_RAMHT_CONTEXT_OFFSET + ofs,
190                         NV_RAMHT_CONTEXT_VALID |
191                         (channel     << NV_RAMHT_CONTEXT_CHANNEL_SHIFT) |
192                         (obj->engine << NV_RAMHT_CONTEXT_ENGINE_SHIFT) |
193                         nouveau_chip_instance_get(dev, obj->instance)
194                         );
195
196         obj->ht_loc = ofs;
197         return 0;
198 }
199
200 static void nouveau_hash_table_remove(drm_device_t* dev,
201                                       struct nouveau_object *obj)
202 {
203         drm_nouveau_private_t *dev_priv = dev->dev_private;
204
205         DRM_DEBUG("Remove handle 0x%08x at 0x%08x from HT\n",
206                         obj->handle, obj->ht_loc);
207         if (obj->ht_loc) {
208                 DRM_DEBUG("... HT entry was: 0x%08x/0x%08x\n",
209                                 NV_READ(obj->ht_loc), NV_READ(obj->ht_loc+4));
210                 NV_WRITE(obj->ht_loc  , 0x00000000);
211                 NV_WRITE(obj->ht_loc+4, 0x00000000);
212         }
213 }
214
215 static struct nouveau_object *
216 nouveau_object_instance_alloc(drm_device_t* dev, int channel)
217 {
218         drm_nouveau_private_t *dev_priv=dev->dev_private;
219         struct nouveau_object       *obj;
220
221         /* Create object struct */
222         obj = drm_calloc(1, sizeof(struct nouveau_object), DRM_MEM_DRIVER);
223         if (!obj) {
224                 DRM_ERROR("couldn't alloc memory for object\n");
225                 return NULL;
226         }
227
228         /* Allocate instance memory */
229         obj->instance  = nouveau_instmem_alloc(dev,
230                         (dev_priv->card_type >= NV_40 ? 32 : 16), 4);
231         if (!obj->instance) {
232                 DRM_ERROR("couldn't alloc RAMIN for object\n");
233                 drm_free(obj, sizeof(struct nouveau_object), DRM_MEM_DRIVER);
234                 return NULL;
235         }
236
237         /* Bind object to channel */
238         obj->channel = channel;
239         obj->handle  = ~0;
240         nouveau_object_link(dev, obj);
241
242         return obj;
243 }
244
245 static void
246 nouveau_object_instance_free(drm_device_t *dev, struct nouveau_object *obj)
247 {
248         drm_nouveau_private_t *dev_priv=dev->dev_private;
249         int i;
250
251         /* Unbind object from channel */
252         nouveau_object_unlink(dev, obj);
253
254         /* Clean RAMIN entry */
255         DRM_DEBUG("Instance entry for 0x%08x"
256                 "(engine %d, class 0x%x) before destroy:\n",
257                 obj->handle, obj->engine, obj->class);
258         for (i=0; i<(obj->instance->size/4); i++) {
259                 DRM_DEBUG("  +0x%02x: 0x%08x\n", (i*4),
260                         INSTANCE_RD(obj->instance, i));
261                 INSTANCE_WR(obj->instance, i, 0x00000000);
262         }
263
264         /* Free RAMIN */
265         nouveau_instmem_free(dev, obj->instance);
266 }
267
268 /*
269    DMA objects are used to reference a piece of memory in the
270    framebuffer, PCI or AGP address space. Each object is 16 bytes big
271    and looks as follows:
272    
273    entry[0]
274    11:0  class (seems like I can always use 0 here)
275    12    page table present?
276    13    page entry linear?
277    15:14 access: 0 rw, 1 ro, 2 wo
278    17:16 target: 0 NV memory, 1 NV memory tiled, 2 PCI, 3 AGP
279    31:20 dma adjust (bits 0-11 of the address)
280    entry[1]
281    dma limit
282    entry[2]
283    1     0 readonly, 1 readwrite
284    31:12 dma frame address (bits 12-31 of the address)
285
286    Non linear page tables seem to need a list of frame addresses afterwards,
287    the rivatv project has some info on this.   
288
289    The method below creates a DMA object in instance RAM and returns a handle
290    to it that can be used to set up context objects.
291 */
292
293 struct nouveau_object *
294 nouveau_object_dma_create(drm_device_t* dev, int channel, int class,
295                           uint32_t offset, uint32_t size,
296                           int access, int target)
297 {
298         drm_nouveau_private_t *dev_priv=dev->dev_private;
299         struct   nouveau_object *obj;
300         uint32_t frame, adjust;
301         uint32_t pte_flags = 0;
302
303         DRM_DEBUG("offset:0x%08x, size:0x%08x, target:%d, access:%d\n",
304                         offset, size, target, access);
305
306         switch (target) {
307         case NV_DMA_TARGET_AGP:
308                 offset += dev_priv->agp_phys;
309                 break;
310         default:
311                 break;
312         }
313
314         switch (access) {
315         case NV_DMA_ACCESS_RO:
316                 break;
317         case NV_DMA_ACCESS_WO:
318         case NV_DMA_ACCESS_RW:
319                 pte_flags  |= (1 << 1);
320                 break;
321         default:
322                 DRM_ERROR("invalid access mode=%d\n", access);
323                 return NULL;
324         }
325
326         frame  = offset & ~0x00000FFF;
327         adjust = offset &  0x00000FFF;
328
329         obj = nouveau_object_instance_alloc(dev, channel);
330         if (!obj) {
331                 DRM_ERROR("couldn't allocate DMA object\n");
332                 return obj;
333         }
334
335         obj->engine = 0;
336         obj->class  = class;
337
338         INSTANCE_WR(obj->instance, 0, ((1<<12) | (1<<13) |
339                                 (adjust << 20) |
340                                 (access << 14) |
341                                 (target << 16) |
342                                 class));
343         INSTANCE_WR(obj->instance, 1, size-1);
344         INSTANCE_WR(obj->instance, 2, frame | pte_flags);
345         INSTANCE_WR(obj->instance, 3, frame | pte_flags);
346
347         return obj;
348 }
349
350
351 /* Context objects in the instance RAM have the following structure.
352  * On NV40 they are 32 byte long, on NV30 and smaller 16 bytes.
353
354    NV4 - NV30:
355
356    entry[0]
357    11:0 class
358    12   chroma key enable
359    13   user clip enable
360    14   swizzle enable
361    17:15 patch config:
362        scrcopy_and, rop_and, blend_and, scrcopy, srccopy_pre, blend_pre
363    18   synchronize enable
364    19   endian: 1 big, 0 little
365    21:20 dither mode
366    23    single step enable
367    24    patch status: 0 invalid, 1 valid
368    25    context_surface 0: 1 valid
369    26    context surface 1: 1 valid
370    27    context pattern: 1 valid
371    28    context rop: 1 valid
372    29,30 context beta, beta4
373    entry[1]
374    7:0   mono format
375    15:8  color format
376    31:16 notify instance address
377    entry[2]
378    15:0  dma 0 instance address
379    31:16 dma 1 instance address
380    entry[3]
381    dma method traps
382
383    NV40:
384    No idea what the exact format is. Here's what can be deducted:
385
386    entry[0]:
387    11:0  class  (maybe uses more bits here?)
388    17    user clip enable
389    21:19 patch config 
390    25    patch status valid ?
391    entry[1]:
392    15:0  DMA notifier  (maybe 20:0)
393    entry[2]:
394    15:0  DMA 0 instance (maybe 20:0)
395    24    big endian
396    entry[3]:
397    15:0  DMA 1 instance (maybe 20:0)
398    entry[4]:
399    entry[5]:
400    set to 0?
401 */
402 struct nouveau_object *
403 nouveau_object_gr_create(drm_device_t* dev, int channel, int class)
404 {
405         drm_nouveau_private_t *dev_priv=dev->dev_private;
406         struct   nouveau_object *obj;
407
408         DRM_DEBUG("class=%x\n", class);
409
410         obj = nouveau_object_instance_alloc(dev, channel);
411         if (!obj) {
412                 DRM_ERROR("couldn't allocate context object\n");
413                 return obj;
414         }
415
416         obj->engine = 1;
417         obj->class  = class;
418
419         switch (class) {
420         case NV_CLASS_NULL:
421                 INSTANCE_WR(obj->instance, 0, 0x00001030);
422                 INSTANCE_WR(obj->instance, 1, 0xFFFFFFFF);
423                 INSTANCE_WR(obj->instance, 2, 0x00000000);
424                 INSTANCE_WR(obj->instance, 2, 0x00000000);
425                 break;
426         default:
427                 if (dev_priv->card_type >= NV_40) {
428                         INSTANCE_WR(obj->instance, 0,  obj->class);
429                         INSTANCE_WR(obj->instance, 1, 0x00000000);
430 #ifdef __BIG_ENDIAN
431                         INSTANCE_WR(obj->instance, 2, 0x01000000);
432 #else
433                         INSTANCE_WR(obj->instance, 2, 0x00000000);
434 #endif
435                         INSTANCE_WR(obj->instance, 3, 0x00000000);
436                         INSTANCE_WR(obj->instance, 4, 0x00000000);
437                         INSTANCE_WR(obj->instance, 5, 0x00000000);
438                         INSTANCE_WR(obj->instance, 6, 0x00000000);
439                         INSTANCE_WR(obj->instance, 7, 0x00000000);
440                 } else {
441 #ifdef __BIG_ENDIAN
442                         INSTANCE_WR(obj->instance, 0, obj->class | 0x00080000);
443 #else
444                         INSTANCE_WR(obj->instance, 0, obj->class);
445 #endif
446                         INSTANCE_WR(obj->instance, 1, 0x00000000);
447                         INSTANCE_WR(obj->instance, 2, 0x00000000);
448                         INSTANCE_WR(obj->instance, 3, 0x00000000);
449                 }
450         }
451
452         return obj;
453 }
454
455 void
456 nouveau_object_free(drm_device_t *dev, struct nouveau_object *obj)
457 {
458         nouveau_object_instance_free(dev, obj);
459         if (obj->handle != ~0)
460                 nouveau_hash_table_remove(dev, obj);
461         drm_free(obj, sizeof(struct nouveau_object), DRM_MEM_DRIVER);
462 }
463
464 void nouveau_object_cleanup(drm_device_t *dev, int channel)
465 {
466         drm_nouveau_private_t *dev_priv=dev->dev_private;
467
468         while (dev_priv->fifos[channel].objs) {
469                 nouveau_object_free(dev, dev_priv->fifos[channel].objs);
470         }
471 }
472
473 int nouveau_ioctl_object_init(DRM_IOCTL_ARGS)
474 {
475         DRM_DEVICE;
476         drm_nouveau_object_init_t init;
477         struct nouveau_object *obj;
478
479         DRM_COPY_FROM_USER_IOCTL(init, (drm_nouveau_object_init_t __user *)
480                 data, sizeof(init));
481
482         if (!nouveau_fifo_owner(dev, filp, init.channel)) {
483                 DRM_ERROR("pid %d doesn't own channel %d\n",
484                                 DRM_CURRENTPID, init.channel);
485                 return DRM_ERR(EINVAL);
486         }
487
488         //FIXME: check args, only allow trusted objects to be created
489
490         if (nouveau_object_handle_find(dev, init.channel, init.handle)) {
491                 DRM_ERROR("Channel %d: handle 0x%08x already exists\n",
492                         init.channel, init.handle);
493                 return DRM_ERR(EINVAL);
494         }
495
496         obj = nouveau_object_gr_create(dev, init.channel, init.class);
497         if (!obj)
498                 return DRM_ERR(ENOMEM);
499
500         if (nouveau_ht_object_insert(dev, init.channel, init.handle, obj)) {
501                 nouveau_object_free(dev, obj);
502                 return DRM_ERR(ENOMEM);
503         }
504
505         return 0;
506 }
507
508 static int
509 nouveau_dma_object_check_access(drm_device_t *dev,
510                                 drm_nouveau_dma_object_init_t *init)
511 {
512         drm_nouveau_private_t *dev_priv = dev->dev_private;
513         uint64_t limit;
514
515         /* Check for known DMA object classes */
516         switch (init->class) {
517         case NV_CLASS_DMA_IN_MEMORY:
518         case NV_CLASS_DMA_FROM_MEMORY:
519         case NV_CLASS_DMA_TO_MEMORY:
520                 break;
521         default:
522                 DRM_ERROR("invalid class = 0x%x\n", init->class);
523                 return DRM_ERR(EPERM);
524         }
525
526         /* Check access mode, and translate to NV_DMA_ACCESS_* */
527         switch (init->access) {
528         case NOUVEAU_MEM_ACCESS_RO:
529                 init->access = NV_DMA_ACCESS_RO;
530                 break;
531         case NOUVEAU_MEM_ACCESS_WO:
532                 init->access = NV_DMA_ACCESS_WO;
533                 break;
534         case NOUVEAU_MEM_ACCESS_RW:
535                 init->access = NV_DMA_ACCESS_RW;
536                 break;
537         default:
538                 DRM_ERROR("invalid access mode = %d\n", init->access);
539                 return DRM_ERR(EPERM);
540         }
541
542         /* Check that request is within the allowed limits of "target" */
543         switch (init->target) {
544         case NOUVEAU_MEM_FB:
545                 limit = dev_priv->fb_available_size;
546                 init->target = NV_DMA_TARGET_VIDMEM;
547                 break;
548         case NOUVEAU_MEM_AGP:
549                 limit = dev_priv->agp_available_size;
550                 init->target = NV_DMA_TARGET_AGP;
551                 break;
552         default:
553                 DRM_ERROR("invalid target = 0x%x\n", init->target);
554                 return DRM_ERR(EPERM);
555         }
556
557         if ((init->offset > limit) || (init->offset + init->size) > limit) {
558                 DRM_ERROR("access out of allowed range (%d,0x%08x,0x%08x)\n",
559                                 init->target, init->offset, init->size);
560                 return DRM_ERR(EPERM);
561         }
562
563         return 0;
564 }
565
566 int nouveau_ioctl_dma_object_init(DRM_IOCTL_ARGS)
567 {
568         DRM_DEVICE;
569         drm_nouveau_dma_object_init_t init;
570         struct nouveau_object *obj;
571
572         DRM_COPY_FROM_USER_IOCTL(init, (drm_nouveau_dma_object_init_t __user *)
573                 data, sizeof(init));
574
575         if (!nouveau_fifo_owner(dev, filp, init.channel)) {
576                 DRM_ERROR("pid %d doesn't own channel %d\n",
577                                 DRM_CURRENTPID, init.channel);
578                 return DRM_ERR(EINVAL);
579         }
580
581         if (nouveau_dma_object_check_access(dev, &init))
582                 return DRM_ERR(EPERM);
583
584         if (nouveau_object_handle_find(dev, init.channel, init.handle)) {
585                 DRM_ERROR("Channel %d: handle 0x%08x already exists\n",
586                         init.channel, init.handle);
587                 return DRM_ERR(EINVAL);
588         }
589
590         obj = nouveau_object_dma_create(dev, init.channel, init.class,
591                                              init.offset, init.size,
592                                              init.access, init.target);
593         if (!obj)
594                 return DRM_ERR(ENOMEM);
595
596         obj->handle = init.handle;
597         if (nouveau_ht_object_insert(dev, init.channel, init.handle, obj)) {
598                 nouveau_object_free(dev, obj);
599                 return DRM_ERR(ENOMEM);
600         }
601
602         return 0;
603 }
604