source: mainline/uspace/lib/drv/generic/remote_ahci.c@ eadaeae8

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since eadaeae8 was a35b458, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 8 years ago

style: Remove trailing whitespace on _all_ lines, including empty ones, for particular file types.

Command used: tools/srepl '\s\+$' '' -- *.c *.h *.py *.sh *.s *.S *.ag

Currently, whitespace on empty lines is very inconsistent.
There are two basic choices: Either remove the whitespace, or keep empty lines
indented to the level of surrounding code. The former is AFAICT more common,
and also much easier to do automatically.

Alternatively, we could write script for automatic indentation, and use that
instead. However, if such a script exists, it's possible to use the indented
style locally, by having the editor apply relevant conversions on load/save,
without affecting remote repository. IMO, it makes more sense to adopt
the simpler rule.

  • Property mode set to 100644
File size: 8.8 KB
Line 
1/*
2 * Copyright (c) 2012 Petr Jerman
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 libdrv
30 * @{
31 */
32/** @file
33 */
34
35#include <as.h>
36#include <async.h>
37#include <devman.h>
38#include <errno.h>
39#include <stdio.h>
40#include <macros.h>
41#include <str.h>
42#include "ahci_iface.h"
43#include "ddf/driver.h"
44
45typedef enum {
46 IPC_M_AHCI_GET_SATA_DEVICE_NAME,
47 IPC_M_AHCI_GET_NUM_BLOCKS,
48 IPC_M_AHCI_GET_BLOCK_SIZE,
49 IPC_M_AHCI_READ_BLOCKS,
50 IPC_M_AHCI_WRITE_BLOCKS
51} ahci_iface_funcs_t;
52
53#define MAX_NAME_LENGTH 1024
54
55#define LO(ptr) \
56 ((uint32_t) (((uint64_t) ((uintptr_t) (ptr))) & 0xffffffff))
57
58#define HI(ptr) \
59 ((uint32_t) (((uint64_t) ((uintptr_t) (ptr))) >> 32))
60
61async_sess_t* ahci_get_sess(devman_handle_t funh, char **name)
62{
63 // FIXME: Use a better way than substring match
64
65 *name = NULL;
66
67 char devn[MAX_NAME_LENGTH];
68 errno_t rc = devman_fun_get_name(funh, devn, MAX_NAME_LENGTH);
69 if (rc != EOK)
70 return NULL;
71
72 size_t devn_size = str_size(devn);
73
74 if ((devn_size > 5) && (str_lcmp(devn, "ahci_", 5) == 0)) {
75 async_sess_t *sess = devman_device_connect(funh, IPC_FLAG_BLOCKING);
76
77 if (sess) {
78 *name = str_dup(devn);
79 return sess;
80 }
81 }
82
83 return NULL;
84}
85
86errno_t ahci_get_sata_device_name(async_sess_t *sess, size_t sata_dev_name_length,
87 char *sata_dev_name)
88{
89 async_exch_t *exch = async_exchange_begin(sess);
90 if (!exch)
91 return EINVAL;
92
93 aid_t req = async_send_2(exch, DEV_IFACE_ID(AHCI_DEV_IFACE),
94 IPC_M_AHCI_GET_SATA_DEVICE_NAME, sata_dev_name_length, NULL);
95
96 async_data_read_start(exch, sata_dev_name, sata_dev_name_length);
97
98 errno_t rc;
99 async_wait_for(req, &rc);
100
101 return rc;
102}
103
104errno_t ahci_get_num_blocks(async_sess_t *sess, uint64_t *blocks)
105{
106 async_exch_t *exch = async_exchange_begin(sess);
107 if (!exch)
108 return EINVAL;
109
110 sysarg_t blocks_hi;
111 sysarg_t blocks_lo;
112 errno_t rc = async_req_1_2(exch, DEV_IFACE_ID(AHCI_DEV_IFACE),
113 IPC_M_AHCI_GET_NUM_BLOCKS, &blocks_hi, &blocks_lo);
114
115 async_exchange_end(exch);
116
117 if (rc == EOK) {
118 *blocks = (((uint64_t) blocks_hi) << 32)
119 | (((uint64_t) blocks_lo) & 0xffffffff);
120 }
121
122 return rc;
123}
124
125errno_t ahci_get_block_size(async_sess_t *sess, size_t *blocks_size)
126{
127 async_exch_t *exch = async_exchange_begin(sess);
128 if (!exch)
129 return EINVAL;
130
131 sysarg_t bs;
132 errno_t rc = async_req_1_1(exch, DEV_IFACE_ID(AHCI_DEV_IFACE),
133 IPC_M_AHCI_GET_BLOCK_SIZE, &bs);
134
135 async_exchange_end(exch);
136
137 if (rc == EOK)
138 *blocks_size = (size_t) bs;
139
140 return rc;
141}
142
143errno_t ahci_read_blocks(async_sess_t *sess, uint64_t blocknum, size_t count,
144 void *buf)
145{
146 async_exch_t *exch = async_exchange_begin(sess);
147 if (!exch)
148 return EINVAL;
149
150 aid_t req;
151 req = async_send_4(exch, DEV_IFACE_ID(AHCI_DEV_IFACE),
152 IPC_M_AHCI_READ_BLOCKS, HI(blocknum), LO(blocknum), count, NULL);
153
154 async_share_out_start(exch, buf, AS_AREA_READ | AS_AREA_WRITE);
155
156 async_exchange_end(exch);
157
158 errno_t rc;
159 async_wait_for(req, &rc);
160
161 return rc;
162}
163
164errno_t ahci_write_blocks(async_sess_t *sess, uint64_t blocknum, size_t count,
165 void* buf)
166{
167 async_exch_t *exch = async_exchange_begin(sess);
168 if (!exch)
169 return EINVAL;
170
171 aid_t req = async_send_4(exch, DEV_IFACE_ID(AHCI_DEV_IFACE),
172 IPC_M_AHCI_WRITE_BLOCKS, HI(blocknum), LO(blocknum), count, NULL);
173
174 async_share_out_start(exch, buf, AS_AREA_READ | AS_AREA_WRITE);
175
176 async_exchange_end(exch);
177
178 errno_t rc;
179 async_wait_for(req, &rc);
180
181 return rc;
182}
183
184static void remote_ahci_get_sata_device_name(ddf_fun_t *, void *, ipc_callid_t,
185 ipc_call_t *);
186static void remote_ahci_get_num_blocks(ddf_fun_t *, void *, ipc_callid_t,
187 ipc_call_t *);
188static void remote_ahci_get_block_size(ddf_fun_t *, void *, ipc_callid_t,
189 ipc_call_t *);
190static void remote_ahci_read_blocks(ddf_fun_t *, void *, ipc_callid_t,
191 ipc_call_t *);
192static void remote_ahci_write_blocks(ddf_fun_t *, void *, ipc_callid_t,
193 ipc_call_t *);
194
195/** Remote AHCI interface operations. */
196static const remote_iface_func_ptr_t remote_ahci_iface_ops [] = {
197 [IPC_M_AHCI_GET_SATA_DEVICE_NAME] = remote_ahci_get_sata_device_name,
198 [IPC_M_AHCI_GET_NUM_BLOCKS] = remote_ahci_get_num_blocks,
199 [IPC_M_AHCI_GET_BLOCK_SIZE] = remote_ahci_get_block_size,
200 [IPC_M_AHCI_READ_BLOCKS] = remote_ahci_read_blocks,
201 [IPC_M_AHCI_WRITE_BLOCKS] = remote_ahci_write_blocks
202};
203
204/** Remote AHCI interface structure.
205 */
206const remote_iface_t remote_ahci_iface = {
207 .method_count = ARRAY_SIZE(remote_ahci_iface_ops),
208 .methods = remote_ahci_iface_ops
209};
210
211void remote_ahci_get_sata_device_name(ddf_fun_t *fun, void *iface,
212 ipc_callid_t callid, ipc_call_t *call)
213{
214 const ahci_iface_t *ahci_iface = (ahci_iface_t *) iface;
215
216 if (ahci_iface->get_sata_device_name == NULL) {
217 async_answer_0(callid, ENOTSUP);
218 return;
219 }
220
221 const size_t sata_dev_name_length =
222 (size_t) DEV_IPC_GET_ARG1(*call);
223
224 char* sata_dev_name = malloc(sata_dev_name_length);
225 if (sata_dev_name == NULL) {
226 async_answer_0(callid, ENOMEM);
227 return;
228 }
229
230 const errno_t ret = ahci_iface->get_sata_device_name(fun,
231 sata_dev_name_length, sata_dev_name);
232
233 size_t real_size;
234 ipc_callid_t cid;
235 if ((async_data_read_receive(&cid, &real_size)) &&
236 (real_size == sata_dev_name_length))
237 async_data_read_finalize(cid, sata_dev_name, sata_dev_name_length);
238
239 free(sata_dev_name);
240 async_answer_0(callid, ret);
241}
242
243static void remote_ahci_get_num_blocks(ddf_fun_t *fun, void *iface,
244 ipc_callid_t callid, ipc_call_t *call)
245{
246 const ahci_iface_t *ahci_iface = (ahci_iface_t *) iface;
247
248 if (ahci_iface->get_num_blocks == NULL) {
249 async_answer_0(callid, ENOTSUP);
250 return;
251 }
252
253 uint64_t blocks;
254 const errno_t ret = ahci_iface->get_num_blocks(fun, &blocks);
255
256 if (ret != EOK)
257 async_answer_0(callid, ret);
258 else
259 async_answer_2(callid, EOK, HI(blocks), LO(blocks));
260}
261
262static void remote_ahci_get_block_size(ddf_fun_t *fun, void *iface,
263 ipc_callid_t callid, ipc_call_t *call)
264{
265 const ahci_iface_t *ahci_iface = (ahci_iface_t *) iface;
266
267 if (ahci_iface->get_block_size == NULL) {
268 async_answer_0(callid, ENOTSUP);
269 return;
270 }
271
272 size_t blocks;
273 const errno_t ret = ahci_iface->get_block_size(fun, &blocks);
274
275 if (ret != EOK)
276 async_answer_0(callid, ret);
277 else
278 async_answer_1(callid, EOK, blocks);
279}
280
281void remote_ahci_read_blocks(ddf_fun_t *fun, void *iface,
282 ipc_callid_t callid, ipc_call_t *call)
283{
284 const ahci_iface_t *ahci_iface = (ahci_iface_t *) iface;
285
286 if (ahci_iface->read_blocks == NULL) {
287 async_answer_0(callid, ENOTSUP);
288 return;
289 }
290
291 size_t maxblock_size;
292 unsigned int flags;
293
294 ipc_callid_t cid;
295 async_share_out_receive(&cid, &maxblock_size, &flags);
296
297 void *buf;
298 async_share_out_finalize(cid, &buf);
299
300 const uint64_t blocknum =
301 (((uint64_t) (DEV_IPC_GET_ARG1(*call))) << 32) |
302 (((uint64_t) (DEV_IPC_GET_ARG2(*call))) & 0xffffffff);
303 const size_t cnt = (size_t) DEV_IPC_GET_ARG3(*call);
304
305 const errno_t ret = ahci_iface->read_blocks(fun, blocknum, cnt, buf);
306
307 async_answer_0(callid, ret);
308}
309
310void remote_ahci_write_blocks(ddf_fun_t *fun, void *iface, ipc_callid_t callid,
311 ipc_call_t *call)
312{
313 const ahci_iface_t *ahci_iface = (ahci_iface_t *) iface;
314
315 if (ahci_iface->read_blocks == NULL) {
316 async_answer_0(callid, ENOTSUP);
317 return;
318 }
319
320 size_t maxblock_size;
321 unsigned int flags;
322
323 ipc_callid_t cid;
324 async_share_out_receive(&cid, &maxblock_size, &flags);
325
326 void *buf;
327 async_share_out_finalize(cid, &buf);
328
329 const uint64_t blocknum =
330 (((uint64_t)(DEV_IPC_GET_ARG1(*call))) << 32) |
331 (((uint64_t)(DEV_IPC_GET_ARG2(*call))) & 0xffffffff);
332 const size_t cnt = (size_t) DEV_IPC_GET_ARG3(*call);
333
334 const errno_t ret = ahci_iface->write_blocks(fun, blocknum, cnt, buf);
335
336 async_answer_0(callid, ret);
337}
338
339/**
340 * @}
341 */
Note: See TracBrowser for help on using the repository browser.