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 /* ----------------------------------- OS Adaptation Layer */
28 #include <dspbridge/ntfy.h>
30 /* ----------------------------------- Platform Manager */
31 #include <dspbridge/chnl.h>
32 #include <dspbridge/dev.h>
33 #include <dspbridge/drv.h>
35 #include <dspbridge/proc.h>
36 #include <dspbridge/strm.h>
38 /* ----------------------------------- Resource Manager */
39 #include <dspbridge/disp.h>
40 #include <dspbridge/mgr.h>
41 #include <dspbridge/node.h>
42 #include <dspbridge/rmm.h>
44 /* ----------------------------------- Others */
45 #include <dspbridge/msg.h>
46 #include <dspbridge/cmm.h>
47 #include <dspbridge/io.h>
49 /* ----------------------------------- This */
50 #include <dspbridge/dspapi.h>
51 #include <dspbridge/dbdcd.h>
53 #include <dspbridge/resourcecleanup.h>
55 /* ----------------------------------- Defines, Data Structures, Typedefs */
56 #define MAX_TRACEBUFLEN 255
57 #define MAX_LOADARGS 16
59 #define MAX_STREAMS 16
62 /* Used to get dspbridge ioctl table */
63 #define DB_GET_IOC_TABLE(cmd) (DB_GET_MODULE(cmd) >> DB_MODULE_SHIFT)
65 /* Device IOCtl function pointer */
67 u32(*fxn
) (union trapped_args
*args
, void *pr_ctxt
);
71 /* ----------------------------------- Globals */
72 static u32 api_c_refs
;
76 * The order of these functions MUST be the same as the order of the command
77 * numbers defined in dspapi-ioctl.h This is how an IOCTL number in user mode
78 * turns into a function call in kernel mode.
81 /* MGR wrapper functions */
82 static struct api_cmd mgr_cmd
[] = {
83 {mgrwrap_enum_node_info
}, /* MGR_ENUMNODE_INFO */
84 {mgrwrap_enum_proc_info
}, /* MGR_ENUMPROC_INFO */
85 {mgrwrap_register_object
}, /* MGR_REGISTEROBJECT */
86 {mgrwrap_unregister_object
}, /* MGR_UNREGISTEROBJECT */
87 {mgrwrap_wait_for_bridge_events
}, /* MGR_WAIT */
88 {mgrwrap_get_process_resources_info
}, /* MGR_GET_PROC_RES */
91 /* PROC wrapper functions */
92 static struct api_cmd proc_cmd
[] = {
93 {procwrap_attach
}, /* PROC_ATTACH */
94 {procwrap_ctrl
}, /* PROC_CTRL */
95 {procwrap_detach
}, /* PROC_DETACH */
96 {procwrap_enum_node_info
}, /* PROC_ENUMNODE */
97 {procwrap_enum_resources
}, /* PROC_ENUMRESOURCES */
98 {procwrap_get_state
}, /* PROC_GET_STATE */
99 {procwrap_get_trace
}, /* PROC_GET_TRACE */
100 {procwrap_load
}, /* PROC_LOAD */
101 {procwrap_register_notify
}, /* PROC_REGISTERNOTIFY */
102 {procwrap_start
}, /* PROC_START */
103 {procwrap_reserve_memory
}, /* PROC_RSVMEM */
104 {procwrap_un_reserve_memory
}, /* PROC_UNRSVMEM */
105 {procwrap_map
}, /* PROC_MAPMEM */
106 {procwrap_un_map
}, /* PROC_UNMAPMEM */
107 {procwrap_flush_memory
}, /* PROC_FLUSHMEMORY */
108 {procwrap_stop
}, /* PROC_STOP */
109 {procwrap_invalidate_memory
}, /* PROC_INVALIDATEMEMORY */
110 {procwrap_begin_dma
}, /* PROC_BEGINDMA */
111 {procwrap_end_dma
}, /* PROC_ENDDMA */
114 /* NODE wrapper functions */
115 static struct api_cmd node_cmd
[] = {
116 {nodewrap_allocate
}, /* NODE_ALLOCATE */
117 {nodewrap_alloc_msg_buf
}, /* NODE_ALLOCMSGBUF */
118 {nodewrap_change_priority
}, /* NODE_CHANGEPRIORITY */
119 {nodewrap_connect
}, /* NODE_CONNECT */
120 {nodewrap_create
}, /* NODE_CREATE */
121 {nodewrap_delete
}, /* NODE_DELETE */
122 {nodewrap_free_msg_buf
}, /* NODE_FREEMSGBUF */
123 {nodewrap_get_attr
}, /* NODE_GETATTR */
124 {nodewrap_get_message
}, /* NODE_GETMESSAGE */
125 {nodewrap_pause
}, /* NODE_PAUSE */
126 {nodewrap_put_message
}, /* NODE_PUTMESSAGE */
127 {nodewrap_register_notify
}, /* NODE_REGISTERNOTIFY */
128 {nodewrap_run
}, /* NODE_RUN */
129 {nodewrap_terminate
}, /* NODE_TERMINATE */
130 {nodewrap_get_uuid_props
}, /* NODE_GETUUIDPROPS */
133 /* STRM wrapper functions */
134 static struct api_cmd strm_cmd
[] = {
135 {strmwrap_allocate_buffer
}, /* STRM_ALLOCATEBUFFER */
136 {strmwrap_close
}, /* STRM_CLOSE */
137 {strmwrap_free_buffer
}, /* STRM_FREEBUFFER */
138 {strmwrap_get_event_handle
}, /* STRM_GETEVENTHANDLE */
139 {strmwrap_get_info
}, /* STRM_GETINFO */
140 {strmwrap_idle
}, /* STRM_IDLE */
141 {strmwrap_issue
}, /* STRM_ISSUE */
142 {strmwrap_open
}, /* STRM_OPEN */
143 {strmwrap_reclaim
}, /* STRM_RECLAIM */
144 {strmwrap_register_notify
}, /* STRM_REGISTERNOTIFY */
145 {strmwrap_select
}, /* STRM_SELECT */
148 /* CMM wrapper functions */
149 static struct api_cmd cmm_cmd
[] = {
150 {cmmwrap_calloc_buf
}, /* CMM_ALLOCBUF */
151 {cmmwrap_free_buf
}, /* CMM_FREEBUF */
152 {cmmwrap_get_handle
}, /* CMM_GETHANDLE */
153 {cmmwrap_get_info
}, /* CMM_GETINFO */
156 /* Array used to store ioctl table sizes. It can hold up to 8 entries */
157 static u8 size_cmd
[] = {
159 ARRAY_SIZE(proc_cmd
),
160 ARRAY_SIZE(node_cmd
),
161 ARRAY_SIZE(strm_cmd
),
165 static inline void _cp_fm_usr(void *to
, const void __user
* from
,
166 int *err
, unsigned long bytes
)
171 if (unlikely(!from
)) {
176 if (unlikely(copy_from_user(to
, from
, bytes
)))
180 #define CP_FM_USR(to, from, err, n) \
181 _cp_fm_usr(to, from, &(err), (n) * sizeof(*(to)))
183 static inline void _cp_to_usr(void __user
*to
, const void *from
,
184 int *err
, unsigned long bytes
)
194 if (unlikely(copy_to_user(to
, from
, bytes
)))
198 #define CP_TO_USR(to, from, err, n) \
199 _cp_to_usr(to, from, &(err), (n) * sizeof(*(from)))
202 * ======== api_call_dev_ioctl ========
204 * Call the (wrapper) function for the corresponding API IOCTL.
206 inline int api_call_dev_ioctl(u32 cmd
, union trapped_args
*args
,
207 u32
*result
, void *pr_ctxt
)
209 u32(*ioctl_cmd
) (union trapped_args
*args
, void *pr_ctxt
) = NULL
;
212 if (_IOC_TYPE(cmd
) != DB
) {
213 pr_err("%s: Incompatible dspbridge ioctl number\n", __func__
);
217 if (DB_GET_IOC_TABLE(cmd
) > ARRAY_SIZE(size_cmd
)) {
218 pr_err("%s: undefined ioctl module\n", __func__
);
222 /* Check the size of the required cmd table */
224 if (i
> size_cmd
[DB_GET_IOC_TABLE(cmd
)]) {
225 pr_err("%s: requested ioctl %d out of bounds for table %d\n",
226 __func__
, i
, DB_GET_IOC_TABLE(cmd
));
230 switch (DB_GET_MODULE(cmd
)) {
232 ioctl_cmd
= mgr_cmd
[i
].fxn
;
235 ioctl_cmd
= proc_cmd
[i
].fxn
;
238 ioctl_cmd
= node_cmd
[i
].fxn
;
241 ioctl_cmd
= strm_cmd
[i
].fxn
;
244 ioctl_cmd
= cmm_cmd
[i
].fxn
;
249 pr_err("%s: requested ioctl not defined\n", __func__
);
252 *result
= (*ioctl_cmd
) (args
, pr_ctxt
);
262 * ======== api_exit ========
273 * ======== api_init ========
275 * Module initialization used by Bridge API.
291 * ======== api_init_complete2 ========
293 * Perform any required bridge initialization which cannot
294 * be performed in api_init() or dev_start_device() due
295 * to the fact that some services are not yet
296 * completely initialized.
299 * 0: Allow this device to load
302 * Bridge API initialized.
305 int api_init_complete2(void)
308 struct cfg_devnode
*dev_node
;
309 struct dev_object
*hdev_obj
;
310 struct drv_data
*drv_datap
;
313 /* Walk the list of DevObjects, get each devnode, and attempting to
314 * autostart the board. Note that this requires COF loading, which
316 for (hdev_obj
= dev_get_first(); hdev_obj
!= NULL
;
317 hdev_obj
= dev_get_next(hdev_obj
)) {
318 if (dev_get_dev_node(hdev_obj
, &dev_node
))
321 if (dev_get_dev_type(hdev_obj
, &dev_type
))
324 if ((dev_type
== DSP_UNIT
) || (dev_type
== IVA_UNIT
)) {
325 drv_datap
= dev_get_drvdata(bridge
);
327 if (drv_datap
&& drv_datap
->base_img
)
328 proc_auto_start(dev_node
, hdev_obj
);
335 /* TODO: Remove deprecated and not implemented ioctl wrappers */
338 * ======== mgrwrap_enum_node_info ========
340 u32
mgrwrap_enum_node_info(union trapped_args
*args
, void *pr_ctxt
)
345 u32 size
= args
->args_mgr_enumnode_info
.ndb_props_size
;
347 if (size
< sizeof(struct dsp_ndbprops
))
350 pndb_props
= kmalloc(size
, GFP_KERNEL
);
351 if (pndb_props
== NULL
)
356 mgr_enum_node_info(args
->args_mgr_enumnode_info
.node_id
,
357 (struct dsp_ndbprops
*)pndb_props
, size
,
360 CP_TO_USR(args
->args_mgr_enumnode_info
.ndb_props
, pndb_props
, status
,
362 CP_TO_USR(args
->args_mgr_enumnode_info
.num_nodes
, &num_nodes
, status
,
370 * ======== mgrwrap_enum_proc_info ========
372 u32
mgrwrap_enum_proc_info(union trapped_args
*args
, void *pr_ctxt
)
377 u32 size
= args
->args_mgr_enumproc_info
.processor_info_size
;
379 if (size
< sizeof(struct dsp_processorinfo
))
382 processor_info
= kmalloc(size
, GFP_KERNEL
);
383 if (processor_info
== NULL
)
388 mgr_enum_processor_info(args
->args_mgr_enumproc_info
.
390 (struct dsp_processorinfo
*)
391 processor_info
, size
, &num_procs
);
393 CP_TO_USR(args
->args_mgr_enumproc_info
.processor_info
, processor_info
,
395 CP_TO_USR(args
->args_mgr_enumproc_info
.num_procs
, &num_procs
,
397 kfree(processor_info
);
402 #define WRAP_MAP2CALLER(x) x
404 * ======== mgrwrap_register_object ========
406 u32
mgrwrap_register_object(union trapped_args
*args
, void *pr_ctxt
)
409 struct dsp_uuid uuid_obj
;
411 char *psz_path_name
= NULL
;
414 CP_FM_USR(&uuid_obj
, args
->args_mgr_registerobject
.uuid_obj
, status
, 1);
417 /* path_size is increased by 1 to accommodate NULL */
418 path_size
= strlen_user((char *)
419 args
->args_mgr_registerobject
.sz_path_name
) +
421 psz_path_name
= kmalloc(path_size
, GFP_KERNEL
);
422 if (!psz_path_name
) {
426 ret
= strncpy_from_user(psz_path_name
,
427 (char *)args
->args_mgr_registerobject
.
428 sz_path_name
, path_size
);
434 if (args
->args_mgr_registerobject
.obj_type
>= DSP_DCDMAXOBJTYPE
) {
439 status
= dcd_register_object(&uuid_obj
,
440 args
->args_mgr_registerobject
.obj_type
,
441 (char *)psz_path_name
);
443 kfree(psz_path_name
);
448 * ======== mgrwrap_unregister_object ========
450 u32
mgrwrap_unregister_object(union trapped_args
*args
, void *pr_ctxt
)
453 struct dsp_uuid uuid_obj
;
455 CP_FM_USR(&uuid_obj
, args
->args_mgr_registerobject
.uuid_obj
, status
, 1);
459 status
= dcd_unregister_object(&uuid_obj
,
460 args
->args_mgr_unregisterobject
.
468 * ======== mgrwrap_wait_for_bridge_events ========
470 u32
mgrwrap_wait_for_bridge_events(union trapped_args
*args
, void *pr_ctxt
)
473 struct dsp_notification
*anotifications
[MAX_EVENTS
];
474 struct dsp_notification notifications
[MAX_EVENTS
];
476 u32 count
= args
->args_mgr_wait
.count
;
478 if (count
> MAX_EVENTS
)
481 /* get the array of pointers to user structures */
482 CP_FM_USR(anotifications
, args
->args_mgr_wait
.anotifications
,
485 for (i
= 0; i
< count
; i
++) {
486 CP_FM_USR(¬ifications
[i
], anotifications
[i
], status
, 1);
487 if (status
|| !notifications
[i
].handle
) {
491 /* set the array of pointers to kernel structures */
492 anotifications
[i
] = ¬ifications
[i
];
495 status
= mgr_wait_for_bridge_events(anotifications
, count
,
500 CP_TO_USR(args
->args_mgr_wait
.index
, &index
, status
, 1);
505 * ======== MGRWRAP_GetProcessResourceInfo ========
507 u32 __deprecated
mgrwrap_get_process_resources_info(union trapped_args
* args
,
510 pr_err("%s: deprecated dspbridge ioctl\n", __func__
);
515 * ======== procwrap_attach ========
517 u32
procwrap_attach(union trapped_args
*args
, void *pr_ctxt
)
521 struct dsp_processorattrin proc_attr_in
, *attr_in
= NULL
;
523 /* Optional argument */
524 if (args
->args_proc_attach
.attr_in
) {
525 CP_FM_USR(&proc_attr_in
, args
->args_proc_attach
.attr_in
, status
,
528 attr_in
= &proc_attr_in
;
533 status
= proc_attach(args
->args_proc_attach
.processor_id
, attr_in
,
534 &processor
, pr_ctxt
);
535 CP_TO_USR(args
->args_proc_attach
.ph_processor
, &processor
, status
, 1);
541 * ======== procwrap_ctrl ========
543 u32
procwrap_ctrl(union trapped_args
*args
, void *pr_ctxt
)
545 u32 cb_data_size
, __user
* psize
= (u32 __user
*)
546 args
->args_proc_ctrl
.args
;
549 void *hprocessor
= ((struct process_context
*)pr_ctxt
)->processor
;
552 if (get_user(cb_data_size
, psize
)) {
556 cb_data_size
+= sizeof(u32
);
557 pargs
= kmalloc(cb_data_size
, GFP_KERNEL
);
563 CP_FM_USR(pargs
, args
->args_proc_ctrl
.args
, status
,
567 status
= proc_ctrl(hprocessor
,
568 args
->args_proc_ctrl
.cmd
,
569 (struct dsp_cbdata
*)pargs
);
572 /* CP_TO_USR(args->args_proc_ctrl.args, pargs, status, 1); */
579 * ======== procwrap_detach ========
581 u32 __deprecated
procwrap_detach(union trapped_args
* args
, void *pr_ctxt
)
583 /* proc_detach called at bridge_release only */
584 pr_err("%s: deprecated dspbridge ioctl\n", __func__
);
589 * ======== procwrap_enum_node_info ========
591 u32
procwrap_enum_node_info(union trapped_args
*args
, void *pr_ctxt
)
594 void *node_tab
[MAX_NODES
];
597 void *hprocessor
= ((struct process_context
*)pr_ctxt
)->processor
;
599 if (!args
->args_proc_enumnode_info
.node_tab_size
)
602 status
= proc_enum_nodes(hprocessor
,
604 args
->args_proc_enumnode_info
.node_tab_size
,
605 &num_nodes
, &alloc_cnt
);
606 CP_TO_USR(args
->args_proc_enumnode_info
.node_tab
, node_tab
, status
,
608 CP_TO_USR(args
->args_proc_enumnode_info
.num_nodes
, &num_nodes
,
610 CP_TO_USR(args
->args_proc_enumnode_info
.allocated
, &alloc_cnt
,
615 u32
procwrap_end_dma(union trapped_args
*args
, void *pr_ctxt
)
619 if (args
->args_proc_dma
.dir
>= DMA_NONE
)
622 status
= proc_end_dma(pr_ctxt
,
623 args
->args_proc_dma
.mpu_addr
,
624 args
->args_proc_dma
.size
,
625 args
->args_proc_dma
.dir
);
629 u32
procwrap_begin_dma(union trapped_args
*args
, void *pr_ctxt
)
633 if (args
->args_proc_dma
.dir
>= DMA_NONE
)
636 status
= proc_begin_dma(pr_ctxt
,
637 args
->args_proc_dma
.mpu_addr
,
638 args
->args_proc_dma
.size
,
639 args
->args_proc_dma
.dir
);
644 * ======== procwrap_flush_memory ========
646 u32
procwrap_flush_memory(union trapped_args
*args
, void *pr_ctxt
)
650 if (args
->args_proc_flushmemory
.flags
>
651 PROC_WRITEBACK_INVALIDATE_MEM
)
654 status
= proc_flush_memory(pr_ctxt
,
655 args
->args_proc_flushmemory
.mpu_addr
,
656 args
->args_proc_flushmemory
.size
,
657 args
->args_proc_flushmemory
.flags
);
662 * ======== procwrap_invalidate_memory ========
664 u32
procwrap_invalidate_memory(union trapped_args
*args
, void *pr_ctxt
)
669 proc_invalidate_memory(pr_ctxt
,
670 args
->args_proc_invalidatememory
.mpu_addr
,
671 args
->args_proc_invalidatememory
.size
);
676 * ======== procwrap_enum_resources ========
678 u32
procwrap_enum_resources(union trapped_args
*args
, void *pr_ctxt
)
681 struct dsp_resourceinfo resource_info
;
682 void *hprocessor
= ((struct process_context
*)pr_ctxt
)->processor
;
684 if (args
->args_proc_enumresources
.resource_info_size
<
685 sizeof(struct dsp_resourceinfo
))
689 proc_get_resource_info(hprocessor
,
690 args
->args_proc_enumresources
.resource_type
,
692 args
->args_proc_enumresources
.
695 CP_TO_USR(args
->args_proc_enumresources
.resource_info
, &resource_info
,
703 * ======== procwrap_get_state ========
705 u32
procwrap_get_state(union trapped_args
*args
, void *pr_ctxt
)
708 struct dsp_processorstate proc_state
;
709 void *hprocessor
= ((struct process_context
*)pr_ctxt
)->processor
;
711 if (args
->args_proc_getstate
.state_info_size
<
712 sizeof(struct dsp_processorstate
))
715 status
= proc_get_state(hprocessor
, &proc_state
,
716 args
->args_proc_getstate
.state_info_size
);
717 CP_TO_USR(args
->args_proc_getstate
.proc_state_obj
, &proc_state
, status
,
724 * ======== procwrap_get_trace ========
726 u32
procwrap_get_trace(union trapped_args
*args
, void *pr_ctxt
)
730 void *hprocessor
= ((struct process_context
*)pr_ctxt
)->processor
;
732 if (args
->args_proc_gettrace
.max_size
> MAX_TRACEBUFLEN
)
735 pbuf
= kzalloc(args
->args_proc_gettrace
.max_size
, GFP_KERNEL
);
737 status
= proc_get_trace(hprocessor
, pbuf
,
738 args
->args_proc_gettrace
.max_size
);
742 CP_TO_USR(args
->args_proc_gettrace
.buf
, pbuf
, status
,
743 args
->args_proc_gettrace
.max_size
);
750 * ======== procwrap_load ========
752 u32
procwrap_load(union trapped_args
*args
, void *pr_ctxt
)
757 s32 count
= args
->args_proc_load
.argc_index
;
758 u8
**argv
= NULL
, **envp
= NULL
;
759 void *hprocessor
= ((struct process_context
*)pr_ctxt
)->processor
;
761 if (count
<= 0 || count
> MAX_LOADARGS
) {
766 argv
= kmalloc(count
* sizeof(u8
*), GFP_KERNEL
);
772 CP_FM_USR(argv
, args
->args_proc_load
.user_args
, status
, count
);
779 for (i
= 0; i
< count
; i
++) {
781 /* User space pointer to argument */
782 temp
= (char *)argv
[i
];
783 /* len is increased by 1 to accommodate NULL */
784 len
= strlen_user((char *)temp
) + 1;
785 /* Kernel space pointer to argument */
786 argv
[i
] = kmalloc(len
, GFP_KERNEL
);
788 CP_FM_USR(argv
[i
], temp
, status
, len
);
800 /* TODO: validate this */
801 if (args
->args_proc_load
.user_envp
) {
802 /* number of elements in the envp array including NULL */
806 args
->args_proc_load
.user_envp
+ count
)) {
812 envp
= kmalloc(count
* sizeof(u8
*), GFP_KERNEL
);
818 CP_FM_USR(envp
, args
->args_proc_load
.user_envp
, status
, count
);
824 for (i
= 0; envp
[i
]; i
++) {
825 /* User space pointer to argument */
826 temp
= (char *)envp
[i
];
827 /* len is increased by 1 to accommodate NULL */
828 len
= strlen_user((char *)temp
) + 1;
829 /* Kernel space pointer to argument */
830 envp
[i
] = kmalloc(len
, GFP_KERNEL
);
832 CP_FM_USR(envp
[i
], temp
, status
, len
);
846 status
= proc_load(hprocessor
,
847 args
->args_proc_load
.argc_index
,
848 (const char **)argv
, (const char **)envp
);
860 count
= args
->args_proc_load
.argc_index
;
861 for (i
= 0; (i
< count
) && argv
[i
]; i
++)
871 * ======== procwrap_map ========
873 u32
procwrap_map(union trapped_args
*args
, void *pr_ctxt
)
877 void *hprocessor
= ((struct process_context
*)pr_ctxt
)->processor
;
879 if (!args
->args_proc_mapmem
.size
)
882 status
= proc_map(args
->args_proc_mapmem
.processor
,
883 args
->args_proc_mapmem
.mpu_addr
,
884 args
->args_proc_mapmem
.size
,
885 args
->args_proc_mapmem
.req_addr
, &map_addr
,
886 args
->args_proc_mapmem
.map_attr
, pr_ctxt
);
888 if (put_user(map_addr
, args
->args_proc_mapmem
.map_addr
)) {
890 proc_un_map(hprocessor
, map_addr
, pr_ctxt
);
898 * ======== procwrap_register_notify ========
900 u32
procwrap_register_notify(union trapped_args
*args
, void *pr_ctxt
)
903 struct dsp_notification notification
;
904 void *hprocessor
= ((struct process_context
*)pr_ctxt
)->processor
;
906 /* Initialize the notification data structure */
907 notification
.name
= NULL
;
908 notification
.handle
= NULL
;
910 status
= proc_register_notify(hprocessor
,
911 args
->args_proc_register_notify
.event_mask
,
912 args
->args_proc_register_notify
.notify_type
,
914 CP_TO_USR(args
->args_proc_register_notify
.notification
, ¬ification
,
920 * ======== procwrap_reserve_memory ========
922 u32
procwrap_reserve_memory(union trapped_args
*args
, void *pr_ctxt
)
926 void *hprocessor
= ((struct process_context
*)pr_ctxt
)->processor
;
928 if ((args
->args_proc_rsvmem
.size
<= 0) ||
929 (args
->args_proc_rsvmem
.size
& (PG_SIZE4K
- 1)) != 0)
932 status
= proc_reserve_memory(hprocessor
,
933 args
->args_proc_rsvmem
.size
, &prsv_addr
,
936 if (put_user(prsv_addr
, args
->args_proc_rsvmem
.rsv_addr
)) {
938 proc_un_reserve_memory(args
->args_proc_rsvmem
.
939 processor
, prsv_addr
, pr_ctxt
);
946 * ======== procwrap_start ========
948 u32
procwrap_start(union trapped_args
*args
, void *pr_ctxt
)
952 ret
= proc_start(((struct process_context
*)pr_ctxt
)->processor
);
957 * ======== procwrap_un_map ========
959 u32
procwrap_un_map(union trapped_args
*args
, void *pr_ctxt
)
963 status
= proc_un_map(((struct process_context
*)pr_ctxt
)->processor
,
964 args
->args_proc_unmapmem
.map_addr
, pr_ctxt
);
969 * ======== procwrap_un_reserve_memory ========
971 u32
procwrap_un_reserve_memory(union trapped_args
*args
, void *pr_ctxt
)
974 void *hprocessor
= ((struct process_context
*)pr_ctxt
)->processor
;
976 status
= proc_un_reserve_memory(hprocessor
,
977 args
->args_proc_unrsvmem
.rsv_addr
,
983 * ======== procwrap_stop ========
985 u32
procwrap_stop(union trapped_args
*args
, void *pr_ctxt
)
989 ret
= proc_stop(((struct process_context
*)pr_ctxt
)->processor
);
995 * ======== find_handle =========
997 inline void find_node_handle(struct node_res_object
**noderes
,
998 void *pr_ctxt
, void *hnode
)
1001 *noderes
= idr_find(((struct process_context
*)pr_ctxt
)->node_id
,
1009 * ======== nodewrap_allocate ========
1011 u32
nodewrap_allocate(union trapped_args
*args
, void *pr_ctxt
)
1014 struct dsp_uuid node_uuid
;
1015 u32 cb_data_size
= 0;
1016 u32 __user
*psize
= (u32 __user
*) args
->args_node_allocate
.args
;
1018 struct dsp_nodeattrin proc_attr_in
, *attr_in
= NULL
;
1019 struct node_res_object
*node_res
;
1021 void *hprocessor
= ((struct process_context
*)pr_ctxt
)->processor
;
1023 /* Optional argument */
1025 if (get_user(cb_data_size
, psize
))
1028 cb_data_size
+= sizeof(u32
);
1030 pargs
= kmalloc(cb_data_size
, GFP_KERNEL
);
1035 CP_FM_USR(pargs
, args
->args_node_allocate
.args
, status
,
1038 CP_FM_USR(&node_uuid
, args
->args_node_allocate
.node_id_ptr
, status
, 1);
1041 /* Optional argument */
1042 if (args
->args_node_allocate
.attr_in
) {
1043 CP_FM_USR(&proc_attr_in
, args
->args_node_allocate
.attr_in
,
1046 attr_in
= &proc_attr_in
;
1052 status
= node_allocate(hprocessor
,
1053 &node_uuid
, (struct dsp_cbdata
*)pargs
,
1054 attr_in
, &node_res
, pr_ctxt
);
1057 nodeid
= node_res
->id
+ 1;
1058 CP_TO_USR(args
->args_node_allocate
.node
, &nodeid
,
1062 node_delete(node_res
, pr_ctxt
);
1072 * ======== nodewrap_alloc_msg_buf ========
1074 u32
nodewrap_alloc_msg_buf(union trapped_args
*args
, void *pr_ctxt
)
1077 struct dsp_bufferattr
*pattr
= NULL
;
1078 struct dsp_bufferattr attr
;
1080 struct node_res_object
*node_res
;
1082 find_node_handle(&node_res
, pr_ctxt
,
1083 args
->args_node_allocmsgbuf
.node
);
1088 if (!args
->args_node_allocmsgbuf
.size
)
1091 if (args
->args_node_allocmsgbuf
.attr
) { /* Optional argument */
1092 CP_FM_USR(&attr
, args
->args_node_allocmsgbuf
.attr
, status
, 1);
1098 CP_FM_USR(&pbuffer
, args
->args_node_allocmsgbuf
.buffer
, status
, 1);
1100 status
= node_alloc_msg_buf(node_res
->node
,
1101 args
->args_node_allocmsgbuf
.size
,
1104 CP_TO_USR(args
->args_node_allocmsgbuf
.buffer
, &pbuffer
, status
, 1);
1109 * ======== nodewrap_change_priority ========
1111 u32
nodewrap_change_priority(union trapped_args
*args
, void *pr_ctxt
)
1114 struct node_res_object
*node_res
;
1116 find_node_handle(&node_res
, pr_ctxt
,
1117 args
->args_node_changepriority
.node
);
1122 ret
= node_change_priority(node_res
->node
,
1123 args
->args_node_changepriority
.prio
);
1129 * ======== nodewrap_connect ========
1131 u32
nodewrap_connect(union trapped_args
*args
, void *pr_ctxt
)
1134 struct dsp_strmattr attrs
;
1135 struct dsp_strmattr
*pattrs
= NULL
;
1137 u32 __user
*psize
= (u32 __user
*) args
->args_node_connect
.conn_param
;
1139 struct node_res_object
*node_res1
, *node_res2
;
1140 struct node_object
*node1
= NULL
, *node2
= NULL
;
1142 if ((int)args
->args_node_connect
.node
!= DSP_HGPPNODE
) {
1143 find_node_handle(&node_res1
, pr_ctxt
,
1144 args
->args_node_connect
.node
);
1146 node1
= node_res1
->node
;
1148 node1
= args
->args_node_connect
.node
;
1151 if ((int)args
->args_node_connect
.other_node
!= DSP_HGPPNODE
) {
1152 find_node_handle(&node_res2
, pr_ctxt
,
1153 args
->args_node_connect
.other_node
);
1155 node2
= node_res2
->node
;
1157 node2
= args
->args_node_connect
.other_node
;
1160 if (!node1
|| !node2
)
1163 /* Optional argument */
1165 if (get_user(cb_data_size
, psize
))
1168 cb_data_size
+= sizeof(u32
);
1170 pargs
= kmalloc(cb_data_size
, GFP_KERNEL
);
1171 if (pargs
== NULL
) {
1177 CP_FM_USR(pargs
, args
->args_node_connect
.conn_param
, status
,
1182 if (args
->args_node_connect
.attrs
) { /* Optional argument */
1183 CP_FM_USR(&attrs
, args
->args_node_connect
.attrs
, status
, 1);
1189 status
= node_connect(node1
,
1190 args
->args_node_connect
.stream_id
,
1192 args
->args_node_connect
.other_stream
,
1193 pattrs
, (struct dsp_cbdata
*)pargs
);
1202 * ======== nodewrap_create ========
1204 u32
nodewrap_create(union trapped_args
*args
, void *pr_ctxt
)
1207 struct node_res_object
*node_res
;
1209 find_node_handle(&node_res
, pr_ctxt
, args
->args_node_create
.node
);
1214 ret
= node_create(node_res
->node
);
1220 * ======== nodewrap_delete ========
1222 u32
nodewrap_delete(union trapped_args
*args
, void *pr_ctxt
)
1225 struct node_res_object
*node_res
;
1227 find_node_handle(&node_res
, pr_ctxt
, args
->args_node_delete
.node
);
1232 ret
= node_delete(node_res
, pr_ctxt
);
1238 * ======== nodewrap_free_msg_buf ========
1240 u32
nodewrap_free_msg_buf(union trapped_args
*args
, void *pr_ctxt
)
1243 struct dsp_bufferattr
*pattr
= NULL
;
1244 struct dsp_bufferattr attr
;
1245 struct node_res_object
*node_res
;
1247 find_node_handle(&node_res
, pr_ctxt
, args
->args_node_freemsgbuf
.node
);
1252 if (args
->args_node_freemsgbuf
.attr
) { /* Optional argument */
1253 CP_FM_USR(&attr
, args
->args_node_freemsgbuf
.attr
, status
, 1);
1259 if (!args
->args_node_freemsgbuf
.buffer
)
1263 status
= node_free_msg_buf(node_res
->node
,
1264 args
->args_node_freemsgbuf
.buffer
,
1272 * ======== nodewrap_get_attr ========
1274 u32
nodewrap_get_attr(union trapped_args
*args
, void *pr_ctxt
)
1277 struct dsp_nodeattr attr
;
1278 struct node_res_object
*node_res
;
1280 find_node_handle(&node_res
, pr_ctxt
, args
->args_node_getattr
.node
);
1285 status
= node_get_attr(node_res
->node
, &attr
,
1286 args
->args_node_getattr
.attr_size
);
1287 CP_TO_USR(args
->args_node_getattr
.attr
, &attr
, status
, 1);
1293 * ======== nodewrap_get_message ========
1295 u32
nodewrap_get_message(union trapped_args
*args
, void *pr_ctxt
)
1299 struct node_res_object
*node_res
;
1301 find_node_handle(&node_res
, pr_ctxt
, args
->args_node_getmessage
.node
);
1306 status
= node_get_message(node_res
->node
, &msg
,
1307 args
->args_node_getmessage
.timeout
);
1309 CP_TO_USR(args
->args_node_getmessage
.message
, &msg
, status
, 1);
1315 * ======== nodewrap_pause ========
1317 u32
nodewrap_pause(union trapped_args
*args
, void *pr_ctxt
)
1320 struct node_res_object
*node_res
;
1322 find_node_handle(&node_res
, pr_ctxt
, args
->args_node_pause
.node
);
1327 ret
= node_pause(node_res
->node
);
1333 * ======== nodewrap_put_message ========
1335 u32
nodewrap_put_message(union trapped_args
*args
, void *pr_ctxt
)
1339 struct node_res_object
*node_res
;
1341 find_node_handle(&node_res
, pr_ctxt
, args
->args_node_putmessage
.node
);
1346 CP_FM_USR(&msg
, args
->args_node_putmessage
.message
, status
, 1);
1350 node_put_message(node_res
->node
, &msg
,
1351 args
->args_node_putmessage
.timeout
);
1358 * ======== nodewrap_register_notify ========
1360 u32
nodewrap_register_notify(union trapped_args
*args
, void *pr_ctxt
)
1363 struct dsp_notification notification
;
1364 struct node_res_object
*node_res
;
1366 find_node_handle(&node_res
, pr_ctxt
,
1367 args
->args_node_registernotify
.node
);
1372 /* Initialize the notification data structure */
1373 notification
.name
= NULL
;
1374 notification
.handle
= NULL
;
1376 if (!args
->args_proc_register_notify
.event_mask
)
1377 CP_FM_USR(¬ification
,
1378 args
->args_proc_register_notify
.notification
,
1381 status
= node_register_notify(node_res
->node
,
1382 args
->args_node_registernotify
.event_mask
,
1383 args
->args_node_registernotify
.
1384 notify_type
, ¬ification
);
1385 CP_TO_USR(args
->args_node_registernotify
.notification
, ¬ification
,
1391 * ======== nodewrap_run ========
1393 u32
nodewrap_run(union trapped_args
*args
, void *pr_ctxt
)
1396 struct node_res_object
*node_res
;
1398 find_node_handle(&node_res
, pr_ctxt
, args
->args_node_run
.node
);
1403 ret
= node_run(node_res
->node
);
1409 * ======== nodewrap_terminate ========
1411 u32
nodewrap_terminate(union trapped_args
*args
, void *pr_ctxt
)
1415 struct node_res_object
*node_res
;
1417 find_node_handle(&node_res
, pr_ctxt
, args
->args_node_terminate
.node
);
1422 status
= node_terminate(node_res
->node
, &tempstatus
);
1424 CP_TO_USR(args
->args_node_terminate
.status
, &tempstatus
, status
, 1);
1430 * ======== nodewrap_get_uuid_props ========
1432 u32
nodewrap_get_uuid_props(union trapped_args
*args
, void *pr_ctxt
)
1435 struct dsp_uuid node_uuid
;
1436 struct dsp_ndbprops
*pnode_props
= NULL
;
1437 void *hprocessor
= ((struct process_context
*)pr_ctxt
)->processor
;
1439 CP_FM_USR(&node_uuid
, args
->args_node_getuuidprops
.node_id_ptr
, status
,
1443 pnode_props
= kmalloc(sizeof(struct dsp_ndbprops
), GFP_KERNEL
);
1444 if (pnode_props
!= NULL
) {
1446 node_get_uuid_props(hprocessor
, &node_uuid
, pnode_props
);
1447 CP_TO_USR(args
->args_node_getuuidprops
.node_props
, pnode_props
,
1457 * ======== find_strm_handle =========
1459 inline void find_strm_handle(struct strm_res_object
**strmres
,
1460 void *pr_ctxt
, void *hstream
)
1463 *strmres
= idr_find(((struct process_context
*)pr_ctxt
)->stream_id
,
1470 * ======== strmwrap_allocate_buffer ========
1472 u32
strmwrap_allocate_buffer(union trapped_args
*args
, void *pr_ctxt
)
1475 u8
**ap_buffer
= NULL
;
1476 u32 num_bufs
= args
->args_strm_allocatebuffer
.num_bufs
;
1477 struct strm_res_object
*strm_res
;
1479 find_strm_handle(&strm_res
, pr_ctxt
,
1480 args
->args_strm_allocatebuffer
.stream
);
1485 if (num_bufs
> MAX_BUFS
)
1488 ap_buffer
= kmalloc((num_bufs
* sizeof(u8
*)), GFP_KERNEL
);
1489 if (ap_buffer
== NULL
)
1492 status
= strm_allocate_buffer(strm_res
,
1493 args
->args_strm_allocatebuffer
.size
,
1494 ap_buffer
, num_bufs
, pr_ctxt
);
1496 CP_TO_USR(args
->args_strm_allocatebuffer
.ap_buffer
, ap_buffer
,
1500 strm_free_buffer(strm_res
,
1501 ap_buffer
, num_bufs
, pr_ctxt
);
1510 * ======== strmwrap_close ========
1512 u32
strmwrap_close(union trapped_args
*args
, void *pr_ctxt
)
1514 struct strm_res_object
*strm_res
;
1516 find_strm_handle(&strm_res
, pr_ctxt
, args
->args_strm_close
.stream
);
1521 return strm_close(strm_res
, pr_ctxt
);
1525 * ======== strmwrap_free_buffer ========
1527 u32
strmwrap_free_buffer(union trapped_args
*args
, void *pr_ctxt
)
1530 u8
**ap_buffer
= NULL
;
1531 u32 num_bufs
= args
->args_strm_freebuffer
.num_bufs
;
1532 struct strm_res_object
*strm_res
;
1534 find_strm_handle(&strm_res
, pr_ctxt
,
1535 args
->args_strm_freebuffer
.stream
);
1540 if (num_bufs
> MAX_BUFS
)
1543 ap_buffer
= kmalloc((num_bufs
* sizeof(u8
*)), GFP_KERNEL
);
1544 if (ap_buffer
== NULL
)
1547 CP_FM_USR(ap_buffer
, args
->args_strm_freebuffer
.ap_buffer
, status
,
1551 status
= strm_free_buffer(strm_res
,
1552 ap_buffer
, num_bufs
, pr_ctxt
);
1554 CP_TO_USR(args
->args_strm_freebuffer
.ap_buffer
, ap_buffer
, status
,
1562 * ======== strmwrap_get_event_handle ========
1564 u32 __deprecated
strmwrap_get_event_handle(union trapped_args
* args
,
1567 pr_err("%s: deprecated dspbridge ioctl\n", __func__
);
1572 * ======== strmwrap_get_info ========
1574 u32
strmwrap_get_info(union trapped_args
*args
, void *pr_ctxt
)
1577 struct stream_info strm_info
;
1578 struct dsp_streaminfo user
;
1579 struct dsp_streaminfo
*temp
;
1580 struct strm_res_object
*strm_res
;
1582 find_strm_handle(&strm_res
, pr_ctxt
,
1583 args
->args_strm_getinfo
.stream
);
1588 CP_FM_USR(&strm_info
, args
->args_strm_getinfo
.stream_info
, status
, 1);
1589 temp
= strm_info
.user_strm
;
1591 strm_info
.user_strm
= &user
;
1594 status
= strm_get_info(strm_res
->stream
,
1596 args
->args_strm_getinfo
.
1599 CP_TO_USR(temp
, strm_info
.user_strm
, status
, 1);
1600 strm_info
.user_strm
= temp
;
1601 CP_TO_USR(args
->args_strm_getinfo
.stream_info
, &strm_info
, status
, 1);
1606 * ======== strmwrap_idle ========
1608 u32
strmwrap_idle(union trapped_args
*args
, void *pr_ctxt
)
1611 struct strm_res_object
*strm_res
;
1613 find_strm_handle(&strm_res
, pr_ctxt
, args
->args_strm_idle
.stream
);
1618 ret
= strm_idle(strm_res
->stream
, args
->args_strm_idle
.flush_flag
);
1624 * ======== strmwrap_issue ========
1626 u32
strmwrap_issue(union trapped_args
*args
, void *pr_ctxt
)
1629 struct strm_res_object
*strm_res
;
1631 find_strm_handle(&strm_res
, pr_ctxt
, args
->args_strm_issue
.stream
);
1636 if (!args
->args_strm_issue
.buffer
)
1639 /* No need of doing CP_FM_USR for the user buffer (pbuffer)
1640 as this is done in Bridge internal function bridge_chnl_add_io_req
1642 status
= strm_issue(strm_res
->stream
,
1643 args
->args_strm_issue
.buffer
,
1644 args
->args_strm_issue
.bytes
,
1645 args
->args_strm_issue
.buf_size
,
1646 args
->args_strm_issue
.arg
);
1652 * ======== strmwrap_open ========
1654 u32
strmwrap_open(union trapped_args
*args
, void *pr_ctxt
)
1657 struct strm_attr attr
;
1658 struct strm_res_object
*strm_res_obj
;
1659 struct dsp_streamattrin strm_attr_in
;
1660 struct node_res_object
*node_res
;
1663 find_node_handle(&node_res
, pr_ctxt
, args
->args_strm_open
.node
);
1668 CP_FM_USR(&attr
, args
->args_strm_open
.attr_in
, status
, 1);
1670 if (attr
.stream_attr_in
!= NULL
) { /* Optional argument */
1671 CP_FM_USR(&strm_attr_in
, attr
.stream_attr_in
, status
, 1);
1673 attr
.stream_attr_in
= &strm_attr_in
;
1674 if (attr
.stream_attr_in
->strm_mode
== STRMMODE_LDMA
)
1679 status
= strm_open(node_res
->node
,
1680 args
->args_strm_open
.direction
,
1681 args
->args_strm_open
.index
, &attr
, &strm_res_obj
,
1684 strmid
= strm_res_obj
->id
+ 1;
1685 CP_TO_USR(args
->args_strm_open
.stream
, &strmid
, status
, 1);
1691 * ======== strmwrap_reclaim ========
1693 u32
strmwrap_reclaim(union trapped_args
*args
, void *pr_ctxt
)
1700 struct strm_res_object
*strm_res
;
1702 find_strm_handle(&strm_res
, pr_ctxt
, args
->args_strm_reclaim
.stream
);
1707 status
= strm_reclaim(strm_res
->stream
, &buf_ptr
,
1708 &ul_bytes
, &ul_buf_size
, &dw_arg
);
1709 CP_TO_USR(args
->args_strm_reclaim
.buf_ptr
, &buf_ptr
, status
, 1);
1710 CP_TO_USR(args
->args_strm_reclaim
.bytes
, &ul_bytes
, status
, 1);
1711 CP_TO_USR(args
->args_strm_reclaim
.arg
, &dw_arg
, status
, 1);
1713 if (args
->args_strm_reclaim
.buf_size_ptr
!= NULL
) {
1714 CP_TO_USR(args
->args_strm_reclaim
.buf_size_ptr
, &ul_buf_size
,
1722 * ======== strmwrap_register_notify ========
1724 u32
strmwrap_register_notify(union trapped_args
*args
, void *pr_ctxt
)
1727 struct dsp_notification notification
;
1728 struct strm_res_object
*strm_res
;
1730 find_strm_handle(&strm_res
, pr_ctxt
,
1731 args
->args_strm_registernotify
.stream
);
1736 /* Initialize the notification data structure */
1737 notification
.name
= NULL
;
1738 notification
.handle
= NULL
;
1740 status
= strm_register_notify(strm_res
->stream
,
1741 args
->args_strm_registernotify
.event_mask
,
1742 args
->args_strm_registernotify
.
1743 notify_type
, ¬ification
);
1744 CP_TO_USR(args
->args_strm_registernotify
.notification
, ¬ification
,
1751 * ======== strmwrap_select ========
1753 u32
strmwrap_select(union trapped_args
*args
, void *pr_ctxt
)
1756 struct strm_object
*strm_tab
[MAX_STREAMS
];
1758 struct strm_res_object
*strm_res
;
1759 int *ids
[MAX_STREAMS
];
1762 if (args
->args_strm_select
.strm_num
> MAX_STREAMS
)
1765 CP_FM_USR(ids
, args
->args_strm_select
.stream_tab
, status
,
1766 args
->args_strm_select
.strm_num
);
1771 for (i
= 0; i
< args
->args_strm_select
.strm_num
; i
++) {
1772 find_strm_handle(&strm_res
, pr_ctxt
, ids
[i
]);
1777 strm_tab
[i
] = strm_res
->stream
;
1781 status
= strm_select(strm_tab
, args
->args_strm_select
.strm_num
,
1782 &mask
, args
->args_strm_select
.timeout
);
1784 CP_TO_USR(args
->args_strm_select
.mask
, &mask
, status
, 1);
1791 * ======== cmmwrap_calloc_buf ========
1793 u32 __deprecated
cmmwrap_calloc_buf(union trapped_args
* args
, void *pr_ctxt
)
1795 /* This operation is done in kernel */
1796 pr_err("%s: deprecated dspbridge ioctl\n", __func__
);
1801 * ======== cmmwrap_free_buf ========
1803 u32 __deprecated
cmmwrap_free_buf(union trapped_args
* args
, void *pr_ctxt
)
1805 /* This operation is done in kernel */
1806 pr_err("%s: deprecated dspbridge ioctl\n", __func__
);
1811 * ======== cmmwrap_get_handle ========
1813 u32
cmmwrap_get_handle(union trapped_args
*args
, void *pr_ctxt
)
1816 struct cmm_object
*hcmm_mgr
;
1817 void *hprocessor
= ((struct process_context
*)pr_ctxt
)->processor
;
1819 status
= cmm_get_handle(hprocessor
, &hcmm_mgr
);
1821 CP_TO_USR(args
->args_cmm_gethandle
.cmm_mgr
, &hcmm_mgr
, status
, 1);
1827 * ======== cmmwrap_get_info ========
1829 u32
cmmwrap_get_info(union trapped_args
*args
, void *pr_ctxt
)
1832 struct cmm_info cmm_info_obj
;
1834 status
= cmm_get_info(args
->args_cmm_getinfo
.cmm_mgr
, &cmm_info_obj
);
1836 CP_TO_USR(args
->args_cmm_getinfo
.cmm_info_obj
, &cmm_info_obj
, status
,