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
41 #include "ahci_iface.h"
42 #include "ddf/driver.h"
45 IPC_M_AHCI_GET_SATA_DEVICE_NAME
,
46 IPC_M_AHCI_GET_NUM_BLOCKS
,
47 IPC_M_AHCI_GET_BLOCK_SIZE
,
48 IPC_M_AHCI_READ_BLOCKS
,
49 IPC_M_AHCI_WRITE_BLOCKS
52 #define MAX_NAME_LENGTH 1024
55 ((uint32_t) (((uint64_t) ((uintptr_t) (ptr))) & 0xffffffff))
58 ((uint32_t) (((uint64_t) ((uintptr_t) (ptr))) >> 32))
60 async_sess_t
* ahci_get_sess(devman_handle_t funh
, char **name
)
62 // FIXME: Use a better way than substring match
66 char devn
[MAX_NAME_LENGTH
];
67 errno_t rc
= devman_fun_get_name(funh
, devn
, MAX_NAME_LENGTH
);
71 size_t devn_size
= str_size(devn
);
73 if ((devn_size
> 5) && (str_lcmp(devn
, "ahci_", 5) == 0)) {
74 async_sess_t
*sess
= devman_device_connect(funh
, IPC_FLAG_BLOCKING
);
77 *name
= str_dup(devn
);
85 errno_t
ahci_get_sata_device_name(async_sess_t
*sess
, size_t sata_dev_name_length
,
88 async_exch_t
*exch
= async_exchange_begin(sess
);
92 aid_t req
= async_send_2(exch
, DEV_IFACE_ID(AHCI_DEV_IFACE
),
93 IPC_M_AHCI_GET_SATA_DEVICE_NAME
, sata_dev_name_length
, NULL
);
95 async_data_read_start(exch
, sata_dev_name
, sata_dev_name_length
);
98 async_wait_for(req
, &rc
);
103 errno_t
ahci_get_num_blocks(async_sess_t
*sess
, uint64_t *blocks
)
105 async_exch_t
*exch
= async_exchange_begin(sess
);
111 errno_t rc
= async_req_1_2(exch
, DEV_IFACE_ID(AHCI_DEV_IFACE
),
112 IPC_M_AHCI_GET_NUM_BLOCKS
, &blocks_hi
, &blocks_lo
);
114 async_exchange_end(exch
);
117 *blocks
= (((uint64_t) blocks_hi
) << 32)
118 | (((uint64_t) blocks_lo
) & 0xffffffff);
124 errno_t
ahci_get_block_size(async_sess_t
*sess
, size_t *blocks_size
)
126 async_exch_t
*exch
= async_exchange_begin(sess
);
131 errno_t rc
= async_req_1_1(exch
, DEV_IFACE_ID(AHCI_DEV_IFACE
),
132 IPC_M_AHCI_GET_BLOCK_SIZE
, &bs
);
134 async_exchange_end(exch
);
137 *blocks_size
= (size_t) bs
;
142 errno_t
ahci_read_blocks(async_sess_t
*sess
, uint64_t blocknum
, size_t count
,
145 async_exch_t
*exch
= async_exchange_begin(sess
);
150 req
= async_send_4(exch
, DEV_IFACE_ID(AHCI_DEV_IFACE
),
151 IPC_M_AHCI_READ_BLOCKS
, HI(blocknum
), LO(blocknum
), count
, NULL
);
153 async_share_out_start(exch
, buf
, AS_AREA_READ
| AS_AREA_WRITE
);
155 async_exchange_end(exch
);
158 async_wait_for(req
, &rc
);
163 errno_t
ahci_write_blocks(async_sess_t
*sess
, uint64_t blocknum
, size_t count
,
166 async_exch_t
*exch
= async_exchange_begin(sess
);
170 aid_t req
= async_send_4(exch
, DEV_IFACE_ID(AHCI_DEV_IFACE
),
171 IPC_M_AHCI_WRITE_BLOCKS
, HI(blocknum
), LO(blocknum
), count
, NULL
);
173 async_share_out_start(exch
, buf
, AS_AREA_READ
| AS_AREA_WRITE
);
175 async_exchange_end(exch
);
178 async_wait_for(req
, &rc
);
183 static void remote_ahci_get_sata_device_name(ddf_fun_t
*, void *, ipc_callid_t
,
185 static void remote_ahci_get_num_blocks(ddf_fun_t
*, void *, ipc_callid_t
,
187 static void remote_ahci_get_block_size(ddf_fun_t
*, void *, ipc_callid_t
,
189 static void remote_ahci_read_blocks(ddf_fun_t
*, void *, ipc_callid_t
,
191 static void remote_ahci_write_blocks(ddf_fun_t
*, void *, ipc_callid_t
,
194 /** Remote AHCI interface operations. */
195 static const remote_iface_func_ptr_t remote_ahci_iface_ops
[] = {
196 [IPC_M_AHCI_GET_SATA_DEVICE_NAME
] = remote_ahci_get_sata_device_name
,
197 [IPC_M_AHCI_GET_NUM_BLOCKS
] = remote_ahci_get_num_blocks
,
198 [IPC_M_AHCI_GET_BLOCK_SIZE
] = remote_ahci_get_block_size
,
199 [IPC_M_AHCI_READ_BLOCKS
] = remote_ahci_read_blocks
,
200 [IPC_M_AHCI_WRITE_BLOCKS
] = remote_ahci_write_blocks
203 /** Remote AHCI interface structure.
205 const remote_iface_t remote_ahci_iface
= {
206 .method_count
= ARRAY_SIZE(remote_ahci_iface_ops
),
207 .methods
= remote_ahci_iface_ops
210 void remote_ahci_get_sata_device_name(ddf_fun_t
*fun
, void *iface
,
211 ipc_callid_t callid
, ipc_call_t
*call
)
213 const ahci_iface_t
*ahci_iface
= (ahci_iface_t
*) iface
;
215 if (ahci_iface
->get_sata_device_name
== NULL
) {
216 async_answer_0(callid
, ENOTSUP
);
220 const size_t sata_dev_name_length
=
221 (size_t) DEV_IPC_GET_ARG1(*call
);
223 char* sata_dev_name
= malloc(sata_dev_name_length
);
224 if (sata_dev_name
== NULL
) {
225 async_answer_0(callid
, ENOMEM
);
229 const errno_t ret
= ahci_iface
->get_sata_device_name(fun
,
230 sata_dev_name_length
, sata_dev_name
);
234 if ((async_data_read_receive(&cid
, &real_size
)) &&
235 (real_size
== sata_dev_name_length
))
236 async_data_read_finalize(cid
, sata_dev_name
, sata_dev_name_length
);
239 async_answer_0(callid
, ret
);
242 static void remote_ahci_get_num_blocks(ddf_fun_t
*fun
, void *iface
,
243 ipc_callid_t callid
, ipc_call_t
*call
)
245 const ahci_iface_t
*ahci_iface
= (ahci_iface_t
*) iface
;
247 if (ahci_iface
->get_num_blocks
== NULL
) {
248 async_answer_0(callid
, ENOTSUP
);
253 const errno_t ret
= ahci_iface
->get_num_blocks(fun
, &blocks
);
256 async_answer_0(callid
, ret
);
258 async_answer_2(callid
, EOK
, HI(blocks
), LO(blocks
));
261 static void remote_ahci_get_block_size(ddf_fun_t
*fun
, void *iface
,
262 ipc_callid_t callid
, ipc_call_t
*call
)
264 const ahci_iface_t
*ahci_iface
= (ahci_iface_t
*) iface
;
266 if (ahci_iface
->get_block_size
== NULL
) {
267 async_answer_0(callid
, ENOTSUP
);
272 const errno_t ret
= ahci_iface
->get_block_size(fun
, &blocks
);
275 async_answer_0(callid
, ret
);
277 async_answer_1(callid
, EOK
, blocks
);
280 void remote_ahci_read_blocks(ddf_fun_t
*fun
, void *iface
,
281 ipc_callid_t callid
, ipc_call_t
*call
)
283 const ahci_iface_t
*ahci_iface
= (ahci_iface_t
*) iface
;
285 if (ahci_iface
->read_blocks
== NULL
) {
286 async_answer_0(callid
, ENOTSUP
);
290 size_t maxblock_size
;
294 async_share_out_receive(&cid
, &maxblock_size
, &flags
);
297 async_share_out_finalize(cid
, &buf
);
299 const uint64_t blocknum
=
300 (((uint64_t) (DEV_IPC_GET_ARG1(*call
))) << 32) |
301 (((uint64_t) (DEV_IPC_GET_ARG2(*call
))) & 0xffffffff);
302 const size_t cnt
= (size_t) DEV_IPC_GET_ARG3(*call
);
304 const errno_t ret
= ahci_iface
->read_blocks(fun
, blocknum
, cnt
, buf
);
306 async_answer_0(callid
, ret
);
309 void remote_ahci_write_blocks(ddf_fun_t
*fun
, void *iface
, ipc_callid_t callid
,
312 const ahci_iface_t
*ahci_iface
= (ahci_iface_t
*) iface
;
314 if (ahci_iface
->read_blocks
== NULL
) {
315 async_answer_0(callid
, ENOTSUP
);
319 size_t maxblock_size
;
323 async_share_out_receive(&cid
, &maxblock_size
, &flags
);
326 async_share_out_finalize(cid
, &buf
);
328 const uint64_t blocknum
=
329 (((uint64_t)(DEV_IPC_GET_ARG1(*call
))) << 32) |
330 (((uint64_t)(DEV_IPC_GET_ARG2(*call
))) & 0xffffffff);
331 const size_t cnt
= (size_t) DEV_IPC_GET_ARG3(*call
);
333 const errno_t ret
= ahci_iface
->write_blocks(fun
, blocknum
, cnt
, buf
);
335 async_answer_0(callid
, ret
);