1/* drm_bufs.h -- Generic buffer template -*- linux-c -*- 2 * Created: Thu Nov 23 03:10:50 2000 by gareth@valinux.com 3 * 4 * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas. 5 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. 6 * All Rights Reserved. 7 * 8 * Permission is hereby granted, free of charge, to any person obtaining a 9 * copy of this software and associated documentation files (the "Software"), 10 * to deal in the Software without restriction, including without limitation 11 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 12 * and/or sell copies of the Software, and to permit persons to whom the 13 * Software is furnished to do so, subject to the following conditions: 14 * 15 * The above copyright notice and this permission notice (including the next 16 * paragraph) shall be included in all copies or substantial portions of the 17 * Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 22 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 * OTHER DEALINGS IN THE SOFTWARE. 26 * 27 * Authors: 28 * Rickard E. (Rik) Faith <faith@valinux.com> 29 * Gareth Hughes <gareth@valinux.com> 30 */ 31 32#include <linux/vmalloc.h> 33#include "drmP.h" 34 35#ifndef __HAVE_PCI_DMA 36#define __HAVE_PCI_DMA 0 37#endif 38 39#ifndef __HAVE_SG 40#define __HAVE_SG 0 41#endif 42 43#ifndef DRIVER_BUF_PRIV_T 44#define DRIVER_BUF_PRIV_T u32 45#endif 46#ifndef DRIVER_AGP_BUFFERS_MAP 47#if __HAVE_AGP && __HAVE_DMA 48#error "You must define DRIVER_AGP_BUFFERS_MAP()" 49#else 50#define DRIVER_AGP_BUFFERS_MAP( dev ) NULL 51#endif 52#endif 53 54/* 55 * Compute order. Can be made faster. 56 */ 57int DRM(order)( unsigned long size ) 58{ 59 int order; 60 unsigned long tmp; 61 62 for ( order = 0, tmp = size ; tmp >>= 1 ; ++order ); 63 64 if ( size & ~(1 << order) ) 65 ++order; 66 67 return order; 68} 69 70int DRM(addmap)( struct inode *inode, struct file *filp, 71 unsigned int cmd, unsigned long arg ) 72{ 73 drm_file_t *priv = filp->private_data; 74 drm_device_t *dev = priv->dev; 75 drm_map_t *map; 76 drm_map_list_t *list; 77 78 if ( !(filp->f_mode & 3) ) return -EACCES; /* Require read/write */ 79 80 map = DRM(alloc)( sizeof(*map), DRM_MEM_MAPS ); 81 if ( !map ) 82 return -ENOMEM; 83 84 if ( copy_from_user( map, (drm_map_t *)arg, sizeof(*map) ) ) { 85 DRM(free)( map, sizeof(*map), DRM_MEM_MAPS ); 86 return -EFAULT; 87 } 88 89 /* Only allow shared memory to be removable since we only keep enough 90 * book keeping information about shared memory to allow for removal 91 * when processes fork. 92 */ 93 if ( (map->flags & _DRM_REMOVABLE) && map->type != _DRM_SHM ) { 94 DRM(free)( map, sizeof(*map), DRM_MEM_MAPS ); 95 return -EINVAL; 96 } 97 DRM_DEBUG( "offset = 0x%08lx, size = 0x%08lx, type = %d\n", 98 map->offset, map->size, map->type ); 99 if ( (map->offset & (~PAGE_MASK)) || (map->size & (~PAGE_MASK)) ) { 100 DRM(free)( map, sizeof(*map), DRM_MEM_MAPS ); 101 return -EINVAL; 102 } 103 map->mtrr = -1; 104 map->handle = 0; 105 106 switch ( map->type ) { 107 case _DRM_REGISTERS: 108 case _DRM_FRAME_BUFFER: 109#if !defined(__sparc__) && !defined(__alpha__) 110 if ( map->offset + map->size < map->offset || 111 map->offset < virt_to_phys(high_memory) ) { 112 DRM(free)( map, sizeof(*map), DRM_MEM_MAPS ); 113 return -EINVAL; 114 } 115#endif 116#ifdef __alpha__ 117 map->offset += dev->hose->mem_space->start; 118#endif 119#if __REALLY_HAVE_MTRR 120 if ( map->type == _DRM_FRAME_BUFFER || 121 (map->flags & _DRM_WRITE_COMBINING) ) { 122 map->mtrr = mtrr_add( map->offset, map->size, 123 MTRR_TYPE_WRCOMB, 1 ); 124 } 125#endif 126 map->handle = DRM(ioremap)( map->offset, map->size ); 127 break; 128 129 case _DRM_SHM: 130 map->handle = vmalloc_32(map->size); 131 DRM_DEBUG( "%ld %d %p\n", 132 map->size, DRM(order)( map->size ), map->handle ); 133 if ( !map->handle ) { 134 DRM(free)( map, sizeof(*map), DRM_MEM_MAPS ); 135 return -ENOMEM; 136 } 137 map->offset = (unsigned long)map->handle; 138 if ( map->flags & _DRM_CONTAINS_LOCK ) { 139 dev->lock.hw_lock = map->handle; /* Pointer to lock */ 140 } 141 break; 142#if __REALLY_HAVE_AGP 143 case _DRM_AGP: 144#ifdef __alpha__ 145 map->offset += dev->hose->mem_space->start; 146#endif 147 map->offset = map->offset + dev->agp->base; 148 map->mtrr = dev->agp->agp_mtrr; /* for getmap */ 149 break; 150#endif 151 case _DRM_SCATTER_GATHER: 152 if (!dev->sg) { 153 DRM(free)(map, sizeof(*map), DRM_MEM_MAPS); 154 return -EINVAL; 155 } 156 map->offset = map->offset + dev->sg->handle; 157 break; 158 159 default: 160 DRM(free)( map, sizeof(*map), DRM_MEM_MAPS ); 161 return -EINVAL; 162 } 163 164 list = DRM(alloc)(sizeof(*list), DRM_MEM_MAPS); 165 if(!list) { 166 DRM(free)(map, sizeof(*map), DRM_MEM_MAPS); 167 return -EINVAL; 168 } 169 memset(list, 0, sizeof(*list)); 170 list->map = map; 171 172 down(&dev->struct_sem); 173 list_add(&list->head, &dev->maplist->head); 174 up(&dev->struct_sem); 175 176 if ( copy_to_user( (drm_map_t *)arg, map, sizeof(*map) ) ) 177 return -EFAULT; 178 if ( map->type != _DRM_SHM ) { 179 if ( copy_to_user( &((drm_map_t *)arg)->handle, 180 &map->offset, 181 sizeof(map->offset) ) ) 182 return -EFAULT; 183 } 184 return 0; 185} 186 187 188/* Remove a map private from list and deallocate resources if the mapping 189 * isn't in use. 190 */ 191 192int DRM(rmmap)(struct inode *inode, struct file *filp, 193 unsigned int cmd, unsigned long arg) 194{ 195 drm_file_t *priv = filp->private_data; 196 drm_device_t *dev = priv->dev; 197 struct list_head *list; 198 drm_map_list_t *r_list = NULL; 199 drm_vma_entry_t *pt, *prev; 200 drm_map_t *map; 201 drm_map_t request; 202 int found_maps = 0; 203 204 if (copy_from_user(&request, (drm_map_t *)arg, 205 sizeof(request))) { 206 return -EFAULT; 207 } 208 209 down(&dev->struct_sem); 210 list = &dev->maplist->head; 211 list_for_each(list, &dev->maplist->head) { 212 r_list = (drm_map_list_t *) list; 213 214 if(r_list->map && 215 r_list->map->handle == request.handle && 216 r_list->map->flags & _DRM_REMOVABLE) break; 217 } 218 219 /* List has wrapped around to the head pointer, or its empty we didn't 220 * find anything. 221 */ 222 if(list == (&dev->maplist->head)) { 223 up(&dev->struct_sem); 224 return -EINVAL; 225 } 226 map = r_list->map; 227 list_del(list); 228 DRM(free)(list, sizeof(*list), DRM_MEM_MAPS); 229 230 for (pt = dev->vmalist, prev = NULL; pt; prev = pt, pt = pt->next) { 231 if (pt->vma->vm_private_data == map) found_maps++; 232 } 233 234 if(!found_maps) { 235 switch (map->type) { 236 case _DRM_REGISTERS: 237 case _DRM_FRAME_BUFFER: 238#if __REALLY_HAVE_MTRR 239 if (map->mtrr >= 0) { 240 int retcode; 241 retcode = mtrr_del(map->mtrr, 242 map->offset, 243 map->size); 244 DRM_DEBUG("mtrr_del = %d\n", retcode); 245 } 246#endif 247 DRM(ioremapfree)(map->handle, map->size); 248 break; 249 case _DRM_SHM: 250 vfree(map->handle); 251 break; 252 case _DRM_AGP: 253 case _DRM_SCATTER_GATHER: 254 break; 255 } 256 DRM(free)(map, sizeof(*map), DRM_MEM_MAPS); 257 } 258 up(&dev->struct_sem); 259 return 0; 260} 261 262#if __HAVE_DMA 263 264 265static void DRM(cleanup_buf_error)(drm_buf_entry_t *entry) 266{ 267 int i; 268 269 if (entry->seg_count) { 270 for (i = 0; i < entry->seg_count; i++) { 271 DRM(free_pages)(entry->seglist[i], 272 entry->page_order, 273 DRM_MEM_DMA); 274 } 275 DRM(free)(entry->seglist, 276 entry->seg_count * 277 sizeof(*entry->seglist), 278 DRM_MEM_SEGS); 279 280 entry->seg_count = 0; 281 } 282 283 if(entry->buf_count) { 284 for(i = 0; i < entry->buf_count; i++) { 285 if(entry->buflist[i].dev_private) { 286 DRM(free)(entry->buflist[i].dev_private, 287 entry->buflist[i].dev_priv_size, 288 DRM_MEM_BUFS); 289 } 290 } 291 DRM(free)(entry->buflist, 292 entry->buf_count * 293 sizeof(*entry->buflist), 294 DRM_MEM_BUFS); 295 296#if __HAVE_DMA_FREELIST 297 DRM(freelist_destroy)(&entry->freelist); 298#endif 299 300 entry->buf_count = 0; 301 } 302} 303 304#if __REALLY_HAVE_AGP 305int DRM(addbufs_agp)( struct inode *inode, struct file *filp, 306 unsigned int cmd, unsigned long arg ) 307{ 308 drm_file_t *priv = filp->private_data; 309 drm_device_t *dev = priv->dev; 310 drm_device_dma_t *dma = dev->dma; 311 drm_buf_desc_t request; 312 drm_buf_entry_t *entry; 313 drm_buf_t *buf; 314 unsigned long offset; 315 unsigned long agp_offset; 316 int count; 317 int order; 318 int size; 319 int alignment; 320 int page_order; 321 int total; 322 int byte_count; 323 int i; 324 drm_buf_t **temp_buflist; 325 326 if ( !dma ) return -EINVAL; 327 328 if ( copy_from_user( &request, (drm_buf_desc_t *)arg, 329 sizeof(request) ) ) 330 return -EFAULT; 331 332 count = request.count; 333 order = DRM(order)( request.size ); 334 size = 1 << order; 335 336 alignment = (request.flags & _DRM_PAGE_ALIGN) 337 ? PAGE_ALIGN(size) : size; 338 page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0; 339 total = PAGE_SIZE << page_order; 340 341 byte_count = 0; 342 agp_offset = dev->agp->base + request.agp_start; 343 344 DRM_DEBUG( "count: %d\n", count ); 345 DRM_DEBUG( "order: %d\n", order ); 346 DRM_DEBUG( "size: %d\n", size ); 347 DRM_DEBUG( "agp_offset: %ld\n", agp_offset ); 348 DRM_DEBUG( "alignment: %d\n", alignment ); 349 DRM_DEBUG( "page_order: %d\n", page_order ); 350 DRM_DEBUG( "total: %d\n", total ); 351 352 if ( order < DRM_MIN_ORDER || order > DRM_MAX_ORDER ) return -EINVAL; 353 if ( dev->queue_count ) return -EBUSY; /* Not while in use */ 354 355 spin_lock( &dev->count_lock ); 356 if ( dev->buf_use ) { 357 spin_unlock( &dev->count_lock ); 358 return -EBUSY; 359 } 360 atomic_inc( &dev->buf_alloc ); 361 spin_unlock( &dev->count_lock ); 362 363 down( &dev->struct_sem ); 364 entry = &dma->bufs[order]; 365 if ( entry->buf_count ) { 366 up( &dev->struct_sem ); 367 atomic_dec( &dev->buf_alloc ); 368 return -ENOMEM; /* May only call once for each order */ 369 } 370 371 if (count < 0 || count > 4096) { 372 up( &dev->struct_sem ); 373 atomic_dec( &dev->buf_alloc ); 374 return -EINVAL; 375 } 376 377 entry->buflist = DRM(alloc)( count * sizeof(*entry->buflist), 378 DRM_MEM_BUFS ); 379 if ( !entry->buflist ) { 380 up( &dev->struct_sem ); 381 atomic_dec( &dev->buf_alloc ); 382 return -ENOMEM; 383 } 384 memset( entry->buflist, 0, count * sizeof(*entry->buflist) ); 385 386 entry->buf_size = size; 387 entry->page_order = page_order; 388 389 offset = 0; 390 391 while ( entry->buf_count < count ) { 392 buf = &entry->buflist[entry->buf_count]; 393 buf->idx = dma->buf_count + entry->buf_count; 394 buf->total = alignment; 395 buf->order = order; 396 buf->used = 0; 397 398 buf->offset = (dma->byte_count + offset); 399 buf->bus_address = agp_offset + offset; 400 buf->address = (void *)(agp_offset + offset); 401 buf->next = NULL; 402 buf->waiting = 0; 403 buf->pending = 0; 404 init_waitqueue_head( &buf->dma_wait ); 405 buf->pid = 0; 406 407 buf->dev_priv_size = sizeof(DRIVER_BUF_PRIV_T); 408 buf->dev_private = DRM(alloc)( sizeof(DRIVER_BUF_PRIV_T), 409 DRM_MEM_BUFS ); 410 if(!buf->dev_private) { 411 /* Set count correctly so we free the proper amount. */ 412 entry->buf_count = count; 413 DRM(cleanup_buf_error)(entry); 414 } 415 memset( buf->dev_private, 0, buf->dev_priv_size ); 416 417#if __HAVE_DMA_HISTOGRAM 418 buf->time_queued = 0; 419 buf->time_dispatched = 0; 420 buf->time_completed = 0; 421 buf->time_freed = 0; 422#endif 423 DRM_DEBUG( "buffer %d @ %p\n", 424 entry->buf_count, buf->address ); 425 426 offset += alignment; 427 entry->buf_count++; 428 byte_count += PAGE_SIZE << page_order; 429 } 430 431 DRM_DEBUG( "byte_count: %d\n", byte_count ); 432 433 temp_buflist = DRM(realloc)( dma->buflist, 434 dma->buf_count * sizeof(*dma->buflist), 435 (dma->buf_count + entry->buf_count) 436 * sizeof(*dma->buflist), 437 DRM_MEM_BUFS ); 438 if(!temp_buflist) { 439 /* Free the entry because it isn't valid */ 440 DRM(cleanup_buf_error)(entry); 441 up( &dev->struct_sem ); 442 atomic_dec( &dev->buf_alloc ); 443 return -ENOMEM; 444 } 445 dma->buflist = temp_buflist; 446 447 for ( i = 0 ; i < entry->buf_count ; i++ ) { 448 dma->buflist[i + dma->buf_count] = &entry->buflist[i]; 449 } 450 451 dma->buf_count += entry->buf_count; 452 dma->byte_count += byte_count; 453 454 DRM_DEBUG( "dma->buf_count : %d\n", dma->buf_count ); 455 DRM_DEBUG( "entry->buf_count : %d\n", entry->buf_count ); 456 457#if __HAVE_DMA_FREELIST 458 DRM(freelist_create)( &entry->freelist, entry->buf_count ); 459 for ( i = 0 ; i < entry->buf_count ; i++ ) { 460 DRM(freelist_put)( dev, &entry->freelist, &entry->buflist[i] ); 461 } 462#endif 463 up( &dev->struct_sem ); 464 465 request.count = entry->buf_count; 466 request.size = size; 467 468 if ( copy_to_user( (drm_buf_desc_t *)arg, &request, sizeof(request) ) ) 469 return -EFAULT; 470 471 dma->flags = _DRM_DMA_USE_AGP; 472 473 atomic_dec( &dev->buf_alloc ); 474 return 0; 475} 476#endif /* __REALLY_HAVE_AGP */ 477 478#if __HAVE_PCI_DMA 479int DRM(addbufs_pci)( struct inode *inode, struct file *filp, 480 unsigned int cmd, unsigned long arg ) 481{ 482 drm_file_t *priv = filp->private_data; 483 drm_device_t *dev = priv->dev; 484 drm_device_dma_t *dma = dev->dma; 485 drm_buf_desc_t request; 486 int count; 487 int order; 488 int size; 489 int total; 490 int page_order; 491 drm_buf_entry_t *entry; 492 unsigned long page; 493 drm_buf_t *buf; 494 int alignment; 495 unsigned long offset; 496 int i; 497 int byte_count; 498 int page_count; 499 unsigned long *temp_pagelist; 500 drm_buf_t **temp_buflist; 501 502 if ( !dma ) return -EINVAL; 503 504 if ( copy_from_user( &request, (drm_buf_desc_t *)arg, 505 sizeof(request) ) ) 506 return -EFAULT; 507 508 count = request.count; 509 order = DRM(order)( request.size ); 510 size = 1 << order; 511 512 DRM_DEBUG( "count=%d, size=%d (%d), order=%d, queue_count=%d\n", 513 request.count, request.size, size, 514 order, dev->queue_count ); 515 516 if ( order < DRM_MIN_ORDER || order > DRM_MAX_ORDER ) return -EINVAL; 517 if ( dev->queue_count ) return -EBUSY; /* Not while in use */ 518 519 alignment = (request.flags & _DRM_PAGE_ALIGN) 520 ? PAGE_ALIGN(size) : size; 521 page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0; 522 total = PAGE_SIZE << page_order; 523 524 spin_lock( &dev->count_lock ); 525 if ( dev->buf_use ) { 526 spin_unlock( &dev->count_lock ); 527 return -EBUSY; 528 } 529 atomic_inc( &dev->buf_alloc ); 530 spin_unlock( &dev->count_lock ); 531 532 down( &dev->struct_sem ); 533 entry = &dma->bufs[order]; 534 if ( entry->buf_count ) { 535 up( &dev->struct_sem ); 536 atomic_dec( &dev->buf_alloc ); 537 return -ENOMEM; /* May only call once for each order */ 538 } 539 540 if (count < 0 || count > 4096) { 541 up( &dev->struct_sem ); 542 atomic_dec( &dev->buf_alloc ); 543 return -EINVAL; 544 } 545 546 entry->buflist = DRM(alloc)( count * sizeof(*entry->buflist), 547 DRM_MEM_BUFS ); 548 if ( !entry->buflist ) { 549 up( &dev->struct_sem ); 550 atomic_dec( &dev->buf_alloc ); 551 return -ENOMEM; 552 } 553 memset( entry->buflist, 0, count * sizeof(*entry->buflist) ); 554 555 entry->seglist = DRM(alloc)( count * sizeof(*entry->seglist), 556 DRM_MEM_SEGS ); 557 if ( !entry->seglist ) { 558 DRM(free)( entry->buflist, 559 count * sizeof(*entry->buflist), 560 DRM_MEM_BUFS ); 561 up( &dev->struct_sem ); 562 atomic_dec( &dev->buf_alloc ); 563 return -ENOMEM; 564 } 565 memset( entry->seglist, 0, count * sizeof(*entry->seglist) ); 566 567 temp_pagelist = DRM(realloc)( dma->pagelist, 568 dma->page_count * sizeof(*dma->pagelist), 569 (dma->page_count + (count << page_order)) 570 * sizeof(*dma->pagelist), 571 DRM_MEM_PAGES ); 572 if(!temp_pagelist) { 573 DRM(free)( entry->buflist, 574 count * sizeof(*entry->buflist), 575 DRM_MEM_BUFS ); 576 DRM(free)( entry->seglist, 577 count * sizeof(*entry->seglist), 578 DRM_MEM_SEGS ); 579 up( &dev->struct_sem ); 580 atomic_dec( &dev->buf_alloc ); 581 return -ENOMEM; 582 } 583 584 dma->pagelist = temp_pagelist; 585 DRM_DEBUG( "pagelist: %d entries\n", 586 dma->page_count + (count << page_order) ); 587 588 entry->buf_size = size; 589 entry->page_order = page_order; 590 byte_count = 0; 591 page_count = 0; 592 593 while ( entry->buf_count < count ) { 594 page = DRM(alloc_pages)( page_order, DRM_MEM_DMA ); 595 if ( !page ) break; 596 entry->seglist[entry->seg_count++] = page; 597 for ( i = 0 ; i < (1 << page_order) ; i++ ) { 598 DRM_DEBUG( "page %d @ 0x%08lx\n", 599 dma->page_count + page_count, 600 page + PAGE_SIZE * i ); 601 dma->pagelist[dma->page_count + page_count++] 602 = page + PAGE_SIZE * i; 603 } 604 for ( offset = 0 ; 605 offset + size <= total && entry->buf_count < count ; 606 offset += alignment, ++entry->buf_count ) { 607 buf = &entry->buflist[entry->buf_count]; 608 buf->idx = dma->buf_count + entry->buf_count; 609 buf->total = alignment; 610 buf->order = order; 611 buf->used = 0; 612 buf->offset = (dma->byte_count + byte_count + offset); 613 buf->address = (void *)(page + offset); 614 buf->next = NULL; 615 buf->waiting = 0; 616 buf->pending = 0; 617 init_waitqueue_head( &buf->dma_wait ); 618 buf->pid = 0; 619#if __HAVE_DMA_HISTOGRAM 620 buf->time_queued = 0; 621 buf->time_dispatched = 0; 622 buf->time_completed = 0; 623 buf->time_freed = 0; 624#endif 625 DRM_DEBUG( "buffer %d @ %p\n", 626 entry->buf_count, buf->address ); 627 } 628 byte_count += PAGE_SIZE << page_order; 629 } 630 631 temp_buflist = DRM(realloc)( dma->buflist, 632 dma->buf_count * sizeof(*dma->buflist), 633 (dma->buf_count + entry->buf_count) 634 * sizeof(*dma->buflist), 635 DRM_MEM_BUFS ); 636 if(!temp_buflist) { 637 /* Free the entry because it isn't valid */ 638 DRM(cleanup_buf_error)(entry); 639 up( &dev->struct_sem ); 640 atomic_dec( &dev->buf_alloc ); 641 return -ENOMEM; 642 } 643 dma->buflist = temp_buflist; 644 645 for ( i = 0 ; i < entry->buf_count ; i++ ) { 646 dma->buflist[i + dma->buf_count] = &entry->buflist[i]; 647 } 648 649 dma->buf_count += entry->buf_count; 650 dma->seg_count += entry->seg_count; 651 dma->page_count += entry->seg_count << page_order; 652 dma->byte_count += PAGE_SIZE * (entry->seg_count << page_order); 653 654#if __HAVE_DMA_FREELIST 655 DRM(freelist_create)( &entry->freelist, entry->buf_count ); 656 for ( i = 0 ; i < entry->buf_count ; i++ ) { 657 DRM(freelist_put)( dev, &entry->freelist, &entry->buflist[i] ); 658 } 659#endif 660 up( &dev->struct_sem ); 661 662 request.count = entry->buf_count; 663 request.size = size; 664 665 if ( copy_to_user( (drm_buf_desc_t *)arg, &request, sizeof(request) ) ) 666 return -EFAULT; 667 668 atomic_dec( &dev->buf_alloc ); 669 return 0; 670 671} 672#endif /* __HAVE_PCI_DMA */ 673 674#ifdef __HAVE_SG 675int DRM(addbufs_sg)( struct inode *inode, struct file *filp, 676 unsigned int cmd, unsigned long arg ) 677{ 678 drm_file_t *priv = filp->private_data; 679 drm_device_t *dev = priv->dev; 680 drm_device_dma_t *dma = dev->dma; 681 drm_buf_desc_t request; 682 drm_buf_entry_t *entry; 683 drm_buf_t *buf; 684 unsigned long offset; 685 unsigned long agp_offset; 686 int count; 687 int order; 688 int size; 689 int alignment; 690 int page_order; 691 int total; 692 int byte_count; 693 int i; 694 drm_buf_t **temp_buflist; 695 696 if ( !dma ) return -EINVAL; 697 698 if ( copy_from_user( &request, (drm_buf_desc_t *)arg, 699 sizeof(request) ) ) 700 return -EFAULT; 701 702 count = request.count; 703 order = DRM(order)( request.size ); 704 size = 1 << order; 705 706 alignment = (request.flags & _DRM_PAGE_ALIGN) 707 ? PAGE_ALIGN(size) : size; 708 page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0; 709 total = PAGE_SIZE << page_order; 710 711 byte_count = 0; 712 agp_offset = request.agp_start; 713 714 DRM_DEBUG( "count: %d\n", count ); 715 DRM_DEBUG( "order: %d\n", order ); 716 DRM_DEBUG( "size: %d\n", size ); 717 DRM_DEBUG( "agp_offset: %ld\n", agp_offset ); 718 DRM_DEBUG( "alignment: %d\n", alignment ); 719 DRM_DEBUG( "page_order: %d\n", page_order ); 720 DRM_DEBUG( "total: %d\n", total ); 721 722 if ( order < DRM_MIN_ORDER || order > DRM_MAX_ORDER ) return -EINVAL; 723 if ( dev->queue_count ) return -EBUSY; /* Not while in use */ 724 725 spin_lock( &dev->count_lock ); 726 if ( dev->buf_use ) { 727 spin_unlock( &dev->count_lock ); 728 return -EBUSY; 729 } 730 atomic_inc( &dev->buf_alloc ); 731 spin_unlock( &dev->count_lock ); 732 733 down( &dev->struct_sem ); 734 entry = &dma->bufs[order]; 735 if ( entry->buf_count ) { 736 up( &dev->struct_sem ); 737 atomic_dec( &dev->buf_alloc ); 738 return -ENOMEM; /* May only call once for each order */ 739 } 740 741 if (count < 0 || count > 4096) { 742 up( &dev->struct_sem ); 743 atomic_dec( &dev->buf_alloc ); 744 return -EINVAL; 745 } 746 747 entry->buflist = DRM(alloc)( count * sizeof(*entry->buflist), 748 DRM_MEM_BUFS ); 749 if ( !entry->buflist ) { 750 up( &dev->struct_sem ); 751 atomic_dec( &dev->buf_alloc ); 752 return -ENOMEM; 753 } 754 memset( entry->buflist, 0, count * sizeof(*entry->buflist) ); 755 756 entry->buf_size = size; 757 entry->page_order = page_order; 758 759 offset = 0; 760 761 while ( entry->buf_count < count ) { 762 buf = &entry->buflist[entry->buf_count]; 763 buf->idx = dma->buf_count + entry->buf_count; 764 buf->total = alignment; 765 buf->order = order; 766 buf->used = 0; 767 768 buf->offset = (dma->byte_count + offset); 769 buf->bus_address = agp_offset + offset; 770 buf->address = (void *)(agp_offset + offset + dev->sg->handle); 771 buf->next = NULL; 772 buf->waiting = 0; 773 buf->pending = 0; 774 init_waitqueue_head( &buf->dma_wait ); 775 buf->pid = 0; 776 777 buf->dev_priv_size = sizeof(DRIVER_BUF_PRIV_T); 778 buf->dev_private = DRM(alloc)( sizeof(DRIVER_BUF_PRIV_T), 779 DRM_MEM_BUFS ); 780 if(!buf->dev_private) { 781 /* Set count correctly so we free the proper amount. */ 782 entry->buf_count = count; 783 DRM(cleanup_buf_error)(entry); 784 up( &dev->struct_sem ); 785 atomic_dec( &dev->buf_alloc ); 786 return -ENOMEM; 787 } 788 789 memset( buf->dev_private, 0, buf->dev_priv_size ); 790 791# if __HAVE_DMA_HISTOGRAM 792 buf->time_queued = 0; 793 buf->time_dispatched = 0; 794 buf->time_completed = 0; 795 buf->time_freed = 0; 796# endif 797 DRM_DEBUG( "buffer %d @ %p\n", 798 entry->buf_count, buf->address ); 799 800 offset += alignment; 801 entry->buf_count++; 802 byte_count += PAGE_SIZE << page_order; 803 } 804 805 DRM_DEBUG( "byte_count: %d\n", byte_count ); 806 807 temp_buflist = DRM(realloc)( dma->buflist, 808 dma->buf_count * sizeof(*dma->buflist), 809 (dma->buf_count + entry->buf_count) 810 * sizeof(*dma->buflist), 811 DRM_MEM_BUFS ); 812 if(!temp_buflist) { 813 /* Free the entry because it isn't valid */ 814 DRM(cleanup_buf_error)(entry); 815 up( &dev->struct_sem ); 816 atomic_dec( &dev->buf_alloc ); 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#if __HAVE_DMA_FREELIST 832 DRM(freelist_create)( &entry->freelist, entry->buf_count ); 833 for ( i = 0 ; i < entry->buf_count ; i++ ) { 834 DRM(freelist_put)( dev, &entry->freelist, &entry->buflist[i] ); 835 } 836#endif 837 up( &dev->struct_sem ); 838 839 request.count = entry->buf_count; 840 request.size = size; 841 842 if ( copy_to_user( (drm_buf_desc_t *)arg, &request, sizeof(request) ) ) 843 return -EFAULT; 844 845 dma->flags = _DRM_DMA_USE_SG; 846 847 atomic_dec( &dev->buf_alloc ); 848 return 0; 849} 850#endif /* __HAVE_SG */ 851 852int DRM(addbufs)( struct inode *inode, struct file *filp, 853 unsigned int cmd, unsigned long arg ) 854{ 855 drm_buf_desc_t request; 856 857 if ( copy_from_user( &request, (drm_buf_desc_t *)arg, 858 sizeof(request) ) ) 859 return -EFAULT; 860 861#if __REALLY_HAVE_AGP 862 if ( request.flags & _DRM_AGP_BUFFER ) 863 return DRM(addbufs_agp)( inode, filp, cmd, arg ); 864 else 865#endif 866#if __HAVE_SG 867 if ( request.flags & _DRM_SG_BUFFER ) 868 return DRM(addbufs_sg)( inode, filp, cmd, arg ); 869 else 870#endif 871#if __HAVE_PCI_DMA 872 return DRM(addbufs_pci)( inode, filp, cmd, arg ); 873#else 874 return -EINVAL; 875#endif 876} 877 878int DRM(infobufs)( struct inode *inode, struct file *filp, 879 unsigned int cmd, unsigned long arg ) 880{ 881 drm_file_t *priv = filp->private_data; 882 drm_device_t *dev = priv->dev; 883 drm_device_dma_t *dma = dev->dma; 884 drm_buf_info_t request; 885 int i; 886 int count; 887 888 if ( !dma ) return -EINVAL; 889 890 spin_lock( &dev->count_lock ); 891 if ( atomic_read( &dev->buf_alloc ) ) { 892 spin_unlock( &dev->count_lock ); 893 return -EBUSY; 894 } 895 ++dev->buf_use; /* Can't allocate more after this call */ 896 spin_unlock( &dev->count_lock ); 897 898 if ( copy_from_user( &request, 899 (drm_buf_info_t *)arg, 900 sizeof(request) ) ) 901 return -EFAULT; 902 903 for ( i = 0, count = 0 ; i < DRM_MAX_ORDER + 1 ; i++ ) { 904 if ( dma->bufs[i].buf_count ) ++count; 905 } 906 907 DRM_DEBUG( "count = %d\n", count ); 908 909 if ( request.count >= count ) { 910 for ( i = 0, count = 0 ; i < DRM_MAX_ORDER + 1 ; i++ ) { 911 if ( dma->bufs[i].buf_count ) { 912 drm_buf_desc_t *to = &request.list[count]; 913 drm_buf_entry_t *from = &dma->bufs[i]; 914 drm_freelist_t *list = &dma->bufs[i].freelist; 915 if ( copy_to_user( &to->count, 916 &from->buf_count, 917 sizeof(from->buf_count) ) || 918 copy_to_user( &to->size, 919 &from->buf_size, 920 sizeof(from->buf_size) ) || 921 copy_to_user( &to->low_mark, 922 &list->low_mark, 923 sizeof(list->low_mark) ) || 924 copy_to_user( &to->high_mark, 925 &list->high_mark, 926 sizeof(list->high_mark) ) ) 927 return -EFAULT; 928 929 DRM_DEBUG( "%d %d %d %d %d\n", 930 i, 931 dma->bufs[i].buf_count, 932 dma->bufs[i].buf_size, 933 dma->bufs[i].freelist.low_mark, 934 dma->bufs[i].freelist.high_mark ); 935 ++count; 936 } 937 } 938 } 939 request.count = count; 940 941 if ( copy_to_user( (drm_buf_info_t *)arg, 942 &request, 943 sizeof(request) ) ) 944 return -EFAULT; 945 946 return 0; 947} 948 949int DRM(markbufs)( struct inode *inode, struct file *filp, 950 unsigned int cmd, unsigned long arg ) 951{ 952 drm_file_t *priv = filp->private_data; 953 drm_device_t *dev = priv->dev; 954 drm_device_dma_t *dma = dev->dma; 955 drm_buf_desc_t request; 956 int order; 957 drm_buf_entry_t *entry; 958 959 if ( !dma ) return -EINVAL; 960 961 if ( copy_from_user( &request, 962 (drm_buf_desc_t *)arg, 963 sizeof(request) ) ) 964 return -EFAULT; 965 966 DRM_DEBUG( "%d, %d, %d\n", 967 request.size, request.low_mark, request.high_mark ); 968 order = DRM(order)( request.size ); 969 if ( order < DRM_MIN_ORDER || order > DRM_MAX_ORDER ) return -EINVAL; 970 entry = &dma->bufs[order]; 971 972 if ( request.low_mark < 0 || request.low_mark > entry->buf_count ) 973 return -EINVAL; 974 if ( request.high_mark < 0 || request.high_mark > entry->buf_count ) 975 return -EINVAL; 976 977 entry->freelist.low_mark = request.low_mark; 978 entry->freelist.high_mark = request.high_mark; 979 980 return 0; 981} 982 983int DRM(freebufs)( struct inode *inode, struct file *filp, 984 unsigned int cmd, unsigned long arg ) 985{ 986 drm_file_t *priv = filp->private_data; 987 drm_device_t *dev = priv->dev; 988 drm_device_dma_t *dma = dev->dma; 989 drm_buf_free_t request; 990 int i; 991 int idx; 992 drm_buf_t *buf; 993 994 if ( !dma ) return -EINVAL; 995 996 if ( copy_from_user( &request, 997 (drm_buf_free_t *)arg, 998 sizeof(request) ) ) 999 return -EFAULT; 1000 1001 DRM_DEBUG( "%d\n", request.count ); 1002 for ( i = 0 ; i < request.count ; i++ ) { 1003 if ( copy_from_user( &idx, 1004 &request.list[i], 1005 sizeof(idx) ) ) 1006 return -EFAULT; 1007 if ( idx < 0 || idx >= dma->buf_count ) { 1008 DRM_ERROR( "Index %d (of %d max)\n", 1009 idx, dma->buf_count - 1 ); 1010 return -EINVAL; 1011 } 1012 buf = dma->buflist[idx]; 1013 if ( buf->pid != current->pid ) { 1014 DRM_ERROR( "Process %d freeing buffer owned by %d\n", 1015 current->pid, buf->pid ); 1016 return -EINVAL; 1017 } 1018 DRM(free_buffer)( dev, buf ); 1019 } 1020 1021 return 0; 1022} 1023 1024int DRM(mapbufs)( struct inode *inode, struct file *filp, 1025 unsigned int cmd, unsigned long arg ) 1026{ 1027 drm_file_t *priv = filp->private_data; 1028 drm_device_t *dev = priv->dev; 1029 drm_device_dma_t *dma = dev->dma; 1030 int retcode = 0; 1031 const int zero = 0; 1032 unsigned long virtual; 1033 unsigned long address; 1034 drm_buf_map_t request; 1035 int i; 1036 1037 if ( !dma ) return -EINVAL; 1038 1039 spin_lock( &dev->count_lock ); 1040 if ( atomic_read( &dev->buf_alloc ) ) { 1041 spin_unlock( &dev->count_lock ); 1042 return -EBUSY; 1043 } 1044 dev->buf_use++; /* Can't allocate more after this call */ 1045 spin_unlock( &dev->count_lock ); 1046 1047 if ( copy_from_user( &request, (drm_buf_map_t *)arg, 1048 sizeof(request) ) ) 1049 return -EFAULT; 1050 1051 if ( request.count >= dma->buf_count ) { 1052 if ( (__HAVE_AGP && (dma->flags & _DRM_DMA_USE_AGP)) || 1053 (__HAVE_SG && (dma->flags & _DRM_DMA_USE_SG)) ) { 1054 drm_map_t *map = DRIVER_AGP_BUFFERS_MAP( dev ); 1055 1056 if ( !map ) { 1057 retcode = -EINVAL; 1058 goto done; 1059 } 1060 1061 down_write( ¤t->mm->mmap_sem ); 1062 virtual = do_mmap( filp, 0, map->size, 1063 PROT_READ | PROT_WRITE, 1064 MAP_SHARED, 1065 (unsigned long)map->offset ); 1066 up_write( ¤t->mm->mmap_sem ); 1067 } else { 1068 down_write( ¤t->mm->mmap_sem ); 1069 virtual = do_mmap( filp, 0, dma->byte_count, 1070 PROT_READ | PROT_WRITE, 1071 MAP_SHARED, 0 ); 1072 up_write( ¤t->mm->mmap_sem ); 1073 } 1074 if ( virtual > -1024UL ) { 1075 /* Real error */ 1076 retcode = (signed long)virtual; 1077 goto done; 1078 } 1079 request.virtual = (void *)virtual; 1080 1081 for ( i = 0 ; i < dma->buf_count ; i++ ) { 1082 if ( copy_to_user( &request.list[i].idx, 1083 &dma->buflist[i]->idx, 1084 sizeof(request.list[0].idx) ) ) { 1085 retcode = -EFAULT; 1086 goto done; 1087 } 1088 if ( copy_to_user( &request.list[i].total, 1089 &dma->buflist[i]->total, 1090 sizeof(request.list[0].total) ) ) { 1091 retcode = -EFAULT; 1092 goto done; 1093 } 1094 if ( copy_to_user( &request.list[i].used, 1095 &zero, 1096 sizeof(zero) ) ) { 1097 retcode = -EFAULT; 1098 goto done; 1099 } 1100 address = virtual + dma->buflist[i]->offset; /* *** */ 1101 if ( copy_to_user( &request.list[i].address, 1102 &address, 1103 sizeof(address) ) ) { 1104 retcode = -EFAULT; 1105 goto done; 1106 } 1107 } 1108 } 1109 done: 1110 request.count = dma->buf_count; 1111 DRM_DEBUG( "%d buffers, retcode = %d\n", request.count, retcode ); 1112 1113 if ( copy_to_user( (drm_buf_map_t *)arg, &request, sizeof(request) ) ) 1114 return -EFAULT; 1115 1116 return retcode; 1117} 1118 1119#endif /* __HAVE_DMA */ 1120