2 * Copyright (C) 2011, 2012 glevand <geoffrey.levand@mail.ru>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer,
10 * without modification, immediately at the beginning of the file.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
32 #include <sys/param.h>
35 #include <sys/kernel.h>
37 #include <sys/module.h>
38 #include <sys/systm.h>
39 #include <sys/fcntl.h>
41 #include <sys/malloc.h>
42 #include <sys/ioccom.h>
46 #include <machine/pmap.h>
48 #include <powerpc/ps3/ps3-hvcall.h>
50 #include "ps3gpu_heap.h"
51 #include "ps3gpu_ctl.h"
54 static int ps3gpu_open(struct cdev
*dev
, int oflags
, int fmt
,
56 static int ps3gpu_mmap(struct cdev
*dev
, vm_ooffset_t offset
,
57 vm_paddr_t
*paddr
, int nprot
, vm_memattr_t
*memattr
);
58 static int ps3gpu_ioctl(struct cdev
*dev
, u_long cmd
, caddr_t data
,
59 int fflag
, struct thread
*td
);
61 static struct ps3gpu_memory_map
*ps3gpu_dev_get_mmap(struct ps3gpu_device
*dev
,
62 unsigned long handle
);
63 static unsigned long ps3gpu_dev_alloc_handle(struct ps3gpu_device
*dev
);
64 static void ps3gpu_dev_free_handle(struct ps3gpu_device
*dev
,
65 unsigned long handle
);
67 static struct cdevsw ps3gpu_cdevsw
= {
68 .d_version
= D_VERSION
,
69 .d_open
= ps3gpu_open
,
70 .d_mmap
= ps3gpu_mmap
,
71 .d_ioctl
= ps3gpu_ioctl
,
75 static struct ps3gpu_device
*ps3gpu_dev
;
77 static struct cdev
*ps3gpu_cdev
;
79 static MALLOC_DEFINE(M_PS3GPU
, "ps3gpu", "PS3 GPU");
80 static MALLOC_DEFINE(M_PS3GPU_GART
, "ps3gpu_gart", "PS3 GPU GART memory");
83 ps3gpu_context_allocate(int vram_size
, struct ps3gpu_context
**pcontext
)
85 struct ps3gpu_context
*context
;
89 sx_xlock(&ps3gpu_dev
->d_lock
);
91 for (id
= 0; id
< PS3GPU_DEVICE_MAX_CONTEXTS
; id
++) {
92 if (!ps3gpu_dev
->d_context
[id
])
96 if (id
>= PS3GPU_DEVICE_MAX_CONTEXTS
) {
97 sx_xunlock(&ps3gpu_dev
->d_lock
);
101 context
= malloc(sizeof(*context
), M_PS3GPU
, M_WAITOK
| M_ZERO
);
103 sx_xunlock(&ps3gpu_dev
->d_lock
);
107 sx_init(&context
->ctx_lock
, "ps3gpu_context");
109 context
->ctx_dev
= ps3gpu_dev
;
110 context
->ctx_id
= id
;
111 context
->ctx_vram_size
= vram_size
* 1024 * 1024;
113 err
= lv1_gpu_memory_allocate(context
->ctx_vram_size
,
114 0 /* 0x80000 */, 0 /* 0x300000 */, 0 /* 0xf */, 0 /* 0x8 */,
115 &context
->ctx_memory_handle
, &context
->ctx_vram_paddr
);
117 printf("lv1_gpu_memory_allocate failed (%d)\n", err
);
122 context
->ctx_vram_vaddr
= (unsigned long) pmap_mapdev(context
->ctx_vram_paddr
,
123 context
->ctx_vram_size
);
124 if (!context
->ctx_vram_vaddr
) {
129 err
= lv1_gpu_context_allocate(context
->ctx_memory_handle
, 0x822,
130 &context
->ctx_handle
, &context
->ctx_control_paddr
,
131 &context
->ctx_driver_info_paddr
, &context
->ctx_reports_paddr
,
132 &context
->ctx_reports_size
);
134 printf("lv1_gpu_context_allocate failed (%d)\n", err
);
139 context
->ctx_control_size
= PAGE_SIZE
;
141 context
->ctx_control_vaddr
= (unsigned long) pmap_mapdev(context
->ctx_control_paddr
,
142 context
->ctx_control_size
);
143 if (!context
->ctx_control_vaddr
) {
145 goto free_gpu_context
;
148 context
->ctx_driver_info_size
= 4 * PAGE_SIZE
;
150 context
->ctx_driver_info_vaddr
= (unsigned long) pmap_mapdev(context
->ctx_driver_info_paddr
,
151 context
->ctx_driver_info_size
);
152 if (!context
->ctx_driver_info_vaddr
) {
157 context
->ctx_reports_vaddr
= (unsigned long) pmap_mapdev(context
->ctx_reports_paddr
,
158 context
->ctx_reports_size
);
159 if (!context
->ctx_reports_vaddr
) {
161 goto unmap_driver_info
;
164 err
= ps3gpu_heap_init(&context
->ctx_heap
[PS3GPU_MEMORY_TYPE_VIDEO
],
165 context
->ctx_vram_size
);
169 err
= ps3gpu_heap_init(&context
->ctx_heap
[PS3GPU_MEMORY_TYPE_GART
],
174 TAILQ_INIT(&context
->ctx_mem_queue
);
176 ps3gpu_dev
->d_context
[id
] = context
;
178 sx_xunlock(&ps3gpu_dev
->d_lock
);
186 ps3gpu_heap_fini(&context
->ctx_heap
[PS3GPU_MEMORY_TYPE_VIDEO
]);
190 pmap_unmapdev(context
->ctx_reports_vaddr
, context
->ctx_reports_size
);
194 pmap_unmapdev(context
->ctx_driver_info_vaddr
, context
->ctx_driver_info_size
);
198 pmap_unmapdev(context
->ctx_control_vaddr
, context
->ctx_control_size
);
202 lv1_gpu_context_free(context
->ctx_handle
);
206 pmap_unmapdev(context
->ctx_vram_vaddr
,
207 context
->ctx_vram_size
);
211 lv1_gpu_memory_free(context
->ctx_memory_handle
);
215 sx_destroy(&context
->ctx_lock
);
217 free(context
, M_PS3GPU
);
219 sx_xunlock(&ps3gpu_dev
->d_lock
);
225 ps3gpu_context_free(struct ps3gpu_context
*context
)
227 struct ps3gpu_memory
*mem
;
229 KASSERT(context
!= NULL
, ("invalid context"));
231 sx_xlock(&context
->ctx_dev
->d_lock
);
232 ps3gpu_dev
->d_context
[context
->ctx_id
] = NULL
;
233 sx_xunlock(&context
->ctx_dev
->d_lock
);
235 while ((mem
= TAILQ_FIRST(&context
->ctx_mem_queue
)))
236 ps3gpu_memory_free(mem
);
238 pmap_unmapdev(context
->ctx_vram_vaddr
, context
->ctx_vram_size
);
239 pmap_unmapdev(context
->ctx_control_vaddr
, context
->ctx_control_size
);
240 pmap_unmapdev(context
->ctx_driver_info_vaddr
,
241 context
->ctx_driver_info_size
);
242 pmap_unmapdev(context
->ctx_reports_vaddr
, context
->ctx_reports_size
);
244 ps3gpu_heap_fini(&context
->ctx_heap
[PS3GPU_MEMORY_TYPE_VIDEO
]);
245 ps3gpu_heap_fini(&context
->ctx_heap
[PS3GPU_MEMORY_TYPE_GART
]);
247 lv1_gpu_context_free(context
->ctx_handle
);
249 lv1_gpu_memory_free(context
->ctx_memory_handle
);
251 sx_destroy(&context
->ctx_lock
);
253 free(context
, M_PS3GPU
);
259 ps3gpu_memory_allocate(struct ps3gpu_context
*context
,
260 int type
, int size
, int align
, struct ps3gpu_memory
**pmem
)
262 struct ps3gpu_memory
*mem
;
267 KASSERT(context
!= NULL
, ("invalid context"));
268 KASSERT(type
== PS3GPU_MEMORY_TYPE_VIDEO
||
269 type
== PS3GPU_MEMORY_TYPE_GART
, ("invalid memory type"));
270 KASSERT((size
% PAGE_SIZE
) == 0,
271 ("size is not a multiple of page size"));
272 KASSERT(align
>= PAGE_SHIFT
, ("alignment is too small"));
274 sx_xlock(&context
->ctx_lock
);
276 err
= ps3gpu_heap_allocate(&context
->ctx_heap
[type
],
277 size
, align
, &start
);
279 sx_xunlock(&context
->ctx_lock
);
283 mem
= malloc(sizeof(*mem
), M_PS3GPU
, M_WAITOK
| M_ZERO
);
289 mem
->m_context
= context
;
292 mem
->m_start
= start
;
295 if (type
== PS3GPU_MEMORY_TYPE_VIDEO
) {
296 mem
->m_paddr
= context
->ctx_vram_paddr
+ mem
->m_start
;
297 mem
->m_vaddr
= context
->ctx_vram_vaddr
+ mem
->m_start
;
298 mem
->m_gaddr
= mem
->m_start
;
300 mem
->m_vaddr
= (unsigned long) malloc(size
, M_PS3GPU_GART
,
307 mem
->m_gaddr
= PS3GPU_MEMORY_GART_ADDRESS_OFFSET
+
310 for (i
= 0; i
< size
/ PAGE_SIZE
; i
++) {
311 err
= lv1_gpu_context_iomap(context
->ctx_handle
,
312 mem
->m_gaddr
+ i
* PAGE_SIZE
,
313 vtophys(mem
->m_vaddr
+ i
* PAGE_SIZE
),
314 PAGE_SIZE
, 0xe000000000000800ul
);
316 printf("lv1_gpu_context_iomap failed (%d)\n", err
);
323 TAILQ_INSERT_TAIL(&context
->ctx_mem_queue
, mem
, m_queue
);
325 sx_xunlock(&context
->ctx_lock
);
333 for (i
= 0; i
< size
/ PAGE_SIZE
; i
++) {
334 lv1_gpu_context_iomap(context
->ctx_handle
,
335 mem
->m_gaddr
+ i
* PAGE_SIZE
,
336 vtophys(mem
->m_vaddr
+ i
* PAGE_SIZE
),
337 PAGE_SIZE
, 0x2000000000000000ul
);
340 free((void *) mem
->m_vaddr
, M_PS3GPU_GART
);
348 ps3gpu_heap_free(&context
->ctx_heap
[type
], start
, size
);
350 sx_xunlock(&context
->ctx_lock
);
356 ps3gpu_memory_free(struct ps3gpu_memory
*mem
)
358 struct ps3gpu_context
*context
= mem
->m_context
;
361 KASSERT(mem
!= NULL
, ("invalid memory"));
362 KASSERT(mem
->m_type
== PS3GPU_MEMORY_TYPE_VIDEO
||
363 mem
->m_type
== PS3GPU_MEMORY_TYPE_GART
, ("invalid memory type"));
364 KASSERT(context
!= NULL
, ("invalid context"));
366 sx_xlock(&context
->ctx_lock
);
368 TAILQ_REMOVE(&context
->ctx_mem_queue
, mem
, m_queue
);
370 if (mem
->m_type
== PS3GPU_MEMORY_TYPE_GART
) {
371 for (i
= 0; i
< mem
->m_size
/ PAGE_SIZE
; i
++) {
372 lv1_gpu_context_iomap(context
->ctx_handle
,
373 mem
->m_gaddr
+ i
* PAGE_SIZE
,
374 vtophys(mem
->m_vaddr
+ i
* PAGE_SIZE
),
375 PAGE_SIZE
, 0x2000000000000000ul
);
378 free((void *) mem
->m_vaddr
, M_PS3GPU_GART
);
381 ps3gpu_heap_free(&context
->ctx_heap
[mem
->m_type
],
382 mem
->m_start
, mem
->m_size
);
386 sx_xunlock(&context
->ctx_lock
);
392 ps3gpu_setup_control(struct ps3gpu_context
*context
,
393 unsigned int put
, unsigned int get
, unsigned int ref
)
397 KASSERT(context
!= NULL
, ("invalid context"));
399 sx_xlock(&context
->ctx_lock
);
401 err
= lv1_gpu_context_attribute(context
->ctx_handle
, 0x1,
404 printf("lv1_gpu_context_attribute failed (%d)\n", err
);
405 sx_xunlock(&context
->ctx_lock
);
409 sx_xunlock(&context
->ctx_lock
);
415 ps3gpu_set_flip_mode(struct ps3gpu_context
*context
, int head
, int mode
)
419 KASSERT(context
!= NULL
, ("invalid context"));
420 KASSERT(head
== PS3GPU_HEAD_A
|| head
== PS3GPU_HEAD_B
,
422 KASSERT(mode
== PS3GPU_FLIP_MODE_HSYNC
||
423 PS3GPU_FLIP_MODE_VSYNC
, ("invalid flip mode"));
425 sx_xlock(&context
->ctx_lock
);
427 err
= lv1_gpu_attribute(0x2, head
, 0, 0, 0);
429 printf("lv1_gpu_attribute failed (%d)\n", err
);
430 sx_xunlock(&context
->ctx_lock
);
434 err
= lv1_gpu_context_attribute(context
->ctx_handle
, 0x101,
437 printf("lv1_gpu_context_attribute failed (%d)\n", err
);
438 sx_xunlock(&context
->ctx_lock
);
442 sx_xunlock(&context
->ctx_lock
);
448 ps3gpu_reset_flip_status(struct ps3gpu_context
*context
, int head
)
452 KASSERT(context
!= NULL
, ("invalid context"));
453 KASSERT(head
== PS3GPU_HEAD_A
|| head
== PS3GPU_HEAD_B
,
456 sx_xlock(&context
->ctx_lock
);
458 err
= lv1_gpu_context_attribute(context
->ctx_handle
, 0x10a,
459 head
, 0x7ffffffful
, 0x00000000ul
, 0);
461 printf("lv1_gpu_context_attribute failed (%d)\n", err
);
462 sx_xunlock(&context
->ctx_lock
);
466 sx_xunlock(&context
->ctx_lock
);
472 ps3gpu_flip(struct ps3gpu_context
*context
, int head
,
477 KASSERT(context
!= NULL
, ("invalid context"));
478 KASSERT(head
== PS3GPU_HEAD_A
|| head
== PS3GPU_HEAD_B
,
481 sx_xlock(&context
->ctx_lock
);
483 err
= lv1_gpu_context_attribute(context
->ctx_handle
, 0x102,
486 printf("lv1_gpu_context_attribute failed (%d)\n", err
);
487 sx_xunlock(&context
->ctx_lock
);
491 sx_xunlock(&context
->ctx_lock
);
497 ps3gpu_display_buffer_set(struct ps3gpu_context
*context
,
498 int buffer_id
, int width
, int height
, int pitch
,
503 KASSERT(context
!= NULL
, ("invalid context"));
504 KASSERT(buffer_id
>= 0 &&
505 buffer_id
< PS3GPU_CONTEXT_MAX_DISPLAY_BUFFERS
,
506 ("invalid display buffer id"));
508 sx_xlock(&context
->ctx_lock
);
510 err
= lv1_gpu_context_attribute(context
->ctx_handle
, 0x104,
511 buffer_id
, (((unsigned long) width
) << 32) | height
,
512 (((unsigned long) pitch
) << 32) | offset
, 0);
514 printf("lv1_gpu_context_attribute failed (%d)\n", err
);
515 sx_xunlock(&context
->ctx_lock
);
519 sx_xunlock(&context
->ctx_lock
);
525 ps3gpu_display_buffer_unset(struct ps3gpu_context
*context
,
530 KASSERT(context
!= NULL
, ("invalid context"));
531 KASSERT(buffer_id
>= 0 &&
532 buffer_id
< PS3GPU_CONTEXT_MAX_DISPLAY_BUFFERS
,
533 ("invalid display buffer id"));
535 sx_xlock(&context
->ctx_lock
);
537 err
= lv1_gpu_context_attribute(context
->ctx_handle
, 0x105,
540 printf("lv1_gpu_context_attribute failed (%d)\n", err
);
541 sx_xunlock(&context
->ctx_lock
);
545 sx_xunlock(&context
->ctx_lock
);
551 ps3gpu_display_buffer_flip(struct ps3gpu_context
*context
, int head
,
556 KASSERT(context
!= NULL
, ("invalid context"));
557 KASSERT(head
== PS3GPU_HEAD_A
|| head
== PS3GPU_HEAD_B
,
559 KASSERT(buffer_id
>= 0 &&
560 buffer_id
< PS3GPU_CONTEXT_MAX_DISPLAY_BUFFERS
,
561 ("invalid display buffer id"));
563 sx_xlock(&context
->ctx_lock
);
565 err
= lv1_gpu_context_attribute(context
->ctx_handle
, 0x102,
566 head
, 0x80000000ul
| (ps3gpu_context_get_channel(context
) << 8) |
569 printf("lv1_gpu_context_attribute failed (%d)\n", err
);
570 sx_xunlock(&context
->ctx_lock
);
574 sx_xunlock(&context
->ctx_lock
);
580 ps3gpu_tile_get_pitch(int pitch
)
582 static const int tile_pitches
[] = {
583 0x00000000, 0x00000200, 0x00000300, 0x00000400,
584 0x00000500, 0x00000600, 0x00000700, 0x00000800,
585 0x00000a00, 0x00000c00, 0x00000d00, 0x00000e00,
586 0x00001000, 0x00001400, 0x00001800, 0x00001a00,
587 0x00001c00, 0x00002000, 0x00002800, 0x00003000,
588 0x00003400, 0x00003800, 0x00004000, 0x00005000,
589 0x00006000, 0x00006800, 0x00007000, 0x00008000,
590 0x0000a000, 0x0000c000, 0x0000d000, 0x0000e000,
596 for (i
= 0; i
< sizeof(tile_pitches
) / sizeof(tile_pitches
[0]) - 1; i
++) {
597 if ((tile_pitches
[i
] < pitch
) && (pitch
<= tile_pitches
[i
+ 1]))
598 return (tile_pitches
[i
+ 1]);
605 ps3gpu_tile_set(struct ps3gpu_context
*context
,
606 int tile_id
, int mem_type
, int size
, int pitch
, int cmp_mode
, int bank
,
607 int base
, unsigned int offset
)
610 unsigned long p1
, p2
, p3
, p4
;
613 KASSERT(context
!= NULL
, ("invalid context"));
614 KASSERT(tile_id
>= 0 &&
615 tile_id
< PS3GPU_CONTEXT_MAX_TILES
,
616 ("invalid tile id"));
617 KASSERT(mem_type
== PS3GPU_MEMORY_TYPE_VIDEO
||
618 mem_type
== PS3GPU_MEMORY_TYPE_GART
, ("invalid memory type"));
620 location
= (mem_type
== PS3GPU_MEMORY_TYPE_GART
) ? 1 : 0;
622 p1
= (location
<< 31) | (offset
& ~0xfffful
) | (bank
<< 4) | (location
+ 1);
623 p2
= (location
<< 31) | ((offset
+ size
- 1) & ~0xfffful
);
624 p3
= pitch
& ~0xfffful
;
625 p4
= 0x40000000ul
| (cmp_mode
<< 26) | ((base
+ ((size
- 1) >> 16)) << 13) | base
;
627 sx_xlock(&context
->ctx_lock
);
629 err
= lv1_gpu_context_attribute(context
->ctx_handle
, 0x300,
630 tile_id
, (p1
<< 32) | p2
, (p3
<< 32) | p4
, 0);
632 printf("lv1_gpu_context_attribute failed (%d)\n", err
);
633 sx_xunlock(&context
->ctx_lock
);
637 sx_xunlock(&context
->ctx_lock
);
643 ps3gpu_tile_unset(struct ps3gpu_context
*context
,
644 int tile_id
, int mem_type
, int bank
, unsigned int offset
)
650 KASSERT(context
!= NULL
, ("invalid context"));
651 KASSERT(tile_id
>= 0 &&
652 tile_id
< PS3GPU_CONTEXT_MAX_TILES
,
653 ("invalid tile id"));
654 KASSERT(mem_type
== PS3GPU_MEMORY_TYPE_VIDEO
||
655 mem_type
== PS3GPU_MEMORY_TYPE_GART
, ("invalid memory type"));
657 location
= (mem_type
== PS3GPU_MEMORY_TYPE_GART
) ? 1 : 0;
659 p1
= (location
<< 31) | (offset
& ~0xfffful
) | (bank
<< 4);
661 sx_xlock(&context
->ctx_lock
);
663 err
= lv1_gpu_context_attribute(context
->ctx_handle
, 0x300,
664 tile_id
, p1
<< 32, 0, 0);
666 printf("lv1_gpu_context_attribute failed (%d)\n", err
);
667 sx_xunlock(&context
->ctx_lock
);
671 sx_xunlock(&context
->ctx_lock
);
677 ps3gpu_cursor_initialize(struct ps3gpu_context
*context
, int head
)
681 KASSERT(context
!= NULL
, ("invalid context"));
682 KASSERT(head
== PS3GPU_HEAD_A
|| head
== PS3GPU_HEAD_B
,
685 sx_xlock(&context
->ctx_lock
);
687 err
= lv1_gpu_context_attribute(context
->ctx_handle
, 0x10b,
690 printf("lv1_gpu_context_attribute failed (%d)\n", err
);
691 sx_xunlock(&context
->ctx_lock
);
695 sx_xunlock(&context
->ctx_lock
);
701 ps3gpu_cursor_set_image(struct ps3gpu_context
*context
, int head
,
706 KASSERT(context
!= NULL
, ("invalid context"));
707 KASSERT(head
== PS3GPU_HEAD_A
|| head
== PS3GPU_HEAD_B
,
710 sx_xlock(&context
->ctx_lock
);
712 err
= lv1_gpu_context_attribute(context
->ctx_handle
, 0x10b,
713 head
, 0x2, offset
, 0);
715 printf("lv1_gpu_context_attribute failed (%d)\n", err
);
716 sx_xunlock(&context
->ctx_lock
);
720 sx_xunlock(&context
->ctx_lock
);
726 ps3gpu_cursor_set_position(struct ps3gpu_context
*context
, int head
,
731 KASSERT(context
!= NULL
, ("invalid context"));
732 KASSERT(head
== PS3GPU_HEAD_A
|| head
== PS3GPU_HEAD_B
,
735 sx_xlock(&context
->ctx_lock
);
737 err
= lv1_gpu_context_attribute(context
->ctx_handle
, 0x10b,
740 printf("lv1_gpu_context_attribute failed (%d)\n", err
);
741 sx_xunlock(&context
->ctx_lock
);
745 sx_xunlock(&context
->ctx_lock
);
751 ps3gpu_cursor_enable(struct ps3gpu_context
*context
, int head
,
756 KASSERT(context
!= NULL
, ("invalid context"));
757 KASSERT(head
== PS3GPU_HEAD_A
|| head
== PS3GPU_HEAD_B
,
760 sx_xlock(&context
->ctx_lock
);
762 err
= lv1_gpu_context_attribute(context
->ctx_handle
, 0x10c,
763 head
, enable
? 0x1 : 0x2, 0, 0);
765 printf("lv1_gpu_context_attribute failed (%d)\n", err
);
766 sx_xunlock(&context
->ctx_lock
);
770 sx_xunlock(&context
->ctx_lock
);
775 static struct ps3gpu_context
*
776 ps3gpu_user_get_context(struct ps3gpu_user
*user
, int id
)
778 struct ps3gpu_context
*context
;
780 KASSERT(user
!= NULL
, ("invalid user"));
782 sx_xlock(&user
->u_lock
);
784 TAILQ_FOREACH(context
, &user
->u_context_queue
, ctx_user_queue
) {
785 if (context
->ctx_id
== id
) {
786 sx_xunlock(&user
->u_lock
);
791 sx_xunlock(&user
->u_lock
);
797 ps3gpu_ctl_context_allocate(struct ps3gpu_user
*user
,
798 struct ps3gpu_ctl_context_allocate
*req
)
800 struct ps3gpu_context
*context
;
801 struct ps3gpu_memory
*mem
;
802 struct ps3gpu_memory_map
*control_mmap
;
803 struct ps3gpu_memory_map
*driver_info_mmap
;
804 struct ps3gpu_memory_map
*reports_mmap
;
807 KASSERT(user
!= NULL
, ("invalid user"));
808 KASSERT(req
!= NULL
, ("invalid request"));
810 err
= ps3gpu_context_allocate(req
->vram_size
, &context
);
814 context
->ctx_user
= user
;
816 mem
= malloc(sizeof(*mem
), M_PS3GPU
, M_WAITOK
| M_ZERO
);
822 mem
->m_context
= context
;
824 mem
->m_type
= PS3GPU_MEMORY_TYPE_REGISTER
;
825 mem
->m_size
= context
->ctx_control_size
;
827 mem
->m_paddr
= context
->ctx_control_paddr
;
828 mem
->m_vaddr
= context
->ctx_control_vaddr
;
830 context
->ctx_control_mem
= mem
;
832 control_mmap
= malloc(sizeof(*control_mmap
), M_PS3GPU
,
836 goto free_control_memory
;
839 control_mmap
->mm_mem
= mem
;
840 control_mmap
->mm_handle
= ps3gpu_dev_alloc_handle(context
->ctx_dev
);
842 mem
= malloc(sizeof(*mem
), M_PS3GPU
, M_WAITOK
| M_ZERO
);
845 goto free_control_memory_map
;
848 mem
->m_context
= context
;
850 mem
->m_type
= PS3GPU_MEMORY_TYPE_REGISTER
;
851 mem
->m_size
= context
->ctx_driver_info_size
;
853 mem
->m_paddr
= context
->ctx_driver_info_paddr
;
854 mem
->m_vaddr
= context
->ctx_driver_info_vaddr
;
856 context
->ctx_driver_info_mem
= mem
;
858 driver_info_mmap
= malloc(sizeof(*driver_info_mmap
), M_PS3GPU
,
860 if (!driver_info_mmap
) {
862 goto free_driver_info_memory
;
865 driver_info_mmap
->mm_mem
= mem
;
866 driver_info_mmap
->mm_handle
= ps3gpu_dev_alloc_handle(context
->ctx_dev
);
868 mem
= malloc(sizeof(*mem
), M_PS3GPU
, M_WAITOK
| M_ZERO
);
871 goto free_driver_info_memory_map
;
874 mem
->m_context
= context
;
876 mem
->m_type
= PS3GPU_MEMORY_TYPE_REGISTER
;
877 mem
->m_size
= context
->ctx_reports_size
;
879 mem
->m_paddr
= context
->ctx_reports_paddr
;
880 mem
->m_vaddr
= context
->ctx_reports_vaddr
;
882 context
->ctx_reports_mem
= mem
;
884 reports_mmap
= malloc(sizeof(*reports_mmap
), M_PS3GPU
,
888 goto free_reports_memory
;
891 reports_mmap
->mm_mem
= mem
;
892 reports_mmap
->mm_handle
= ps3gpu_dev_alloc_handle(context
->ctx_dev
);
894 sx_xlock(&context
->ctx_dev
->d_lock
);
895 TAILQ_INSERT_TAIL(&context
->ctx_dev
->d_mmap_queue
, control_mmap
, mm_queue
);
896 TAILQ_INSERT_TAIL(&context
->ctx_dev
->d_mmap_queue
, driver_info_mmap
, mm_queue
);
897 TAILQ_INSERT_TAIL(&context
->ctx_dev
->d_mmap_queue
, reports_mmap
, mm_queue
);
898 sx_xunlock(&context
->ctx_dev
->d_lock
);
900 sx_xlock(&user
->u_lock
);
901 TAILQ_INSERT_TAIL(&user
->u_context_queue
, context
, ctx_user_queue
);
902 sx_xunlock(&user
->u_lock
);
904 req
->context_id
= context
->ctx_id
;
905 req
->control_handle
= control_mmap
->mm_handle
;
906 req
->control_size
= control_mmap
->mm_mem
->m_size
;
907 req
->driver_info_handle
= driver_info_mmap
->mm_handle
;
908 req
->driver_info_size
= driver_info_mmap
->mm_mem
->m_size
;
909 req
->reports_handle
= reports_mmap
->mm_handle
;
910 req
->reports_size
= reports_mmap
->mm_mem
->m_size
;
916 free(context
->ctx_reports_mem
, M_PS3GPU
);
918 free_driver_info_memory_map
:
920 ps3gpu_dev_free_handle(context
->ctx_dev
, driver_info_mmap
->mm_handle
);
921 free(driver_info_mmap
, M_PS3GPU
);
923 free_driver_info_memory
:
925 free(context
->ctx_driver_info_mem
, M_PS3GPU
);
927 free_control_memory_map
:
929 ps3gpu_dev_free_handle(context
->ctx_dev
, control_mmap
->mm_handle
);
930 free(control_mmap
, M_PS3GPU
);
934 free(context
->ctx_control_mem
, M_PS3GPU
);
938 ps3gpu_context_free(context
);
944 ps3gpu_ctl_context_free(struct ps3gpu_user
*user
,
945 struct ps3gpu_ctl_context_free
*req
)
947 struct ps3gpu_context
*context
;
948 struct ps3gpu_memory_map
*mmap
, *mmap_temp
;
950 KASSERT(user
!= NULL
, ("invalid user"));
951 KASSERT(req
!= NULL
, ("invalid request"));
953 context
= ps3gpu_user_get_context(user
, req
->context_id
);
957 sx_xlock(&user
->u_lock
);
958 TAILQ_REMOVE(&user
->u_context_queue
, context
, ctx_user_queue
);
959 sx_xunlock(&user
->u_lock
);
961 sx_xlock(&context
->ctx_dev
->d_lock
);
963 TAILQ_FOREACH_SAFE(mmap
, &context
->ctx_dev
->d_mmap_queue
, mm_queue
, mmap_temp
) {
964 if (mmap
->mm_mem
->m_context
== context
) {
965 TAILQ_REMOVE(&context
->ctx_dev
->d_mmap_queue
, mmap
, mm_queue
);
966 free_unr(context
->ctx_dev
->d_mmap_unrhdr
,
967 mmap
->mm_handle
>> PS3GPU_MEMORY_MAP_HANDLE_SHIFT
);
968 free(mmap
, M_PS3GPU
);
972 sx_xunlock(&context
->ctx_dev
->d_lock
);
974 free(context
->ctx_control_mem
, M_PS3GPU
);
975 free(context
->ctx_driver_info_mem
, M_PS3GPU
);
976 free(context
->ctx_reports_mem
, M_PS3GPU
);
978 ps3gpu_context_free(context
);
984 ps3gpu_ctl_memory_allocate(struct ps3gpu_user
*user
,
985 struct ps3gpu_ctl_memory_allocate
*req
)
987 struct ps3gpu_context
*context
;
988 struct ps3gpu_memory
*mem
;
989 struct ps3gpu_memory_map
*mmap
;
993 KASSERT(user
!= NULL
, ("invalid user"));
994 KASSERT(req
!= NULL
, ("invalid request"));
997 case PS3GPU_CTL_MEMORY_TYPE_VIDEO
:
998 type
= PS3GPU_MEMORY_TYPE_VIDEO
;
1000 case PS3GPU_CTL_MEMORY_TYPE_GART
:
1001 type
= PS3GPU_MEMORY_TYPE_GART
;
1007 if (req
->size
% PAGE_SIZE
)
1010 if (req
->align
< PAGE_SHIFT
)
1013 context
= ps3gpu_user_get_context(user
, req
->context_id
);
1017 err
= ps3gpu_memory_allocate(context
, type
, req
->size
, req
->align
,
1022 mmap
= malloc(sizeof(*mmap
), M_PS3GPU
, M_WAITOK
| M_ZERO
);
1024 ps3gpu_memory_free(mem
);
1029 mmap
->mm_handle
= ps3gpu_dev_alloc_handle(context
->ctx_dev
);
1031 sx_xlock(&context
->ctx_dev
->d_lock
);
1032 TAILQ_INSERT_TAIL(&context
->ctx_dev
->d_mmap_queue
, mmap
, mm_queue
);
1033 sx_xunlock(&context
->ctx_dev
->d_lock
);
1035 req
->handle
= mmap
->mm_handle
;
1036 req
->gpu_addr
= mmap
->mm_mem
->m_gaddr
;
1042 ps3gpu_ctl_memory_free(struct ps3gpu_user
*user
,
1043 struct ps3gpu_ctl_memory_free
*req
)
1045 struct ps3gpu_context
*context
;
1046 struct ps3gpu_memory
*mem
;
1047 struct ps3gpu_memory_map
*mmap
;
1049 KASSERT(user
!= NULL
, ("invalid user"));
1050 KASSERT(req
!= NULL
, ("invalid request"));
1052 mmap
= ps3gpu_dev_get_mmap(ps3gpu_dev
, req
->handle
);
1057 context
= mem
->m_context
;
1059 KASSERT(context
!= NULL
, ("invalid context"));
1061 sx_xlock(&context
->ctx_dev
->d_lock
);
1062 TAILQ_REMOVE(&context
->ctx_dev
->d_mmap_queue
, mmap
, mm_queue
);
1063 sx_xunlock(&context
->ctx_dev
->d_lock
);
1065 ps3gpu_dev_free_handle(context
->ctx_dev
, mmap
->mm_handle
);
1067 free(mmap
, M_PS3GPU
);
1069 ps3gpu_memory_free(mem
);
1075 ps3gpu_ctl_setup_control(struct ps3gpu_user
*user
,
1076 struct ps3gpu_ctl_setup_control
*req
)
1078 struct ps3gpu_context
*put_context
, *get_context
;
1079 struct ps3gpu_memory
*put_mem
, *get_mem
;
1080 struct ps3gpu_memory_map
*put_mmap
, *get_mmap
;
1081 unsigned long put_handle
, put_offset
, get_handle
, get_offset
;
1084 KASSERT(user
!= NULL
, ("invalid user"));
1085 KASSERT(req
!= NULL
, ("invalid request"));
1087 put_handle
= PS3GPU_MEMORY_MAP_HANDLE(req
->put
);
1088 put_offset
= PS3GPU_MEMORY_MAP_OFFSET(req
->put
);
1090 put_mmap
= ps3gpu_dev_get_mmap(ps3gpu_dev
, put_handle
);
1094 put_mem
= put_mmap
->mm_mem
;
1095 put_context
= put_mem
->m_context
;
1097 KASSERT(put_context
!= NULL
, ("invalid context"));
1099 get_handle
= PS3GPU_MEMORY_MAP_HANDLE(req
->get
);
1100 get_offset
= PS3GPU_MEMORY_MAP_OFFSET(req
->get
);
1102 get_mmap
= ps3gpu_dev_get_mmap(ps3gpu_dev
, get_handle
);
1106 get_mem
= get_mmap
->mm_mem
;
1107 get_context
= get_mem
->m_context
;
1109 KASSERT(get_context
!= NULL
, ("invalid context"));
1111 if (put_context
->ctx_id
!= req
->context_id
||
1112 put_context
!= get_context
)
1115 err
= ps3gpu_setup_control(put_context
, put_mem
->m_gaddr
+ put_offset
,
1116 get_mem
->m_gaddr
+ get_offset
, req
->ref
);
1124 ps3gpu_ctl_set_flip_mode(struct ps3gpu_user
*user
,
1125 struct ps3gpu_ctl_set_flip_mode
*req
)
1127 struct ps3gpu_context
*context
;
1131 KASSERT(user
!= NULL
, ("invalid user"));
1132 KASSERT(req
!= NULL
, ("invalid request"));
1134 switch (req
->head
) {
1135 case PS3GPU_CTL_HEAD_A
:
1136 head
= PS3GPU_HEAD_A
;
1138 case PS3GPU_CTL_HEAD_B
:
1139 head
= PS3GPU_HEAD_B
;
1145 switch (req
->mode
) {
1146 case PS3GPU_CTL_FLIP_MODE_HSYNC
:
1147 mode
= PS3GPU_FLIP_MODE_HSYNC
;
1149 case PS3GPU_CTL_FLIP_MODE_VSYNC
:
1150 mode
= PS3GPU_FLIP_MODE_VSYNC
;
1156 context
= ps3gpu_user_get_context(user
, req
->context_id
);
1160 err
= ps3gpu_set_flip_mode(context
, head
, mode
);
1168 ps3gpu_ctl_reset_flip_status(struct ps3gpu_user
*user
,
1169 struct ps3gpu_ctl_reset_flip_status
*req
)
1171 struct ps3gpu_context
*context
;
1175 KASSERT(user
!= NULL
, ("invalid user"));
1176 KASSERT(req
!= NULL
, ("invalid request"));
1178 switch (req
->head
) {
1179 case PS3GPU_CTL_HEAD_A
:
1180 head
= PS3GPU_HEAD_A
;
1182 case PS3GPU_CTL_HEAD_B
:
1183 head
= PS3GPU_HEAD_B
;
1189 context
= ps3gpu_user_get_context(user
, req
->context_id
);
1193 err
= ps3gpu_reset_flip_status(context
, head
);
1201 ps3gpu_ctl_flip(struct ps3gpu_user
*user
,
1202 struct ps3gpu_ctl_flip
*req
)
1204 struct ps3gpu_context
*context
;
1205 struct ps3gpu_memory
*mem
;
1206 struct ps3gpu_memory_map
*mmap
;
1208 unsigned long handle
, offset
;
1211 KASSERT(user
!= NULL
, ("invalid user"));
1212 KASSERT(req
!= NULL
, ("invalid request"));
1214 switch (req
->head
) {
1215 case PS3GPU_CTL_HEAD_A
:
1216 head
= PS3GPU_HEAD_A
;
1218 case PS3GPU_CTL_HEAD_B
:
1219 head
= PS3GPU_HEAD_B
;
1225 handle
= PS3GPU_MEMORY_MAP_HANDLE(req
->offset
);
1226 offset
= PS3GPU_MEMORY_MAP_OFFSET(req
->offset
);
1228 mmap
= ps3gpu_dev_get_mmap(ps3gpu_dev
, handle
);
1233 context
= mem
->m_context
;
1235 KASSERT(context
!= NULL
, ("invalid context"));
1237 if (req
->context_id
!= context
->ctx_id
)
1240 err
= ps3gpu_flip(context
, head
, mem
->m_start
+ offset
);
1248 ps3gpu_ctl_display_buffer_set(struct ps3gpu_user
*user
,
1249 struct ps3gpu_ctl_display_buffer_set
*req
)
1251 struct ps3gpu_context
*context
;
1252 struct ps3gpu_memory
*mem
;
1253 struct ps3gpu_memory_map
*mmap
;
1254 unsigned long handle
, offset
;
1257 KASSERT(user
!= NULL
, ("invalid user"));
1258 KASSERT(req
!= NULL
, ("invalid request"));
1260 if (req
->buffer_id
< 0 ||
1261 req
->buffer_id
>= PS3GPU_CONTEXT_MAX_DISPLAY_BUFFERS
)
1264 handle
= PS3GPU_MEMORY_MAP_HANDLE(req
->offset
);
1265 offset
= PS3GPU_MEMORY_MAP_OFFSET(req
->offset
);
1267 mmap
= ps3gpu_dev_get_mmap(ps3gpu_dev
, handle
);
1272 context
= mem
->m_context
;
1274 KASSERT(context
!= NULL
, ("invalid context"));
1276 if (req
->context_id
!= context
->ctx_id
)
1279 err
= ps3gpu_display_buffer_set(context
, req
->buffer_id
,
1280 req
->width
, req
->height
, req
->pitch
, mem
->m_gaddr
+ offset
);
1288 ps3gpu_ctl_display_buffer_unset(struct ps3gpu_user
*user
,
1289 struct ps3gpu_ctl_display_buffer_unset
*req
)
1291 struct ps3gpu_context
*context
;
1294 KASSERT(user
!= NULL
, ("invalid user"));
1295 KASSERT(req
!= NULL
, ("invalid request"));
1297 if (req
->buffer_id
< 0 ||
1298 req
->buffer_id
>= PS3GPU_CONTEXT_MAX_DISPLAY_BUFFERS
)
1301 context
= ps3gpu_user_get_context(user
, req
->context_id
);
1305 err
= ps3gpu_display_buffer_unset(context
, req
->buffer_id
);
1313 ps3gpu_ctl_display_buffer_flip(struct ps3gpu_user
*user
,
1314 struct ps3gpu_ctl_display_buffer_flip
*req
)
1316 struct ps3gpu_context
*context
;
1320 KASSERT(user
!= NULL
, ("invalid user"));
1321 KASSERT(req
!= NULL
, ("invalid request"));
1323 switch (req
->head
) {
1324 case PS3GPU_CTL_HEAD_A
:
1325 head
= PS3GPU_HEAD_A
;
1327 case PS3GPU_CTL_HEAD_B
:
1328 head
= PS3GPU_HEAD_B
;
1334 if (req
->buffer_id
< 0 ||
1335 req
->buffer_id
>= PS3GPU_CONTEXT_MAX_DISPLAY_BUFFERS
)
1338 context
= ps3gpu_user_get_context(user
, req
->context_id
);
1342 if (req
->context_id
!= context
->ctx_id
)
1345 err
= ps3gpu_display_buffer_flip(context
, head
, req
->buffer_id
);
1353 ps3gpu_ctl_tile_set(struct ps3gpu_user
*user
,
1354 struct ps3gpu_ctl_tile_set
*req
)
1356 struct ps3gpu_context
*context
;
1357 struct ps3gpu_memory
*mem
;
1358 struct ps3gpu_memory_map
*mmap
;
1359 unsigned long handle
, offset
;
1363 KASSERT(user
!= NULL
, ("invalid user"));
1364 KASSERT(req
!= NULL
, ("invalid request"));
1366 switch (req
->cmp_mode
) {
1367 case PS3GPU_CTL_TILE_CMP_MODE_NONE
:
1368 cmp_mode
= PS3GPU_TILE_CMP_MODE_NONE
;
1370 case PS3GPU_CTL_TILE_CMP_MODE_C32_2X1
:
1371 cmp_mode
= PS3GPU_TILE_CMP_MODE_C32_2X1
;
1373 case PS3GPU_CTL_TILE_CMP_MODE_C32_2X2
:
1374 cmp_mode
= PS3GPU_TILE_CMP_MODE_C32_2X2
;
1376 case PS3GPU_CTL_TILE_CMP_MODE_Z32_SEP
:
1377 cmp_mode
= PS3GPU_TILE_CMP_MODE_Z32_SEP
;
1379 case PS3GPU_CTL_TILE_CMP_MODE_Z32_SEP_REG
:
1380 cmp_mode
= PS3GPU_TILE_CMP_MODE_Z32_SEP_REG
;
1382 case PS3GPU_CTL_TILE_CMP_MODE_Z32_SEP_DIAG
:
1383 cmp_mode
= PS3GPU_TILE_CMP_MODE_Z32_SEP_DIAG
;
1385 case PS3GPU_CTL_TILE_CMP_MODE_Z32_SEP_ROT
:
1386 cmp_mode
= PS3GPU_TILE_CMP_MODE_Z32_SEP_ROT
;
1392 if (req
->tile_id
< 0 ||
1393 req
->tile_id
>= PS3GPU_CONTEXT_MAX_TILES
)
1396 handle
= PS3GPU_MEMORY_MAP_HANDLE(req
->offset
);
1397 offset
= PS3GPU_MEMORY_MAP_OFFSET(req
->offset
);
1399 mmap
= ps3gpu_dev_get_mmap(ps3gpu_dev
, handle
);
1404 context
= mem
->m_context
;
1406 KASSERT(context
[0] != NULL
, ("invalid context"));
1408 if (req
->context_id
!= context
->ctx_id
)
1411 if (mem
->m_type
!= PS3GPU_MEMORY_TYPE_VIDEO
&&
1412 mem
->m_type
!= PS3GPU_MEMORY_TYPE_GART
)
1415 err
= ps3gpu_tile_set(context
, req
->tile_id
,
1416 mem
->m_type
, req
->size
, req
->pitch
, cmp_mode
, req
->bank
,
1417 req
->base
, mem
->m_start
+ offset
);
1425 ps3gpu_ctl_tile_unset(struct ps3gpu_user
*user
,
1426 struct ps3gpu_ctl_tile_unset
*req
)
1428 struct ps3gpu_context
*context
;
1429 struct ps3gpu_memory
*mem
;
1430 struct ps3gpu_memory_map
*mmap
;
1431 unsigned long handle
, offset
;
1434 KASSERT(user
!= NULL
, ("invalid user"));
1435 KASSERT(req
!= NULL
, ("invalid request"));
1437 if (req
->tile_id
< 0 ||
1438 req
->tile_id
>= PS3GPU_CONTEXT_MAX_TILES
)
1441 handle
= PS3GPU_MEMORY_MAP_HANDLE(req
->offset
);
1442 offset
= PS3GPU_MEMORY_MAP_OFFSET(req
->offset
);
1444 mmap
= ps3gpu_dev_get_mmap(ps3gpu_dev
, handle
);
1449 context
= mem
->m_context
;
1451 KASSERT(context
!= NULL
, ("invalid context"));
1453 if (req
->context_id
!= context
->ctx_id
)
1456 if (mem
->m_type
!= PS3GPU_MEMORY_TYPE_VIDEO
&&
1457 mem
->m_type
!= PS3GPU_MEMORY_TYPE_GART
)
1460 err
= ps3gpu_tile_unset(context
, req
->tile_id
, mem
->m_type
,
1461 req
->bank
, mem
->m_start
+ offset
);
1469 ps3gpu_ctl_cursor_initialize(struct ps3gpu_user
*user
,
1470 struct ps3gpu_ctl_cursor_initialize
*req
)
1472 struct ps3gpu_context
*context
;
1476 KASSERT(user
!= NULL
, ("invalid user"));
1477 KASSERT(req
!= NULL
, ("invalid request"));
1479 switch (req
->head
) {
1480 case PS3GPU_CTL_HEAD_A
:
1481 head
= PS3GPU_HEAD_A
;
1483 case PS3GPU_CTL_HEAD_B
:
1484 head
= PS3GPU_HEAD_B
;
1490 context
= ps3gpu_user_get_context(user
, req
->context_id
);
1494 err
= ps3gpu_cursor_initialize(context
, head
);
1502 ps3gpu_ctl_cursor_set_image(struct ps3gpu_user
*user
,
1503 struct ps3gpu_ctl_cursor_set_image
*req
)
1505 struct ps3gpu_context
*context
;
1506 struct ps3gpu_memory
*mem
;
1507 struct ps3gpu_memory_map
*mmap
;
1509 unsigned long handle
, offset
;
1512 KASSERT(user
!= NULL
, ("invalid user"));
1513 KASSERT(req
!= NULL
, ("invalid request"));
1515 switch (req
->head
) {
1516 case PS3GPU_CTL_HEAD_A
:
1517 head
= PS3GPU_HEAD_A
;
1519 case PS3GPU_CTL_HEAD_B
:
1520 head
= PS3GPU_HEAD_B
;
1526 handle
= PS3GPU_MEMORY_MAP_HANDLE(req
->offset
);
1527 offset
= PS3GPU_MEMORY_MAP_OFFSET(req
->offset
);
1529 mmap
= ps3gpu_dev_get_mmap(ps3gpu_dev
, handle
);
1534 context
= mem
->m_context
;
1536 KASSERT(context
!= NULL
, ("invalid context"));
1538 if (req
->context_id
!= context
->ctx_id
)
1541 err
= ps3gpu_cursor_set_image(context
, head
, mem
->m_start
+ offset
);
1549 ps3gpu_ctl_cursor_set_position(struct ps3gpu_user
*user
,
1550 struct ps3gpu_ctl_cursor_set_position
*req
)
1552 struct ps3gpu_context
*context
;
1556 KASSERT(user
!= NULL
, ("invalid user"));
1557 KASSERT(req
!= NULL
, ("invalid request"));
1559 switch (req
->head
) {
1560 case PS3GPU_CTL_HEAD_A
:
1561 head
= PS3GPU_HEAD_A
;
1563 case PS3GPU_CTL_HEAD_B
:
1564 head
= PS3GPU_HEAD_B
;
1570 context
= ps3gpu_user_get_context(user
, req
->context_id
);
1574 err
= ps3gpu_cursor_set_position(context
, head
, req
->x
, req
->y
);
1582 ps3gpu_ctl_cursor_enable(struct ps3gpu_user
*user
,
1583 struct ps3gpu_ctl_cursor_enable
*req
)
1585 struct ps3gpu_context
*context
;
1589 KASSERT(user
!= NULL
, ("invalid user"));
1590 KASSERT(req
!= NULL
, ("invalid request"));
1592 switch (req
->head
) {
1593 case PS3GPU_CTL_HEAD_A
:
1594 head
= PS3GPU_HEAD_A
;
1596 case PS3GPU_CTL_HEAD_B
:
1597 head
= PS3GPU_HEAD_B
;
1603 context
= ps3gpu_user_get_context(user
, req
->context_id
);
1607 err
= ps3gpu_cursor_enable(context
, head
, req
->enable
);
1615 ps3gpu_user_dtr(void *data
)
1617 struct ps3gpu_user
*user
= data
;
1618 struct ps3gpu_context
*context
;
1619 struct ps3gpu_memory_map
*mmap
;
1621 KASSERT(user
!= NULL
, ("invalid user"));
1623 sx_xlock(&user
->u_lock
);
1625 sx_xlock(&ps3gpu_dev
->d_lock
);
1627 while ((mmap
= TAILQ_FIRST(&ps3gpu_dev
->d_mmap_queue
))) {
1628 TAILQ_REMOVE(&ps3gpu_dev
->d_mmap_queue
, mmap
, mm_queue
);
1629 free_unr(ps3gpu_dev
->d_mmap_unrhdr
,
1630 mmap
->mm_handle
>> PS3GPU_MEMORY_MAP_HANDLE_SHIFT
);
1631 free(mmap
, M_PS3GPU
);
1634 sx_xunlock(&ps3gpu_dev
->d_lock
);
1636 while ((context
= TAILQ_FIRST(&user
->u_context_queue
))) {
1637 TAILQ_REMOVE(&user
->u_context_queue
, context
, ctx_user_queue
);
1638 free(context
->ctx_control_mem
, M_PS3GPU
);
1639 free(context
->ctx_driver_info_mem
, M_PS3GPU
);
1640 free(context
->ctx_reports_mem
, M_PS3GPU
);
1641 ps3gpu_context_free(context
);
1644 sx_xunlock(&user
->u_lock
);
1646 sx_destroy(&user
->u_lock
);
1648 free(user
, M_PS3GPU
);
1652 ps3gpu_open(struct cdev
*dev
, int oflags
, int fmt
,
1655 struct ps3gpu_user
*user
;
1658 if ((oflags
& (FREAD
| FWRITE
)) != (FREAD
| FWRITE
))
1661 user
= malloc(sizeof(*user
), M_PS3GPU
, M_WAITOK
| M_ZERO
);
1665 sx_init(&user
->u_lock
, "ps3gpu_user");
1667 TAILQ_INIT(&user
->u_context_queue
);
1669 err
= devfs_set_cdevpriv(user
, ps3gpu_user_dtr
);
1671 sx_destroy(&user
->u_lock
);
1672 free(user
, M_PS3GPU
);
1680 ps3gpu_mmap(struct cdev
*dev
, vm_ooffset_t offset
,
1681 vm_paddr_t
*paddr
, int nprot
, vm_memattr_t
*memattr
)
1683 struct ps3gpu_user
*user
= NULL
;
1684 struct ps3gpu_context
*context
;
1685 struct ps3gpu_memory
*mem
;
1686 struct ps3gpu_memory_map
*mmap
;
1687 unsigned long handle
;
1689 if (nprot
& PROT_EXEC
)
1692 devfs_get_cdevpriv((void **) &user
);
1694 handle
= PS3GPU_MEMORY_MAP_HANDLE(offset
);
1695 offset
= PS3GPU_MEMORY_MAP_OFFSET(offset
);
1697 mmap
= ps3gpu_dev_get_mmap(ps3gpu_dev
, handle
);
1702 context
= mem
->m_context
;
1704 KASSERT(context
!= NULL
, ("invalid context"));
1706 if (user
&& context
->ctx_user
!= user
)
1709 if (offset
>= mem
->m_size
)
1712 switch (mem
->m_type
) {
1713 case PS3GPU_MEMORY_TYPE_VIDEO
:
1714 *paddr
= mem
->m_paddr
+ offset
;
1715 *memattr
= VM_MEMATTR_WRITE_COMBINING
;
1717 case PS3GPU_MEMORY_TYPE_GART
:
1718 *paddr
= vtophys(mem
->m_vaddr
+ offset
);
1719 *memattr
= VM_MEMATTR_DEFAULT
;
1721 case PS3GPU_MEMORY_TYPE_REGISTER
:
1722 *paddr
= mem
->m_paddr
+ offset
;
1723 *memattr
= VM_MEMATTR_UNCACHEABLE
;
1731 ps3gpu_ioctl(struct cdev
*dev
, u_long cmd
, caddr_t data
,
1732 int fflag
, struct thread
*td
)
1734 struct ps3gpu_user
*user
;
1737 err
= devfs_get_cdevpriv((void **) &user
);
1742 case PS3GPU_CTL_CONTEXT_ALLOCATE
:
1744 struct ps3gpu_ctl_context_allocate
*req
=
1745 (struct ps3gpu_ctl_context_allocate
*) data
;
1747 err
= ps3gpu_ctl_context_allocate(user
, req
);
1750 case PS3GPU_CTL_CONTEXT_FREE
:
1752 struct ps3gpu_ctl_context_free
*req
=
1753 (struct ps3gpu_ctl_context_free
*) data
;
1755 err
= ps3gpu_ctl_context_free(user
, req
);
1758 case PS3GPU_CTL_MEMORY_ALLOCATE
:
1760 struct ps3gpu_ctl_memory_allocate
*req
=
1761 (struct ps3gpu_ctl_memory_allocate
*) data
;
1763 err
= ps3gpu_ctl_memory_allocate(user
, req
);
1766 case PS3GPU_CTL_MEMORY_FREE
:
1768 struct ps3gpu_ctl_memory_free
*req
=
1769 (struct ps3gpu_ctl_memory_free
*) data
;
1771 err
= ps3gpu_ctl_memory_free(user
, req
);
1774 case PS3GPU_CTL_SETUP_CONTROL
:
1776 struct ps3gpu_ctl_setup_control
*req
=
1777 (struct ps3gpu_ctl_setup_control
*) data
;
1779 err
= ps3gpu_ctl_setup_control(user
, req
);
1782 case PS3GPU_CTL_SET_FLIP_MODE
:
1784 struct ps3gpu_ctl_set_flip_mode
*req
=
1785 (struct ps3gpu_ctl_set_flip_mode
*) data
;
1787 err
= ps3gpu_ctl_set_flip_mode(user
, req
);
1790 case PS3GPU_CTL_RESET_FLIP_STATUS
:
1792 struct ps3gpu_ctl_reset_flip_status
*req
=
1793 (struct ps3gpu_ctl_reset_flip_status
*) data
;
1795 err
= ps3gpu_ctl_reset_flip_status(user
, req
);
1798 case PS3GPU_CTL_FLIP
:
1800 struct ps3gpu_ctl_flip
*req
=
1801 (struct ps3gpu_ctl_flip
*) data
;
1803 err
= ps3gpu_ctl_flip(user
, req
);
1806 case PS3GPU_CTL_DISPLAY_BUFFER_SET
:
1808 struct ps3gpu_ctl_display_buffer_set
*req
=
1809 (struct ps3gpu_ctl_display_buffer_set
*) data
;
1811 err
= ps3gpu_ctl_display_buffer_set(user
, req
);
1814 case PS3GPU_CTL_DISPLAY_BUFFER_UNSET
:
1816 struct ps3gpu_ctl_display_buffer_unset
*req
=
1817 (struct ps3gpu_ctl_display_buffer_unset
*) data
;
1819 err
= ps3gpu_ctl_display_buffer_unset(user
, req
);
1822 case PS3GPU_CTL_DISPLAY_BUFFER_FLIP
:
1824 struct ps3gpu_ctl_display_buffer_flip
*req
=
1825 (struct ps3gpu_ctl_display_buffer_flip
*) data
;
1827 err
= ps3gpu_ctl_display_buffer_flip(user
, req
);
1830 case PS3GPU_CTL_TILE_SET
:
1832 struct ps3gpu_ctl_tile_set
*req
=
1833 (struct ps3gpu_ctl_tile_set
*) data
;
1835 err
= ps3gpu_ctl_tile_set(user
, req
);
1838 case PS3GPU_CTL_TILE_UNSET
:
1840 struct ps3gpu_ctl_tile_unset
*req
=
1841 (struct ps3gpu_ctl_tile_unset
*) data
;
1843 err
= ps3gpu_ctl_tile_unset(user
, req
);
1846 case PS3GPU_CTL_CURSOR_INITIALIZE
:
1848 struct ps3gpu_ctl_cursor_initialize
*req
=
1849 (struct ps3gpu_ctl_cursor_initialize
*) data
;
1851 err
= ps3gpu_ctl_cursor_initialize(user
, req
);
1854 case PS3GPU_CTL_CURSOR_SET_IMAGE
:
1856 struct ps3gpu_ctl_cursor_set_image
*req
=
1857 (struct ps3gpu_ctl_cursor_set_image
*) data
;
1859 err
= ps3gpu_ctl_cursor_set_image(user
, req
);
1862 case PS3GPU_CTL_CURSOR_SET_POSITION
:
1864 struct ps3gpu_ctl_cursor_set_position
*req
=
1865 (struct ps3gpu_ctl_cursor_set_position
*) data
;
1867 err
= ps3gpu_ctl_cursor_set_position(user
, req
);
1870 case PS3GPU_CTL_CURSOR_ENABLE
:
1872 struct ps3gpu_ctl_cursor_enable
*req
=
1873 (struct ps3gpu_ctl_cursor_enable
*) data
;
1875 err
= ps3gpu_ctl_cursor_enable(user
, req
);
1887 ps3gpu_device_init(struct ps3gpu_device
**pdev
)
1889 struct ps3gpu_device
*dev
;
1891 dev
= malloc(sizeof(*dev
), M_PS3GPU
, M_WAITOK
| M_ZERO
);
1895 sx_init(&dev
->d_lock
, "ps3gpu_device");
1897 TAILQ_INIT(&dev
->d_mmap_queue
);
1899 dev
->d_mmap_unrhdr
= new_unrhdr(1,
1900 ((1 << PS3GPU_MEMORY_MAP_HANDLE_BITS
) - 1), NULL
);
1901 if (!dev
->d_mmap_unrhdr
) {
1902 sx_destroy(&dev
->d_lock
);
1903 free(dev
, M_PS3GPU
);
1913 ps3gpu_device_fini(struct ps3gpu_device
*dev
)
1917 for (i
= 0; i
< PS3GPU_DEVICE_MAX_CONTEXTS
; i
++) {
1918 if (dev
->d_context
[i
])
1919 ps3gpu_context_free(dev
->d_context
[i
]);
1922 delete_unrhdr(dev
->d_mmap_unrhdr
);
1924 sx_destroy(&dev
->d_lock
);
1926 free(dev
, M_PS3GPU
);
1929 static struct ps3gpu_memory_map
*
1930 ps3gpu_dev_get_mmap(struct ps3gpu_device
*dev
,
1931 unsigned long handle
)
1933 struct ps3gpu_memory_map
*mmap
;
1935 sx_xlock(&dev
->d_lock
);
1937 TAILQ_FOREACH(mmap
, &dev
->d_mmap_queue
, mm_queue
) {
1938 if (mmap
->mm_handle
== handle
) {
1939 sx_xunlock(&dev
->d_lock
);
1944 sx_xunlock(&dev
->d_lock
);
1949 static unsigned long
1950 ps3gpu_dev_alloc_handle(struct ps3gpu_device
*dev
)
1952 unsigned long handle
;
1954 sx_xlock(&dev
->d_lock
);
1956 handle
= (unsigned long) alloc_unr(dev
->d_mmap_unrhdr
) <<
1957 PS3GPU_MEMORY_MAP_HANDLE_SHIFT
;
1959 sx_xunlock(&dev
->d_lock
);
1965 ps3gpu_dev_free_handle(struct ps3gpu_device
*dev
,
1966 unsigned long handle
)
1968 sx_xlock(&dev
->d_lock
);
1970 free_unr(dev
->d_mmap_unrhdr
,
1971 handle
>> PS3GPU_MEMORY_MAP_HANDLE_SHIFT
);
1973 sx_xunlock(&dev
->d_lock
);
1978 ps3gpu_modevent(module_t mod
, int type
, void *arg
)
1984 /* Create GPU device */
1986 err
= ps3gpu_device_init(&ps3gpu_dev
);
1988 printf("ps3gpu: Failed to create GPU device\n");
1992 /* Create char device */
1994 ps3gpu_cdev
= make_dev(&ps3gpu_cdevsw
, 0,
1995 UID_ROOT
, GID_WHEEL
, 0600, "ps3gpu");
1997 printf("ps3gpu: Failed to create /dev/ps3gpu\n");
1998 ps3gpu_device_fini(ps3gpu_dev
);
2003 /* Destroy char device */
2006 destroy_dev(ps3gpu_cdev
);
2009 ps3gpu_device_fini(ps3gpu_dev
);
2014 return (EOPNOTSUPP
);
2020 DEV_MODULE(ps3gpu
, ps3gpu_modevent
, NULL
);
2021 MODULE_VERSION(ps3gpu
, 1);