source: mainline/uspace/lib/device/src/devman.c@ accdf882

Last change on this file since accdf882 was 832cbe7, checked in by Jiri Svoboda <jiri@…>, 5 months ago

Add proper IDE PCI to ISA fallback mechanism.

To determine if legacy IDE I/O ports are free, isa-ide asks isa,
who asks pciintel. pciintel waits for bus enumeration to complete,
then waits for all functions except the one who is asking
(which is ISA bus) to stabilize. During attach pci-ide will claim
the legacy IDE ports. Thus, if at this point legacy IDE ports
are unclaimed, pciintel tells ISA they are free, which tells isa-ide,
which continues to attach. If they are not free, isa-ide will not
attach.

This works for all use cases, including system without PCI bus,
system with PCI bus, but no (or disabled) PCI IDE, system with PCI
IDE with unrecognized VID/PID (which we will handle in legacy ISA mode).

  • Property mode set to 100644
File size: 17.7 KB
RevLine 
[729fa2d6]1/*
[832cbe7]2 * Copyright (c) 2025 Jiri Svoboda
[729fa2d6]3 * Copyright (c) 2007 Josef Cejka
4 * Copyright (c) 2010 Lenka Trochtova
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * - Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * - Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * - The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
[64d2b10]30
[edeee9f]31/** @addtogroup libdevice
[5cd136ab]32 * @{
33 */
34/** @file
35 */
[729fa2d6]36
[b72efe8]37#include <adt/list.h>
[c47e1a8]38#include <str.h>
[729fa2d6]39#include <ipc/services.h>
[79ae36dd]40#include <ns.h>
[729fa2d6]41#include <ipc/devman.h>
42#include <devman.h>
[622dea8]43#include <fibril_synch.h>
[79ae36dd]44#include <async.h>
[729fa2d6]45#include <errno.h>
[38d150e]46#include <stdlib.h>
[729fa2d6]47
[79ae36dd]48static FIBRIL_MUTEX_INITIALIZE(devman_driver_block_mutex);
49static FIBRIL_MUTEX_INITIALIZE(devman_client_block_mutex);
50
51static FIBRIL_MUTEX_INITIALIZE(devman_driver_mutex);
52static FIBRIL_MUTEX_INITIALIZE(devman_client_mutex);
[729fa2d6]53
[79ae36dd]54static async_sess_t *devman_driver_block_sess = NULL;
55static async_sess_t *devman_client_block_sess = NULL;
[622dea8]56
[79ae36dd]57static async_sess_t *devman_driver_sess = NULL;
58static async_sess_t *devman_client_sess = NULL;
59
60static void clone_session(fibril_mutex_t *mtx, async_sess_t *src,
61 async_sess_t **dst)
62{
63 fibril_mutex_lock(mtx);
[a35b458]64
[79ae36dd]65 if ((*dst == NULL) && (src != NULL))
66 *dst = src;
[a35b458]67
[79ae36dd]68 fibril_mutex_unlock(mtx);
69}
70
71/** Start an async exchange on the devman session (blocking).
72 *
73 * @param iface Device manager interface to choose
74 *
75 * @return New exchange.
76 *
77 */
[f9b2cb4c]78async_exch_t *devman_exchange_begin_blocking(iface_t iface)
[729fa2d6]79{
80 switch (iface) {
[f9b2cb4c]81 case INTERFACE_DDF_DRIVER:
[79ae36dd]82 fibril_mutex_lock(&devman_driver_block_mutex);
[a35b458]83
[79ae36dd]84 while (devman_driver_block_sess == NULL) {
85 clone_session(&devman_driver_mutex, devman_driver_sess,
86 &devman_driver_block_sess);
[a35b458]87
[79ae36dd]88 if (devman_driver_block_sess == NULL)
89 devman_driver_block_sess =
[f9b2cb4c]90 service_connect_blocking(SERVICE_DEVMAN,
[01900b6]91 INTERFACE_DDF_DRIVER, 0, NULL);
[622dea8]92 }
[a35b458]93
[79ae36dd]94 fibril_mutex_unlock(&devman_driver_block_mutex);
[a35b458]95
[79ae36dd]96 clone_session(&devman_driver_mutex, devman_driver_block_sess,
97 &devman_driver_sess);
[a35b458]98
[79ae36dd]99 return async_exchange_begin(devman_driver_block_sess);
[f9b2cb4c]100 case INTERFACE_DDF_CLIENT:
[79ae36dd]101 fibril_mutex_lock(&devman_client_block_mutex);
[a35b458]102
[79ae36dd]103 while (devman_client_block_sess == NULL) {
104 clone_session(&devman_client_mutex, devman_client_sess,
105 &devman_client_block_sess);
[a35b458]106
[79ae36dd]107 if (devman_client_block_sess == NULL)
108 devman_client_block_sess =
[f9b2cb4c]109 service_connect_blocking(SERVICE_DEVMAN,
[01900b6]110 INTERFACE_DDF_CLIENT, 0, NULL);
[4db43721]111 }
[a35b458]112
[79ae36dd]113 fibril_mutex_unlock(&devman_client_block_mutex);
[a35b458]114
[79ae36dd]115 clone_session(&devman_client_mutex, devman_client_block_sess,
116 &devman_client_sess);
[a35b458]117
[79ae36dd]118 return async_exchange_begin(devman_client_block_sess);
[729fa2d6]119 default:
[79ae36dd]120 return NULL;
[729fa2d6]121 }
122}
123
[79ae36dd]124/** Start an async exchange on the devman session.
125 *
126 * @param iface Device manager interface to choose
127 *
128 * @return New exchange.
129 *
130 */
[f9b2cb4c]131async_exch_t *devman_exchange_begin(iface_t iface)
[79ae36dd]132{
133 switch (iface) {
[f9b2cb4c]134 case INTERFACE_DDF_DRIVER:
[79ae36dd]135 fibril_mutex_lock(&devman_driver_mutex);
[a35b458]136
[79ae36dd]137 if (devman_driver_sess == NULL)
138 devman_driver_sess =
[f9b2cb4c]139 service_connect(SERVICE_DEVMAN,
[01900b6]140 INTERFACE_DDF_DRIVER, 0, NULL);
[a35b458]141
[79ae36dd]142 fibril_mutex_unlock(&devman_driver_mutex);
[a35b458]143
[79ae36dd]144 if (devman_driver_sess == NULL)
145 return NULL;
[a35b458]146
[79ae36dd]147 return async_exchange_begin(devman_driver_sess);
[f9b2cb4c]148 case INTERFACE_DDF_CLIENT:
[79ae36dd]149 fibril_mutex_lock(&devman_client_mutex);
[a35b458]150
[79ae36dd]151 if (devman_client_sess == NULL)
152 devman_client_sess =
[f9b2cb4c]153 service_connect(SERVICE_DEVMAN,
[01900b6]154 INTERFACE_DDF_CLIENT, 0, NULL);
[a35b458]155
[79ae36dd]156 fibril_mutex_unlock(&devman_client_mutex);
[a35b458]157
[79ae36dd]158 if (devman_client_sess == NULL)
159 return NULL;
[a35b458]160
[79ae36dd]161 return async_exchange_begin(devman_client_sess);
162 default:
163 return NULL;
164 }
165}
166
167/** Finish an async exchange on the devman session.
168 *
169 * @param exch Exchange to be finished.
170 *
171 */
172void devman_exchange_end(async_exch_t *exch)
173{
174 async_exchange_end(exch);
175}
176
[729fa2d6]177/** Register running driver with device manager. */
[b7fd2a0]178errno_t devman_driver_register(const char *name)
[729fa2d6]179{
[f9b2cb4c]180 async_exch_t *exch = devman_exchange_begin_blocking(INTERFACE_DDF_DRIVER);
[a35b458]181
[729fa2d6]182 ipc_call_t answer;
[79ae36dd]183 aid_t req = async_send_2(exch, DEVMAN_DRIVER_REGISTER, 0, 0, &answer);
[b7fd2a0]184 errno_t retval = async_data_write_start(exch, name, str_size(name));
[a35b458]185
[79ae36dd]186 devman_exchange_end(exch);
[a35b458]187
[729fa2d6]188 if (retval != EOK) {
[50b581d]189 async_forget(req);
[79ae36dd]190 return retval;
[729fa2d6]191 }
[a35b458]192
[f9b2cb4c]193 exch = devman_exchange_begin(INTERFACE_DDF_DRIVER);
[9b1baac]194 async_connect_to_me(exch, INTERFACE_ANY, 0, 0);
[79ae36dd]195 devman_exchange_end(exch);
[a35b458]196
[79ae36dd]197 async_wait_for(req, &retval);
[729fa2d6]198 return retval;
199}
200
[8b1e15ac]201/** Add function to a device.
202 *
203 * Request devman to add a new function to the specified device owned by
204 * this driver task.
205 *
[79ae36dd]206 * @param name Name of the new function
207 * @param ftype Function type, fun_inner or fun_exposed
208 * @param match_ids Match IDs (should be empty for fun_exposed)
209 * @param devh Devman handle of the device
210 * @param funh Place to store handle of the new function
211 *
[cde999a]212 * @return EOK on success or an error code.
[8b1e15ac]213 *
214 */
[b7fd2a0]215errno_t devman_add_function(const char *name, fun_type_t ftype,
[8b1e15ac]216 match_id_list_t *match_ids, devman_handle_t devh, devman_handle_t *funh)
[1b367b4]217{
[be12474]218 unsigned long match_count = list_count(&match_ids->ids);
[f9b2cb4c]219 async_exch_t *exch = devman_exchange_begin_blocking(INTERFACE_DDF_DRIVER);
[a35b458]220
[7707954]221 ipc_call_t answer;
[79ae36dd]222 aid_t req = async_send_3(exch, DEVMAN_ADD_FUNCTION, (sysarg_t) ftype,
[8b1e15ac]223 devh, match_count, &answer);
[b7fd2a0]224 errno_t retval = async_data_write_start(exch, name, str_size(name));
[7707954]225 if (retval != EOK) {
[79ae36dd]226 devman_exchange_end(exch);
[50b581d]227 async_forget(req);
[7707954]228 return retval;
229 }
[a35b458]230
[feeac0d]231 list_foreach(match_ids->ids, link, match_id_t, match_id) {
[15e54f5]232 ipc_call_t answer2;
233 aid_t req2 = async_send_1(exch, DEVMAN_ADD_MATCH_ID,
234 match_id->score, &answer2);
[79ae36dd]235 retval = async_data_write_start(exch, match_id->id,
236 str_size(match_id->id));
237 if (retval != EOK) {
238 devman_exchange_end(exch);
[50b581d]239 async_forget(req2);
240 async_forget(req);
[79ae36dd]241 return retval;
242 }
[a35b458]243
[15e54f5]244 async_wait_for(req2, &retval);
[79ae36dd]245 if (retval != EOK) {
246 devman_exchange_end(exch);
[50b581d]247 async_forget(req);
[79ae36dd]248 return retval;
249 }
[4265fd4]250 }
[a35b458]251
[79ae36dd]252 devman_exchange_end(exch);
[a35b458]253
[15e54f5]254 async_wait_for(req, &retval);
[e6211f8]255 if (retval == EOK) {
[15e54f5]256 if (funh != NULL)
[fafb8e5]257 *funh = (int) ipc_get_arg1(&answer);
[15e54f5]258 } else {
259 if (funh != NULL)
260 *funh = -1;
261 }
[a35b458]262
[15e54f5]263 return retval;
[7707954]264}
265
[b7fd2a0]266errno_t devman_add_device_to_category(devman_handle_t devman_handle,
[1dc4a5e]267 const char *cat_name)
[692c40cb]268{
[f9b2cb4c]269 async_exch_t *exch = devman_exchange_begin_blocking(INTERFACE_DDF_DRIVER);
[a35b458]270
[692c40cb]271 ipc_call_t answer;
[1dc4a5e]272 aid_t req = async_send_1(exch, DEVMAN_ADD_DEVICE_TO_CATEGORY,
[1b367b4]273 devman_handle, &answer);
[b7fd2a0]274 errno_t retval = async_data_write_start(exch, cat_name,
[1dc4a5e]275 str_size(cat_name));
[a35b458]276
[79ae36dd]277 devman_exchange_end(exch);
[a35b458]278
[692c40cb]279 if (retval != EOK) {
[50b581d]280 async_forget(req);
[692c40cb]281 return retval;
282 }
[a35b458]283
[692c40cb]284 async_wait_for(req, &retval);
[1b367b4]285 return retval;
[692c40cb]286}
287
[f9b2cb4c]288async_sess_t *devman_device_connect(devman_handle_t handle, unsigned int flags)
[5cd136ab]289{
[79ae36dd]290 async_sess_t *sess;
[a35b458]291
[79ae36dd]292 if (flags & IPC_FLAG_BLOCKING)
[f9b2cb4c]293 sess = service_connect_blocking(SERVICE_DEVMAN,
[01900b6]294 INTERFACE_DEVMAN_DEVICE, handle, NULL);
[79ae36dd]295 else
[f9b2cb4c]296 sess = service_connect(SERVICE_DEVMAN,
[01900b6]297 INTERFACE_DEVMAN_DEVICE, handle, NULL);
[a35b458]298
[79ae36dd]299 return sess;
[5cd136ab]300}
301
[d0dd7b5]302/** Remove function from device.
303 *
304 * Request devman to remove function owned by this driver task.
305 * @param funh Devman handle of the function
306 *
[cde999a]307 * @return EOK on success or an error code.
[d0dd7b5]308 */
[b7fd2a0]309errno_t devman_remove_function(devman_handle_t funh)
[d0dd7b5]310{
311 async_exch_t *exch;
[b7fd2a0]312 errno_t retval;
[a35b458]313
[f9b2cb4c]314 exch = devman_exchange_begin_blocking(INTERFACE_DDF_DRIVER);
[d0dd7b5]315 retval = async_req_1_0(exch, DEVMAN_REMOVE_FUNCTION, (sysarg_t) funh);
316 devman_exchange_end(exch);
[a35b458]317
[25a179e]318 return retval;
[d0dd7b5]319}
320
[b7fd2a0]321errno_t devman_drv_fun_online(devman_handle_t funh)
[1a5b252]322{
[f9b2cb4c]323 async_exch_t *exch = devman_exchange_begin(INTERFACE_DDF_DRIVER);
[1a5b252]324 if (exch == NULL)
325 return ENOMEM;
[a35b458]326
[b7fd2a0]327 errno_t retval = async_req_1_0(exch, DEVMAN_DRV_FUN_ONLINE, funh);
[a35b458]328
[1a5b252]329 devman_exchange_end(exch);
[25a179e]330 return retval;
[1a5b252]331}
332
[b7fd2a0]333errno_t devman_drv_fun_offline(devman_handle_t funh)
[1a5b252]334{
[f9b2cb4c]335 async_exch_t *exch = devman_exchange_begin(INTERFACE_DDF_DRIVER);
[1a5b252]336 if (exch == NULL)
337 return ENOMEM;
[a35b458]338
[b7fd2a0]339 errno_t retval = async_req_1_0(exch, DEVMAN_DRV_FUN_OFFLINE, funh);
[a35b458]340
[1a5b252]341 devman_exchange_end(exch);
[25a179e]342 return retval;
[1a5b252]343}
344
[832cbe7]345errno_t devman_drv_fun_wait_stable(devman_handle_t funh)
346{
347 async_exch_t *exch = devman_exchange_begin(INTERFACE_DDF_DRIVER);
348 if (exch == NULL)
349 return ENOMEM;
350
351 errno_t retval = async_req_1_0(exch, DEVMAN_DRV_FUN_WAIT_STABLE, funh);
352
353 devman_exchange_end(exch);
354 return retval;
355}
356
[f9b2cb4c]357async_sess_t *devman_parent_device_connect(devman_handle_t handle,
358 unsigned int flags)
[5cd136ab]359{
[79ae36dd]360 async_sess_t *sess;
[a35b458]361
[79ae36dd]362 if (flags & IPC_FLAG_BLOCKING)
[f9b2cb4c]363 sess = service_connect_blocking(SERVICE_DEVMAN,
[01900b6]364 INTERFACE_DEVMAN_PARENT, handle, NULL);
[79ae36dd]365 else
[01900b6]366 sess = service_connect(SERVICE_DEVMAN,
367 INTERFACE_DEVMAN_PARENT, handle, NULL);
[a35b458]368
[79ae36dd]369 return sess;
[5cd136ab]370}
371
[b7fd2a0]372errno_t devman_fun_get_handle(const char *pathname, devman_handle_t *handle,
[1b367b4]373 unsigned int flags)
[f658458]374{
[79ae36dd]375 async_exch_t *exch;
[a35b458]376
[79ae36dd]377 if (flags & IPC_FLAG_BLOCKING)
[f9b2cb4c]378 exch = devman_exchange_begin_blocking(INTERFACE_DDF_CLIENT);
[79ae36dd]379 else {
[f9b2cb4c]380 exch = devman_exchange_begin(INTERFACE_DDF_CLIENT);
[79ae36dd]381 if (exch == NULL)
[e280857]382 return ENOMEM;
[79ae36dd]383 }
[a35b458]384
[f658458]385 ipc_call_t answer;
[79ae36dd]386 aid_t req = async_send_2(exch, DEVMAN_DEVICE_GET_HANDLE, flags, 0,
[f658458]387 &answer);
[b7fd2a0]388 errno_t retval = async_data_write_start(exch, pathname,
[1b367b4]389 str_size(pathname));
[a35b458]390
[79ae36dd]391 devman_exchange_end(exch);
[a35b458]392
[f658458]393 if (retval != EOK) {
[50b581d]394 async_forget(req);
[f658458]395 return retval;
396 }
[a35b458]397
[f658458]398 async_wait_for(req, &retval);
[a35b458]399
[f658458]400 if (retval != EOK) {
401 if (handle != NULL)
[0b5a4131]402 *handle = (devman_handle_t) -1;
[a35b458]403
[f658458]404 return retval;
405 }
[a35b458]406
[f658458]407 if (handle != NULL)
[fafb8e5]408 *handle = (devman_handle_t) ipc_get_arg1(&answer);
[a35b458]409
[f658458]410 return retval;
411}
412
[b7fd2a0]413static errno_t devman_get_str_internal(sysarg_t method, sysarg_t arg1,
[4c9b28a]414 sysarg_t arg2, sysarg_t *r1, char *buf, size_t buf_size)
[431d6d6]415{
[7beb220]416 async_exch_t *exch;
417 ipc_call_t dreply;
418 size_t act_size;
[b7fd2a0]419 errno_t dretval;
[a35b458]420
[f9b2cb4c]421 exch = devman_exchange_begin_blocking(INTERFACE_DDF_CLIENT);
[a35b458]422
[7beb220]423 ipc_call_t answer;
[4c9b28a]424 aid_t req = async_send_2(exch, method, arg1, arg2, &answer);
[7beb220]425 aid_t dreq = async_data_read(exch, buf, buf_size - 1, &dreply);
426 async_wait_for(dreq, &dretval);
[a35b458]427
[79ae36dd]428 devman_exchange_end(exch);
[a35b458]429
[7beb220]430 if (dretval != EOK) {
[50b581d]431 async_forget(req);
[7beb220]432 return dretval;
[431d6d6]433 }
[a35b458]434
[b7fd2a0]435 errno_t retval;
[7beb220]436 async_wait_for(req, &retval);
[a35b458]437
[3f57fb7]438 if (retval != EOK) {
[7beb220]439 return retval;
[3f57fb7]440 }
[a35b458]441
[4c9b28a]442 if (r1 != NULL)
[fafb8e5]443 *r1 = ipc_get_arg1(&answer);
444 act_size = ipc_get_arg2(&dreply);
[7beb220]445 assert(act_size <= buf_size - 1);
446 buf[act_size] = '\0';
[a35b458]447
[7beb220]448 return EOK;
449}
450
[b7fd2a0]451errno_t devman_fun_get_path(devman_handle_t handle, char *buf, size_t buf_size)
[7beb220]452{
[4c9b28a]453 return devman_get_str_internal(DEVMAN_FUN_GET_PATH, handle, 0, NULL,
454 buf, buf_size);
455}
456
[b7fd2a0]457errno_t devman_fun_get_match_id(devman_handle_t handle, size_t index, char *buf,
[4c9b28a]458 size_t buf_size, unsigned int *rscore)
459{
[b7fd2a0]460 errno_t rc;
[4c9b28a]461 sysarg_t score = 0;
462
463 rc = devman_get_str_internal(DEVMAN_FUN_GET_MATCH_ID, handle, index,
464 &score, buf, buf_size);
465 if (rc != EOK)
466 return rc;
467
468 *rscore = score;
469 return rc;
[7beb220]470}
471
[b7fd2a0]472errno_t devman_fun_get_name(devman_handle_t handle, char *buf, size_t buf_size)
[7beb220]473{
[4c9b28a]474 return devman_get_str_internal(DEVMAN_FUN_GET_NAME, handle, 0, NULL,
475 buf, buf_size);
[7beb220]476}
477
[b7fd2a0]478errno_t devman_fun_get_driver_name(devman_handle_t handle, char *buf, size_t buf_size)
[3f57fb7]479{
[4c9b28a]480 return devman_get_str_internal(DEVMAN_FUN_GET_DRIVER_NAME, handle, 0,
481 NULL, buf, buf_size);
[3f57fb7]482}
483
[b7fd2a0]484errno_t devman_fun_online(devman_handle_t funh)
[1a5b252]485{
[f9b2cb4c]486 async_exch_t *exch = devman_exchange_begin(INTERFACE_DDF_CLIENT);
[1a5b252]487 if (exch == NULL)
488 return ENOMEM;
[a35b458]489
[b7fd2a0]490 errno_t retval = async_req_1_0(exch, DEVMAN_FUN_ONLINE, funh);
[a35b458]491
[1a5b252]492 devman_exchange_end(exch);
[25a179e]493 return retval;
[1a5b252]494}
495
[b7fd2a0]496errno_t devman_fun_offline(devman_handle_t funh)
[1a5b252]497{
[f9b2cb4c]498 async_exch_t *exch = devman_exchange_begin(INTERFACE_DDF_CLIENT);
[1a5b252]499 if (exch == NULL)
500 return ENOMEM;
[a35b458]501
[b7fd2a0]502 errno_t retval = async_req_1_0(exch, DEVMAN_FUN_OFFLINE, funh);
[a35b458]503
[1a5b252]504 devman_exchange_end(exch);
[25a179e]505 return retval;
[1a5b252]506}
507
[b7fd2a0]508static errno_t devman_get_handles_once(sysarg_t method, sysarg_t arg1,
[7beb220]509 devman_handle_t *handle_buf, size_t buf_size, size_t *act_size)
510{
[f9b2cb4c]511 async_exch_t *exch = devman_exchange_begin_blocking(INTERFACE_DDF_CLIENT);
[7beb220]512
513 ipc_call_t answer;
514 aid_t req = async_send_1(exch, method, arg1, &answer);
[b7fd2a0]515 errno_t rc = async_data_read_start(exch, handle_buf, buf_size);
[a35b458]516
[7beb220]517 devman_exchange_end(exch);
[a35b458]518
[7beb220]519 if (rc != EOK) {
[50b581d]520 async_forget(req);
[7beb220]521 return rc;
[431d6d6]522 }
[a35b458]523
[b7fd2a0]524 errno_t retval;
[7beb220]525 async_wait_for(req, &retval);
[a35b458]526
[7beb220]527 if (retval != EOK) {
528 return retval;
529 }
[a35b458]530
[fafb8e5]531 *act_size = ipc_get_arg1(&answer);
[431d6d6]532 return EOK;
533}
534
[7beb220]535/** Get list of handles.
536 *
537 * Returns an allocated array of handles.
538 *
539 * @param method IPC method
540 * @param arg1 IPC argument 1
541 * @param data Place to store pointer to array of handles
542 * @param count Place to store number of handles
[cde999a]543 * @return EOK on success or an error code
[7beb220]544 */
[b7fd2a0]545static errno_t devman_get_handles_internal(sysarg_t method, sysarg_t arg1,
[7beb220]546 devman_handle_t **data, size_t *count)
547{
548 devman_handle_t *handles;
549 size_t act_size;
550 size_t alloc_size;
[b7fd2a0]551 errno_t rc;
[7beb220]552
553 *data = NULL;
554 act_size = 0; /* silence warning */
555
556 rc = devman_get_handles_once(method, arg1, NULL, 0,
557 &act_size);
558 if (rc != EOK)
559 return rc;
560
561 alloc_size = act_size;
562 handles = malloc(alloc_size);
563 if (handles == NULL)
564 return ENOMEM;
565
566 while (true) {
567 rc = devman_get_handles_once(method, arg1, handles, alloc_size,
568 &act_size);
569 if (rc != EOK)
570 return rc;
571
572 if (act_size <= alloc_size)
573 break;
574
575 alloc_size *= 2;
576 free(handles);
577
578 handles = malloc(alloc_size);
579 if (handles == NULL)
580 return ENOMEM;
581 }
582
583 *count = act_size / sizeof(devman_handle_t);
584 *data = handles;
585 return EOK;
586}
587
[b7fd2a0]588errno_t devman_fun_get_child(devman_handle_t funh, devman_handle_t *devh)
[7beb220]589{
[f9b2cb4c]590 async_exch_t *exch = devman_exchange_begin(INTERFACE_DDF_CLIENT);
[7beb220]591 if (exch == NULL)
592 return ENOMEM;
[a35b458]593
[b7fd2a0]594 errno_t retval = async_req_1_1(exch, DEVMAN_FUN_GET_CHILD,
[7beb220]595 funh, devh);
[a35b458]596
[7beb220]597 devman_exchange_end(exch);
[25a179e]598 return retval;
[7beb220]599}
600
[b7fd2a0]601errno_t devman_dev_get_functions(devman_handle_t devh, devman_handle_t **funcs,
[7beb220]602 size_t *count)
603{
604 return devman_get_handles_internal(DEVMAN_DEV_GET_FUNCTIONS,
605 devh, funcs, count);
606}
607
[b7fd2a0]608errno_t devman_dev_get_parent(devman_handle_t devh, devman_handle_t *funh)
[1db5669]609{
[f9b2cb4c]610 async_exch_t *exch = devman_exchange_begin(INTERFACE_DDF_CLIENT);
[1db5669]611 if (exch == NULL)
612 return ENOMEM;
[a35b458]613
[b7fd2a0]614 errno_t retval = async_req_1_1(exch, DEVMAN_DEV_GET_PARENT,
[1db5669]615 devh, funh);
[a35b458]616
[1db5669]617 devman_exchange_end(exch);
[25a179e]618 return retval;
[1db5669]619}
620
[b7fd2a0]621errno_t devman_fun_sid_to_handle(service_id_t sid, devman_handle_t *handle)
[e280857]622{
[f9b2cb4c]623 async_exch_t *exch = devman_exchange_begin(INTERFACE_DDF_CLIENT);
[e280857]624 if (exch == NULL)
625 return ENOMEM;
[a35b458]626
[b7fd2a0]627 errno_t retval = async_req_1_1(exch, DEVMAN_FUN_SID_TO_HANDLE,
[e280857]628 sid, handle);
[a35b458]629
[e280857]630 devman_exchange_end(exch);
[25a179e]631 return retval;
[e280857]632}
633
[b7fd2a0]634errno_t devman_get_drivers(devman_handle_t **drvs,
[0511549]635 size_t *count)
636{
637 return devman_get_handles_internal(DEVMAN_GET_DRIVERS, 0, drvs, count);
638}
639
[b7fd2a0]640errno_t devman_driver_get_devices(devman_handle_t drvh, devman_handle_t **devs,
[1db5669]641 size_t *count)
642{
643 return devman_get_handles_internal(DEVMAN_DRIVER_GET_DEVICES,
644 drvh, devs, count);
645}
646
[b7fd2a0]647errno_t devman_driver_get_handle(const char *drvname, devman_handle_t *handle)
[7969087]648{
649 async_exch_t *exch;
650
[f9b2cb4c]651 exch = devman_exchange_begin(INTERFACE_DDF_CLIENT);
[7969087]652 if (exch == NULL)
653 return ENOMEM;
[a35b458]654
[7969087]655 ipc_call_t answer;
656 aid_t req = async_send_0(exch, DEVMAN_DRIVER_GET_HANDLE, &answer);
[b7fd2a0]657 errno_t retval = async_data_write_start(exch, drvname,
[7969087]658 str_size(drvname));
[a35b458]659
[7969087]660 devman_exchange_end(exch);
[a35b458]661
[7969087]662 if (retval != EOK) {
663 async_forget(req);
664 return retval;
665 }
[a35b458]666
[7969087]667 async_wait_for(req, &retval);
[a35b458]668
[7969087]669 if (retval != EOK) {
670 if (handle != NULL)
671 *handle = (devman_handle_t) -1;
[a35b458]672
[7969087]673 return retval;
674 }
[a35b458]675
[7969087]676 if (handle != NULL)
[fafb8e5]677 *handle = (devman_handle_t) ipc_get_arg1(&answer);
[a35b458]678
[7969087]679 return retval;
680}
681
[b7fd2a0]682errno_t devman_driver_get_match_id(devman_handle_t handle, size_t index, char *buf,
[4c9b28a]683 size_t buf_size, unsigned int *rscore)
684{
[b7fd2a0]685 errno_t rc;
[4c9b28a]686 sysarg_t score = 0;
687
688 rc = devman_get_str_internal(DEVMAN_DRIVER_GET_MATCH_ID, handle, index,
689 &score, buf, buf_size);
690 if (rc != EOK)
691 return rc;
692
693 *rscore = score;
694 return rc;
695}
696
[b7fd2a0]697errno_t devman_driver_get_name(devman_handle_t handle, char *buf, size_t buf_size)
[0511549]698{
[4c9b28a]699 return devman_get_str_internal(DEVMAN_DRIVER_GET_NAME, handle, 0, NULL,
700 buf, buf_size);
[0511549]701}
702
[b7fd2a0]703errno_t devman_driver_get_state(devman_handle_t drvh, driver_state_t *rstate)
[e5556e4a]704{
705 sysarg_t state;
[f9b2cb4c]706 async_exch_t *exch = devman_exchange_begin(INTERFACE_DDF_CLIENT);
[e5556e4a]707 if (exch == NULL)
708 return ENOMEM;
[a35b458]709
[b7fd2a0]710 errno_t rc = async_req_1_1(exch, DEVMAN_DRIVER_GET_STATE, drvh,
[e5556e4a]711 &state);
[a35b458]712
[e5556e4a]713 devman_exchange_end(exch);
714 if (rc != EOK)
715 return rc;
716
717 *rstate = state;
718 return rc;
719}
720
[b7fd2a0]721errno_t devman_driver_load(devman_handle_t drvh)
[7969087]722{
[f9b2cb4c]723 async_exch_t *exch = devman_exchange_begin(INTERFACE_DDF_CLIENT);
[7969087]724 if (exch == NULL)
725 return ENOMEM;
[a35b458]726
[b7fd2a0]727 errno_t rc = async_req_1_0(exch, DEVMAN_DRIVER_LOAD, drvh);
[a35b458]728
[7969087]729 devman_exchange_end(exch);
730 return rc;
731}
732
[b7fd2a0]733errno_t devman_driver_unload(devman_handle_t drvh)
[81685dd9]734{
735 async_exch_t *exch = devman_exchange_begin(INTERFACE_DDF_CLIENT);
736 if (exch == NULL)
737 return ENOMEM;
[a35b458]738
[b7fd2a0]739 errno_t rc = async_req_1_0(exch, DEVMAN_DRIVER_UNLOAD, drvh);
[a35b458]740
[81685dd9]741 devman_exchange_end(exch);
742 return rc;
743}
744
[5cd136ab]745/** @}
[398c4d7]746 */
Note: See TracBrowser for help on using the repository browser.