4 * DSP-BIOS Bridge driver support functions for TI OMAP processors.
6 * Common DSP API functions, also includes the wrapper
7 * functions called directly by the DeviceIOControl interface.
9 * Copyright (C) 2005-2006 Texas Instruments, Inc.
11 * This package is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
15 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19 #include <linux/types.h>
21 /* ----------------------------------- Host OS */
22 #include <dspbridge/host_os.h>
24 /* ----------------------------------- DSP/BIOS Bridge */
25 #include <dspbridge/dbdefs.h>
27 /* ----------------------------------- Trace & Debug */
28 #include <dspbridge/dbc.h>
30 /* ----------------------------------- OS Adaptation Layer */
31 #include <dspbridge/ntfy.h>
33 /* ----------------------------------- Platform Manager */
34 #include <dspbridge/chnl.h>
35 #include <dspbridge/dev.h>
36 #include <dspbridge/drv.h>
38 #include <dspbridge/proc.h>
39 #include <dspbridge/strm.h>
41 /* ----------------------------------- Resource Manager */
42 #include <dspbridge/disp.h>
43 #include <dspbridge/mgr.h>
44 #include <dspbridge/node.h>
45 #include <dspbridge/rmm.h>
47 /* ----------------------------------- Others */
48 #include <dspbridge/msg.h>
49 #include <dspbridge/cmm.h>
50 #include <dspbridge/io.h>
52 /* ----------------------------------- This */
53 #include <dspbridge/dspapi.h>
54 #include <dspbridge/dbdcd.h>
56 #include <dspbridge/resourcecleanup.h>
58 /* ----------------------------------- Defines, Data Structures, Typedefs */
59 #define MAX_TRACEBUFLEN 255
60 #define MAX_LOADARGS 16
62 #define MAX_STREAMS 16
65 /* Used to get dspbridge ioctl table */
66 #define DB_GET_IOC_TABLE(cmd) (DB_GET_MODULE(cmd) >> DB_MODULE_SHIFT)
68 /* Device IOCtl function pointer */
70 u32(*fxn
) (union trapped_args
*args
, void *pr_ctxt
);
74 /* ----------------------------------- Globals */
75 static u32 api_c_refs
;
79 * The order of these functions MUST be the same as the order of the command
80 * numbers defined in dspapi-ioctl.h This is how an IOCTL number in user mode
81 * turns into a function call in kernel mode.
84 /* MGR wrapper functions */
85 static struct api_cmd mgr_cmd
[] = {
86 {mgrwrap_enum_node_info
}, /* MGR_ENUMNODE_INFO */
87 {mgrwrap_enum_proc_info
}, /* MGR_ENUMPROC_INFO */
88 {mgrwrap_register_object
}, /* MGR_REGISTEROBJECT */
89 {mgrwrap_unregister_object
}, /* MGR_UNREGISTEROBJECT */
90 {mgrwrap_wait_for_bridge_events
}, /* MGR_WAIT */
91 {mgrwrap_get_process_resources_info
}, /* MGR_GET_PROC_RES */
94 /* PROC wrapper functions */
95 static struct api_cmd proc_cmd
[] = {
96 {procwrap_attach
}, /* PROC_ATTACH */
97 {procwrap_ctrl
}, /* PROC_CTRL */
98 {procwrap_detach
}, /* PROC_DETACH */
99 {procwrap_enum_node_info
}, /* PROC_ENUMNODE */
100 {procwrap_enum_resources
}, /* PROC_ENUMRESOURCES */
101 {procwrap_get_state
}, /* PROC_GET_STATE */
102 {procwrap_get_trace
}, /* PROC_GET_TRACE */
103 {procwrap_load
}, /* PROC_LOAD */
104 {procwrap_register_notify
}, /* PROC_REGISTERNOTIFY */
105 {procwrap_start
}, /* PROC_START */
106 {procwrap_reserve_memory
}, /* PROC_RSVMEM */
107 {procwrap_un_reserve_memory
}, /* PROC_UNRSVMEM */
108 {procwrap_map
}, /* PROC_MAPMEM */
109 {procwrap_un_map
}, /* PROC_UNMAPMEM */
110 {procwrap_flush_memory
}, /* PROC_FLUSHMEMORY */
111 {procwrap_stop
}, /* PROC_STOP */
112 {procwrap_invalidate_memory
}, /* PROC_INVALIDATEMEMORY */
113 {procwrap_begin_dma
}, /* PROC_BEGINDMA */
114 {procwrap_end_dma
}, /* PROC_ENDDMA */
117 /* NODE wrapper functions */
118 static struct api_cmd node_cmd
[] = {
119 {nodewrap_allocate
}, /* NODE_ALLOCATE */
120 {nodewrap_alloc_msg_buf
}, /* NODE_ALLOCMSGBUF */
121 {nodewrap_change_priority
}, /* NODE_CHANGEPRIORITY */
122 {nodewrap_connect
}, /* NODE_CONNECT */
123 {nodewrap_create
}, /* NODE_CREATE */
124 {nodewrap_delete
}, /* NODE_DELETE */
125 {nodewrap_free_msg_buf
}, /* NODE_FREEMSGBUF */
126 {nodewrap_get_attr
}, /* NODE_GETATTR */
127 {nodewrap_get_message
}, /* NODE_GETMESSAGE */
128 {nodewrap_pause
}, /* NODE_PAUSE */
129 {nodewrap_put_message
}, /* NODE_PUTMESSAGE */
130 {nodewrap_register_notify
}, /* NODE_REGISTERNOTIFY */
131 {nodewrap_run
}, /* NODE_RUN */
132 {nodewrap_terminate
}, /* NODE_TERMINATE */
133 {nodewrap_get_uuid_props
}, /* NODE_GETUUIDPROPS */
136 /* STRM wrapper functions */
137 static struct api_cmd strm_cmd
[] = {
138 {strmwrap_allocate_buffer
}, /* STRM_ALLOCATEBUFFER */
139 {strmwrap_close
}, /* STRM_CLOSE */
140 {strmwrap_free_buffer
}, /* STRM_FREEBUFFER */
141 {strmwrap_get_event_handle
}, /* STRM_GETEVENTHANDLE */
142 {strmwrap_get_info
}, /* STRM_GETINFO */
143 {strmwrap_idle
}, /* STRM_IDLE */
144 {strmwrap_issue
}, /* STRM_ISSUE */
145 {strmwrap_open
}, /* STRM_OPEN */
146 {strmwrap_reclaim
}, /* STRM_RECLAIM */
147 {strmwrap_register_notify
}, /* STRM_REGISTERNOTIFY */
148 {strmwrap_select
}, /* STRM_SELECT */
151 /* CMM wrapper functions */
152 static struct api_cmd cmm_cmd
[] = {
153 {cmmwrap_calloc_buf
}, /* CMM_ALLOCBUF */
154 {cmmwrap_free_buf
}, /* CMM_FREEBUF */
155 {cmmwrap_get_handle
}, /* CMM_GETHANDLE */
156 {cmmwrap_get_info
}, /* CMM_GETINFO */
159 /* Array used to store ioctl table sizes. It can hold up to 8 entries */
160 static u8 size_cmd
[] = {
162 ARRAY_SIZE(proc_cmd
),
163 ARRAY_SIZE(node_cmd
),
164 ARRAY_SIZE(strm_cmd
),
168 static inline void _cp_fm_usr(void *to
, const void __user
* from
,
169 int *err
, unsigned long bytes
)
174 if (unlikely(!from
)) {
179 if (unlikely(copy_from_user(to
, from
, bytes
)))
183 #define CP_FM_USR(to, from, err, n) \
184 _cp_fm_usr(to, from, &(err), (n) * sizeof(*(to)))
186 static inline void _cp_to_usr(void __user
*to
, const void *from
,
187 int *err
, unsigned long bytes
)
197 if (unlikely(copy_to_user(to
, from
, bytes
)))
201 #define CP_TO_USR(to, from, err, n) \
202 _cp_to_usr(to, from, &(err), (n) * sizeof(*(from)))
205 * ======== api_call_dev_ioctl ========
207 * Call the (wrapper) function for the corresponding API IOCTL.
209 inline int api_call_dev_ioctl(u32 cmd
, union trapped_args
*args
,
210 u32
*result
, void *pr_ctxt
)
212 u32(*ioctl_cmd
) (union trapped_args
*args
, void *pr_ctxt
) = NULL
;
215 if (_IOC_TYPE(cmd
) != DB
) {
216 pr_err("%s: Incompatible dspbridge ioctl number\n", __func__
);
220 if (DB_GET_IOC_TABLE(cmd
) > ARRAY_SIZE(size_cmd
)) {
221 pr_err("%s: undefined ioctl module\n", __func__
);
225 /* Check the size of the required cmd table */
227 if (i
> size_cmd
[DB_GET_IOC_TABLE(cmd
)]) {
228 pr_err("%s: requested ioctl %d out of bounds for table %d\n",
229 __func__
, i
, DB_GET_IOC_TABLE(cmd
));
233 switch (DB_GET_MODULE(cmd
)) {
235 ioctl_cmd
= mgr_cmd
[i
].fxn
;
238 ioctl_cmd
= proc_cmd
[i
].fxn
;
241 ioctl_cmd
= node_cmd
[i
].fxn
;
244 ioctl_cmd
= strm_cmd
[i
].fxn
;
247 ioctl_cmd
= cmm_cmd
[i
].fxn
;
252 pr_err("%s: requested ioctl not defined\n", __func__
);
255 *result
= (*ioctl_cmd
) (args
, pr_ctxt
);
265 * ======== api_exit ========
269 DBC_REQUIRE(api_c_refs
> 0);
272 if (api_c_refs
== 0) {
273 /* Release all modules initialized in api_init(). */
287 DBC_ENSURE(api_c_refs
>= 0);
291 * ======== api_init ========
293 * Module initialization used by Bridge API.
298 bool fdrv
, fdev
, fcod
, fchnl
, fmsg
, fio
;
299 bool fmgr
, fproc
, fnode
, fdisp
, fstrm
, frmm
;
301 if (api_c_refs
== 0) {
302 /* initialize driver and other modules */
311 fmsg
= msg_mod_init();
315 ret
= fdrv
&& fdev
&& fchnl
&& fcod
&& fmsg
&& fio
;
316 ret
= ret
&& fmgr
&& fproc
&& frmm
;
363 * ======== api_init_complete2 ========
365 * Perform any required bridge initialization which cannot
366 * be performed in api_init() or dev_start_device() due
367 * to the fact that some services are not yet
368 * completely initialized.
371 * 0: Allow this device to load
374 * Bridge API initialized.
377 int api_init_complete2(void)
380 struct cfg_devnode
*dev_node
;
381 struct dev_object
*hdev_obj
;
382 struct drv_data
*drv_datap
;
385 DBC_REQUIRE(api_c_refs
> 0);
387 /* Walk the list of DevObjects, get each devnode, and attempting to
388 * autostart the board. Note that this requires COF loading, which
390 for (hdev_obj
= dev_get_first(); hdev_obj
!= NULL
;
391 hdev_obj
= dev_get_next(hdev_obj
)) {
392 if (dev_get_dev_node(hdev_obj
, &dev_node
))
395 if (dev_get_dev_type(hdev_obj
, &dev_type
))
398 if ((dev_type
== DSP_UNIT
) || (dev_type
== IVA_UNIT
)) {
399 drv_datap
= dev_get_drvdata(bridge
);
401 if (drv_datap
&& drv_datap
->base_img
)
402 proc_auto_start(dev_node
, hdev_obj
);
409 /* TODO: Remove deprecated and not implemented ioctl wrappers */
412 * ======== mgrwrap_enum_node_info ========
414 u32
mgrwrap_enum_node_info(union trapped_args
*args
, void *pr_ctxt
)
419 u32 size
= args
->args_mgr_enumnode_info
.undb_props_size
;
421 if (size
< sizeof(struct dsp_ndbprops
))
424 pndb_props
= kmalloc(size
, GFP_KERNEL
);
425 if (pndb_props
== NULL
)
430 mgr_enum_node_info(args
->args_mgr_enumnode_info
.node_id
,
431 (struct dsp_ndbprops
*)pndb_props
, size
,
434 CP_TO_USR(args
->args_mgr_enumnode_info
.pndb_props
, pndb_props
, status
,
436 CP_TO_USR(args
->args_mgr_enumnode_info
.pu_num_nodes
, &num_nodes
, status
,
444 * ======== mgrwrap_enum_proc_info ========
446 u32
mgrwrap_enum_proc_info(union trapped_args
*args
, void *pr_ctxt
)
451 u32 size
= args
->args_mgr_enumproc_info
.processor_info_size
;
453 if (size
< sizeof(struct dsp_processorinfo
))
456 processor_info
= kmalloc(size
, GFP_KERNEL
);
457 if (processor_info
== NULL
)
462 mgr_enum_processor_info(args
->args_mgr_enumproc_info
.
464 (struct dsp_processorinfo
*)
465 processor_info
, size
, &num_procs
);
467 CP_TO_USR(args
->args_mgr_enumproc_info
.processor_info
, processor_info
,
469 CP_TO_USR(args
->args_mgr_enumproc_info
.pu_num_procs
, &num_procs
,
471 kfree(processor_info
);
476 #define WRAP_MAP2CALLER(x) x
478 * ======== mgrwrap_register_object ========
480 u32
mgrwrap_register_object(union trapped_args
*args
, void *pr_ctxt
)
483 struct dsp_uuid uuid_obj
;
485 char *psz_path_name
= NULL
;
488 CP_FM_USR(&uuid_obj
, args
->args_mgr_registerobject
.uuid_obj
, status
, 1);
491 /* path_size is increased by 1 to accommodate NULL */
492 path_size
= strlen_user((char *)
493 args
->args_mgr_registerobject
.psz_path_name
) +
495 psz_path_name
= kmalloc(path_size
, GFP_KERNEL
);
496 if (!psz_path_name
) {
500 ret
= strncpy_from_user(psz_path_name
,
501 (char *)args
->args_mgr_registerobject
.
502 psz_path_name
, path_size
);
508 if (args
->args_mgr_registerobject
.obj_type
>= DSP_DCDMAXOBJTYPE
) {
513 status
= dcd_register_object(&uuid_obj
,
514 args
->args_mgr_registerobject
.obj_type
,
515 (char *)psz_path_name
);
517 kfree(psz_path_name
);
522 * ======== mgrwrap_unregister_object ========
524 u32
mgrwrap_unregister_object(union trapped_args
*args
, void *pr_ctxt
)
527 struct dsp_uuid uuid_obj
;
529 CP_FM_USR(&uuid_obj
, args
->args_mgr_registerobject
.uuid_obj
, status
, 1);
533 status
= dcd_unregister_object(&uuid_obj
,
534 args
->args_mgr_unregisterobject
.
542 * ======== mgrwrap_wait_for_bridge_events ========
544 u32
mgrwrap_wait_for_bridge_events(union trapped_args
*args
, void *pr_ctxt
)
547 struct dsp_notification
*anotifications
[MAX_EVENTS
];
548 struct dsp_notification notifications
[MAX_EVENTS
];
550 u32 count
= args
->args_mgr_wait
.count
;
552 if (count
> MAX_EVENTS
)
555 /* get the array of pointers to user structures */
556 CP_FM_USR(anotifications
, args
->args_mgr_wait
.anotifications
,
559 for (i
= 0; i
< count
; i
++) {
560 CP_FM_USR(¬ifications
[i
], anotifications
[i
], status
, 1);
561 if (status
|| !notifications
[i
].handle
) {
565 /* set the array of pointers to kernel structures */
566 anotifications
[i
] = ¬ifications
[i
];
569 status
= mgr_wait_for_bridge_events(anotifications
, count
,
574 CP_TO_USR(args
->args_mgr_wait
.pu_index
, &index
, status
, 1);
579 * ======== MGRWRAP_GetProcessResourceInfo ========
581 u32 __deprecated
mgrwrap_get_process_resources_info(union trapped_args
* args
,
584 pr_err("%s: deprecated dspbridge ioctl\n", __func__
);
589 * ======== procwrap_attach ========
591 u32
procwrap_attach(union trapped_args
*args
, void *pr_ctxt
)
595 struct dsp_processorattrin proc_attr_in
, *attr_in
= NULL
;
597 /* Optional argument */
598 if (args
->args_proc_attach
.attr_in
) {
599 CP_FM_USR(&proc_attr_in
, args
->args_proc_attach
.attr_in
, status
,
602 attr_in
= &proc_attr_in
;
607 status
= proc_attach(args
->args_proc_attach
.processor_id
, attr_in
,
608 &processor
, pr_ctxt
);
609 CP_TO_USR(args
->args_proc_attach
.ph_processor
, &processor
, status
, 1);
615 * ======== procwrap_ctrl ========
617 u32
procwrap_ctrl(union trapped_args
*args
, void *pr_ctxt
)
619 u32 cb_data_size
, __user
* psize
= (u32 __user
*)
620 args
->args_proc_ctrl
.pargs
;
623 void *hprocessor
= ((struct process_context
*)pr_ctxt
)->hprocessor
;
626 if (get_user(cb_data_size
, psize
)) {
630 cb_data_size
+= sizeof(u32
);
631 pargs
= kmalloc(cb_data_size
, GFP_KERNEL
);
637 CP_FM_USR(pargs
, args
->args_proc_ctrl
.pargs
, status
,
641 status
= proc_ctrl(hprocessor
,
642 args
->args_proc_ctrl
.dw_cmd
,
643 (struct dsp_cbdata
*)pargs
);
646 /* CP_TO_USR(args->args_proc_ctrl.pargs, pargs, status, 1); */
653 * ======== procwrap_detach ========
655 u32 __deprecated
procwrap_detach(union trapped_args
* args
, void *pr_ctxt
)
657 /* proc_detach called at bridge_release only */
658 pr_err("%s: deprecated dspbridge ioctl\n", __func__
);
663 * ======== procwrap_enum_node_info ========
665 u32
procwrap_enum_node_info(union trapped_args
*args
, void *pr_ctxt
)
668 void *node_tab
[MAX_NODES
];
671 void *hprocessor
= ((struct process_context
*)pr_ctxt
)->hprocessor
;
673 if (!args
->args_proc_enumnode_info
.node_tab_size
)
676 status
= proc_enum_nodes(hprocessor
,
678 args
->args_proc_enumnode_info
.node_tab_size
,
679 &num_nodes
, &alloc_cnt
);
680 CP_TO_USR(args
->args_proc_enumnode_info
.node_tab
, node_tab
, status
,
682 CP_TO_USR(args
->args_proc_enumnode_info
.pu_num_nodes
, &num_nodes
,
684 CP_TO_USR(args
->args_proc_enumnode_info
.pu_allocated
, &alloc_cnt
,
689 u32
procwrap_end_dma(union trapped_args
*args
, void *pr_ctxt
)
693 if (args
->args_proc_dma
.dir
>= DMA_NONE
)
696 status
= proc_end_dma(pr_ctxt
,
697 args
->args_proc_dma
.pmpu_addr
,
698 args
->args_proc_dma
.ul_size
,
699 args
->args_proc_dma
.dir
);
703 u32
procwrap_begin_dma(union trapped_args
*args
, void *pr_ctxt
)
707 if (args
->args_proc_dma
.dir
>= DMA_NONE
)
710 status
= proc_begin_dma(pr_ctxt
,
711 args
->args_proc_dma
.pmpu_addr
,
712 args
->args_proc_dma
.ul_size
,
713 args
->args_proc_dma
.dir
);
718 * ======== procwrap_flush_memory ========
720 u32
procwrap_flush_memory(union trapped_args
*args
, void *pr_ctxt
)
724 if (args
->args_proc_flushmemory
.ul_flags
>
725 PROC_WRITEBACK_INVALIDATE_MEM
)
728 status
= proc_flush_memory(pr_ctxt
,
729 args
->args_proc_flushmemory
.pmpu_addr
,
730 args
->args_proc_flushmemory
.ul_size
,
731 args
->args_proc_flushmemory
.ul_flags
);
736 * ======== procwrap_invalidate_memory ========
738 u32
procwrap_invalidate_memory(union trapped_args
*args
, void *pr_ctxt
)
743 proc_invalidate_memory(pr_ctxt
,
744 args
->args_proc_invalidatememory
.pmpu_addr
,
745 args
->args_proc_invalidatememory
.ul_size
);
750 * ======== procwrap_enum_resources ========
752 u32
procwrap_enum_resources(union trapped_args
*args
, void *pr_ctxt
)
755 struct dsp_resourceinfo resource_info
;
756 void *hprocessor
= ((struct process_context
*)pr_ctxt
)->hprocessor
;
758 if (args
->args_proc_enumresources
.resource_info_size
<
759 sizeof(struct dsp_resourceinfo
))
763 proc_get_resource_info(hprocessor
,
764 args
->args_proc_enumresources
.resource_type
,
766 args
->args_proc_enumresources
.
769 CP_TO_USR(args
->args_proc_enumresources
.resource_info
, &resource_info
,
777 * ======== procwrap_get_state ========
779 u32
procwrap_get_state(union trapped_args
*args
, void *pr_ctxt
)
782 struct dsp_processorstate proc_state
;
783 void *hprocessor
= ((struct process_context
*)pr_ctxt
)->hprocessor
;
785 if (args
->args_proc_getstate
.state_info_size
<
786 sizeof(struct dsp_processorstate
))
789 status
= proc_get_state(hprocessor
, &proc_state
,
790 args
->args_proc_getstate
.state_info_size
);
791 CP_TO_USR(args
->args_proc_getstate
.proc_state_obj
, &proc_state
, status
,
798 * ======== procwrap_get_trace ========
800 u32
procwrap_get_trace(union trapped_args
*args
, void *pr_ctxt
)
804 void *hprocessor
= ((struct process_context
*)pr_ctxt
)->hprocessor
;
806 if (args
->args_proc_gettrace
.max_size
> MAX_TRACEBUFLEN
)
809 pbuf
= kzalloc(args
->args_proc_gettrace
.max_size
, GFP_KERNEL
);
811 status
= proc_get_trace(hprocessor
, pbuf
,
812 args
->args_proc_gettrace
.max_size
);
816 CP_TO_USR(args
->args_proc_gettrace
.pbuf
, pbuf
, status
,
817 args
->args_proc_gettrace
.max_size
);
824 * ======== procwrap_load ========
826 u32
procwrap_load(union trapped_args
*args
, void *pr_ctxt
)
831 s32 count
= args
->args_proc_load
.argc_index
;
832 u8
**argv
= NULL
, **envp
= NULL
;
833 void *hprocessor
= ((struct process_context
*)pr_ctxt
)->hprocessor
;
835 if (count
<= 0 || count
> MAX_LOADARGS
) {
840 argv
= kmalloc(count
* sizeof(u8
*), GFP_KERNEL
);
846 CP_FM_USR(argv
, args
->args_proc_load
.user_args
, status
, count
);
853 for (i
= 0; i
< count
; i
++) {
855 /* User space pointer to argument */
856 temp
= (char *)argv
[i
];
857 /* len is increased by 1 to accommodate NULL */
858 len
= strlen_user((char *)temp
) + 1;
859 /* Kernel space pointer to argument */
860 argv
[i
] = kmalloc(len
, GFP_KERNEL
);
862 CP_FM_USR(argv
[i
], temp
, status
, len
);
874 /* TODO: validate this */
875 if (args
->args_proc_load
.user_envp
) {
876 /* number of elements in the envp array including NULL */
880 args
->args_proc_load
.user_envp
+ count
)) {
886 envp
= kmalloc(count
* sizeof(u8
*), GFP_KERNEL
);
892 CP_FM_USR(envp
, args
->args_proc_load
.user_envp
, status
, count
);
898 for (i
= 0; envp
[i
]; i
++) {
899 /* User space pointer to argument */
900 temp
= (char *)envp
[i
];
901 /* len is increased by 1 to accommodate NULL */
902 len
= strlen_user((char *)temp
) + 1;
903 /* Kernel space pointer to argument */
904 envp
[i
] = kmalloc(len
, GFP_KERNEL
);
906 CP_FM_USR(envp
[i
], temp
, status
, len
);
920 status
= proc_load(hprocessor
,
921 args
->args_proc_load
.argc_index
,
922 (const char **)argv
, (const char **)envp
);
934 count
= args
->args_proc_load
.argc_index
;
935 for (i
= 0; (i
< count
) && argv
[i
]; i
++)
945 * ======== procwrap_map ========
947 u32
procwrap_map(union trapped_args
*args
, void *pr_ctxt
)
951 void *hprocessor
= ((struct process_context
*)pr_ctxt
)->hprocessor
;
953 if (!args
->args_proc_mapmem
.ul_size
)
956 status
= proc_map(args
->args_proc_mapmem
.hprocessor
,
957 args
->args_proc_mapmem
.pmpu_addr
,
958 args
->args_proc_mapmem
.ul_size
,
959 args
->args_proc_mapmem
.req_addr
, &map_addr
,
960 args
->args_proc_mapmem
.ul_map_attr
, pr_ctxt
);
962 if (put_user(map_addr
, args
->args_proc_mapmem
.pp_map_addr
)) {
964 proc_un_map(hprocessor
, map_addr
, pr_ctxt
);
972 * ======== procwrap_register_notify ========
974 u32
procwrap_register_notify(union trapped_args
*args
, void *pr_ctxt
)
977 struct dsp_notification notification
;
978 void *hprocessor
= ((struct process_context
*)pr_ctxt
)->hprocessor
;
980 /* Initialize the notification data structure */
981 notification
.ps_name
= NULL
;
982 notification
.handle
= NULL
;
984 status
= proc_register_notify(hprocessor
,
985 args
->args_proc_register_notify
.event_mask
,
986 args
->args_proc_register_notify
.notify_type
,
988 CP_TO_USR(args
->args_proc_register_notify
.hnotification
, ¬ification
,
994 * ======== procwrap_reserve_memory ========
996 u32 __deprecated
procwrap_reserve_memory(union trapped_args
*args
,
1003 * ======== procwrap_start ========
1005 u32
procwrap_start(union trapped_args
*args
, void *pr_ctxt
)
1009 ret
= proc_start(((struct process_context
*)pr_ctxt
)->hprocessor
);
1014 * ======== procwrap_un_map ========
1016 u32
procwrap_un_map(union trapped_args
*args
, void *pr_ctxt
)
1020 status
= proc_un_map(((struct process_context
*)pr_ctxt
)->hprocessor
,
1021 args
->args_proc_unmapmem
.map_addr
, pr_ctxt
);
1026 * ======== procwrap_un_reserve_memory ========
1028 u32 __deprecated
procwrap_un_reserve_memory(union trapped_args
*args
,
1035 * ======== procwrap_stop ========
1037 u32
procwrap_stop(union trapped_args
*args
, void *pr_ctxt
)
1041 ret
= proc_stop(((struct process_context
*)pr_ctxt
)->hprocessor
);
1047 * ======== find_handle =========
1049 inline void find_node_handle(struct node_res_object
**noderes
,
1050 void *pr_ctxt
, void *hnode
)
1053 *noderes
= idr_find(((struct process_context
*)pr_ctxt
)->node_id
,
1061 * ======== nodewrap_allocate ========
1063 u32
nodewrap_allocate(union trapped_args
*args
, void *pr_ctxt
)
1066 struct dsp_uuid node_uuid
;
1067 u32 cb_data_size
= 0;
1068 u32 __user
*psize
= (u32 __user
*) args
->args_node_allocate
.pargs
;
1070 struct dsp_nodeattrin proc_attr_in
, *attr_in
= NULL
;
1071 struct node_res_object
*node_res
;
1073 void *hprocessor
= ((struct process_context
*)pr_ctxt
)->hprocessor
;
1075 /* Optional argument */
1077 if (get_user(cb_data_size
, psize
))
1080 cb_data_size
+= sizeof(u32
);
1082 pargs
= kmalloc(cb_data_size
, GFP_KERNEL
);
1087 CP_FM_USR(pargs
, args
->args_node_allocate
.pargs
, status
,
1090 CP_FM_USR(&node_uuid
, args
->args_node_allocate
.node_id_ptr
, status
, 1);
1093 /* Optional argument */
1094 if (args
->args_node_allocate
.attr_in
) {
1095 CP_FM_USR(&proc_attr_in
, args
->args_node_allocate
.attr_in
,
1098 attr_in
= &proc_attr_in
;
1104 status
= node_allocate(hprocessor
,
1105 &node_uuid
, (struct dsp_cbdata
*)pargs
,
1106 attr_in
, &node_res
, pr_ctxt
);
1109 nodeid
= node_res
->id
+ 1;
1110 CP_TO_USR(args
->args_node_allocate
.ph_node
, &nodeid
,
1114 node_delete(node_res
, pr_ctxt
);
1124 * ======== nodewrap_alloc_msg_buf ========
1126 u32
nodewrap_alloc_msg_buf(union trapped_args
*args
, void *pr_ctxt
)
1129 struct dsp_bufferattr
*pattr
= NULL
;
1130 struct dsp_bufferattr attr
;
1132 struct node_res_object
*node_res
;
1134 find_node_handle(&node_res
, pr_ctxt
,
1135 args
->args_node_allocmsgbuf
.hnode
);
1140 if (!args
->args_node_allocmsgbuf
.usize
)
1143 if (args
->args_node_allocmsgbuf
.pattr
) { /* Optional argument */
1144 CP_FM_USR(&attr
, args
->args_node_allocmsgbuf
.pattr
, status
, 1);
1150 CP_FM_USR(&pbuffer
, args
->args_node_allocmsgbuf
.pbuffer
, status
, 1);
1152 status
= node_alloc_msg_buf(node_res
->hnode
,
1153 args
->args_node_allocmsgbuf
.usize
,
1156 CP_TO_USR(args
->args_node_allocmsgbuf
.pbuffer
, &pbuffer
, status
, 1);
1161 * ======== nodewrap_change_priority ========
1163 u32
nodewrap_change_priority(union trapped_args
*args
, void *pr_ctxt
)
1166 struct node_res_object
*node_res
;
1168 find_node_handle(&node_res
, pr_ctxt
,
1169 args
->args_node_changepriority
.hnode
);
1174 ret
= node_change_priority(node_res
->hnode
,
1175 args
->args_node_changepriority
.prio
);
1181 * ======== nodewrap_connect ========
1183 u32
nodewrap_connect(union trapped_args
*args
, void *pr_ctxt
)
1186 struct dsp_strmattr attrs
;
1187 struct dsp_strmattr
*pattrs
= NULL
;
1189 u32 __user
*psize
= (u32 __user
*) args
->args_node_connect
.conn_param
;
1191 struct node_res_object
*node_res1
, *node_res2
;
1192 struct node_object
*node1
= NULL
, *node2
= NULL
;
1194 if ((int)args
->args_node_connect
.hnode
!= DSP_HGPPNODE
) {
1195 find_node_handle(&node_res1
, pr_ctxt
,
1196 args
->args_node_connect
.hnode
);
1198 node1
= node_res1
->hnode
;
1200 node1
= args
->args_node_connect
.hnode
;
1203 if ((int)args
->args_node_connect
.other_node
!= DSP_HGPPNODE
) {
1204 find_node_handle(&node_res2
, pr_ctxt
,
1205 args
->args_node_connect
.other_node
);
1207 node2
= node_res2
->hnode
;
1209 node2
= args
->args_node_connect
.other_node
;
1212 if (!node1
|| !node2
)
1215 /* Optional argument */
1217 if (get_user(cb_data_size
, psize
))
1220 cb_data_size
+= sizeof(u32
);
1222 pargs
= kmalloc(cb_data_size
, GFP_KERNEL
);
1223 if (pargs
== NULL
) {
1229 CP_FM_USR(pargs
, args
->args_node_connect
.conn_param
, status
,
1234 if (args
->args_node_connect
.pattrs
) { /* Optional argument */
1235 CP_FM_USR(&attrs
, args
->args_node_connect
.pattrs
, status
, 1);
1241 status
= node_connect(node1
,
1242 args
->args_node_connect
.stream_id
,
1244 args
->args_node_connect
.other_stream
,
1245 pattrs
, (struct dsp_cbdata
*)pargs
);
1254 * ======== nodewrap_create ========
1256 u32
nodewrap_create(union trapped_args
*args
, void *pr_ctxt
)
1259 struct node_res_object
*node_res
;
1261 find_node_handle(&node_res
, pr_ctxt
, args
->args_node_create
.hnode
);
1266 ret
= node_create(node_res
->hnode
);
1272 * ======== nodewrap_delete ========
1274 u32
nodewrap_delete(union trapped_args
*args
, void *pr_ctxt
)
1277 struct node_res_object
*node_res
;
1279 find_node_handle(&node_res
, pr_ctxt
, args
->args_node_delete
.hnode
);
1284 ret
= node_delete(node_res
, pr_ctxt
);
1290 * ======== nodewrap_free_msg_buf ========
1292 u32
nodewrap_free_msg_buf(union trapped_args
*args
, void *pr_ctxt
)
1295 struct dsp_bufferattr
*pattr
= NULL
;
1296 struct dsp_bufferattr attr
;
1297 struct node_res_object
*node_res
;
1299 find_node_handle(&node_res
, pr_ctxt
, args
->args_node_freemsgbuf
.hnode
);
1304 if (args
->args_node_freemsgbuf
.pattr
) { /* Optional argument */
1305 CP_FM_USR(&attr
, args
->args_node_freemsgbuf
.pattr
, status
, 1);
1311 if (!args
->args_node_freemsgbuf
.pbuffer
)
1315 status
= node_free_msg_buf(node_res
->hnode
,
1316 args
->args_node_freemsgbuf
.pbuffer
,
1324 * ======== nodewrap_get_attr ========
1326 u32
nodewrap_get_attr(union trapped_args
*args
, void *pr_ctxt
)
1329 struct dsp_nodeattr attr
;
1330 struct node_res_object
*node_res
;
1332 find_node_handle(&node_res
, pr_ctxt
, args
->args_node_getattr
.hnode
);
1337 status
= node_get_attr(node_res
->hnode
, &attr
,
1338 args
->args_node_getattr
.attr_size
);
1339 CP_TO_USR(args
->args_node_getattr
.pattr
, &attr
, status
, 1);
1345 * ======== nodewrap_get_message ========
1347 u32
nodewrap_get_message(union trapped_args
*args
, void *pr_ctxt
)
1351 struct node_res_object
*node_res
;
1353 find_node_handle(&node_res
, pr_ctxt
, args
->args_node_getmessage
.hnode
);
1358 status
= node_get_message(node_res
->hnode
, &msg
,
1359 args
->args_node_getmessage
.utimeout
);
1361 CP_TO_USR(args
->args_node_getmessage
.message
, &msg
, status
, 1);
1367 * ======== nodewrap_pause ========
1369 u32
nodewrap_pause(union trapped_args
*args
, void *pr_ctxt
)
1372 struct node_res_object
*node_res
;
1374 find_node_handle(&node_res
, pr_ctxt
, args
->args_node_pause
.hnode
);
1379 ret
= node_pause(node_res
->hnode
);
1385 * ======== nodewrap_put_message ========
1387 u32
nodewrap_put_message(union trapped_args
*args
, void *pr_ctxt
)
1391 struct node_res_object
*node_res
;
1393 find_node_handle(&node_res
, pr_ctxt
, args
->args_node_putmessage
.hnode
);
1398 CP_FM_USR(&msg
, args
->args_node_putmessage
.message
, status
, 1);
1402 node_put_message(node_res
->hnode
, &msg
,
1403 args
->args_node_putmessage
.utimeout
);
1410 * ======== nodewrap_register_notify ========
1412 u32
nodewrap_register_notify(union trapped_args
*args
, void *pr_ctxt
)
1415 struct dsp_notification notification
;
1416 struct node_res_object
*node_res
;
1418 find_node_handle(&node_res
, pr_ctxt
,
1419 args
->args_node_registernotify
.hnode
);
1424 /* Initialize the notification data structure */
1425 notification
.ps_name
= NULL
;
1426 notification
.handle
= NULL
;
1428 if (!args
->args_proc_register_notify
.event_mask
)
1429 CP_FM_USR(¬ification
,
1430 args
->args_proc_register_notify
.hnotification
,
1433 status
= node_register_notify(node_res
->hnode
,
1434 args
->args_node_registernotify
.event_mask
,
1435 args
->args_node_registernotify
.
1436 notify_type
, ¬ification
);
1437 CP_TO_USR(args
->args_node_registernotify
.hnotification
, ¬ification
,
1443 * ======== nodewrap_run ========
1445 u32
nodewrap_run(union trapped_args
*args
, void *pr_ctxt
)
1448 struct node_res_object
*node_res
;
1450 find_node_handle(&node_res
, pr_ctxt
, args
->args_node_run
.hnode
);
1455 ret
= node_run(node_res
->hnode
);
1461 * ======== nodewrap_terminate ========
1463 u32
nodewrap_terminate(union trapped_args
*args
, void *pr_ctxt
)
1467 struct node_res_object
*node_res
;
1469 find_node_handle(&node_res
, pr_ctxt
, args
->args_node_terminate
.hnode
);
1474 status
= node_terminate(node_res
->hnode
, &tempstatus
);
1476 CP_TO_USR(args
->args_node_terminate
.pstatus
, &tempstatus
, status
, 1);
1482 * ======== nodewrap_get_uuid_props ========
1484 u32
nodewrap_get_uuid_props(union trapped_args
*args
, void *pr_ctxt
)
1487 struct dsp_uuid node_uuid
;
1488 struct dsp_ndbprops
*pnode_props
= NULL
;
1489 void *hprocessor
= ((struct process_context
*)pr_ctxt
)->hprocessor
;
1491 CP_FM_USR(&node_uuid
, args
->args_node_getuuidprops
.node_id_ptr
, status
,
1495 pnode_props
= kmalloc(sizeof(struct dsp_ndbprops
), GFP_KERNEL
);
1496 if (pnode_props
!= NULL
) {
1498 node_get_uuid_props(hprocessor
, &node_uuid
, pnode_props
);
1499 CP_TO_USR(args
->args_node_getuuidprops
.node_props
, pnode_props
,
1509 * ======== find_strm_handle =========
1511 inline void find_strm_handle(struct strm_res_object
**strmres
,
1512 void *pr_ctxt
, void *hstream
)
1515 *strmres
= idr_find(((struct process_context
*)pr_ctxt
)->stream_id
,
1522 * ======== strmwrap_allocate_buffer ========
1524 u32
strmwrap_allocate_buffer(union trapped_args
*args
, void *pr_ctxt
)
1527 u8
**ap_buffer
= NULL
;
1528 u32 num_bufs
= args
->args_strm_allocatebuffer
.num_bufs
;
1529 struct strm_res_object
*strm_res
;
1531 find_strm_handle(&strm_res
, pr_ctxt
,
1532 args
->args_strm_allocatebuffer
.hstream
);
1537 if (num_bufs
> MAX_BUFS
)
1540 ap_buffer
= kmalloc((num_bufs
* sizeof(u8
*)), GFP_KERNEL
);
1541 if (ap_buffer
== NULL
)
1544 status
= strm_allocate_buffer(strm_res
,
1545 args
->args_strm_allocatebuffer
.usize
,
1546 ap_buffer
, num_bufs
, pr_ctxt
);
1548 CP_TO_USR(args
->args_strm_allocatebuffer
.ap_buffer
, ap_buffer
,
1552 strm_free_buffer(strm_res
,
1553 ap_buffer
, num_bufs
, pr_ctxt
);
1562 * ======== strmwrap_close ========
1564 u32
strmwrap_close(union trapped_args
*args
, void *pr_ctxt
)
1566 struct strm_res_object
*strm_res
;
1568 find_strm_handle(&strm_res
, pr_ctxt
, args
->args_strm_close
.hstream
);
1573 return strm_close(strm_res
, pr_ctxt
);
1577 * ======== strmwrap_free_buffer ========
1579 u32
strmwrap_free_buffer(union trapped_args
*args
, void *pr_ctxt
)
1582 u8
**ap_buffer
= NULL
;
1583 u32 num_bufs
= args
->args_strm_freebuffer
.num_bufs
;
1584 struct strm_res_object
*strm_res
;
1586 find_strm_handle(&strm_res
, pr_ctxt
,
1587 args
->args_strm_freebuffer
.hstream
);
1592 if (num_bufs
> MAX_BUFS
)
1595 ap_buffer
= kmalloc((num_bufs
* sizeof(u8
*)), GFP_KERNEL
);
1596 if (ap_buffer
== NULL
)
1599 CP_FM_USR(ap_buffer
, args
->args_strm_freebuffer
.ap_buffer
, status
,
1603 status
= strm_free_buffer(strm_res
,
1604 ap_buffer
, num_bufs
, pr_ctxt
);
1606 CP_TO_USR(args
->args_strm_freebuffer
.ap_buffer
, ap_buffer
, status
,
1614 * ======== strmwrap_get_event_handle ========
1616 u32 __deprecated
strmwrap_get_event_handle(union trapped_args
* args
,
1619 pr_err("%s: deprecated dspbridge ioctl\n", __func__
);
1624 * ======== strmwrap_get_info ========
1626 u32
strmwrap_get_info(union trapped_args
*args
, void *pr_ctxt
)
1629 struct stream_info strm_info
;
1630 struct dsp_streaminfo user
;
1631 struct dsp_streaminfo
*temp
;
1632 struct strm_res_object
*strm_res
;
1634 find_strm_handle(&strm_res
, pr_ctxt
,
1635 args
->args_strm_getinfo
.hstream
);
1640 CP_FM_USR(&strm_info
, args
->args_strm_getinfo
.stream_info
, status
, 1);
1641 temp
= strm_info
.user_strm
;
1643 strm_info
.user_strm
= &user
;
1646 status
= strm_get_info(strm_res
->hstream
,
1648 args
->args_strm_getinfo
.
1651 CP_TO_USR(temp
, strm_info
.user_strm
, status
, 1);
1652 strm_info
.user_strm
= temp
;
1653 CP_TO_USR(args
->args_strm_getinfo
.stream_info
, &strm_info
, status
, 1);
1658 * ======== strmwrap_idle ========
1660 u32
strmwrap_idle(union trapped_args
*args
, void *pr_ctxt
)
1663 struct strm_res_object
*strm_res
;
1665 find_strm_handle(&strm_res
, pr_ctxt
, args
->args_strm_idle
.hstream
);
1670 ret
= strm_idle(strm_res
->hstream
, args
->args_strm_idle
.flush_flag
);
1676 * ======== strmwrap_issue ========
1678 u32
strmwrap_issue(union trapped_args
*args
, void *pr_ctxt
)
1681 struct strm_res_object
*strm_res
;
1683 find_strm_handle(&strm_res
, pr_ctxt
, args
->args_strm_issue
.hstream
);
1688 if (!args
->args_strm_issue
.pbuffer
)
1691 /* No need of doing CP_FM_USR for the user buffer (pbuffer)
1692 as this is done in Bridge internal function bridge_chnl_add_io_req
1694 status
= strm_issue(strm_res
->hstream
,
1695 args
->args_strm_issue
.pbuffer
,
1696 args
->args_strm_issue
.dw_bytes
,
1697 args
->args_strm_issue
.dw_buf_size
,
1698 args
->args_strm_issue
.dw_arg
);
1704 * ======== strmwrap_open ========
1706 u32
strmwrap_open(union trapped_args
*args
, void *pr_ctxt
)
1709 struct strm_attr attr
;
1710 struct strm_res_object
*strm_res_obj
;
1711 struct dsp_streamattrin strm_attr_in
;
1712 struct node_res_object
*node_res
;
1715 find_node_handle(&node_res
, pr_ctxt
, args
->args_strm_open
.hnode
);
1720 CP_FM_USR(&attr
, args
->args_strm_open
.attr_in
, status
, 1);
1722 if (attr
.stream_attr_in
!= NULL
) { /* Optional argument */
1723 CP_FM_USR(&strm_attr_in
, attr
.stream_attr_in
, status
, 1);
1725 attr
.stream_attr_in
= &strm_attr_in
;
1726 if (attr
.stream_attr_in
->strm_mode
== STRMMODE_LDMA
)
1731 status
= strm_open(node_res
->hnode
,
1732 args
->args_strm_open
.direction
,
1733 args
->args_strm_open
.index
, &attr
, &strm_res_obj
,
1736 strmid
= strm_res_obj
->id
+ 1;
1737 CP_TO_USR(args
->args_strm_open
.ph_stream
, &strmid
, status
, 1);
1743 * ======== strmwrap_reclaim ========
1745 u32
strmwrap_reclaim(union trapped_args
*args
, void *pr_ctxt
)
1752 struct strm_res_object
*strm_res
;
1754 find_strm_handle(&strm_res
, pr_ctxt
, args
->args_strm_reclaim
.hstream
);
1759 status
= strm_reclaim(strm_res
->hstream
, &buf_ptr
,
1760 &ul_bytes
, &ul_buf_size
, &dw_arg
);
1761 CP_TO_USR(args
->args_strm_reclaim
.buf_ptr
, &buf_ptr
, status
, 1);
1762 CP_TO_USR(args
->args_strm_reclaim
.bytes
, &ul_bytes
, status
, 1);
1763 CP_TO_USR(args
->args_strm_reclaim
.pdw_arg
, &dw_arg
, status
, 1);
1765 if (args
->args_strm_reclaim
.buf_size_ptr
!= NULL
) {
1766 CP_TO_USR(args
->args_strm_reclaim
.buf_size_ptr
, &ul_buf_size
,
1774 * ======== strmwrap_register_notify ========
1776 u32
strmwrap_register_notify(union trapped_args
*args
, void *pr_ctxt
)
1779 struct dsp_notification notification
;
1780 struct strm_res_object
*strm_res
;
1782 find_strm_handle(&strm_res
, pr_ctxt
,
1783 args
->args_strm_registernotify
.hstream
);
1788 /* Initialize the notification data structure */
1789 notification
.ps_name
= NULL
;
1790 notification
.handle
= NULL
;
1792 status
= strm_register_notify(strm_res
->hstream
,
1793 args
->args_strm_registernotify
.event_mask
,
1794 args
->args_strm_registernotify
.
1795 notify_type
, ¬ification
);
1796 CP_TO_USR(args
->args_strm_registernotify
.hnotification
, ¬ification
,
1803 * ======== strmwrap_select ========
1805 u32
strmwrap_select(union trapped_args
*args
, void *pr_ctxt
)
1808 struct strm_object
*strm_tab
[MAX_STREAMS
];
1810 struct strm_res_object
*strm_res
;
1811 int *ids
[MAX_STREAMS
];
1814 if (args
->args_strm_select
.strm_num
> MAX_STREAMS
)
1817 CP_FM_USR(ids
, args
->args_strm_select
.stream_tab
, status
,
1818 args
->args_strm_select
.strm_num
);
1823 for (i
= 0; i
< args
->args_strm_select
.strm_num
; i
++) {
1824 find_strm_handle(&strm_res
, pr_ctxt
, ids
[i
]);
1829 strm_tab
[i
] = strm_res
->hstream
;
1833 status
= strm_select(strm_tab
, args
->args_strm_select
.strm_num
,
1834 &mask
, args
->args_strm_select
.utimeout
);
1836 CP_TO_USR(args
->args_strm_select
.pmask
, &mask
, status
, 1);
1843 * ======== cmmwrap_calloc_buf ========
1845 u32 __deprecated
cmmwrap_calloc_buf(union trapped_args
* args
, void *pr_ctxt
)
1847 /* This operation is done in kernel */
1848 pr_err("%s: deprecated dspbridge ioctl\n", __func__
);
1853 * ======== cmmwrap_free_buf ========
1855 u32 __deprecated
cmmwrap_free_buf(union trapped_args
* args
, void *pr_ctxt
)
1857 /* This operation is done in kernel */
1858 pr_err("%s: deprecated dspbridge ioctl\n", __func__
);
1863 * ======== cmmwrap_get_handle ========
1865 u32
cmmwrap_get_handle(union trapped_args
*args
, void *pr_ctxt
)
1868 struct cmm_object
*hcmm_mgr
;
1869 void *hprocessor
= ((struct process_context
*)pr_ctxt
)->hprocessor
;
1871 status
= cmm_get_handle(hprocessor
, &hcmm_mgr
);
1873 CP_TO_USR(args
->args_cmm_gethandle
.ph_cmm_mgr
, &hcmm_mgr
, status
, 1);
1879 * ======== cmmwrap_get_info ========
1881 u32
cmmwrap_get_info(union trapped_args
*args
, void *pr_ctxt
)
1884 struct cmm_info cmm_info_obj
;
1886 status
= cmm_get_info(args
->args_cmm_getinfo
.hcmm_mgr
, &cmm_info_obj
);
1888 CP_TO_USR(args
->args_cmm_getinfo
.cmm_info_obj
, &cmm_info_obj
, status
,