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