source: mainline/uspace/lib/c/generic/bd_srv.c@ 97b199b1

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

Allow more than one client connection to block device.

  • 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->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_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->srvs->ops->write_blocks == NULL) {
149 async_answer_0(callid, ENOTSUP);
150 return;
151 }
152
153 rc = srv->srvs->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->srvs->ops->get_block_size == NULL) {
165 async_answer_0(callid, ENOTSUP);
166 return;
167 }
168
169 rc = srv->srvs->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->srvs->ops->get_num_blocks == NULL) {
180 async_answer_0(callid, ENOTSUP);
181 return;
182 }
183
184 rc = srv->srvs->ops->get_num_blocks(srv, &num_blocks);
185 async_answer_2(callid, rc, LOWER32(num_blocks), UPPER32(num_blocks));
186}
187
188static bd_srv_t *bd_srv_create(bd_srvs_t *srvs)
189{
190 bd_srv_t *srv;
191
192 srv = calloc(1, sizeof(srv));
193 if (srv == NULL)
194 return NULL;
195
196 srv->srvs = srvs;
197 return srv;
198}
199
200void bd_srvs_init(bd_srvs_t *srvs)
201{
202 srvs->ops = NULL;
203 srvs->sarg = NULL;
204}
205
206int bd_conn(ipc_callid_t iid, ipc_call_t *icall, bd_srvs_t *srvs)
207{
208 bd_srv_t *srv;
209 int rc;
210
211 /* Accept the connection */
212 async_answer_0(iid, EOK);
213
214 srv = bd_srv_create(srvs);
215 if (srv == NULL)
216 return ENOMEM;
217
218 async_sess_t *sess = async_callback_receive(EXCHANGE_SERIALIZE);
219 if (sess == NULL)
220 return ENOMEM;
221
222 srv->client_sess = sess;
223
224 rc = srvs->ops->open(srvs, srv);
225 if (rc != EOK)
226 return rc;
227
228 while (true) {
229 ipc_call_t call;
230 ipc_callid_t callid = async_get_call(&call);
231 sysarg_t method = IPC_GET_IMETHOD(call);
232
233 if (!method) {
234 /* The other side has hung up */
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 rc = srvs->ops->close(srv);
261 free(srv);
262
263 return rc;
264}
265
266/** @}
267 */
Note: See TracBrowser for help on using the repository browser.