rpmsg proxy: Use hil_proc poll to wait
[processor-sdk/open-amp.git] / lib / proxy / rpmsg_retarget.c
1 #include "openamp/open_amp.h"
2 #include "openamp/rpmsg_retarget.h"
3 #include <stdio.h>
4 #include <string.h>
5 #include <fcntl.h>
7 /*************************************************************************
8  *      Description
9  *      This files contains rpmsg based redefinitions for C RTL system calls
10  *      such as _open, _read, _write, _close.
11  *************************************************************************/
12 static struct _rpc_data *rpc_data;
14 int send_rpc(void *data, int len);
16 void rpc_cb(struct rpmsg_channel *rtl_rp_chnl, void *data, int len, void *priv,
17             unsigned long src)
18 {
19         (void)priv;
20         (void)src;
22         memcpy(rpc_data->rpc_response, data, len);
24         atomic_flag_clear(&rpc_data->sync);
25         if (rpc_data->rpc_response->id == TERM_SYSCALL_ID) {
26                 /* Application terminate signal is received from the proxy app,
27                  * so let the application know of terminate message.
28                  */
29                 rpc_data->shutdown_cb(rtl_rp_chnl);
30         }
31 }
33 int send_rpc(void *data, int len)
34 {
35         int retval;
37         retval = rpmsg_sendto(rpc_data->rpmsg_chnl, data, len, PROXY_ENDPOINT);
38         return retval;
39 }
41 int rpmsg_retarget_init(struct rpmsg_channel *rp_chnl, rpc_shutdown_cb cb)
42 {
43         /* Allocate memory for rpc control block */
44         rpc_data =
45             (struct _rpc_data *)env_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 = env_allocate_memory(RPC_BUFF_SIZE);
58         rpc_data->rpc_response = env_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         env_free_memory(rpc_data->rpc);
69         env_free_memory(rpc_data->rpc_response);
70         metal_mutex_deinit(&rpc_data->rpc_lock);
71         rpmsg_destroy_ept(rpc_data->rp_ept);
72         env_free_memory(rpc_data);
74         return 0;
75 }
77 int rpmsg_retarget_send(void *data, int len)
78 {
79         return send_rpc(data, len);
80 }
82 static inline void rpmsg_retarget_wait(struct _rpc_data *rpc)
83 {
84         struct hil_proc *proc = rpc->rpmsg_chnl->rdev->proc;
85         while (atomic_flag_test_and_set(&rpc->sync)) {
86                 hil_poll(proc, 0);
87         }
88 }
90 /*************************************************************************
91  *
92  *   FUNCTION
93  *
94  *       _open
95  *
96  *   DESCRIPTION
97  *
98  *       Open a file.  Minimal implementation
99  *
100  *************************************************************************/
101 int _open(const char *filename, int flags, int mode)
103         int filename_len = strlen(filename) + 1;
104         int payload_size = sizeof(struct _sys_rpc) + filename_len;
105         int retval = -1;
107         if ((!filename) || (filename_len > FILE_NAME_LEN)) {
108                 return -1;
109         }
111         /* Construct rpc payload */
112         rpc_data->rpc->id = OPEN_SYSCALL_ID;
113         rpc_data->rpc->sys_call_args.int_field1 = flags;
114         rpc_data->rpc->sys_call_args.int_field2 = mode;
115         rpc_data->rpc->sys_call_args.data_len = filename_len;
116         memcpy(&rpc_data->rpc->sys_call_args.data, filename, filename_len);
118         /* Transmit rpc request */
119         metal_mutex_acquire(&rpc_data->rpc_lock);
120         send_rpc((void *)rpc_data->rpc, payload_size);
121         metal_mutex_release(&rpc_data->rpc_lock);
123         /* Wait for response from proxy on master */
124         rpmsg_retarget_wait(rpc_data);
126         /* Obtain return args and return to caller */
127         if (rpc_data->rpc_response->id == OPEN_SYSCALL_ID) {
128                 retval = rpc_data->rpc_response->sys_call_args.int_field1;
129         }
131         return retval;
134 /*************************************************************************
135  *
136  *   FUNCTION
137  *
138  *       _read
139  *
140  *   DESCRIPTION
141  *
142  *       Low level function to redirect IO to serial.
143  *
144  *************************************************************************/
145 int _read(int fd, char *buffer, int buflen)
147         int payload_size = sizeof(struct _sys_rpc);
148         int retval = -1;
150         if (!buffer || !buflen)
151                 return retval;
153         /* Construct rpc payload */
154         rpc_data->rpc->id = READ_SYSCALL_ID;
155         rpc_data->rpc->sys_call_args.int_field1 = fd;
156         rpc_data->rpc->sys_call_args.int_field2 = buflen;
157         rpc_data->rpc->sys_call_args.data_len = 0;      /*not used */
159         /* Transmit rpc request */
160         metal_mutex_acquire(&rpc_data->rpc_lock);
161         send_rpc((void *)rpc_data->rpc, payload_size);
162         metal_mutex_release(&rpc_data->rpc_lock);
164         /* Wait for response from proxy on master */
165         rpmsg_retarget_wait(rpc_data);
167         /* Obtain return args and return to caller */
168         if (rpc_data->rpc_response->id == READ_SYSCALL_ID) {
169                 if (rpc_data->rpc_response->sys_call_args.int_field1 > 0) {
170                         memcpy(buffer,
171                                rpc_data->rpc_response->sys_call_args.data,
172                                rpc_data->rpc_response->sys_call_args.data_len);
173                 }
175                 retval = rpc_data->rpc_response->sys_call_args.int_field1;
176         }
178         return retval;
181 /*************************************************************************
182  *
183  *   FUNCTION
184  *
185  *       _write
186  *
187  *   DESCRIPTION
188  *
189  *       Low level function to redirect IO to serial.
190  *
191  *************************************************************************/
192 int _write(int fd, const char *ptr, int len)
194         int retval = -1;
195         int payload_size = sizeof(struct _sys_rpc) + len;
196         int null_term = 0;
198         if (fd == 1) {
199                 null_term = 1;
200         }
202         rpc_data->rpc->id = WRITE_SYSCALL_ID;
203         rpc_data->rpc->sys_call_args.int_field1 = fd;
204         rpc_data->rpc->sys_call_args.int_field2 = len;
205         rpc_data->rpc->sys_call_args.data_len = len + null_term;
206         memcpy(rpc_data->rpc->sys_call_args.data, ptr, len);
207         if (null_term) {
208                 *(char *)(rpc_data->rpc->sys_call_args.data + len + null_term) =
209                     0;
210         }
212         metal_mutex_acquire(&rpc_data->rpc_lock);
213         send_rpc((void *)rpc_data->rpc, payload_size);
214         metal_mutex_release(&rpc_data->rpc_lock);
216         /* Wait for response from proxy on master */
217         rpmsg_retarget_wait(rpc_data);
219         if (rpc_data->rpc_response->id == WRITE_SYSCALL_ID) {
220                 retval = rpc_data->rpc_response->sys_call_args.int_field1;
221         }
223         return retval;
227 /*************************************************************************
228  *
229  *   FUNCTION
230  *
231  *       _close
232  *
233  *   DESCRIPTION
234  *
235  *       Close a file.  Minimal implementation
236  *
237  *************************************************************************/
238 int _close(int fd)
240         int payload_size = sizeof(struct _sys_rpc);
241         int retval = -1;
243         rpc_data->rpc->id = CLOSE_SYSCALL_ID;
244         rpc_data->rpc->sys_call_args.int_field1 = fd;
245         rpc_data->rpc->sys_call_args.int_field2 = 0;    /*not used */
246         rpc_data->rpc->sys_call_args.data_len = 0;      /*not used */
248         metal_mutex_acquire(&rpc_data->rpc_lock);
249         send_rpc((void *)rpc_data->rpc, payload_size);
250         metal_mutex_release(&rpc_data->rpc_lock);
252         /* Wait for response from proxy on master */
253         rpmsg_retarget_wait(rpc_data);
255         if (rpc_data->rpc_response->id == CLOSE_SYSCALL_ID) {
256                 retval = rpc_data->rpc_response->sys_call_args.int_field1;
257         }
259         return retval;