2 * Copyright (c) 2012 Petr Jerman
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
29 /** @addtogroup libdrv
42 #include "ahci_iface.h"
43 #include "ddf/driver.h"
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
53 #define MAX_NAME_LENGTH 1024
56 ((uint32_t) (((uint64_t) ((uintptr_t) (ptr))) & 0xffffffff))
59 ((uint32_t) (((uint64_t) ((uintptr_t) (ptr))) >> 32))
61 async_sess_t
*ahci_get_sess(devman_handle_t funh
, char **name
)
63 // FIXME: Use a better way than substring match
67 char devn
[MAX_NAME_LENGTH
];
68 errno_t rc
= devman_fun_get_name(funh
, devn
, MAX_NAME_LENGTH
);
72 size_t devn_size
= str_size(devn
);
74 if ((devn_size
> 5) && (str_lcmp(devn
, "ahci_", 5) == 0)) {
75 async_sess_t
*sess
= devman_device_connect(funh
, IPC_FLAG_BLOCKING
);
78 *name
= str_dup(devn
);
86 errno_t
ahci_get_sata_device_name(async_sess_t
*sess
, size_t sata_dev_name_length
,
89 async_exch_t
*exch
= async_exchange_begin(sess
);
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
);
96 async_data_read_start(exch
, sata_dev_name
, sata_dev_name_length
);
99 async_wait_for(req
, &rc
);
104 errno_t
ahci_get_num_blocks(async_sess_t
*sess
, uint64_t *blocks
)
106 async_exch_t
*exch
= async_exchange_begin(sess
);
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
);
115 async_exchange_end(exch
);
118 *blocks
= (((uint64_t) blocks_hi
) << 32) |
119 (((uint64_t) blocks_lo
) & 0xffffffff);
125 errno_t
ahci_get_block_size(async_sess_t
*sess
, size_t *blocks_size
)
127 async_exch_t
*exch
= async_exchange_begin(sess
);
132 errno_t rc
= async_req_1_1(exch
, DEV_IFACE_ID(AHCI_DEV_IFACE
),
133 IPC_M_AHCI_GET_BLOCK_SIZE
, &bs
);
135 async_exchange_end(exch
);
138 *blocks_size
= (size_t) bs
;
143 errno_t
ahci_read_blocks(async_sess_t
*sess
, uint64_t blocknum
, size_t count
,
146 async_exch_t
*exch
= async_exchange_begin(sess
);
151 req
= async_send_4(exch
, DEV_IFACE_ID(AHCI_DEV_IFACE
),
152 IPC_M_AHCI_READ_BLOCKS
, HI(blocknum
), LO(blocknum
), count
, NULL
);
154 async_share_out_start(exch
, buf
, AS_AREA_READ
| AS_AREA_WRITE
);
156 async_exchange_end(exch
);
159 async_wait_for(req
, &rc
);
164 errno_t
ahci_write_blocks(async_sess_t
*sess
, uint64_t blocknum
, size_t count
,
167 async_exch_t
*exch
= async_exchange_begin(sess
);
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
);
174 async_share_out_start(exch
, buf
, AS_AREA_READ
| AS_AREA_WRITE
);
176 async_exchange_end(exch
);
179 async_wait_for(req
, &rc
);
184 static void remote_ahci_get_sata_device_name(ddf_fun_t
*, void *, ipc_call_t
*);
185 static void remote_ahci_get_num_blocks(ddf_fun_t
*, void *, ipc_call_t
*);
186 static void remote_ahci_get_block_size(ddf_fun_t
*, void *, ipc_call_t
*);
187 static void remote_ahci_read_blocks(ddf_fun_t
*, void *, ipc_call_t
*);
188 static void remote_ahci_write_blocks(ddf_fun_t
*, void *, ipc_call_t
*);
190 /** Remote AHCI interface operations. */
191 static const remote_iface_func_ptr_t remote_ahci_iface_ops
[] = {
192 [IPC_M_AHCI_GET_SATA_DEVICE_NAME
] = remote_ahci_get_sata_device_name
,
193 [IPC_M_AHCI_GET_NUM_BLOCKS
] = remote_ahci_get_num_blocks
,
194 [IPC_M_AHCI_GET_BLOCK_SIZE
] = remote_ahci_get_block_size
,
195 [IPC_M_AHCI_READ_BLOCKS
] = remote_ahci_read_blocks
,
196 [IPC_M_AHCI_WRITE_BLOCKS
] = remote_ahci_write_blocks
199 /** Remote AHCI interface structure.
201 const remote_iface_t remote_ahci_iface
= {
202 .method_count
= ARRAY_SIZE(remote_ahci_iface_ops
),
203 .methods
= remote_ahci_iface_ops
206 void remote_ahci_get_sata_device_name(ddf_fun_t
*fun
, void *iface
,
209 const ahci_iface_t
*ahci_iface
= (ahci_iface_t
*) iface
;
211 if (ahci_iface
->get_sata_device_name
== NULL
) {
212 async_answer_0(call
, ENOTSUP
);
216 const size_t sata_dev_name_length
=
217 (size_t) DEV_IPC_GET_ARG1(*call
);
219 char *sata_dev_name
= malloc(sata_dev_name_length
);
220 if (sata_dev_name
== NULL
) {
221 async_answer_0(call
, ENOMEM
);
225 const errno_t ret
= ahci_iface
->get_sata_device_name(fun
,
226 sata_dev_name_length
, sata_dev_name
);
230 if ((async_data_read_receive(&data
, &real_size
)) &&
231 (real_size
== sata_dev_name_length
))
232 async_data_read_finalize(&data
, sata_dev_name
,
233 sata_dev_name_length
);
236 async_answer_0(call
, ret
);
239 static void remote_ahci_get_num_blocks(ddf_fun_t
*fun
, void *iface
,
242 const ahci_iface_t
*ahci_iface
= (ahci_iface_t
*) iface
;
244 if (ahci_iface
->get_num_blocks
== NULL
) {
245 async_answer_0(call
, ENOTSUP
);
250 const errno_t ret
= ahci_iface
->get_num_blocks(fun
, &blocks
);
253 async_answer_0(call
, ret
);
255 async_answer_2(call
, EOK
, HI(blocks
), LO(blocks
));
258 static void remote_ahci_get_block_size(ddf_fun_t
*fun
, void *iface
,
261 const ahci_iface_t
*ahci_iface
= (ahci_iface_t
*) iface
;
263 if (ahci_iface
->get_block_size
== NULL
) {
264 async_answer_0(call
, ENOTSUP
);
269 const errno_t ret
= ahci_iface
->get_block_size(fun
, &blocks
);
272 async_answer_0(call
, ret
);
274 async_answer_1(call
, EOK
, blocks
);
277 void remote_ahci_read_blocks(ddf_fun_t
*fun
, void *iface
, ipc_call_t
*call
)
279 const ahci_iface_t
*ahci_iface
= (ahci_iface_t
*) iface
;
281 if (ahci_iface
->read_blocks
== NULL
) {
282 async_answer_0(call
, ENOTSUP
);
287 size_t maxblock_size
;
289 async_share_out_receive(&data
, &maxblock_size
, &flags
);
292 async_share_out_finalize(&data
, &buf
);
294 const uint64_t blocknum
=
295 (((uint64_t) (DEV_IPC_GET_ARG1(*call
))) << 32) |
296 (((uint64_t) (DEV_IPC_GET_ARG2(*call
))) & 0xffffffff);
297 const size_t cnt
= (size_t) DEV_IPC_GET_ARG3(*call
);
299 const errno_t ret
= ahci_iface
->read_blocks(fun
, blocknum
, cnt
, buf
);
301 async_answer_0(call
, ret
);
304 void remote_ahci_write_blocks(ddf_fun_t
*fun
, void *iface
, ipc_call_t
*call
)
306 const ahci_iface_t
*ahci_iface
= (ahci_iface_t
*) iface
;
308 if (ahci_iface
->read_blocks
== NULL
) {
309 async_answer_0(call
, ENOTSUP
);
314 size_t maxblock_size
;
316 async_share_out_receive(&data
, &maxblock_size
, &flags
);
319 async_share_out_finalize(&data
, &buf
);
321 const uint64_t blocknum
=
322 (((uint64_t)(DEV_IPC_GET_ARG1(*call
))) << 32) |
323 (((uint64_t)(DEV_IPC_GET_ARG2(*call
))) & 0xffffffff);
324 const size_t cnt
= (size_t) DEV_IPC_GET_ARG3(*call
);
326 const errno_t ret
= ahci_iface
->write_blocks(fun
, blocknum
, cnt
, buf
);
328 async_answer_0(call
, ret
);