source: mainline/uspace/lib/device/src/bd_srv.c

Last change on this file was 4285f384, checked in by Jiri Svoboda <jiri@…>, 5 months ago

Allow physically ejecting CD-ROM using vol eject -s

  • Property mode set to 100644
File size: 6.5 KB
RevLine 
[4802dd7]1/*
[4285f384]2 * Copyright (c) 2025 Jiri Svoboda
[4802dd7]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
[edeee9f]29/** @addtogroup libdevice
[4802dd7]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>
[8d2dd7f2]40#include <stddef.h>
41#include <stdint.h>
[4802dd7]42
43#include <bd_srv.h>
44
[984a9ba]45static void bd_read_blocks_srv(bd_srv_t *srv, ipc_call_t *call)
[4802dd7]46{
47 aoff64_t ba;
48 size_t cnt;
49 void *buf;
50 size_t size;
[b7fd2a0]51 errno_t rc;
[4802dd7]52
[fafb8e5]53 ba = MERGE_LOUP32(ipc_get_arg1(call), ipc_get_arg2(call));
54 cnt = ipc_get_arg3(call);
[4802dd7]55
[984a9ba]56 ipc_call_t rcall;
57 if (!async_data_read_receive(&rcall, &size)) {
[cdd6fc9]58 async_answer_0(&rcall, EINVAL);
[984a9ba]59 async_answer_0(call, EINVAL);
[4802dd7]60 return;
61 }
62
63 buf = malloc(size);
64 if (buf == NULL) {
[984a9ba]65 async_answer_0(&rcall, ENOMEM);
66 async_answer_0(call, ENOMEM);
[4802dd7]67 return;
68 }
69
[135486d]70 if (srv->srvs->ops->read_blocks == NULL) {
[984a9ba]71 async_answer_0(&rcall, ENOTSUP);
72 async_answer_0(call, ENOTSUP);
[ccfe9c3]73 free(buf);
[4802dd7]74 return;
75 }
76
[135486d]77 rc = srv->srvs->ops->read_blocks(srv, ba, cnt, buf, size);
[4802dd7]78 if (rc != EOK) {
[984a9ba]79 async_answer_0(&rcall, ENOMEM);
80 async_answer_0(call, ENOMEM);
[ccfe9c3]81 free(buf);
[4802dd7]82 return;
83 }
84
[984a9ba]85 async_data_read_finalize(&rcall, buf, size);
[4802dd7]86
87 free(buf);
[984a9ba]88 async_answer_0(call, EOK);
[4802dd7]89}
90
[984a9ba]91static void bd_read_toc_srv(bd_srv_t *srv, ipc_call_t *call)
[4802dd7]92{
93 uint8_t session;
94 void *buf;
95 size_t size;
[b7fd2a0]96 errno_t rc;
[4802dd7]97
[fafb8e5]98 session = ipc_get_arg1(call);
[4802dd7]99
[984a9ba]100 ipc_call_t rcall;
101 if (!async_data_read_receive(&rcall, &size)) {
[cdd6fc9]102 async_answer_0(&rcall, EINVAL);
[984a9ba]103 async_answer_0(call, EINVAL);
[4802dd7]104 return;
105 }
106
107 buf = malloc(size);
108 if (buf == NULL) {
[984a9ba]109 async_answer_0(&rcall, ENOMEM);
110 async_answer_0(call, ENOMEM);
[4802dd7]111 return;
112 }
113
[135486d]114 if (srv->srvs->ops->read_toc == NULL) {
[984a9ba]115 async_answer_0(&rcall, ENOTSUP);
116 async_answer_0(call, ENOTSUP);
[ccfe9c3]117 free(buf);
[4802dd7]118 return;
119 }
120
[135486d]121 rc = srv->srvs->ops->read_toc(srv, session, buf, size);
[4802dd7]122 if (rc != EOK) {
[984a9ba]123 async_answer_0(&rcall, ENOMEM);
124 async_answer_0(call, ENOMEM);
[ccfe9c3]125 free(buf);
[4802dd7]126 return;
127 }
128
[984a9ba]129 async_data_read_finalize(&rcall, buf, size);
[4802dd7]130
131 free(buf);
[984a9ba]132 async_answer_0(call, EOK);
[4802dd7]133}
134
[984a9ba]135static void bd_sync_cache_srv(bd_srv_t *srv, ipc_call_t *call)
[dd8b6a8]136{
137 aoff64_t ba;
138 size_t cnt;
[b7fd2a0]139 errno_t rc;
[dd8b6a8]140
[fafb8e5]141 ba = MERGE_LOUP32(ipc_get_arg1(call), ipc_get_arg2(call));
142 cnt = ipc_get_arg3(call);
[dd8b6a8]143
144 if (srv->srvs->ops->sync_cache == NULL) {
[984a9ba]145 async_answer_0(call, ENOTSUP);
[dd8b6a8]146 return;
147 }
148
149 rc = srv->srvs->ops->sync_cache(srv, ba, cnt);
[984a9ba]150 async_answer_0(call, rc);
[dd8b6a8]151}
152
[984a9ba]153static void bd_write_blocks_srv(bd_srv_t *srv, ipc_call_t *call)
[4802dd7]154{
155 aoff64_t ba;
156 size_t cnt;
157 void *data;
158 size_t size;
[b7fd2a0]159 errno_t rc;
[4802dd7]160
[fafb8e5]161 ba = MERGE_LOUP32(ipc_get_arg1(call), ipc_get_arg2(call));
162 cnt = ipc_get_arg3(call);
[4802dd7]163
164 rc = async_data_write_accept(&data, false, 0, 0, 0, &size);
165 if (rc != EOK) {
[984a9ba]166 async_answer_0(call, rc);
[4802dd7]167 return;
168 }
169
[135486d]170 if (srv->srvs->ops->write_blocks == NULL) {
[984a9ba]171 async_answer_0(call, ENOTSUP);
[4802dd7]172 return;
173 }
174
[135486d]175 rc = srv->srvs->ops->write_blocks(srv, ba, cnt, data, size);
[4802dd7]176 free(data);
[984a9ba]177 async_answer_0(call, rc);
[4802dd7]178}
179
[984a9ba]180static void bd_get_block_size_srv(bd_srv_t *srv, ipc_call_t *call)
[4802dd7]181{
[b7fd2a0]182 errno_t rc;
[4802dd7]183 size_t block_size;
184
[135486d]185 if (srv->srvs->ops->get_block_size == NULL) {
[984a9ba]186 async_answer_0(call, ENOTSUP);
[4802dd7]187 return;
188 }
189
[135486d]190 rc = srv->srvs->ops->get_block_size(srv, &block_size);
[984a9ba]191 async_answer_1(call, rc, block_size);
[4802dd7]192}
193
[984a9ba]194static void bd_get_num_blocks_srv(bd_srv_t *srv, ipc_call_t *call)
[4802dd7]195{
[b7fd2a0]196 errno_t rc;
[4802dd7]197 aoff64_t num_blocks;
198
[135486d]199 if (srv->srvs->ops->get_num_blocks == NULL) {
[984a9ba]200 async_answer_0(call, ENOTSUP);
[4802dd7]201 return;
202 }
203
[135486d]204 rc = srv->srvs->ops->get_num_blocks(srv, &num_blocks);
[984a9ba]205 async_answer_2(call, rc, LOWER32(num_blocks), UPPER32(num_blocks));
[4802dd7]206}
207
[4285f384]208static void bd_eject_srv(bd_srv_t *srv, ipc_call_t *call)
209{
210 errno_t rc;
211
212 if (srv->srvs->ops->eject == NULL) {
213 async_answer_0(call, ENOTSUP);
214 return;
215 }
216
217 rc = srv->srvs->ops->eject(srv);
218 async_answer_0(call, rc);
219}
220
[135486d]221static bd_srv_t *bd_srv_create(bd_srvs_t *srvs)
[4802dd7]222{
[135486d]223 bd_srv_t *srv;
224
[75751db6]225 srv = calloc(1, sizeof(bd_srv_t));
[135486d]226 if (srv == NULL)
227 return NULL;
228
229 srv->srvs = srvs;
230 return srv;
[4802dd7]231}
232
[135486d]233void bd_srvs_init(bd_srvs_t *srvs)
[4802dd7]234{
[135486d]235 srvs->ops = NULL;
236 srvs->sarg = NULL;
237}
[4802dd7]238
[984a9ba]239errno_t bd_conn(ipc_call_t *icall, bd_srvs_t *srvs)
[135486d]240{
241 bd_srv_t *srv;
[b7fd2a0]242 errno_t rc;
[4802dd7]243
244 /* Accept the connection */
[beb83c1]245 async_accept_0(icall);
[4802dd7]246
[135486d]247 srv = bd_srv_create(srvs);
248 if (srv == NULL)
249 return ENOMEM;
250
[4802dd7]251 async_sess_t *sess = async_callback_receive(EXCHANGE_SERIALIZE);
252 if (sess == NULL)
253 return ENOMEM;
254
255 srv->client_sess = sess;
256
[135486d]257 rc = srvs->ops->open(srvs, srv);
[4802dd7]258 if (rc != EOK)
259 return rc;
260
261 while (true) {
262 ipc_call_t call;
[984a9ba]263 async_get_call(&call);
[fafb8e5]264 sysarg_t method = ipc_get_imethod(&call);
[4802dd7]265
266 if (!method) {
267 /* The other side has hung up */
[984a9ba]268 async_answer_0(&call, EOK);
[4802dd7]269 break;
270 }
271
272 switch (method) {
273 case BD_READ_BLOCKS:
[984a9ba]274 bd_read_blocks_srv(srv, &call);
[4802dd7]275 break;
276 case BD_READ_TOC:
[984a9ba]277 bd_read_toc_srv(srv, &call);
[4802dd7]278 break;
[dd8b6a8]279 case BD_SYNC_CACHE:
[984a9ba]280 bd_sync_cache_srv(srv, &call);
[dd8b6a8]281 break;
[4802dd7]282 case BD_WRITE_BLOCKS:
[984a9ba]283 bd_write_blocks_srv(srv, &call);
[4802dd7]284 break;
285 case BD_GET_BLOCK_SIZE:
[984a9ba]286 bd_get_block_size_srv(srv, &call);
[4802dd7]287 break;
288 case BD_GET_NUM_BLOCKS:
[984a9ba]289 bd_get_num_blocks_srv(srv, &call);
[4802dd7]290 break;
[4285f384]291 case BD_EJECT:
292 bd_eject_srv(srv, &call);
293 break;
[4802dd7]294 default:
[984a9ba]295 async_answer_0(&call, EINVAL);
[4802dd7]296 }
297 }
298
[135486d]299 rc = srvs->ops->close(srv);
300 free(srv);
301
302 return rc;
[4802dd7]303}
304
305/** @}
306 */
Note: See TracBrowser for help on using the repository browser.