drm: Handle drm masters and minors like Linux
[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                         if (dev->primary->master->lock.hw_lock != NULL) {
184                                 drm_free(map->handle, M_DRM);
185                                 drm_free(map, M_DRM);
186                                 return -EBUSY;
187                         }
188                         dev->sigdata.lock = dev->primary->master->lock.hw_lock = map->handle;   /* Pointer to lock */
189                 }
190                 break;
191         case _DRM_AGP:
192                 /*valid = 0;*/
193                 /* In some cases (i810 driver), user space may have already
194                  * added the AGP base itself, because dev->agp->base previously
195                  * only got set during AGP enable.  So, only add the base
196                  * address if the map's offset isn't already within the
197                  * aperture.
198                  */
199                 if (map->offset < dev->agp->base ||
200                     map->offset > dev->agp->base +
201                     dev->agp->agp_info.ai_aperture_size - 1) {
202                         map->offset += dev->agp->base;
203                 }
204                 map->mtrr   = dev->agp->agp_mtrr; /* for getmap */
205                 /*for (entry = dev->agp->memory; entry; entry = entry->next) {
206                         if ((map->offset >= entry->bound) &&
207                             (map->offset + map->size <=
208                             entry->bound + entry->pages * PAGE_SIZE)) {
209                                 valid = 1;
210                                 break;
211                         }
212                 }
213                 if (!valid) {
214                         drm_free(map, M_DRM);
215                         return EACCES;
216                 }*/
217                 break;
218         case _DRM_SCATTER_GATHER:
219                 if (!dev->sg) {
220                         drm_free(map, M_DRM);
221                         return EINVAL;
222                 }
223                 map->handle = (void *)(uintptr_t)(dev->sg->vaddr + offset);
224                 map->offset = dev->sg->vaddr + offset;
225                 break;
226         case _DRM_CONSISTENT:
227                 /* dma_addr_t is 64bit on i386 with CONFIG_HIGHMEM64G,
228                  * As we're limiting the address to 2^32-1 (or less),
229                  * casting it down to 32 bits is no problem, but we
230                  * need to point to a 64bit variable first. */
231                 dmah = drm_pci_alloc(dev, map->size, map->size);
232                 if (!dmah) {
233                         kfree(map, M_DRM);
234                         return -ENOMEM;
235                 }
236                 map->handle = dmah->vaddr;
237                 map->offset = dmah->busaddr;
238                 break;
239         default:
240                 DRM_ERROR("Bad map type %d\n", map->type);
241                 drm_free(map, M_DRM);
242                 return EINVAL;
243         }
244
245         list_add(&entry->head, &dev->maplist);
246
247 done:
248         /* Jumped to, with lock held, when a kernel map is found. */
249
250         DRM_DEBUG("Added map %d 0x%lx/0x%lx\n", map->type, map->offset,
251             map->size);
252
253         *map_ptr = map;
254
255         return 0;
256 }
257
258 /**
259  * Ioctl to specify a range of memory that is available for mapping by a
260  * non-root process.
261  *
262  * \param inode device inode.
263  * \param file_priv DRM file private.
264  * \param cmd command.
265  * \param arg pointer to a drm_map structure.
266  * \return zero on success or a negative value on error.
267  *
268  */
269 int drm_addmap_ioctl(struct drm_device *dev, void *data,
270                      struct drm_file *file_priv)
271 {
272         struct drm_map *request = data;
273         drm_local_map_t *map;
274         int err;
275
276         if (!(dev->flags & (FREAD|FWRITE)))
277                 return EACCES; /* Require read/write */
278
279         if (!DRM_SUSER(DRM_CURPROC) && request->type != _DRM_AGP)
280                 return EACCES;
281
282         err = drm_addmap(dev, request->offset, request->size, request->type,
283             request->flags, &map);
284
285         if (err)
286                 return err;
287
288         request->offset = map->offset;
289         request->size = map->size;
290         request->type = map->type;
291         request->flags = map->flags;
292         request->mtrr   = map->mtrr;
293         request->handle = (void *)map->handle;
294
295         return 0;
296 }
297
298 /**
299  * Remove a map private from list and deallocate resources if the mapping
300  * isn't in use.
301  *
302  * Searches the map on drm_device::maplist, removes it from the list, see if
303  * its being used, and free any associate resource (such as MTRR's) if it's not
304  * being on use.
305  *
306  * \sa drm_addmap
307  */
308 int drm_rmmap_locked(struct drm_device *dev, struct drm_local_map *map)
309 {
310         struct drm_map_list *r_list = NULL, *list_t;
311         drm_dma_handle_t dmah;
312         int found = 0;
313         struct drm_master *master;
314
315         /* Find the list entry for the map and remove it */
316         list_for_each_entry_safe(r_list, list_t, &dev->maplist, head) {
317                 if (r_list->map == map) {
318                         master = r_list->master;
319                         list_del(&r_list->head);
320                         drm_ht_remove_key(&dev->map_hash,
321                                           r_list->user_token >> PAGE_SHIFT);
322                         kfree(r_list, M_DRM);
323                         found = 1;
324                         break;
325                 }
326         }
327
328         if (!found)
329                 return -EINVAL;
330
331         switch (map->type) {
332         case _DRM_REGISTERS:
333                 drm_ioremapfree(map);
334                 /* FALLTHROUGH */
335         case _DRM_FRAME_BUFFER:
336                 if (map->mtrr) {
337                         int retcode;
338                         retcode = drm_mtrr_del(0, map->offset, map->size, DRM_MTRR_WC);
339                         DRM_DEBUG("mtrr_del=%d\n", retcode);
340                 }
341                 break;
342         case _DRM_SHM:
343                 drm_free(map->handle, M_DRM);
344                 if (master) {
345                         if (dev->sigdata.lock == master->lock.hw_lock)
346                                 dev->sigdata.lock = NULL;
347                         master->lock.hw_lock = NULL;   /* SHM removed */
348                         master->lock.file_priv = NULL;
349                         wake_up_interruptible_all(&master->lock.lock_queue);
350                 }
351                 break;
352         case _DRM_AGP:
353         case _DRM_SCATTER_GATHER:
354                 break;
355         case _DRM_CONSISTENT:
356                 dmah.vaddr = map->handle;
357                 dmah.busaddr = map->offset;
358                 drm_pci_free(dev, &dmah);
359                 break;
360         case _DRM_GEM:
361                 DRM_ERROR("tried to rmmap GEM object\n");
362                 break;
363         }
364         drm_free(map, M_DRM);
365
366         return 0;
367 }
368 EXPORT_SYMBOL(drm_rmmap_locked);
369
370 int drm_rmmap(struct drm_device *dev, struct drm_local_map *map)
371 {
372         int ret;
373
374         mutex_lock(&dev->struct_mutex);
375         ret = drm_rmmap_locked(dev, map);
376         mutex_unlock(&dev->struct_mutex);
377
378         return ret;
379 }
380 EXPORT_SYMBOL(drm_rmmap);
381
382 /* The rmmap ioctl appears to be unnecessary.  All mappings are torn down on
383  * the last close of the device, and this is necessary for cleanup when things
384  * exit uncleanly.  Therefore, having userland manually remove mappings seems
385  * like a pointless exercise since they're going away anyway.
386  *
387  * One use case might be after addmap is allowed for normal users for SHM and
388  * gets used by drivers that the server doesn't need to care about.  This seems
389  * unlikely.
390  *
391  * \param inode device inode.
392  * \param file_priv DRM file private.
393  * \param cmd command.
394  * \param arg pointer to a struct drm_map structure.
395  * \return zero on success or a negative value on error.
396  */
397 int drm_rmmap_ioctl(struct drm_device *dev, void *data,
398                     struct drm_file *file_priv)
399 {
400         struct drm_map *request = data;
401         struct drm_local_map *map = NULL;
402         struct drm_map_list *r_list;
403
404         DRM_LOCK(dev);
405         list_for_each_entry(r_list, &dev->maplist, head) {
406                 if (r_list->map &&
407                     r_list->user_token == (unsigned long)request->handle &&
408                     r_list->map->flags & _DRM_REMOVABLE) {
409                         map = r_list->map;
410                         break;
411                 }
412         }
413
414         /* List has wrapped around to the head pointer, or its empty we didn't
415          * find anything.
416          */
417         if (list_empty(&dev->maplist) || !map) {
418                 DRM_UNLOCK(dev);
419                 return -EINVAL;
420         }
421
422         /* Register and framebuffer maps are permanent */
423         if ((map->type == _DRM_REGISTERS) || (map->type == _DRM_FRAME_BUFFER)) {
424                 DRM_UNLOCK(dev);
425                 return 0;
426         }
427
428         drm_rmmap(dev, map);
429
430         DRM_UNLOCK(dev);
431
432         return 0;
433 }
434
435 /**
436  * Cleanup after an error on one of the addbufs() functions.
437  *
438  * \param dev DRM device.
439  * \param entry buffer entry where the error occurred.
440  *
441  * Frees any pages and buffers associated with the given entry.
442  */
443 static void drm_cleanup_buf_error(struct drm_device * dev,
444                                   struct drm_buf_entry * entry)
445 {
446         int i;
447
448         if (entry->seg_count) {
449                 for (i = 0; i < entry->seg_count; i++) {
450                         drm_pci_free(dev, entry->seglist[i]);
451                 }
452                 drm_free(entry->seglist, M_DRM);
453
454                 entry->seg_count = 0;
455         }
456
457         if (entry->buf_count) {
458                 for (i = 0; i < entry->buf_count; i++) {
459                         drm_free(entry->buflist[i].dev_private, M_DRM);
460                 }
461                 drm_free(entry->buflist, M_DRM);
462
463                 entry->buf_count = 0;
464         }
465 }
466
467 static int drm_do_addbufs_agp(struct drm_device *dev, struct drm_buf_desc *request)
468 {
469         drm_device_dma_t *dma = dev->dma;
470         drm_buf_entry_t *entry;
471         /*drm_agp_mem_t *agp_entry;
472         int valid*/
473         drm_buf_t *buf;
474         unsigned long offset;
475         unsigned long agp_offset;
476         int count;
477         int order;
478         int size;
479         int alignment;
480         int page_order;
481         int total;
482         int byte_count;
483         int i;
484         drm_buf_t **temp_buflist;
485
486         count = request->count;
487         order = drm_order(request->size);
488         size = 1 << order;
489
490         alignment  = (request->flags & _DRM_PAGE_ALIGN)
491             ? round_page(size) : size;
492         page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
493         total = PAGE_SIZE << page_order;
494
495         byte_count = 0;
496         agp_offset = dev->agp->base + request->agp_start;
497
498         DRM_DEBUG("count:      %d\n",  count);
499         DRM_DEBUG("order:      %d\n",  order);
500         DRM_DEBUG("size:       %d\n",  size);
501         DRM_DEBUG("agp_offset: 0x%lx\n", agp_offset);
502         DRM_DEBUG("alignment:  %d\n",  alignment);
503         DRM_DEBUG("page_order: %d\n",  page_order);
504         DRM_DEBUG("total:      %d\n",  total);
505
506         /* Make sure buffers are located in AGP memory that we own */
507         /* Breaks MGA due to drm_alloc_agp not setting up entries for the
508          * memory.  Safe to ignore for now because these ioctls are still
509          * root-only.
510          */
511         /*valid = 0;
512         for (agp_entry = dev->agp->memory; agp_entry;
513             agp_entry = agp_entry->next) {
514                 if ((agp_offset >= agp_entry->bound) &&
515                     (agp_offset + total * count <=
516                     agp_entry->bound + agp_entry->pages * PAGE_SIZE)) {
517                         valid = 1;
518                         break;
519                 }
520         }
521         if (!valid) {
522                 DRM_DEBUG("zone invalid\n");
523                 return EINVAL;
524         }*/
525
526         entry = &dma->bufs[order];
527
528         entry->buflist = kmalloc(count * sizeof(*entry->buflist), M_DRM,
529                                  M_WAITOK | M_NULLOK | M_ZERO);
530         if (!entry->buflist) {
531                 return ENOMEM;
532         }
533
534         entry->buf_size = size;
535         entry->page_order = page_order;
536
537         offset = 0;
538
539         while (entry->buf_count < count) {
540                 buf          = &entry->buflist[entry->buf_count];
541                 buf->idx     = dma->buf_count + entry->buf_count;
542                 buf->total   = alignment;
543                 buf->order   = order;
544                 buf->used    = 0;
545
546                 buf->offset  = (dma->byte_count + offset);
547                 buf->bus_address = agp_offset + offset;
548                 buf->address = (void *)(agp_offset + offset);
549                 buf->next    = NULL;
550                 buf->pending = 0;
551                 buf->file_priv = NULL;
552
553                 buf->dev_priv_size = dev->driver->buf_priv_size;
554                 buf->dev_private = kmalloc(buf->dev_priv_size, M_DRM,
555                                            M_WAITOK | M_NULLOK | M_ZERO);
556                 if (buf->dev_private == NULL) {
557                         /* Set count correctly so we free the proper amount. */
558                         entry->buf_count = count;
559                         drm_cleanup_buf_error(dev, entry);
560                         return ENOMEM;
561                 }
562
563                 offset += alignment;
564                 entry->buf_count++;
565                 byte_count += PAGE_SIZE << page_order;
566         }
567
568         DRM_DEBUG("byte_count: %d\n", byte_count);
569
570         temp_buflist = krealloc(dma->buflist,
571             (dma->buf_count + entry->buf_count) * sizeof(*dma->buflist),
572             M_DRM, M_WAITOK | M_NULLOK);
573         if (temp_buflist == NULL) {
574                 /* Free the entry because it isn't valid */
575                 drm_cleanup_buf_error(dev, entry);
576                 return ENOMEM;
577         }
578         dma->buflist = temp_buflist;
579
580         for (i = 0; i < entry->buf_count; i++) {
581                 dma->buflist[i + dma->buf_count] = &entry->buflist[i];
582         }
583
584         dma->buf_count += entry->buf_count;
585         dma->byte_count += byte_count;
586
587         DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count);
588         DRM_DEBUG("entry->buf_count : %d\n", entry->buf_count);
589
590         request->count = entry->buf_count;
591         request->size = size;
592
593         dma->flags = _DRM_DMA_USE_AGP;
594
595         return 0;
596 }
597
598 static int drm_do_addbufs_pci(struct drm_device *dev, struct drm_buf_desc *request)
599 {
600         drm_device_dma_t *dma = dev->dma;
601         int count;
602         int order;
603         int size;
604         int total;
605         int page_order;
606         drm_buf_entry_t *entry;
607         drm_dma_handle_t *dmah;
608         drm_buf_t *buf;
609         int alignment;
610         unsigned long offset;
611         int i;
612         int byte_count;
613         int page_count;
614         unsigned long *temp_pagelist;
615         drm_buf_t **temp_buflist;
616
617         count = request->count;
618         order = drm_order(request->size);
619         size = 1 << order;
620
621         DRM_DEBUG("count=%d, size=%d (%d), order=%d\n",
622             request->count, request->size, size, order);
623
624         alignment = (request->flags & _DRM_PAGE_ALIGN)
625             ? round_page(size) : size;
626         page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
627         total = PAGE_SIZE << page_order;
628
629         entry = &dma->bufs[order];
630
631         entry->buflist = kmalloc(count * sizeof(*entry->buflist), M_DRM,
632                                  M_WAITOK | M_NULLOK | M_ZERO);
633         entry->seglist = kmalloc(count * sizeof(*entry->seglist), M_DRM,
634                                  M_WAITOK | M_NULLOK | M_ZERO);
635
636         /* Keep the original pagelist until we know all the allocations
637          * have succeeded
638          */
639         temp_pagelist = kmalloc((dma->page_count + (count << page_order)) *
640                                 sizeof(*dma->pagelist),
641                                 M_DRM, M_WAITOK | M_NULLOK);
642
643         if (entry->buflist == NULL || entry->seglist == NULL || 
644             temp_pagelist == NULL) {
645                 drm_free(temp_pagelist, M_DRM);
646                 drm_free(entry->seglist, M_DRM);
647                 drm_free(entry->buflist, M_DRM);
648                 return ENOMEM;
649         }
650
651         memcpy(temp_pagelist, dma->pagelist, dma->page_count * 
652             sizeof(*dma->pagelist));
653
654         DRM_DEBUG("pagelist: %d entries\n",
655             dma->page_count + (count << page_order));
656
657         entry->buf_size = size;
658         entry->page_order = page_order;
659         byte_count = 0;
660         page_count = 0;
661
662         while (entry->buf_count < count) {
663                 spin_unlock(&dev->dma_lock);
664                 dmah = drm_pci_alloc(dev, PAGE_SIZE << page_order, 0x1000);
665                 spin_lock(&dev->dma_lock);
666
667                 if (!dmah) {
668                         /* Set count correctly so we free the proper amount. */
669                         entry->buf_count = count;
670                         entry->seg_count = count;
671                         drm_cleanup_buf_error(dev, entry);
672                         drm_free(temp_pagelist, M_DRM);
673                         return -ENOMEM;
674                 }
675
676                 entry->seglist[entry->seg_count++] = dmah;
677                 for (i = 0; i < (1 << page_order); i++) {
678                         DRM_DEBUG("page %d @ 0x%08lx\n",
679                                   dma->page_count + page_count,
680                                   (unsigned long)dmah->vaddr + PAGE_SIZE * i);
681                         temp_pagelist[dma->page_count + page_count++]
682                                 = (unsigned long)dmah->vaddr + PAGE_SIZE * i;
683                 }
684                 for (offset = 0;
685                     offset + size <= total && entry->buf_count < count;
686                     offset += alignment, ++entry->buf_count) {
687                         buf          = &entry->buflist[entry->buf_count];
688                         buf->idx     = dma->buf_count + entry->buf_count;
689                         buf->total   = alignment;
690                         buf->order   = order;
691                         buf->used    = 0;
692                         buf->offset  = (dma->byte_count + byte_count + offset);
693                         buf->address = ((char *)dmah->vaddr + offset);
694                         buf->bus_address = dmah->busaddr + offset;
695                         buf->next    = NULL;
696                         buf->pending = 0;
697                         buf->file_priv = NULL;
698
699                         buf->dev_priv_size = dev->driver->buf_priv_size;
700                         buf->dev_private = kmalloc(buf->dev_priv_size,
701                                                    M_DRM,
702                                                    M_WAITOK | M_NULLOK |
703                                                     M_ZERO);
704                         if (buf->dev_private == NULL) {
705                                 /* Set count correctly so we free the proper amount. */
706                                 entry->buf_count = count;
707                                 entry->seg_count = count;
708                                 drm_cleanup_buf_error(dev, entry);
709                                 drm_free(temp_pagelist, M_DRM);
710                                 return ENOMEM;
711                         }
712
713                         DRM_DEBUG("buffer %d @ %p\n",
714                             entry->buf_count, buf->address);
715                 }
716                 byte_count += PAGE_SIZE << page_order;
717         }
718
719         temp_buflist = krealloc(dma->buflist,
720             (dma->buf_count + entry->buf_count) * sizeof(*dma->buflist),
721             M_DRM, M_WAITOK | M_NULLOK);
722         if (temp_buflist == NULL) {
723                 /* Free the entry because it isn't valid */
724                 drm_cleanup_buf_error(dev, entry);
725                 drm_free(temp_pagelist, M_DRM);
726                 return ENOMEM;
727         }
728         dma->buflist = temp_buflist;
729
730         for (i = 0; i < entry->buf_count; i++) {
731                 dma->buflist[i + dma->buf_count] = &entry->buflist[i];
732         }
733
734         /* No allocations failed, so now we can replace the orginal pagelist
735          * with the new one.
736          */
737         drm_free(dma->pagelist, M_DRM);
738         dma->pagelist = temp_pagelist;
739
740         dma->buf_count += entry->buf_count;
741         dma->seg_count += entry->seg_count;
742         dma->page_count += entry->seg_count << page_order;
743         dma->byte_count += PAGE_SIZE * (entry->seg_count << page_order);
744
745         request->count = entry->buf_count;
746         request->size = size;
747
748         return 0;
749
750 }
751
752 static int drm_do_addbufs_sg(struct drm_device *dev, struct drm_buf_desc *request)
753 {
754         drm_device_dma_t *dma = dev->dma;
755         drm_buf_entry_t *entry;
756         drm_buf_t *buf;
757         unsigned long offset;
758         unsigned long agp_offset;
759         int count;
760         int order;
761         int size;
762         int alignment;
763         int page_order;
764         int total;
765         int byte_count;
766         int i;
767         drm_buf_t **temp_buflist;
768
769         count = request->count;
770         order = drm_order(request->size);
771         size = 1 << order;
772
773         alignment  = (request->flags & _DRM_PAGE_ALIGN)
774             ? round_page(size) : size;
775         page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
776         total = PAGE_SIZE << page_order;
777
778         byte_count = 0;
779         agp_offset = request->agp_start;
780
781         DRM_DEBUG("count:      %d\n",  count);
782         DRM_DEBUG("order:      %d\n",  order);
783         DRM_DEBUG("size:       %d\n",  size);
784         DRM_DEBUG("agp_offset: %ld\n", agp_offset);
785         DRM_DEBUG("alignment:  %d\n",  alignment);
786         DRM_DEBUG("page_order: %d\n",  page_order);
787         DRM_DEBUG("total:      %d\n",  total);
788
789         entry = &dma->bufs[order];
790
791         entry->buflist = kmalloc(count * sizeof(*entry->buflist), M_DRM,
792                                  M_WAITOK | M_NULLOK | M_ZERO);
793         if (entry->buflist == NULL)
794                 return ENOMEM;
795
796         entry->buf_size = size;
797         entry->page_order = page_order;
798
799         offset = 0;
800
801         while (entry->buf_count < count) {
802                 buf          = &entry->buflist[entry->buf_count];
803                 buf->idx     = dma->buf_count + entry->buf_count;
804                 buf->total   = alignment;
805                 buf->order   = order;
806                 buf->used    = 0;
807
808                 buf->offset  = (dma->byte_count + offset);
809                 buf->bus_address = agp_offset + offset;
810                 buf->address = (void *)(agp_offset + offset + dev->sg->vaddr);
811                 buf->next    = NULL;
812                 buf->pending = 0;
813                 buf->file_priv = NULL;
814
815                 buf->dev_priv_size = dev->driver->buf_priv_size;
816                 buf->dev_private = kmalloc(buf->dev_priv_size, M_DRM,
817                                            M_WAITOK | M_NULLOK | M_ZERO);
818                 if (buf->dev_private == NULL) {
819                         /* Set count correctly so we free the proper amount. */
820                         entry->buf_count = count;
821                         drm_cleanup_buf_error(dev, entry);
822                         return ENOMEM;
823                 }
824
825                 DRM_DEBUG("buffer %d @ %p\n",
826                     entry->buf_count, buf->address);
827
828                 offset += alignment;
829                 entry->buf_count++;
830                 byte_count += PAGE_SIZE << page_order;
831         }
832
833         DRM_DEBUG("byte_count: %d\n", byte_count);
834
835         temp_buflist = krealloc(dma->buflist,
836             (dma->buf_count + entry->buf_count) * sizeof(*dma->buflist),
837             M_DRM, M_WAITOK | M_NULLOK);
838         if (temp_buflist == NULL) {
839                 /* Free the entry because it isn't valid */
840                 drm_cleanup_buf_error(dev, entry);
841                 return ENOMEM;
842         }
843         dma->buflist = temp_buflist;
844
845         for (i = 0; i < entry->buf_count; i++) {
846                 dma->buflist[i + dma->buf_count] = &entry->buflist[i];
847         }
848
849         dma->buf_count += entry->buf_count;
850         dma->byte_count += byte_count;
851
852         DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count);
853         DRM_DEBUG("entry->buf_count : %d\n", entry->buf_count);
854
855         request->count = entry->buf_count;
856         request->size = size;
857
858         dma->flags = _DRM_DMA_USE_SG;
859
860         return 0;
861 }
862
863 /**
864  * Add AGP buffers for DMA transfers.
865  *
866  * \param dev struct drm_device to which the buffers are to be added.
867  * \param request pointer to a struct drm_buf_desc describing the request.
868  * \return zero on success or a negative number on failure.
869  *
870  * After some sanity checks creates a drm_buf structure for each buffer and
871  * reallocates the buffer list of the same size order to accommodate the new
872  * buffers.
873  */
874 int drm_addbufs_agp(struct drm_device * dev, struct drm_buf_desc * request)
875 {
876         int order, ret;
877
878         if (request->count < 0 || request->count > 4096)
879                 return EINVAL;
880         
881         order = drm_order(request->size);
882         if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER)
883                 return EINVAL;
884
885         spin_lock(&dev->dma_lock);
886
887         /* No more allocations after first buffer-using ioctl. */
888         if (dev->buf_use != 0) {
889                 spin_unlock(&dev->dma_lock);
890                 return EBUSY;
891         }
892         /* No more than one allocation per order */
893         if (dev->dma->bufs[order].buf_count != 0) {
894                 spin_unlock(&dev->dma_lock);
895                 return ENOMEM;
896         }
897
898         ret = drm_do_addbufs_agp(dev, request);
899
900         spin_unlock(&dev->dma_lock);
901
902         return ret;
903 }
904
905 static int drm_addbufs_sg(struct drm_device * dev, struct drm_buf_desc * request)
906 {
907         int order, ret;
908
909         if (!DRM_SUSER(DRM_CURPROC))
910                 return EACCES;
911
912         if (request->count < 0 || request->count > 4096)
913                 return EINVAL;
914
915         order = drm_order(request->size);
916         if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER)
917                 return EINVAL;
918
919         spin_lock(&dev->dma_lock);
920
921         /* No more allocations after first buffer-using ioctl. */
922         if (dev->buf_use != 0) {
923                 spin_unlock(&dev->dma_lock);
924                 return EBUSY;
925         }
926         /* No more than one allocation per order */
927         if (dev->dma->bufs[order].buf_count != 0) {
928                 spin_unlock(&dev->dma_lock);
929                 return ENOMEM;
930         }
931
932         ret = drm_do_addbufs_sg(dev, request);
933
934         spin_unlock(&dev->dma_lock);
935
936         return ret;
937 }
938
939 int drm_addbufs_pci(struct drm_device * dev, struct drm_buf_desc * request)
940 {
941         int order, ret;
942
943         if (!DRM_SUSER(DRM_CURPROC))
944                 return EACCES;
945
946         if (request->count < 0 || request->count > 4096)
947                 return EINVAL;
948
949         order = drm_order(request->size);
950         if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER)
951                 return EINVAL;
952
953         spin_lock(&dev->dma_lock);
954
955         /* No more allocations after first buffer-using ioctl. */
956         if (dev->buf_use != 0) {
957                 spin_unlock(&dev->dma_lock);
958                 return EBUSY;
959         }
960         /* No more than one allocation per order */
961         if (dev->dma->bufs[order].buf_count != 0) {
962                 spin_unlock(&dev->dma_lock);
963                 return ENOMEM;
964         }
965
966         ret = drm_do_addbufs_pci(dev, request);
967
968         spin_unlock(&dev->dma_lock);
969
970         return ret;
971 }
972
973 /**
974  * Add buffers for DMA transfers (ioctl).
975  *
976  * \param inode device inode.
977  * \param file_priv DRM file private.
978  * \param cmd command.
979  * \param arg pointer to a struct drm_buf_desc request.
980  * \return zero on success or a negative number on failure.
981  *
982  * According with the memory type specified in drm_buf_desc::flags and the
983  * build options, it dispatches the call either to addbufs_agp(),
984  * addbufs_sg() or addbufs_pci() for AGP, scatter-gather or consistent
985  * PCI memory respectively.
986  */
987 int drm_addbufs(struct drm_device *dev, void *data,
988                 struct drm_file *file_priv)
989 {
990         struct drm_buf_desc *request = data;
991         int err;
992
993         if (request->flags & _DRM_AGP_BUFFER)
994                 err = drm_addbufs_agp(dev, request);
995         else if (request->flags & _DRM_SG_BUFFER)
996                 err = drm_addbufs_sg(dev, request);
997         else
998                 err = drm_addbufs_pci(dev, request);
999
1000         return err;
1001 }
1002
1003 /**
1004  * Get information about the buffer mappings.
1005  *
1006  * This was originally mean for debugging purposes, or by a sophisticated
1007  * client library to determine how best to use the available buffers (e.g.,
1008  * large buffers can be used for image transfer).
1009  *
1010  * \param inode device inode.
1011  * \param file_priv DRM file private.
1012  * \param cmd command.
1013  * \param arg pointer to a drm_buf_info structure.
1014  * \return zero on success or a negative number on failure.
1015  *
1016  * Increments drm_device::buf_use while holding the drm_device::count_lock
1017  * lock, preventing of allocating more buffers after this call. Information
1018  * about each requested buffer is then copied into user space.
1019  */
1020 int drm_infobufs(struct drm_device *dev, void *data,
1021                  struct drm_file *file_priv)
1022 {
1023         drm_device_dma_t *dma = dev->dma;
1024         struct drm_buf_info *request = data;
1025         int i;
1026         int count;
1027         int retcode = 0;
1028
1029         spin_lock(&dev->dma_lock);
1030         ++dev->buf_use;         /* Can't allocate more after this call */
1031         spin_unlock(&dev->dma_lock);
1032
1033         for (i = 0, count = 0; i < DRM_MAX_ORDER + 1; i++) {
1034                 if (dma->bufs[i].buf_count)
1035                         ++count;
1036         }
1037
1038         DRM_DEBUG("count = %d\n", count);
1039
1040         if (request->count >= count) {
1041                 for (i = 0, count = 0; i < DRM_MAX_ORDER + 1; i++) {
1042                         if (dma->bufs[i].buf_count) {
1043                                 struct drm_buf_desc from;
1044
1045                                 from.count = dma->bufs[i].buf_count;
1046                                 from.size = dma->bufs[i].buf_size;
1047                                 from.low_mark = dma->bufs[i].freelist.low_mark;
1048                                 from.high_mark = dma->bufs[i].freelist.high_mark;
1049
1050                                 if (DRM_COPY_TO_USER(&request->list[count], &from,
1051                                     sizeof(struct drm_buf_desc)) != 0) {
1052                                         retcode = EFAULT;
1053                                         break;
1054                                 }
1055
1056                                 DRM_DEBUG("%d %d %d %d %d\n",
1057                                     i, dma->bufs[i].buf_count,
1058                                     dma->bufs[i].buf_size,
1059                                     dma->bufs[i].freelist.low_mark,
1060                                     dma->bufs[i].freelist.high_mark);
1061                                 ++count;
1062                         }
1063                 }
1064         }
1065         request->count = count;
1066
1067         return retcode;
1068 }
1069
1070 /**
1071  * Specifies a low and high water mark for buffer allocation
1072  *
1073  * \param inode device inode.
1074  * \param file_priv DRM file private.
1075  * \param cmd command.
1076  * \param arg a pointer to a drm_buf_desc structure.
1077  * \return zero on success or a negative number on failure.
1078  *
1079  * Verifies that the size order is bounded between the admissible orders and
1080  * updates the respective drm_device_dma::bufs entry low and high water mark.
1081  *
1082  * \note This ioctl is deprecated and mostly never used.
1083  */
1084 int drm_markbufs(struct drm_device *dev, void *data,
1085                  struct drm_file *file_priv)
1086 {
1087         drm_device_dma_t *dma = dev->dma;
1088         struct drm_buf_desc *request = data;
1089         int order;
1090
1091         DRM_DEBUG("%d, %d, %d\n",
1092                   request->size, request->low_mark, request->high_mark);
1093         
1094
1095         order = drm_order(request->size);       
1096         if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER ||
1097             request->low_mark < 0 || request->high_mark < 0) {
1098                 return EINVAL;
1099         }
1100
1101         spin_lock(&dev->dma_lock);
1102         if (request->low_mark > dma->bufs[order].buf_count ||
1103             request->high_mark > dma->bufs[order].buf_count) {
1104                 spin_unlock(&dev->dma_lock);
1105                 return EINVAL;
1106         }
1107
1108         dma->bufs[order].freelist.low_mark  = request->low_mark;
1109         dma->bufs[order].freelist.high_mark = request->high_mark;
1110         spin_unlock(&dev->dma_lock);
1111
1112         return 0;
1113 }
1114
1115 /**
1116  * Unreserve the buffers in list, previously reserved using drmDMA.
1117  *
1118  * \param inode device inode.
1119  * \param file_priv DRM file private.
1120  * \param cmd command.
1121  * \param arg pointer to a drm_buf_free structure.
1122  * \return zero on success or a negative number on failure.
1123  *
1124  * Calls free_buffer() for each used buffer.
1125  * This function is primarily used for debugging.
1126  */
1127 int drm_freebufs(struct drm_device *dev, void *data,
1128                  struct drm_file *file_priv)
1129 {
1130         drm_device_dma_t *dma = dev->dma;
1131         struct drm_buf_free *request = data;
1132         int i;
1133         int idx;
1134         drm_buf_t *buf;
1135         int retcode = 0;
1136
1137         DRM_DEBUG("%d\n", request->count);
1138         
1139         spin_lock(&dev->dma_lock);
1140         for (i = 0; i < request->count; i++) {
1141                 if (DRM_COPY_FROM_USER(&idx, &request->list[i], sizeof(idx))) {
1142                         retcode = EFAULT;
1143                         break;
1144                 }
1145                 if (idx < 0 || idx >= dma->buf_count) {
1146                         DRM_ERROR("Index %d (of %d max)\n",
1147                             idx, dma->buf_count - 1);
1148                         retcode = EINVAL;
1149                         break;
1150                 }
1151                 buf = dma->buflist[idx];
1152                 if (buf->file_priv != file_priv) {
1153                         DRM_ERROR("Process %d freeing buffer not owned\n",
1154                             DRM_CURRENTPID);
1155                         retcode = EINVAL;
1156                         break;
1157                 }
1158                 drm_free_buffer(dev, buf);
1159         }
1160         spin_unlock(&dev->dma_lock);
1161
1162         return retcode;
1163 }
1164
1165 /**
1166  * Maps all of the DMA buffers into client-virtual space (ioctl).
1167  *
1168  * \param inode device inode.
1169  * \param file_priv DRM file private.
1170  * \param cmd command.
1171  * \param arg pointer to a drm_buf_map structure.
1172  * \return zero on success or a negative number on failure.
1173  *
1174  * Maps the AGP, SG or PCI buffer region with vm_mmap(), and copies information
1175  * about each buffer into user space. For PCI buffers, it calls vm_mmap() with
1176  * offset equal to 0, which drm_mmap() interpretes as PCI buffers and calls
1177  * drm_mmap_dma().
1178  */
1179 int drm_mapbufs(struct drm_device *dev, void *data,
1180                 struct drm_file *file_priv)
1181 {
1182         drm_device_dma_t *dma = dev->dma;
1183         int retcode = 0;
1184         const int zero = 0;
1185         vm_offset_t address;
1186         struct vmspace *vms;
1187         vm_ooffset_t foff;
1188         vm_size_t size;
1189         vm_offset_t vaddr;
1190         struct drm_buf_map *request = data;
1191         int i;
1192
1193         vms = DRM_CURPROC->td_proc->p_vmspace;
1194
1195         spin_lock(&dev->dma_lock);
1196         dev->buf_use++;         /* Can't allocate more after this call */
1197         spin_unlock(&dev->dma_lock);
1198
1199         if (request->count < dma->buf_count)
1200                 goto done;
1201
1202         if ((drm_core_has_AGP(dev) && (dma->flags & _DRM_DMA_USE_AGP)) ||
1203             (drm_core_check_feature(dev, DRIVER_SG) &&
1204             (dma->flags & _DRM_DMA_USE_SG))) {
1205                 drm_local_map_t *map = dev->agp_buffer_map;
1206
1207                 if (map == NULL) {
1208                         retcode = EINVAL;
1209                         goto done;
1210                 }
1211                 size = round_page(map->size);
1212                 foff = (unsigned long)map->handle;
1213         } else {
1214                 size = round_page(dma->byte_count),
1215                 foff = 0;
1216         }
1217
1218         vaddr = round_page((vm_offset_t)vms->vm_daddr + MAXDSIZ);
1219         retcode = vm_mmap(&vms->vm_map, &vaddr, size, PROT_READ | PROT_WRITE,
1220             VM_PROT_ALL, MAP_SHARED | MAP_NOSYNC,
1221             SLIST_FIRST(&dev->devnode->si_hlist), foff);
1222         if (retcode)
1223                 goto done;
1224
1225         request->virtual = (void *)vaddr;
1226
1227         for (i = 0; i < dma->buf_count; i++) {
1228                 if (DRM_COPY_TO_USER(&request->list[i].idx,
1229                     &dma->buflist[i]->idx, sizeof(request->list[0].idx))) {
1230                         retcode = EFAULT;
1231                         goto done;
1232                 }
1233                 if (DRM_COPY_TO_USER(&request->list[i].total,
1234                     &dma->buflist[i]->total, sizeof(request->list[0].total))) {
1235                         retcode = EFAULT;
1236                         goto done;
1237                 }
1238                 if (DRM_COPY_TO_USER(&request->list[i].used, &zero,
1239                     sizeof(zero))) {
1240                         retcode = EFAULT;
1241                         goto done;
1242                 }
1243                 address = vaddr + dma->buflist[i]->offset; /* *** */
1244                 if (DRM_COPY_TO_USER(&request->list[i].address, &address,
1245                     sizeof(address))) {
1246                         retcode = EFAULT;
1247                         goto done;
1248                 }
1249         }
1250
1251  done:
1252         request->count = dma->buf_count;
1253
1254         DRM_DEBUG("%d buffers, retcode = %d\n", request->count, retcode);
1255
1256         return retcode;
1257 }
1258
1259 /**
1260  * Compute size order.  Returns the exponent of the smaller power of two which
1261  * is greater or equal to given number.
1262  *
1263  * \param size size.
1264  * \return order.
1265  *
1266  * \todo Can be made faster.
1267  */
1268 int drm_order(unsigned long size)
1269 {
1270         int order;
1271         unsigned long tmp;
1272
1273         for (order = 0, tmp = size >> 1; tmp; tmp >>= 1, order++) ;
1274
1275         if (size & (size - 1))
1276                 ++order;
1277
1278         return order;
1279 }
1280 EXPORT_SYMBOL(drm_order);