source: mainline/uspace/lib/c/generic/bd_srv.c@ 58f26cb

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 58f26cb was 75751db6, checked in by Jiri Svoboda <jiri@…>, 11 years ago

Factor out chardev IPC from pl050, i8042, xtkbd and ps2mouse.

  • Property mode set to 100644
File size: 6.3 KB
Line 
1/*
2 * Copyright (c) 2012 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup libc
30 * @{
31 */
32/**
33 * @file
34 * @brief Block device server stub
35 */
36#include <errno.h>
37#include <ipc/bd.h>
38#include <macros.h>
39#include <stdlib.h>
40#include <sys/types.h>
41
42#include <bd_srv.h>
43
44static void bd_read_blocks_srv(bd_srv_t *srv, ipc_callid_t callid,
45 ipc_call_t *call)
46{
47 aoff64_t ba;
48 size_t cnt;
49 void *buf;
50 size_t size;
51 int rc;
52 ipc_callid_t rcallid;
53
54 ba = MERGE_LOUP32(IPC_GET_ARG1(*call), IPC_GET_ARG2(*call));
55 cnt = IPC_GET_ARG3(*call);
56
57 if (!async_data_read_receive(&rcallid, &size)) {
58 async_answer_0(callid, EINVAL);
59 return;
60 }
61
62 buf = malloc(size);
63 if (buf == NULL) {
64 async_answer_0(rcallid, ENOMEM);
65 async_answer_0(callid, ENOMEM);
66 return;
67 }
68
69 if (srv->srvs->ops->read_blocks == NULL) {
70 async_answer_0(rcallid, ENOTSUP);
71 async_answer_0(callid, ENOTSUP);
72 return;
73 }
74
75 rc = srv->srvs->ops->read_blocks(srv, ba, cnt, buf, size);
76 if (rc != EOK) {
77 async_answer_0(rcallid, ENOMEM);
78 async_answer_0(callid, ENOMEM);
79 return;
80 }
81
82 async_data_read_finalize(rcallid, buf, size);
83
84 free(buf);
85 async_answer_0(callid, EOK);
86}
87
88static void bd_read_toc_srv(bd_srv_t *srv, ipc_callid_t callid,
89 ipc_call_t *call)
90{
91 uint8_t session;
92 void *buf;
93 size_t size;
94 int rc;
95 ipc_callid_t rcallid;
96
97 session = IPC_GET_ARG1(*call);
98
99 if (!async_data_read_receive(&rcallid, &size)) {
100 async_answer_0(callid, EINVAL);
101 return;
102 }
103
104 buf = malloc(size);
105 if (buf == NULL) {
106 async_answer_0(rcallid, ENOMEM);
107 async_answer_0(callid, ENOMEM);
108 return;
109 }
110
111 if (srv->srvs->ops->read_toc == NULL) {
112 async_answer_0(rcallid, ENOTSUP);
113 async_answer_0(callid, ENOTSUP);
114 return;
115 }
116
117 rc = srv->srvs->ops->read_toc(srv, session, buf, size);
118 if (rc != EOK) {
119 async_answer_0(rcallid, ENOMEM);
120 async_answer_0(callid, ENOMEM);
121 return;
122 }
123
124 async_data_read_finalize(rcallid, buf, size);
125
126 free(buf);
127 async_answer_0(callid, EOK);
128}
129
130static void bd_sync_cache_srv(bd_srv_t *srv, ipc_callid_t callid,
131 ipc_call_t *call)
132{
133 aoff64_t ba;
134 size_t cnt;
135 int rc;
136
137 ba = MERGE_LOUP32(IPC_GET_ARG1(*call), IPC_GET_ARG2(*call));
138 cnt = IPC_GET_ARG3(*call);
139
140 if (srv->srvs->ops->sync_cache == NULL) {
141 async_answer_0(callid, ENOTSUP);
142 return;
143 }
144
145 rc = srv->srvs->ops->sync_cache(srv, ba, cnt);
146 async_answer_0(callid, rc);
147}
148
149static void bd_write_blocks_srv(bd_srv_t *srv, ipc_callid_t callid,
150 ipc_call_t *call)
151{
152 aoff64_t ba;
153 size_t cnt;
154 void *data;
155 size_t size;
156 int rc;
157
158 ba = MERGE_LOUP32(IPC_GET_ARG1(*call), IPC_GET_ARG2(*call));
159 cnt = IPC_GET_ARG3(*call);
160
161 rc = async_data_write_accept(&data, false, 0, 0, 0, &size);
162 if (rc != EOK) {
163 async_answer_0(callid, rc);
164 return;
165 }
166
167 if (srv->srvs->ops->write_blocks == NULL) {
168 async_answer_0(callid, ENOTSUP);
169 return;
170 }
171
172 rc = srv->srvs->ops->write_blocks(srv, ba, cnt, data, size);
173 free(data);
174 async_answer_0(callid, rc);
175}
176
177static void bd_get_block_size_srv(bd_srv_t *srv, ipc_callid_t callid,
178 ipc_call_t *call)
179{
180 int rc;
181 size_t block_size;
182
183 if (srv->srvs->ops->get_block_size == NULL) {
184 async_answer_0(callid, ENOTSUP);
185 return;
186 }
187
188 rc = srv->srvs->ops->get_block_size(srv, &block_size);
189 async_answer_1(callid, rc, block_size);
190}
191
192static void bd_get_num_blocks_srv(bd_srv_t *srv, ipc_callid_t callid,
193 ipc_call_t *call)
194{
195 int rc;
196 aoff64_t num_blocks;
197
198 if (srv->srvs->ops->get_num_blocks == NULL) {
199 async_answer_0(callid, ENOTSUP);
200 return;
201 }
202
203 rc = srv->srvs->ops->get_num_blocks(srv, &num_blocks);
204 async_answer_2(callid, rc, LOWER32(num_blocks), UPPER32(num_blocks));
205}
206
207static bd_srv_t *bd_srv_create(bd_srvs_t *srvs)
208{
209 bd_srv_t *srv;
210
211 srv = calloc(1, sizeof(bd_srv_t));
212 if (srv == NULL)
213 return NULL;
214
215 srv->srvs = srvs;
216 return srv;
217}
218
219void bd_srvs_init(bd_srvs_t *srvs)
220{
221 srvs->ops = NULL;
222 srvs->sarg = NULL;
223}
224
225int bd_conn(ipc_callid_t iid, ipc_call_t *icall, bd_srvs_t *srvs)
226{
227 bd_srv_t *srv;
228 int rc;
229
230 /* Accept the connection */
231 async_answer_0(iid, EOK);
232
233 srv = bd_srv_create(srvs);
234 if (srv == NULL)
235 return ENOMEM;
236
237 async_sess_t *sess = async_callback_receive(EXCHANGE_SERIALIZE);
238 if (sess == NULL)
239 return ENOMEM;
240
241 srv->client_sess = sess;
242
243 rc = srvs->ops->open(srvs, srv);
244 if (rc != EOK)
245 return rc;
246
247 while (true) {
248 ipc_call_t call;
249 ipc_callid_t callid = async_get_call(&call);
250 sysarg_t method = IPC_GET_IMETHOD(call);
251
252 if (!method) {
253 /* The other side has hung up */
254 async_answer_0(callid, EOK);
255 break;
256 }
257
258 switch (method) {
259 case BD_READ_BLOCKS:
260 bd_read_blocks_srv(srv, callid, &call);
261 break;
262 case BD_READ_TOC:
263 bd_read_toc_srv(srv, callid, &call);
264 break;
265 case BD_SYNC_CACHE:
266 bd_sync_cache_srv(srv, callid, &call);
267 break;
268 case BD_WRITE_BLOCKS:
269 bd_write_blocks_srv(srv, callid, &call);
270 break;
271 case BD_GET_BLOCK_SIZE:
272 bd_get_block_size_srv(srv, callid, &call);
273 break;
274 case BD_GET_NUM_BLOCKS:
275 bd_get_num_blocks_srv(srv, callid, &call);
276 break;
277 default:
278 async_answer_0(callid, EINVAL);
279 }
280 }
281
282 rc = srvs->ops->close(srv);
283 free(srv);
284
285 return rc;
286}
287
288/** @}
289 */
Note: See TracBrowser for help on using the repository browser.