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

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

Selected ccheck-proposed comment fixes.

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