ef4576695db18930768a5bfb603f17fbf4bd2974
[dragonfly.git] / sys / dev / drm / drm_bufs.c
1 /**
2  * \file drm_bufs.c
3  * Generic buffer template
4  *
5  * \author Rickard E. (Rik) Faith <faith@valinux.com>
6  * \author Gareth Hughes <gareth@valinux.com>
7  */
8
9 /*
10  * Created: Thu Nov 23 03:10:50 2000 by gareth@valinux.com
11  *
12  * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
13  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
14  * All Rights Reserved.
15  *
16  * Permission is hereby granted, free of charge, to any person obtaining a
17  * copy of this software and associated documentation files (the "Software"),
18  * to deal in the Software without restriction, including without limitation
19  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
20  * and/or sell copies of the Software, and to permit persons to whom the
21  * Software is furnished to do so, subject to the following conditions:
22  *
23  * The above copyright notice and this permission notice (including the next
24  * paragraph) shall be included in all copies or substantial portions of the
25  * Software.
26  *
27  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
30  * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
31  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
32  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
33  * OTHER DEALINGS IN THE SOFTWARE.
34  *
35  * $FreeBSD: src/sys/dev/drm2/drm_bufs.c,v 1.1 2012/05/22 11:07:44 kib Exp $
36  */
37
38 #include <sys/conf.h>
39 #include <bus/pci/pcireg.h>
40 #include <linux/types.h>
41 #include <linux/export.h>
42 #include <drm/drmP.h>
43
44 /* Allocation of PCI memory resources (framebuffer, registers, etc.) for
45  * drm_get_resource_*.  Note that they are not RF_ACTIVE, so there's no virtual
46  * address for accessing them.  Cleaned up at unload.
47  */
48 static int drm_alloc_resource(struct drm_device *dev, int resource)
49 {
50         struct resource *res;
51         int rid;
52
53         DRM_LOCK_ASSERT(dev);
54
55         if (resource >= DRM_MAX_PCI_RESOURCE) {
56                 DRM_ERROR("Resource %d too large\n", resource);
57                 return 1;
58         }
59
60         if (dev->pcir[resource] != NULL) {
61                 return 0;
62         }
63
64         DRM_UNLOCK(dev);
65         rid = PCIR_BAR(resource);
66         res = bus_alloc_resource_any(dev->dev, SYS_RES_MEMORY, &rid,
67             RF_SHAREABLE);
68         DRM_LOCK(dev);
69         if (res == NULL) {
70                 DRM_ERROR("Couldn't find resource 0x%x\n", resource);
71                 return 1;
72         }
73
74         if (dev->pcir[resource] == NULL) {
75                 dev->pcirid[resource] = rid;
76                 dev->pcir[resource] = res;
77         }
78
79         return 0;
80 }
81
82 unsigned long drm_get_resource_start(struct drm_device *dev,
83                                      unsigned int resource)
84 {
85         if (drm_alloc_resource(dev, resource) != 0)
86                 return 0;
87
88         return rman_get_start(dev->pcir[resource]);
89 }
90
91 unsigned long drm_get_resource_len(struct drm_device *dev,
92                                    unsigned int resource)
93 {
94         if (drm_alloc_resource(dev, resource) != 0)
95                 return 0;
96
97         return rman_get_size(dev->pcir[resource]);
98 }
99
100 int drm_addmap(struct drm_device * dev, resource_size_t offset,
101                unsigned int size, enum drm_map_type type,
102                enum drm_map_flags flags, struct drm_local_map ** map_ptr)
103 {
104         struct drm_local_map *map;
105         struct drm_map_list *entry = NULL;
106         drm_dma_handle_t *dmah;
107
108         /* Allocate a new map structure, fill it in, and do any type-specific
109          * initialization necessary.
110          */
111         map = kmalloc(sizeof(*map), M_DRM, M_ZERO | M_WAITOK | M_NULLOK);
112         if (!map) {
113                 return ENOMEM;
114         }
115
116         map->offset = offset;
117         map->size = size;
118         map->type = type;
119         map->flags = flags;
120
121         /* Only allow shared memory to be removable since we only keep enough
122          * book keeping information about shared memory to allow for removal
123          * when processes fork.
124          */
125         if ((flags & _DRM_REMOVABLE) && type != _DRM_SHM) {
126                 DRM_ERROR("Requested removable map for non-DRM_SHM\n");
127                 drm_free(map, M_DRM);
128                 return EINVAL;
129         }
130         if ((offset & PAGE_MASK) || (size & PAGE_MASK)) {
131                 DRM_ERROR("offset/size not page aligned: 0x%jx/0x%04x\n",
132                     (uintmax_t)offset, size);
133                 drm_free(map, M_DRM);
134                 return EINVAL;
135         }
136         if (offset + size < offset) {
137                 DRM_ERROR("offset and size wrap around: 0x%jx/0x%04x\n",
138                     (uintmax_t)offset, size);
139                 drm_free(map, M_DRM);
140                 return EINVAL;
141         }
142
143         DRM_DEBUG("offset = 0x%08llx, size = 0x%08lx, type = %d\n",
144                   (unsigned long long)map->offset, map->size, map->type);
145
146         /* Check if this is just another version of a kernel-allocated map, and
147          * just hand that back if so.
148          */
149         if (type == _DRM_REGISTERS || type == _DRM_FRAME_BUFFER ||
150             type == _DRM_SHM) {
151                 list_for_each_entry(entry, &dev->maplist, head) {
152                         if (entry->map->type == type && (entry->map->offset == offset ||
153                             (entry->map->type == _DRM_SHM &&
154                             entry->map->flags == _DRM_CONTAINS_LOCK))) {
155                                 entry->map->size = size;
156                                 DRM_DEBUG("Found kernel map %d\n", type);
157                                 goto done;
158                         }
159                 }
160         }
161
162         switch (map->type) {
163         case _DRM_REGISTERS:
164                 map->handle = drm_ioremap(dev, map);
165                 if (!(map->flags & _DRM_WRITE_COMBINING))
166                         break;
167                 /* FALLTHROUGH */
168         case _DRM_FRAME_BUFFER:
169                 if (drm_mtrr_add(map->offset, map->size, DRM_MTRR_WC) == 0)
170                         map->mtrr = 1;
171                 break;
172         case _DRM_SHM:
173                 map->handle = kmalloc(map->size, M_DRM, M_WAITOK | M_NULLOK);
174                 DRM_DEBUG("%lu %d %p\n",
175                     map->size, drm_order(map->size), map->handle);
176                 if (!map->handle) {
177                         drm_free(map, M_DRM);
178                         return ENOMEM;
179                 }
180                 map->offset = (unsigned long)map->handle;
181                 if (map->flags & _DRM_CONTAINS_LOCK) {
182                         /* Prevent a 2nd X Server from creating a 2nd lock */
183                         DRM_LOCK(dev);
184                         if (dev->lock.hw_lock != NULL) {
185                                 DRM_UNLOCK(dev);
186                                 drm_free(map->handle, M_DRM);
187                                 drm_free(map, M_DRM);
188                                 return EBUSY;
189                         }
190                         dev->lock.hw_lock = map->handle; /* Pointer to lock */
191                         DRM_UNLOCK(dev);
192                 }
193                 break;
194         case _DRM_AGP:
195                 /*valid = 0;*/
196                 /* In some cases (i810 driver), user space may have already
197                  * added the AGP base itself, because dev->agp->base previously
198                  * only got set during AGP enable.  So, only add the base
199                  * address if the map's offset isn't already within the
200                  * aperture.
201                  */
202                 if (map->offset < dev->agp->base ||
203                     map->offset > dev->agp->base +
204                     dev->agp->agp_info.ai_aperture_size - 1) {
205                         map->offset += dev->agp->base;
206                 }
207                 map->mtrr   = dev->agp->agp_mtrr; /* for getmap */
208                 /*for (entry = dev->agp->memory; entry; entry = entry->next) {
209                         if ((map->offset >= entry->bound) &&
210                             (map->offset + map->size <=
211                             entry->bound + entry->pages * PAGE_SIZE)) {
212                                 valid = 1;
213                                 break;
214                         }
215                 }
216                 if (!valid) {
217                         drm_free(map, M_DRM);
218                         return EACCES;
219                 }*/
220                 break;
221         case _DRM_SCATTER_GATHER:
222                 if (!dev->sg) {
223                         drm_free(map, M_DRM);
224                         return EINVAL;
225                 }
226                 map->handle = (void *)(uintptr_t)(dev->sg->vaddr + offset);
227                 map->offset = dev->sg->vaddr + offset;
228                 break;
229         case _DRM_CONSISTENT:
230                 /* dma_addr_t is 64bit on i386 with CONFIG_HIGHMEM64G,
231                  * As we're limiting the address to 2^32-1 (or less),
232                  * casting it down to 32 bits is no problem, but we
233                  * need to point to a 64bit variable first. */
234                 dmah = drm_pci_alloc(dev, map->size, map->size);
235                 if (!dmah) {
236                         kfree(map, M_DRM);
237                         return -ENOMEM;
238                 }
239                 map->handle = dmah->vaddr;
240                 map->offset = dmah->busaddr;
241                 break;
242         default:
243                 DRM_ERROR("Bad map type %d\n", map->type);
244                 drm_free(map, M_DRM);
245                 return EINVAL;
246         }
247
248         list_add(&entry->head, &dev->maplist);
249
250 done:
251         /* Jumped to, with lock held, when a kernel map is found. */
252
253         DRM_DEBUG("Added map %d 0x%lx/0x%lx\n", map->type, map->offset,
254             map->size);
255
256         *map_ptr = map;
257
258         return 0;
259 }
260
261 /**
262  * Ioctl to specify a range of memory that is available for mapping by a
263  * non-root process.
264  *
265  * \param inode device inode.
266  * \param file_priv DRM file private.
267  * \param cmd command.
268  * \param arg pointer to a drm_map structure.
269  * \return zero on success or a negative value on error.
270  *
271  */
272 int drm_addmap_ioctl(struct drm_device *dev, void *data,
273                      struct drm_file *file_priv)
274 {
275         struct drm_map *request = data;
276         drm_local_map_t *map;
277         int err;
278
279         if (!(dev->flags & (FREAD|FWRITE)))
280                 return EACCES; /* Require read/write */
281
282         if (!DRM_SUSER(DRM_CURPROC) && request->type != _DRM_AGP)
283                 return EACCES;
284
285         DRM_LOCK(dev);
286         err = drm_addmap(dev, request->offset, request->size, request->type,
287             request->flags, &map);
288         DRM_UNLOCK(dev);
289         if (err != 0)
290                 return err;
291
292         request->offset = map->offset;
293         request->size = map->size;
294         request->type = map->type;
295         request->flags = map->flags;
296         request->mtrr   = map->mtrr;
297         request->handle = (void *)map->handle;
298
299         return 0;
300 }
301
302 void drm_rmmap(struct drm_device *dev, struct drm_local_map *map)
303 {
304         struct drm_map_list *r_list = NULL, *list_t;
305         drm_dma_handle_t dmah;
306         int found = 0;
307
308         DRM_LOCK_ASSERT(dev);
309
310         if (map == NULL)
311                 return;
312
313         /* Find the list entry for the map and remove it */
314         list_for_each_entry_safe(r_list, list_t, &dev->maplist, head) {
315                 if (r_list->map == map) {
316                         list_del(&r_list->head);
317                         drm_free(r_list, M_DRM);
318                         found = 1;
319                         break;
320                 }
321         }
322
323         if (!found)
324                 return;
325
326         switch (map->type) {
327         case _DRM_REGISTERS:
328                 drm_ioremapfree(map);
329                 /* FALLTHROUGH */
330         case _DRM_FRAME_BUFFER:
331                 if (map->mtrr) {
332                         int __unused retcode;
333                         
334                         retcode = drm_mtrr_del(0, map->offset, map->size,
335                             DRM_MTRR_WC);
336                         DRM_DEBUG("mtrr_del = %d\n", retcode);
337                 }
338                 break;
339         case _DRM_SHM:
340                 drm_free(map->handle, M_DRM);
341                 break;
342         case _DRM_AGP:
343         case _DRM_SCATTER_GATHER:
344                 break;
345         case _DRM_CONSISTENT:
346                 dmah.vaddr = map->handle;
347                 dmah.busaddr = map->offset;
348                 drm_pci_free(dev, &dmah);
349                 break;
350         default:
351                 DRM_ERROR("Bad map type %d\n", map->type);
352                 break;
353         }
354
355         drm_free(map, M_DRM);
356 }
357
358 /* The rmmap ioctl appears to be unnecessary.  All mappings are torn down on
359  * the last close of the device, and this is necessary for cleanup when things
360  * exit uncleanly.  Therefore, having userland manually remove mappings seems
361  * like a pointless exercise since they're going away anyway.
362  *
363  * One use case might be after addmap is allowed for normal users for SHM and
364  * gets used by drivers that the server doesn't need to care about.  This seems
365  * unlikely.
366  *
367  * \param inode device inode.
368  * \param file_priv DRM file private.
369  * \param cmd command.
370  * \param arg pointer to a struct drm_map structure.
371  * \return zero on success or a negative value on error.
372  */
373 int drm_rmmap_ioctl(struct drm_device *dev, void *data,
374                     struct drm_file *file_priv)
375 {
376         struct drm_map *request = data;
377         struct drm_local_map *map = NULL;
378         struct drm_map_list *r_list;
379
380         DRM_LOCK(dev);
381         list_for_each_entry(r_list, &dev->maplist, head) {
382                 if (r_list->map &&
383                     r_list->user_token == (unsigned long)request->handle &&
384                     r_list->map->flags & _DRM_REMOVABLE) {
385                         map = r_list->map;
386                         break;
387                 }
388         }
389
390         /* List has wrapped around to the head pointer, or its empty we didn't
391          * find anything.
392          */
393         if (list_empty(&dev->maplist) || !map) {
394                 DRM_UNLOCK(dev);
395                 return -EINVAL;
396         }
397
398         /* Register and framebuffer maps are permanent */
399         if ((map->type == _DRM_REGISTERS) || (map->type == _DRM_FRAME_BUFFER)) {
400                 DRM_UNLOCK(dev);
401                 return 0;
402         }
403
404         drm_rmmap(dev, map);
405
406         DRM_UNLOCK(dev);
407
408         return 0;
409 }
410
411 /**
412  * Cleanup after an error on one of the addbufs() functions.
413  *
414  * \param dev DRM device.
415  * \param entry buffer entry where the error occurred.
416  *
417  * Frees any pages and buffers associated with the given entry.
418  */
419 static void drm_cleanup_buf_error(struct drm_device * dev,
420                                   struct drm_buf_entry * entry)
421 {
422         int i;
423
424         if (entry->seg_count) {
425                 for (i = 0; i < entry->seg_count; i++) {
426                         drm_pci_free(dev, entry->seglist[i]);
427                 }
428                 drm_free(entry->seglist, M_DRM);
429
430                 entry->seg_count = 0;
431         }
432
433         if (entry->buf_count) {
434                 for (i = 0; i < entry->buf_count; i++) {
435                         drm_free(entry->buflist[i].dev_private, M_DRM);
436                 }
437                 drm_free(entry->buflist, M_DRM);
438
439                 entry->buf_count = 0;
440         }
441 }
442
443 static int drm_do_addbufs_agp(struct drm_device *dev, struct drm_buf_desc *request)
444 {
445         drm_device_dma_t *dma = dev->dma;
446         drm_buf_entry_t *entry;
447         /*drm_agp_mem_t *agp_entry;
448         int valid*/
449         drm_buf_t *buf;
450         unsigned long offset;
451         unsigned long agp_offset;
452         int count;
453         int order;
454         int size;
455         int alignment;
456         int page_order;
457         int total;
458         int byte_count;
459         int i;
460         drm_buf_t **temp_buflist;
461
462         count = request->count;
463         order = drm_order(request->size);
464         size = 1 << order;
465
466         alignment  = (request->flags & _DRM_PAGE_ALIGN)
467             ? round_page(size) : size;
468         page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
469         total = PAGE_SIZE << page_order;
470
471         byte_count = 0;
472         agp_offset = dev->agp->base + request->agp_start;
473
474         DRM_DEBUG("count:      %d\n",  count);
475         DRM_DEBUG("order:      %d\n",  order);
476         DRM_DEBUG("size:       %d\n",  size);
477         DRM_DEBUG("agp_offset: 0x%lx\n", agp_offset);
478         DRM_DEBUG("alignment:  %d\n",  alignment);
479         DRM_DEBUG("page_order: %d\n",  page_order);
480         DRM_DEBUG("total:      %d\n",  total);
481
482         /* Make sure buffers are located in AGP memory that we own */
483         /* Breaks MGA due to drm_alloc_agp not setting up entries for the
484          * memory.  Safe to ignore for now because these ioctls are still
485          * root-only.
486          */
487         /*valid = 0;
488         for (agp_entry = dev->agp->memory; agp_entry;
489             agp_entry = agp_entry->next) {
490                 if ((agp_offset >= agp_entry->bound) &&
491                     (agp_offset + total * count <=
492                     agp_entry->bound + agp_entry->pages * PAGE_SIZE)) {
493                         valid = 1;
494                         break;
495                 }
496         }
497         if (!valid) {
498                 DRM_DEBUG("zone invalid\n");
499                 return EINVAL;
500         }*/
501
502         entry = &dma->bufs[order];
503
504         entry->buflist = kmalloc(count * sizeof(*entry->buflist), M_DRM,
505                                  M_WAITOK | M_NULLOK | M_ZERO);
506         if (!entry->buflist) {
507                 return ENOMEM;
508         }
509
510         entry->buf_size = size;
511         entry->page_order = page_order;
512
513         offset = 0;
514
515         while (entry->buf_count < count) {
516                 buf          = &entry->buflist[entry->buf_count];
517                 buf->idx     = dma->buf_count + entry->buf_count;
518                 buf->total   = alignment;
519                 buf->order   = order;
520                 buf->used    = 0;
521
522                 buf->offset  = (dma->byte_count + offset);
523                 buf->bus_address = agp_offset + offset;
524                 buf->address = (void *)(agp_offset + offset);
525                 buf->next    = NULL;
526                 buf->pending = 0;
527                 buf->file_priv = NULL;
528
529                 buf->dev_priv_size = dev->driver->buf_priv_size;
530                 buf->dev_private = kmalloc(buf->dev_priv_size, M_DRM,
531                                            M_WAITOK | M_NULLOK | M_ZERO);
532                 if (buf->dev_private == NULL) {
533                         /* Set count correctly so we free the proper amount. */
534                         entry->buf_count = count;
535                         drm_cleanup_buf_error(dev, entry);
536                         return ENOMEM;
537                 }
538
539                 offset += alignment;
540                 entry->buf_count++;
541                 byte_count += PAGE_SIZE << page_order;
542         }
543
544         DRM_DEBUG("byte_count: %d\n", byte_count);
545
546         temp_buflist = krealloc(dma->buflist,
547             (dma->buf_count + entry->buf_count) * sizeof(*dma->buflist),
548             M_DRM, M_WAITOK | M_NULLOK);
549         if (temp_buflist == NULL) {
550                 /* Free the entry because it isn't valid */
551                 drm_cleanup_buf_error(dev, entry);
552                 return ENOMEM;
553         }
554         dma->buflist = temp_buflist;
555
556         for (i = 0; i < entry->buf_count; i++) {
557                 dma->buflist[i + dma->buf_count] = &entry->buflist[i];
558         }
559
560         dma->buf_count += entry->buf_count;
561         dma->byte_count += byte_count;
562
563         DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count);
564         DRM_DEBUG("entry->buf_count : %d\n", entry->buf_count);
565
566         request->count = entry->buf_count;
567         request->size = size;
568
569         dma->flags = _DRM_DMA_USE_AGP;
570
571         return 0;
572 }
573
574 static int drm_do_addbufs_pci(struct drm_device *dev, struct drm_buf_desc *request)
575 {
576         drm_device_dma_t *dma = dev->dma;
577         int count;
578         int order;
579         int size;
580         int total;
581         int page_order;
582         drm_buf_entry_t *entry;
583         drm_dma_handle_t *dmah;
584         drm_buf_t *buf;
585         int alignment;
586         unsigned long offset;
587         int i;
588         int byte_count;
589         int page_count;
590         unsigned long *temp_pagelist;
591         drm_buf_t **temp_buflist;
592
593         count = request->count;
594         order = drm_order(request->size);
595         size = 1 << order;
596
597         DRM_DEBUG("count=%d, size=%d (%d), order=%d\n",
598             request->count, request->size, size, order);
599
600         alignment = (request->flags & _DRM_PAGE_ALIGN)
601             ? round_page(size) : size;
602         page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
603         total = PAGE_SIZE << page_order;
604
605         entry = &dma->bufs[order];
606
607         entry->buflist = kmalloc(count * sizeof(*entry->buflist), M_DRM,
608                                  M_WAITOK | M_NULLOK | M_ZERO);
609         entry->seglist = kmalloc(count * sizeof(*entry->seglist), M_DRM,
610                                  M_WAITOK | M_NULLOK | M_ZERO);
611
612         /* Keep the original pagelist until we know all the allocations
613          * have succeeded
614          */
615         temp_pagelist = kmalloc((dma->page_count + (count << page_order)) *
616                                 sizeof(*dma->pagelist),
617                                 M_DRM, M_WAITOK | M_NULLOK);
618
619         if (entry->buflist == NULL || entry->seglist == NULL || 
620             temp_pagelist == NULL) {
621                 drm_free(temp_pagelist, M_DRM);
622                 drm_free(entry->seglist, M_DRM);
623                 drm_free(entry->buflist, M_DRM);
624                 return ENOMEM;
625         }
626
627         memcpy(temp_pagelist, dma->pagelist, dma->page_count * 
628             sizeof(*dma->pagelist));
629
630         DRM_DEBUG("pagelist: %d entries\n",
631             dma->page_count + (count << page_order));
632
633         entry->buf_size = size;
634         entry->page_order = page_order;
635         byte_count = 0;
636         page_count = 0;
637
638         while (entry->buf_count < count) {
639                 spin_unlock(&dev->dma_lock);
640                 dmah = drm_pci_alloc(dev, PAGE_SIZE << page_order, 0x1000);
641                 spin_lock(&dev->dma_lock);
642
643                 if (!dmah) {
644                         /* Set count correctly so we free the proper amount. */
645                         entry->buf_count = count;
646                         entry->seg_count = count;
647                         drm_cleanup_buf_error(dev, entry);
648                         drm_free(temp_pagelist, M_DRM);
649                         return -ENOMEM;
650                 }
651
652                 entry->seglist[entry->seg_count++] = dmah;
653                 for (i = 0; i < (1 << page_order); i++) {
654                         DRM_DEBUG("page %d @ 0x%08lx\n",
655                                   dma->page_count + page_count,
656                                   (unsigned long)dmah->vaddr + PAGE_SIZE * i);
657                         temp_pagelist[dma->page_count + page_count++]
658                                 = (unsigned long)dmah->vaddr + PAGE_SIZE * i;
659                 }
660                 for (offset = 0;
661                     offset + size <= total && entry->buf_count < count;
662                     offset += alignment, ++entry->buf_count) {
663                         buf          = &entry->buflist[entry->buf_count];
664                         buf->idx     = dma->buf_count + entry->buf_count;
665                         buf->total   = alignment;
666                         buf->order   = order;
667                         buf->used    = 0;
668                         buf->offset  = (dma->byte_count + byte_count + offset);
669                         buf->address = ((char *)dmah->vaddr + offset);
670                         buf->bus_address = dmah->busaddr + offset;
671                         buf->next    = NULL;
672                         buf->pending = 0;
673                         buf->file_priv = NULL;
674
675                         buf->dev_priv_size = dev->driver->buf_priv_size;
676                         buf->dev_private = kmalloc(buf->dev_priv_size,
677                                                    M_DRM,
678                                                    M_WAITOK | M_NULLOK |
679                                                     M_ZERO);
680                         if (buf->dev_private == NULL) {
681                                 /* Set count correctly so we free the proper amount. */
682                                 entry->buf_count = count;
683                                 entry->seg_count = count;
684                                 drm_cleanup_buf_error(dev, entry);
685                                 drm_free(temp_pagelist, M_DRM);
686                                 return ENOMEM;
687                         }
688
689                         DRM_DEBUG("buffer %d @ %p\n",
690                             entry->buf_count, buf->address);
691                 }
692                 byte_count += PAGE_SIZE << page_order;
693         }
694
695         temp_buflist = krealloc(dma->buflist,
696             (dma->buf_count + entry->buf_count) * sizeof(*dma->buflist),
697             M_DRM, M_WAITOK | M_NULLOK);
698         if (temp_buflist == NULL) {
699                 /* Free the entry because it isn't valid */
700                 drm_cleanup_buf_error(dev, entry);
701                 drm_free(temp_pagelist, M_DRM);
702                 return ENOMEM;
703         }
704         dma->buflist = temp_buflist;
705
706         for (i = 0; i < entry->buf_count; i++) {
707                 dma->buflist[i + dma->buf_count] = &entry->buflist[i];
708         }
709
710         /* No allocations failed, so now we can replace the orginal pagelist
711          * with the new one.
712          */
713         drm_free(dma->pagelist, M_DRM);
714         dma->pagelist = temp_pagelist;
715
716         dma->buf_count += entry->buf_count;
717         dma->seg_count += entry->seg_count;
718         dma->page_count += entry->seg_count << page_order;
719         dma->byte_count += PAGE_SIZE * (entry->seg_count << page_order);
720
721         request->count = entry->buf_count;
722         request->size = size;
723
724         return 0;
725
726 }
727
728 static int drm_do_addbufs_sg(struct drm_device *dev, struct drm_buf_desc *request)
729 {
730         drm_device_dma_t *dma = dev->dma;
731         drm_buf_entry_t *entry;
732         drm_buf_t *buf;
733         unsigned long offset;
734         unsigned long agp_offset;
735         int count;
736         int order;
737         int size;
738         int alignment;
739         int page_order;
740         int total;
741         int byte_count;
742         int i;
743         drm_buf_t **temp_buflist;
744
745         count = request->count;
746         order = drm_order(request->size);
747         size = 1 << order;
748
749         alignment  = (request->flags & _DRM_PAGE_ALIGN)
750             ? round_page(size) : size;
751         page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
752         total = PAGE_SIZE << page_order;
753
754         byte_count = 0;
755         agp_offset = request->agp_start;
756
757         DRM_DEBUG("count:      %d\n",  count);
758         DRM_DEBUG("order:      %d\n",  order);
759         DRM_DEBUG("size:       %d\n",  size);
760         DRM_DEBUG("agp_offset: %ld\n", agp_offset);
761         DRM_DEBUG("alignment:  %d\n",  alignment);
762         DRM_DEBUG("page_order: %d\n",  page_order);
763         DRM_DEBUG("total:      %d\n",  total);
764
765         entry = &dma->bufs[order];
766
767         entry->buflist = kmalloc(count * sizeof(*entry->buflist), M_DRM,
768                                  M_WAITOK | M_NULLOK | M_ZERO);
769         if (entry->buflist == NULL)
770                 return ENOMEM;
771
772         entry->buf_size = size;
773         entry->page_order = page_order;
774
775         offset = 0;
776
777         while (entry->buf_count < count) {
778                 buf          = &entry->buflist[entry->buf_count];
779                 buf->idx     = dma->buf_count + entry->buf_count;
780                 buf->total   = alignment;
781                 buf->order   = order;
782                 buf->used    = 0;
783
784                 buf->offset  = (dma->byte_count + offset);
785                 buf->bus_address = agp_offset + offset;
786                 buf->address = (void *)(agp_offset + offset + dev->sg->vaddr);
787                 buf->next    = NULL;
788                 buf->pending = 0;
789                 buf->file_priv = NULL;
790
791                 buf->dev_priv_size = dev->driver->buf_priv_size;
792                 buf->dev_private = kmalloc(buf->dev_priv_size, M_DRM,
793                                            M_WAITOK | M_NULLOK | M_ZERO);
794                 if (buf->dev_private == NULL) {
795                         /* Set count correctly so we free the proper amount. */
796                         entry->buf_count = count;
797                         drm_cleanup_buf_error(dev, entry);
798                         return ENOMEM;
799                 }
800
801                 DRM_DEBUG("buffer %d @ %p\n",
802                     entry->buf_count, buf->address);
803
804                 offset += alignment;
805                 entry->buf_count++;
806                 byte_count += PAGE_SIZE << page_order;
807         }
808
809         DRM_DEBUG("byte_count: %d\n", byte_count);
810
811         temp_buflist = krealloc(dma->buflist,
812             (dma->buf_count + entry->buf_count) * sizeof(*dma->buflist),
813             M_DRM, M_WAITOK | M_NULLOK);
814         if (temp_buflist == NULL) {
815                 /* Free the entry because it isn't valid */
816                 drm_cleanup_buf_error(dev, entry);
817                 return ENOMEM;
818         }
819         dma->buflist = temp_buflist;
820
821         for (i = 0; i < entry->buf_count; i++) {
822                 dma->buflist[i + dma->buf_count] = &entry->buflist[i];
823         }
824
825         dma->buf_count += entry->buf_count;
826         dma->byte_count += byte_count;
827
828         DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count);
829         DRM_DEBUG("entry->buf_count : %d\n", entry->buf_count);
830
831         request->count = entry->buf_count;
832         request->size = size;
833
834         dma->flags = _DRM_DMA_USE_SG;
835
836         return 0;
837 }
838
839 /**
840  * Add AGP buffers for DMA transfers.
841  *
842  * \param dev struct drm_device to which the buffers are to be added.
843  * \param request pointer to a struct drm_buf_desc describing the request.
844  * \return zero on success or a negative number on failure.
845  *
846  * After some sanity checks creates a drm_buf structure for each buffer and
847  * reallocates the buffer list of the same size order to accommodate the new
848  * buffers.
849  */
850 int drm_addbufs_agp(struct drm_device * dev, struct drm_buf_desc * request)
851 {
852         int order, ret;
853
854         if (request->count < 0 || request->count > 4096)
855                 return EINVAL;
856         
857         order = drm_order(request->size);
858         if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER)
859                 return EINVAL;
860
861         spin_lock(&dev->dma_lock);
862
863         /* No more allocations after first buffer-using ioctl. */
864         if (dev->buf_use != 0) {
865                 spin_unlock(&dev->dma_lock);
866                 return EBUSY;
867         }
868         /* No more than one allocation per order */
869         if (dev->dma->bufs[order].buf_count != 0) {
870                 spin_unlock(&dev->dma_lock);
871                 return ENOMEM;
872         }
873
874         ret = drm_do_addbufs_agp(dev, request);
875
876         spin_unlock(&dev->dma_lock);
877
878         return ret;
879 }
880
881 static int drm_addbufs_sg(struct drm_device * dev, struct drm_buf_desc * request)
882 {
883         int order, ret;
884
885         if (!DRM_SUSER(DRM_CURPROC))
886                 return EACCES;
887
888         if (request->count < 0 || request->count > 4096)
889                 return EINVAL;
890
891         order = drm_order(request->size);
892         if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER)
893                 return EINVAL;
894
895         spin_lock(&dev->dma_lock);
896
897         /* No more allocations after first buffer-using ioctl. */
898         if (dev->buf_use != 0) {
899                 spin_unlock(&dev->dma_lock);
900                 return EBUSY;
901         }
902         /* No more than one allocation per order */
903         if (dev->dma->bufs[order].buf_count != 0) {
904                 spin_unlock(&dev->dma_lock);
905                 return ENOMEM;
906         }
907
908         ret = drm_do_addbufs_sg(dev, request);
909
910         spin_unlock(&dev->dma_lock);
911
912         return ret;
913 }
914
915 int drm_addbufs_pci(struct drm_device * dev, struct drm_buf_desc * request)
916 {
917         int order, ret;
918
919         if (!DRM_SUSER(DRM_CURPROC))
920                 return EACCES;
921
922         if (request->count < 0 || request->count > 4096)
923                 return EINVAL;
924
925         order = drm_order(request->size);
926         if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER)
927                 return EINVAL;
928
929         spin_lock(&dev->dma_lock);
930
931         /* No more allocations after first buffer-using ioctl. */
932         if (dev->buf_use != 0) {
933                 spin_unlock(&dev->dma_lock);
934                 return EBUSY;
935         }
936         /* No more than one allocation per order */
937         if (dev->dma->bufs[order].buf_count != 0) {
938                 spin_unlock(&dev->dma_lock);
939                 return ENOMEM;
940         }
941
942         ret = drm_do_addbufs_pci(dev, request);
943
944         spin_unlock(&dev->dma_lock);
945
946         return ret;
947 }
948
949 /**
950  * Add buffers for DMA transfers (ioctl).
951  *
952  * \param inode device inode.
953  * \param file_priv DRM file private.
954  * \param cmd command.
955  * \param arg pointer to a struct drm_buf_desc request.
956  * \return zero on success or a negative number on failure.
957  *
958  * According with the memory type specified in drm_buf_desc::flags and the
959  * build options, it dispatches the call either to addbufs_agp(),
960  * addbufs_sg() or addbufs_pci() for AGP, scatter-gather or consistent
961  * PCI memory respectively.
962  */
963 int drm_addbufs(struct drm_device *dev, void *data,
964                 struct drm_file *file_priv)
965 {
966         struct drm_buf_desc *request = data;
967         int err;
968
969         if (request->flags & _DRM_AGP_BUFFER)
970                 err = drm_addbufs_agp(dev, request);
971         else if (request->flags & _DRM_SG_BUFFER)
972                 err = drm_addbufs_sg(dev, request);
973         else
974                 err = drm_addbufs_pci(dev, request);
975
976         return err;
977 }
978
979 /**
980  * Get information about the buffer mappings.
981  *
982  * This was originally mean for debugging purposes, or by a sophisticated
983  * client library to determine how best to use the available buffers (e.g.,
984  * large buffers can be used for image transfer).
985  *
986  * \param inode device inode.
987  * \param file_priv DRM file private.
988  * \param cmd command.
989  * \param arg pointer to a drm_buf_info structure.
990  * \return zero on success or a negative number on failure.
991  *
992  * Increments drm_device::buf_use while holding the drm_device::count_lock
993  * lock, preventing of allocating more buffers after this call. Information
994  * about each requested buffer is then copied into user space.
995  */
996 int drm_infobufs(struct drm_device *dev, void *data,
997                  struct drm_file *file_priv)
998 {
999         drm_device_dma_t *dma = dev->dma;
1000         struct drm_buf_info *request = data;
1001         int i;
1002         int count;
1003         int retcode = 0;
1004
1005         spin_lock(&dev->dma_lock);
1006         ++dev->buf_use;         /* Can't allocate more after this call */
1007         spin_unlock(&dev->dma_lock);
1008
1009         for (i = 0, count = 0; i < DRM_MAX_ORDER + 1; i++) {
1010                 if (dma->bufs[i].buf_count)
1011                         ++count;
1012         }
1013
1014         DRM_DEBUG("count = %d\n", count);
1015
1016         if (request->count >= count) {
1017                 for (i = 0, count = 0; i < DRM_MAX_ORDER + 1; i++) {
1018                         if (dma->bufs[i].buf_count) {
1019                                 struct drm_buf_desc from;
1020
1021                                 from.count = dma->bufs[i].buf_count;
1022                                 from.size = dma->bufs[i].buf_size;
1023                                 from.low_mark = dma->bufs[i].freelist.low_mark;
1024                                 from.high_mark = dma->bufs[i].freelist.high_mark;
1025
1026                                 if (DRM_COPY_TO_USER(&request->list[count], &from,
1027                                     sizeof(struct drm_buf_desc)) != 0) {
1028                                         retcode = EFAULT;
1029                                         break;
1030                                 }
1031
1032                                 DRM_DEBUG("%d %d %d %d %d\n",
1033                                     i, dma->bufs[i].buf_count,
1034                                     dma->bufs[i].buf_size,
1035                                     dma->bufs[i].freelist.low_mark,
1036                                     dma->bufs[i].freelist.high_mark);
1037                                 ++count;
1038                         }
1039                 }
1040         }
1041         request->count = count;
1042
1043         return retcode;
1044 }
1045
1046 /**
1047  * Specifies a low and high water mark for buffer allocation
1048  *
1049  * \param inode device inode.
1050  * \param file_priv DRM file private.
1051  * \param cmd command.
1052  * \param arg a pointer to a drm_buf_desc structure.
1053  * \return zero on success or a negative number on failure.
1054  *
1055  * Verifies that the size order is bounded between the admissible orders and
1056  * updates the respective drm_device_dma::bufs entry low and high water mark.
1057  *
1058  * \note This ioctl is deprecated and mostly never used.
1059  */
1060 int drm_markbufs(struct drm_device *dev, void *data,
1061                  struct drm_file *file_priv)
1062 {
1063         drm_device_dma_t *dma = dev->dma;
1064         struct drm_buf_desc *request = data;
1065         int order;
1066
1067         DRM_DEBUG("%d, %d, %d\n",
1068                   request->size, request->low_mark, request->high_mark);
1069         
1070
1071         order = drm_order(request->size);       
1072         if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER ||
1073             request->low_mark < 0 || request->high_mark < 0) {
1074                 return EINVAL;
1075         }
1076
1077         spin_lock(&dev->dma_lock);
1078         if (request->low_mark > dma->bufs[order].buf_count ||
1079             request->high_mark > dma->bufs[order].buf_count) {
1080                 spin_unlock(&dev->dma_lock);
1081                 return EINVAL;
1082         }
1083
1084         dma->bufs[order].freelist.low_mark  = request->low_mark;
1085         dma->bufs[order].freelist.high_mark = request->high_mark;
1086         spin_unlock(&dev->dma_lock);
1087
1088         return 0;
1089 }
1090
1091 /**
1092  * Unreserve the buffers in list, previously reserved using drmDMA.
1093  *
1094  * \param inode device inode.
1095  * \param file_priv DRM file private.
1096  * \param cmd command.
1097  * \param arg pointer to a drm_buf_free structure.
1098  * \return zero on success or a negative number on failure.
1099  *
1100  * Calls free_buffer() for each used buffer.
1101  * This function is primarily used for debugging.
1102  */
1103 int drm_freebufs(struct drm_device *dev, void *data,
1104                  struct drm_file *file_priv)
1105 {
1106         drm_device_dma_t *dma = dev->dma;
1107         struct drm_buf_free *request = data;
1108         int i;
1109         int idx;
1110         drm_buf_t *buf;
1111         int retcode = 0;
1112
1113         DRM_DEBUG("%d\n", request->count);
1114         
1115         spin_lock(&dev->dma_lock);
1116         for (i = 0; i < request->count; i++) {
1117                 if (DRM_COPY_FROM_USER(&idx, &request->list[i], sizeof(idx))) {
1118                         retcode = EFAULT;
1119                         break;
1120                 }
1121                 if (idx < 0 || idx >= dma->buf_count) {
1122                         DRM_ERROR("Index %d (of %d max)\n",
1123                             idx, dma->buf_count - 1);
1124                         retcode = EINVAL;
1125                         break;
1126                 }
1127                 buf = dma->buflist[idx];
1128                 if (buf->file_priv != file_priv) {
1129                         DRM_ERROR("Process %d freeing buffer not owned\n",
1130                             DRM_CURRENTPID);
1131                         retcode = EINVAL;
1132                         break;
1133                 }
1134                 drm_free_buffer(dev, buf);
1135         }
1136         spin_unlock(&dev->dma_lock);
1137
1138         return retcode;
1139 }
1140
1141 /**
1142  * Maps all of the DMA buffers into client-virtual space (ioctl).
1143  *
1144  * \param inode device inode.
1145  * \param file_priv DRM file private.
1146  * \param cmd command.
1147  * \param arg pointer to a drm_buf_map structure.
1148  * \return zero on success or a negative number on failure.
1149  *
1150  * Maps the AGP, SG or PCI buffer region with vm_mmap(), and copies information
1151  * about each buffer into user space. For PCI buffers, it calls vm_mmap() with
1152  * offset equal to 0, which drm_mmap() interpretes as PCI buffers and calls
1153  * drm_mmap_dma().
1154  */
1155 int drm_mapbufs(struct drm_device *dev, void *data,
1156                 struct drm_file *file_priv)
1157 {
1158         drm_device_dma_t *dma = dev->dma;
1159         int retcode = 0;
1160         const int zero = 0;
1161         vm_offset_t address;
1162         struct vmspace *vms;
1163         vm_ooffset_t foff;
1164         vm_size_t size;
1165         vm_offset_t vaddr;
1166         struct drm_buf_map *request = data;
1167         int i;
1168
1169         vms = DRM_CURPROC->td_proc->p_vmspace;
1170
1171         spin_lock(&dev->dma_lock);
1172         dev->buf_use++;         /* Can't allocate more after this call */
1173         spin_unlock(&dev->dma_lock);
1174
1175         if (request->count < dma->buf_count)
1176                 goto done;
1177
1178         if ((drm_core_has_AGP(dev) && (dma->flags & _DRM_DMA_USE_AGP)) ||
1179             (drm_core_check_feature(dev, DRIVER_SG) &&
1180             (dma->flags & _DRM_DMA_USE_SG))) {
1181                 drm_local_map_t *map = dev->agp_buffer_map;
1182
1183                 if (map == NULL) {
1184                         retcode = EINVAL;
1185                         goto done;
1186                 }
1187                 size = round_page(map->size);
1188                 foff = (unsigned long)map->handle;
1189         } else {
1190                 size = round_page(dma->byte_count),
1191                 foff = 0;
1192         }
1193
1194         vaddr = round_page((vm_offset_t)vms->vm_daddr + MAXDSIZ);
1195         retcode = vm_mmap(&vms->vm_map, &vaddr, size, PROT_READ | PROT_WRITE,
1196             VM_PROT_ALL, MAP_SHARED | MAP_NOSYNC,
1197             SLIST_FIRST(&dev->devnode->si_hlist), foff);
1198         if (retcode)
1199                 goto done;
1200
1201         request->virtual = (void *)vaddr;
1202
1203         for (i = 0; i < dma->buf_count; i++) {
1204                 if (DRM_COPY_TO_USER(&request->list[i].idx,
1205                     &dma->buflist[i]->idx, sizeof(request->list[0].idx))) {
1206                         retcode = EFAULT;
1207                         goto done;
1208                 }
1209                 if (DRM_COPY_TO_USER(&request->list[i].total,
1210                     &dma->buflist[i]->total, sizeof(request->list[0].total))) {
1211                         retcode = EFAULT;
1212                         goto done;
1213                 }
1214                 if (DRM_COPY_TO_USER(&request->list[i].used, &zero,
1215                     sizeof(zero))) {
1216                         retcode = EFAULT;
1217                         goto done;
1218                 }
1219                 address = vaddr + dma->buflist[i]->offset; /* *** */
1220                 if (DRM_COPY_TO_USER(&request->list[i].address, &address,
1221                     sizeof(address))) {
1222                         retcode = EFAULT;
1223                         goto done;
1224                 }
1225         }
1226
1227  done:
1228         request->count = dma->buf_count;
1229
1230         DRM_DEBUG("%d buffers, retcode = %d\n", request->count, retcode);
1231
1232         return retcode;
1233 }
1234
1235 /**
1236  * Compute size order.  Returns the exponent of the smaller power of two which
1237  * is greater or equal to given number.
1238  *
1239  * \param size size.
1240  * \return order.
1241  *
1242  * \todo Can be made faster.
1243  */
1244 int drm_order(unsigned long size)
1245 {
1246         int order;
1247         unsigned long tmp;
1248
1249         for (order = 0, tmp = size >> 1; tmp; tmp >>= 1, order++) ;
1250
1251         if (size & (size - 1))
1252                 ++order;
1253
1254         return order;
1255 }
1256 EXPORT_SYMBOL(drm_order);