apps: machine: zynqmp_r5: correct IPI setting.
[processor-sdk/open-amp.git] / lib / proxy / rpmsg_retarget.c
1 #include "openamp/open_amp.h"
2 #include "openamp/rpmsg_retarget.h"
3 #include "metal/alloc.h"
4 #include <stdio.h>
5 #include <string.h>
6 #include <fcntl.h>
8 /*************************************************************************
9  *      Description
10  *      This files contains rpmsg based redefinitions for C RTL system calls
11  *      such as _open, _read, _write, _close.
12  *************************************************************************/
13 static struct _rpc_data *rpc_data = 0;
15 int send_rpc(void *data, int len);
17 void rpc_cb(struct rpmsg_channel *rtl_rp_chnl, void *data, int len, void *priv,
18             unsigned long src)
19 {
20         (void)priv;
21         (void)src;
23         memcpy(rpc_data->rpc_response, data, len);
25         atomic_flag_clear(&rpc_data->sync);
26         if (rpc_data->rpc_response->id == TERM_SYSCALL_ID) {
27                 /* Application terminate signal is received from the proxy app,
28                  * so let the application know of terminate message.
29                  */
30                 rpc_data->shutdown_cb(rtl_rp_chnl);
31         }
32 }
34 int send_rpc(void *data, int len)
35 {
36         int retval;
38         retval = rpmsg_sendto(rpc_data->rpmsg_chnl, data, len, PROXY_ENDPOINT);
39         return retval;
40 }
42 int rpmsg_retarget_init(struct rpmsg_channel *rp_chnl, rpc_shutdown_cb cb)
43 {
44         /* Allocate memory for rpc control block */
45         rpc_data = (struct _rpc_data *)metal_allocate_memory(sizeof(struct _rpc_data));
47         /* Create a mutex for synchronization */
48         metal_mutex_init(&rpc_data->rpc_lock);
50         /* Create a mutex for synchronization */
51         atomic_store(&rpc_data->sync, 1);
53         /* Create a endpoint to handle rpc response from master */
54         rpc_data->rpmsg_chnl = rp_chnl;
55         rpc_data->rp_ept = rpmsg_create_ept(rpc_data->rpmsg_chnl, rpc_cb,
56                                             RPMSG_NULL, PROXY_ENDPOINT);
57         rpc_data->rpc = metal_allocate_memory(RPC_BUFF_SIZE);
58         rpc_data->rpc_response = metal_allocate_memory(RPC_BUFF_SIZE);
59         rpc_data->shutdown_cb = cb;
61         return 0;
62 }
64 int rpmsg_retarget_deinit(struct rpmsg_channel *rp_chnl)
65 {
66         (void)rp_chnl;
68         metal_free_memory(rpc_data->rpc);
69         metal_free_memory(rpc_data->rpc_response);
70         metal_mutex_deinit(&rpc_data->rpc_lock);
71         rpmsg_destroy_ept(rpc_data->rp_ept);
72         metal_free_memory(rpc_data);
73         rpc_data = NULL;
75         return 0;
76 }
78 int rpmsg_retarget_send(void *data, int len)
79 {
80         return send_rpc(data, len);
81 }
83 static inline void rpmsg_retarget_wait(struct _rpc_data *rpc)
84 {
85         struct hil_proc *proc = rpc->rpmsg_chnl->rdev->proc;
86         while (atomic_flag_test_and_set(&rpc->sync)) {
87                 hil_poll(proc, 0);
88         }
89 }
91 /*************************************************************************
92  *
93  *   FUNCTION
94  *
95  *       _open
96  *
97  *   DESCRIPTION
98  *
99  *       Open a file.  Minimal implementation
100  *
101  *************************************************************************/
102 int _open(const char *filename, int flags, int mode)
104         int filename_len = strlen(filename) + 1;
105         int payload_size = sizeof(struct _sys_rpc) + filename_len;
106         int retval = -1;
108         if ((!filename) || (filename_len > FILE_NAME_LEN)) {
109                 return -1;
110         }
112         if (!rpc_data)
113                 return retval;
115         /* Construct rpc payload */
116         rpc_data->rpc->id = OPEN_SYSCALL_ID;
117         rpc_data->rpc->sys_call_args.int_field1 = flags;
118         rpc_data->rpc->sys_call_args.int_field2 = mode;
119         rpc_data->rpc->sys_call_args.data_len = filename_len;
120         memcpy(&rpc_data->rpc->sys_call_args.data, filename, filename_len);
122         /* Transmit rpc request */
123         metal_mutex_acquire(&rpc_data->rpc_lock);
124         send_rpc((void *)rpc_data->rpc, payload_size);
125         metal_mutex_release(&rpc_data->rpc_lock);
127         /* Wait for response from proxy on master */
128         rpmsg_retarget_wait(rpc_data);
130         /* Obtain return args and return to caller */
131         if (rpc_data->rpc_response->id == OPEN_SYSCALL_ID) {
132                 retval = rpc_data->rpc_response->sys_call_args.int_field1;
133         }
135         return retval;
138 /*************************************************************************
139  *
140  *   FUNCTION
141  *
142  *       _read
143  *
144  *   DESCRIPTION
145  *
146  *       Low level function to redirect IO to serial.
147  *
148  *************************************************************************/
149 int _read(int fd, char *buffer, int buflen)
151         int payload_size = sizeof(struct _sys_rpc);
152         int retval = -1;
154         if (!buffer || !buflen)
155                 return retval;
156         if (!rpc_data)
157                 return retval;
159         /* Construct rpc payload */
160         rpc_data->rpc->id = READ_SYSCALL_ID;
161         rpc_data->rpc->sys_call_args.int_field1 = fd;
162         rpc_data->rpc->sys_call_args.int_field2 = buflen;
163         rpc_data->rpc->sys_call_args.data_len = 0;      /*not used */
165         /* Transmit rpc request */
166         metal_mutex_acquire(&rpc_data->rpc_lock);
167         send_rpc((void *)rpc_data->rpc, payload_size);
168         metal_mutex_release(&rpc_data->rpc_lock);
170         /* Wait for response from proxy on master */
171         rpmsg_retarget_wait(rpc_data);
173         /* Obtain return args and return to caller */
174         if (rpc_data->rpc_response->id == READ_SYSCALL_ID) {
175                 if (rpc_data->rpc_response->sys_call_args.int_field1 > 0) {
176                         memcpy(buffer,
177                                rpc_data->rpc_response->sys_call_args.data,
178                                rpc_data->rpc_response->sys_call_args.data_len);
179                 }
181                 retval = rpc_data->rpc_response->sys_call_args.int_field1;
182         }
184         return retval;
187 /*************************************************************************
188  *
189  *   FUNCTION
190  *
191  *       _write
192  *
193  *   DESCRIPTION
194  *
195  *       Low level function to redirect IO to serial.
196  *
197  *************************************************************************/
198 int _write(int fd, const char *ptr, int len)
200         int retval = -1;
201         int payload_size = sizeof(struct _sys_rpc) + len;
202         int null_term = 0;
204         if (fd == 1) {
205                 null_term = 1;
206         }
207         if (!rpc_data)
208                 return retval;
210         rpc_data->rpc->id = WRITE_SYSCALL_ID;
211         rpc_data->rpc->sys_call_args.int_field1 = fd;
212         rpc_data->rpc->sys_call_args.int_field2 = len;
213         rpc_data->rpc->sys_call_args.data_len = len + null_term;
214         memcpy(rpc_data->rpc->sys_call_args.data, ptr, len);
215         if (null_term) {
216                 *(char *)(rpc_data->rpc->sys_call_args.data + len + null_term) =
217                     0;
218         }
220         metal_mutex_acquire(&rpc_data->rpc_lock);
221         send_rpc((void *)rpc_data->rpc, payload_size);
222         metal_mutex_release(&rpc_data->rpc_lock);
224         /* Wait for response from proxy on master */
225         rpmsg_retarget_wait(rpc_data);
227         if (rpc_data->rpc_response->id == WRITE_SYSCALL_ID) {
228                 retval = rpc_data->rpc_response->sys_call_args.int_field1;
229         }
231         return retval;
235 /*************************************************************************
236  *
237  *   FUNCTION
238  *
239  *       _close
240  *
241  *   DESCRIPTION
242  *
243  *       Close a file.  Minimal implementation
244  *
245  *************************************************************************/
246 int _close(int fd)
248         int payload_size = sizeof(struct _sys_rpc);
249         int retval = -1;
251         if (!rpc_data)
252                 return retval;
253         rpc_data->rpc->id = CLOSE_SYSCALL_ID;
254         rpc_data->rpc->sys_call_args.int_field1 = fd;
255         rpc_data->rpc->sys_call_args.int_field2 = 0;    /*not used */
256         rpc_data->rpc->sys_call_args.data_len = 0;      /*not used */
258         metal_mutex_acquire(&rpc_data->rpc_lock);
259         send_rpc((void *)rpc_data->rpc, payload_size);
260         metal_mutex_release(&rpc_data->rpc_lock);
262         /* Wait for response from proxy on master */
263         rpmsg_retarget_wait(rpc_data);
265         if (rpc_data->rpc_response->id == CLOSE_SYSCALL_ID) {
266                 retval = rpc_data->rpc_response->sys_call_args.int_field1;
267         }
269         return retval;