source: mainline/uspace/lib/c/generic/bd_srv.c@ cddcc4a3

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since cddcc4a3 was 4802dd7, checked in by Jiri Svoboda <jiri@…>, 13 years ago

Factor out client and server IPC stubs for block devices.

  • Property mode set to 100644
File size: 5.9 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->ops->read_blocks == NULL) {
70 async_answer_0(rcallid, ENOTSUP);
71 async_answer_0(callid, ENOTSUP);
72 return;
73 }
74
75 rc = srv->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->ops->read_toc == NULL) {
112 async_answer_0(rcallid, ENOTSUP);
113 async_answer_0(callid, ENOTSUP);
114 return;
115 }
116
117 rc = srv->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_write_blocks_srv(bd_srv_t *srv, ipc_callid_t callid,
131 ipc_call_t *call)
132{
133 aoff64_t ba;
134 size_t cnt;
135 void *data;
136 size_t size;
137 int rc;
138
139 ba = MERGE_LOUP32(IPC_GET_ARG1(*call), IPC_GET_ARG2(*call));
140 cnt = IPC_GET_ARG3(*call);
141
142 rc = async_data_write_accept(&data, false, 0, 0, 0, &size);
143 if (rc != EOK) {
144 async_answer_0(callid, rc);
145 return;
146 }
147
148 if (srv->ops->write_blocks == NULL) {
149 async_answer_0(callid, ENOTSUP);
150 return;
151 }
152
153 rc = srv->ops->write_blocks(srv, ba, cnt, data, size);
154 free(data);
155 async_answer_0(callid, rc);
156}
157
158static void bd_get_block_size_srv(bd_srv_t *srv, ipc_callid_t callid,
159 ipc_call_t *call)
160{
161 int rc;
162 size_t block_size;
163
164 if (srv->ops->get_block_size == NULL) {
165 async_answer_0(callid, ENOTSUP);
166 return;
167 }
168
169 rc = srv->ops->get_block_size(srv, &block_size);
170 async_answer_1(callid, rc, block_size);
171}
172
173static void bd_get_num_blocks_srv(bd_srv_t *srv, ipc_callid_t callid,
174 ipc_call_t *call)
175{
176 int rc;
177 aoff64_t num_blocks;
178
179 if (srv->ops->get_num_blocks == NULL) {
180 async_answer_0(callid, ENOTSUP);
181 return;
182 }
183
184 rc = srv->ops->get_num_blocks(srv, &num_blocks);
185 async_answer_2(callid, rc, LOWER32(num_blocks), UPPER32(num_blocks));
186}
187
188void bd_srv_init(bd_srv_t *srv)
189{
190 fibril_mutex_initialize(&srv->lock);
191 srv->connected = false;
192 srv->ops = NULL;
193 srv->arg = NULL;
194 srv->client_sess = NULL;
195}
196
197int bd_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
198{
199 bd_srv_t *srv = (bd_srv_t *)arg;
200 int rc;
201
202 fibril_mutex_lock(&srv->lock);
203 if (srv->connected) {
204 fibril_mutex_unlock(&srv->lock);
205 async_answer_0(iid, EBUSY);
206 return EBUSY;
207 }
208
209 srv->connected = true;
210 fibril_mutex_unlock(&srv->lock);
211
212 /* Accept the connection */
213 async_answer_0(iid, EOK);
214
215 async_sess_t *sess = async_callback_receive(EXCHANGE_SERIALIZE);
216 if (sess == NULL)
217 return ENOMEM;
218
219 srv->client_sess = sess;
220
221 rc = srv->ops->open(srv);
222 if (rc != EOK)
223 return rc;
224
225 while (true) {
226 ipc_call_t call;
227 ipc_callid_t callid = async_get_call(&call);
228 sysarg_t method = IPC_GET_IMETHOD(call);
229
230 if (!method) {
231 /* The other side has hung up */
232 fibril_mutex_lock(&srv->lock);
233 srv->connected = false;
234 fibril_mutex_unlock(&srv->lock);
235 async_answer_0(callid, EOK);
236 break;
237 }
238
239 switch (method) {
240 case BD_READ_BLOCKS:
241 bd_read_blocks_srv(srv, callid, &call);
242 break;
243 case BD_READ_TOC:
244 bd_read_toc_srv(srv, callid, &call);
245 break;
246 case BD_WRITE_BLOCKS:
247 bd_write_blocks_srv(srv, callid, &call);
248 break;
249 case BD_GET_BLOCK_SIZE:
250 bd_get_block_size_srv(srv, callid, &call);
251 break;
252 case BD_GET_NUM_BLOCKS:
253 bd_get_num_blocks_srv(srv, callid, &call);
254 break;
255 default:
256 async_answer_0(callid, EINVAL);
257 }
258 }
259
260 return srv->ops->close(srv);
261}
262
263/** @}
264 */
Note: See TracBrowser for help on using the repository browser.