Subversion Repositories HelenOS

Rev

Rev 4540 | Rev 4591 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 4540 Rev 4570
1
/*
1
/*
2
 * Copyright (c) 2007 Josef Cejka
2
 * Copyright (c) 2007 Josef Cejka
3
 * All rights reserved.
3
 * All rights reserved.
4
 *
4
 *
5
 * Redistribution and use in source and binary forms, with or without
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
6
 * modification, are permitted provided that the following conditions
7
 * are met:
7
 * are met:
8
 *
8
 *
9
 * - Redistributions of source code must retain the above copyright
9
 * - Redistributions of source code must retain the above copyright
10
 *   notice, this list of conditions and the following disclaimer.
10
 *   notice, this list of conditions and the following disclaimer.
11
 * - Redistributions in binary form must reproduce the above copyright
11
 * - Redistributions in binary form must reproduce the above copyright
12
 *   notice, this list of conditions and the following disclaimer in the
12
 *   notice, this list of conditions and the following disclaimer in the
13
 *   documentation and/or other materials provided with the distribution.
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
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.
15
 *   derived from this software without specific prior written permission.
16
 *
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
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
18
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
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
23
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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
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.
26
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
 */
27
 */
28
 
28
 
29
/**
29
/**
30
 * @defgroup devmap Device mapper.
30
 * @defgroup devmap Device mapper.
31
 * @brief HelenOS device mapper.
31
 * @brief HelenOS device mapper.
32
 * @{
32
 * @{
33
 */
33
 */
34
 
34
 
35
/** @file
35
/** @file
36
 */
36
 */
37
 
37
 
38
#include <ipc/services.h>
38
#include <ipc/services.h>
39
#include <ipc/ns.h>
39
#include <ipc/ns.h>
40
#include <async.h>
40
#include <async.h>
41
#include <stdio.h>
41
#include <stdio.h>
42
#include <errno.h>
42
#include <errno.h>
43
#include <bool.h>
43
#include <bool.h>
44
#include <fibril_sync.h>
44
#include <fibril_sync.h>
45
#include <stdlib.h>
45
#include <stdlib.h>
46
#include <string.h>
46
#include <string.h>
47
#include <ipc/devmap.h>
47
#include <ipc/devmap.h>
48
#include <assert.h>
-
 
49
 
48
 
50
#define NAME  "devmap"
49
#define NAME  "devmap"
51
 
50
 
52
/** Representation of device driver.
51
/** Representation of device driver.
53
 *
52
 *
54
 * Each driver is responsible for a set of devices.
53
 * Each driver is responsible for a set of devices.
55
 *
54
 *
56
 */
55
 */
57
typedef struct {
56
typedef struct {
58
    /** Pointers to previous and next drivers in linked list */
57
    /** Pointers to previous and next drivers in linked list */
59
    link_t drivers;
58
    link_t drivers;
60
    /** Pointer to the linked list of devices controlled by this driver */
59
    /** Pointer to the linked list of devices controlled by this driver */
61
    link_t devices;
60
    link_t devices;
62
    /** Phone asociated with this driver */
61
    /** Phone asociated with this driver */
63
    ipcarg_t phone;
62
    ipcarg_t phone;
64
    /** Device driver name */
63
    /** Device driver name */
65
    char *name;
64
    char *name;
66
    /** Fibril mutex for list of devices owned by this driver */
65
    /** Fibril mutex for list of devices owned by this driver */
67
    fibril_mutex_t devices_mutex;
66
    fibril_mutex_t devices_mutex;
68
} devmap_driver_t;
67
} devmap_driver_t;
69
 
68
 
70
/** Info about registered device
69
/** Info about registered device
71
 *
70
 *
72
 */
71
 */
73
typedef struct {
72
typedef struct {
74
    /** Pointer to the previous and next device in the list of all devices */
73
    /** Pointer to the previous and next device in the list of all devices */
75
    link_t devices;
74
    link_t devices;
76
    /** Pointer to the previous and next device in the list of devices
75
    /** Pointer to the previous and next device in the list of devices
77
        owned by one driver */
76
        owned by one driver */
78
    link_t driver_devices;
77
    link_t driver_devices;
79
    /** Unique device identifier  */
78
    /** Unique device identifier  */
80
    dev_handle_t handle;
79
    dev_handle_t handle;
81
    /** Device name */
80
    /** Device name */
82
    char *name;
81
    char *name;
83
    /** Device driver handling this device */
82
    /** Device driver handling this device */
84
    devmap_driver_t *driver;
83
    devmap_driver_t *driver;
85
} devmap_device_t;
84
} devmap_device_t;
86
 
85
 
87
/** Pending lookup structure. */
-
 
88
typedef struct {
-
 
89
    link_t link;
-
 
90
    char *name;              /**< Device name */
-
 
91
    ipc_callid_t callid;     /**< Call ID waiting for the lookup */
-
 
92
} pending_req_t;
-
 
93
 
-
 
94
LIST_INITIALIZE(devices_list);
86
LIST_INITIALIZE(devices_list);
95
LIST_INITIALIZE(drivers_list);
87
LIST_INITIALIZE(drivers_list);
96
LIST_INITIALIZE(pending_req);
-
 
97
 
-
 
98
static bool pending_new_dev = false;
-
 
99
static FIBRIL_CONDVAR_INITIALIZE(pending_cv);
-
 
100
 
88
 
101
/* Locking order:
89
/* Locking order:
102
 *  drivers_list_mutex
90
 *  drivers_list_mutex
103
 *  devices_list_mutex
91
 *  devices_list_mutex
104
 *  (devmap_driver_t *)->devices_mutex
92
 *  (devmap_driver_t *)->devices_mutex
105
 *  create_handle_mutex
93
 *  create_handle_mutex
106
 **/
94
 **/
107
 
95
 
108
static FIBRIL_MUTEX_INITIALIZE(devices_list_mutex);
96
static FIBRIL_MUTEX_INITIALIZE(devices_list_mutex);
-
 
97
static FIBRIL_CONDVAR_INITIALIZE(devices_list_cv);
109
static FIBRIL_MUTEX_INITIALIZE(drivers_list_mutex);
98
static FIBRIL_MUTEX_INITIALIZE(drivers_list_mutex);
110
static FIBRIL_MUTEX_INITIALIZE(create_handle_mutex);
99
static FIBRIL_MUTEX_INITIALIZE(create_handle_mutex);
111
 
100
 
112
static dev_handle_t last_handle = 0;
101
static dev_handle_t last_handle = 0;
113
 
102
 
114
static dev_handle_t devmap_create_handle(void)
103
static dev_handle_t devmap_create_handle(void)
115
{
104
{
116
    /* TODO: allow reusing old handles after their unregistration
105
    /* TODO: allow reusing old handles after their unregistration
117
     * and implement some version of LRU algorithm, avoid overflow
106
     * and implement some version of LRU algorithm, avoid overflow
118
     */
107
     */
119
   
108
   
120
    fibril_mutex_lock(&create_handle_mutex);
109
    fibril_mutex_lock(&create_handle_mutex);
121
    last_handle++;
110
    last_handle++;
122
    fibril_mutex_unlock(&create_handle_mutex);
111
    fibril_mutex_unlock(&create_handle_mutex);
123
   
112
   
124
    return last_handle;
113
    return last_handle;
125
}
114
}
126
 
115
 
127
/** Find device with given name.
116
/** Find device with given name.
128
 *
117
 *
129
 */
118
 */
130
static devmap_device_t *devmap_device_find_name(const char *name)
119
static devmap_device_t *devmap_device_find_name(const char *name)
131
{
120
{
132
    link_t *item = devices_list.next;
121
    link_t *item = devices_list.next;
133
    devmap_device_t *device = NULL;
122
    devmap_device_t *device = NULL;
134
   
123
   
135
    while (item != &devices_list) {
124
    while (item != &devices_list) {
136
        device = list_get_instance(item, devmap_device_t, devices);
125
        device = list_get_instance(item, devmap_device_t, devices);
137
        if (str_cmp(device->name, name) == 0)
126
        if (str_cmp(device->name, name) == 0)
138
            break;
127
            break;
139
        item = item->next;
128
        item = item->next;
140
    }
129
    }
141
   
130
   
142
    if (item == &devices_list)
131
    if (item == &devices_list)
143
        return NULL;
132
        return NULL;
144
   
133
   
145
    device = list_get_instance(item, devmap_device_t, devices);
134
    device = list_get_instance(item, devmap_device_t, devices);
146
    return device;
135
    return device;
147
}
136
}
148
 
137
 
149
/** Find device with given handle.
138
/** Find device with given handle.
150
 *
139
 *
151
 * @todo: use hash table
140
 * @todo: use hash table
152
 *
141
 *
153
 */
142
 */
154
static devmap_device_t *devmap_device_find_handle(dev_handle_t handle)
143
static devmap_device_t *devmap_device_find_handle(dev_handle_t handle)
155
{
144
{
156
    fibril_mutex_lock(&devices_list_mutex);
145
    fibril_mutex_lock(&devices_list_mutex);
157
   
146
   
158
    link_t *item = (&devices_list)->next;
147
    link_t *item = (&devices_list)->next;
159
    devmap_device_t *device = NULL;
148
    devmap_device_t *device = NULL;
160
   
149
   
161
    while (item != &devices_list) {
150
    while (item != &devices_list) {
162
        device = list_get_instance(item, devmap_device_t, devices);
151
        device = list_get_instance(item, devmap_device_t, devices);
163
        if (device->handle == handle)
152
        if (device->handle == handle)
164
            break;
153
            break;
165
        item = item->next;
154
        item = item->next;
166
    }
155
    }
167
   
156
   
168
    if (item == &devices_list) {
157
    if (item == &devices_list) {
169
        fibril_mutex_unlock(&devices_list_mutex);
158
        fibril_mutex_unlock(&devices_list_mutex);
170
        return NULL;
159
        return NULL;
171
    }
160
    }
172
   
161
   
173
    device = list_get_instance(item, devmap_device_t, devices);
162
    device = list_get_instance(item, devmap_device_t, devices);
174
   
163
   
175
    fibril_mutex_unlock(&devices_list_mutex);
164
    fibril_mutex_unlock(&devices_list_mutex);
176
   
165
   
177
    return device;
166
    return device;
178
}
167
}
179
 
168
 
180
/**
169
/**
181
 * Unregister device and free it. It's assumed that driver's device list is
170
 * Unregister device and free it. It's assumed that driver's device list is
182
 * already locked.
171
 * already locked.
183
 */
172
 */
184
static int devmap_device_unregister_core(devmap_device_t *device)
173
static int devmap_device_unregister_core(devmap_device_t *device)
185
{
174
{
186
    list_remove(&(device->devices));
175
    list_remove(&(device->devices));
187
    list_remove(&(device->driver_devices));
176
    list_remove(&(device->driver_devices));
188
   
177
   
189
    free(device->name);
178
    free(device->name);
190
    free(device);
179
    free(device);
191
   
180
   
192
    return EOK;
181
    return EOK;
193
}
182
}
194
 
183
 
195
/**
184
/**
196
 * Read info about new driver and add it into linked list of registered
185
 * Read info about new driver and add it into linked list of registered
197
 * drivers.
186
 * drivers.
198
 */
187
 */
199
static void devmap_driver_register(devmap_driver_t **odriver)
188
static void devmap_driver_register(devmap_driver_t **odriver)
200
{
189
{
201
    *odriver = NULL;
190
    *odriver = NULL;
202
   
191
   
203
    ipc_call_t icall;
192
    ipc_call_t icall;
204
    ipc_callid_t iid = async_get_call(&icall);
193
    ipc_callid_t iid = async_get_call(&icall);
205
   
194
   
206
    if (IPC_GET_METHOD(icall) != DEVMAP_DRIVER_REGISTER) {
195
    if (IPC_GET_METHOD(icall) != DEVMAP_DRIVER_REGISTER) {
207
        ipc_answer_0(iid, EREFUSED);
196
        ipc_answer_0(iid, EREFUSED);
208
        return;
197
        return;
209
    }
198
    }
210
   
199
   
211
    devmap_driver_t *driver = (devmap_driver_t *) malloc(sizeof(devmap_driver_t));
200
    devmap_driver_t *driver = (devmap_driver_t *) malloc(sizeof(devmap_driver_t));
212
   
201
   
213
    if (driver == NULL) {
202
    if (driver == NULL) {
214
        ipc_answer_0(iid, ENOMEM);
203
        ipc_answer_0(iid, ENOMEM);
215
        return;
204
        return;
216
    }
205
    }
217
   
206
   
218
    /*
207
    /*
219
     * Get driver name
208
     * Get driver name
220
     */
209
     */
221
    ipc_callid_t callid;
210
    ipc_callid_t callid;
222
    size_t name_size;
211
    size_t name_size;
223
    if (!ipc_data_write_receive(&callid, &name_size)) {
212
    if (!ipc_data_write_receive(&callid, &name_size)) {
224
        free(driver);
213
        free(driver);
225
        ipc_answer_0(callid, EREFUSED);
214
        ipc_answer_0(callid, EREFUSED);
226
        ipc_answer_0(iid, EREFUSED);
215
        ipc_answer_0(iid, EREFUSED);
227
        return;
216
        return;
228
    }
217
    }
229
   
218
   
230
    if (name_size > DEVMAP_NAME_MAXLEN) {
219
    if (name_size > DEVMAP_NAME_MAXLEN) {
231
        free(driver);
220
        free(driver);
232
        ipc_answer_0(callid, EINVAL);
221
        ipc_answer_0(callid, EINVAL);
233
        ipc_answer_0(iid, EREFUSED);
222
        ipc_answer_0(iid, EREFUSED);
234
        return;
223
        return;
235
    }
224
    }
236
   
225
   
237
    /*
226
    /*
238
     * Allocate buffer for device name.
227
     * Allocate buffer for device name.
239
     */
228
     */
240
    driver->name = (char *) malloc(name_size + 1);
229
    driver->name = (char *) malloc(name_size + 1);
241
    if (driver->name == NULL) {
230
    if (driver->name == NULL) {
242
        free(driver);
231
        free(driver);
243
        ipc_answer_0(callid, ENOMEM);
232
        ipc_answer_0(callid, ENOMEM);
244
        ipc_answer_0(iid, EREFUSED);
233
        ipc_answer_0(iid, EREFUSED);
245
        return;
234
        return;
246
    }
235
    }
247
   
236
   
248
    /*
237
    /*
249
     * Send confirmation to sender and get data into buffer.
238
     * Send confirmation to sender and get data into buffer.
250
     */
239
     */
251
    if (ipc_data_write_finalize(callid, driver->name, name_size) != EOK) {
240
    if (ipc_data_write_finalize(callid, driver->name, name_size) != EOK) {
252
        free(driver->name);
241
        free(driver->name);
253
        free(driver);
242
        free(driver);
254
        ipc_answer_0(iid, EREFUSED);
243
        ipc_answer_0(iid, EREFUSED);
255
        return;
244
        return;
256
    }
245
    }
257
   
246
   
258
    driver->name[name_size] = 0;
247
    driver->name[name_size] = 0;
259
   
248
   
260
    /* Initialize mutex for list of devices owned by this driver */
249
    /* Initialize mutex for list of devices owned by this driver */
261
    fibril_mutex_initialize(&driver->devices_mutex);
250
    fibril_mutex_initialize(&driver->devices_mutex);
262
   
251
   
263
    /*
252
    /*
264
     * Initialize list of asociated devices
253
     * Initialize list of asociated devices
265
     */
254
     */
266
    list_initialize(&driver->devices);
255
    list_initialize(&driver->devices);
267
   
256
   
268
    /*
257
    /*
269
     * Create connection to the driver
258
     * Create connection to the driver
270
     */
259
     */
271
    ipc_call_t call;
260
    ipc_call_t call;
272
    callid = async_get_call(&call);
261
    callid = async_get_call(&call);
273
   
262
   
274
    if (IPC_GET_METHOD(call) != IPC_M_CONNECT_TO_ME) {
263
    if (IPC_GET_METHOD(call) != IPC_M_CONNECT_TO_ME) {
275
        ipc_answer_0(callid, ENOTSUP);
264
        ipc_answer_0(callid, ENOTSUP);
276
       
265
       
277
        free(driver->name);
266
        free(driver->name);
278
        free(driver);
267
        free(driver);
279
        ipc_answer_0(iid, ENOTSUP);
268
        ipc_answer_0(iid, ENOTSUP);
280
        return;
269
        return;
281
    }
270
    }
282
   
271
   
283
    driver->phone = IPC_GET_ARG5(call);
272
    driver->phone = IPC_GET_ARG5(call);
284
   
273
   
285
    ipc_answer_0(callid, EOK);
274
    ipc_answer_0(callid, EOK);
286
   
275
   
287
    list_initialize(&(driver->drivers));
276
    list_initialize(&(driver->drivers));
288
   
277
   
289
    fibril_mutex_lock(&drivers_list_mutex);
278
    fibril_mutex_lock(&drivers_list_mutex);
290
   
279
   
291
    /* TODO:
280
    /* TODO:
292
     * check that no driver with name equal to driver->name is registered
281
     * check that no driver with name equal to driver->name is registered
293
     */
282
     */
294
   
283
   
295
    /*
284
    /*
296
     * Insert new driver into list of registered drivers
285
     * Insert new driver into list of registered drivers
297
     */
286
     */
298
    list_append(&(driver->drivers), &drivers_list);
287
    list_append(&(driver->drivers), &drivers_list);
299
    fibril_mutex_unlock(&drivers_list_mutex);
288
    fibril_mutex_unlock(&drivers_list_mutex);
300
   
289
   
301
    ipc_answer_0(iid, EOK);
290
    ipc_answer_0(iid, EOK);
302
   
291
   
303
    *odriver = driver;
292
    *odriver = driver;
304
}
293
}
305
 
294
 
306
/**
295
/**
307
 * Unregister device driver, unregister all its devices and free driver
296
 * Unregister device driver, unregister all its devices and free driver
308
 * structure.
297
 * structure.
309
 *
298
 *
310
 */
299
 */
311
static int devmap_driver_unregister(devmap_driver_t *driver)
300
static int devmap_driver_unregister(devmap_driver_t *driver)
312
{
301
{
313
    if (driver == NULL)
302
    if (driver == NULL)
314
        return EEXISTS;
303
        return EEXISTS;
315
   
304
   
316
    fibril_mutex_lock(&drivers_list_mutex);
305
    fibril_mutex_lock(&drivers_list_mutex);
317
   
306
   
318
    if (driver->phone != 0)
307
    if (driver->phone != 0)
319
        ipc_hangup(driver->phone);
308
        ipc_hangup(driver->phone);
320
   
309
   
321
    /* Remove it from list of drivers */
310
    /* Remove it from list of drivers */
322
    list_remove(&(driver->drivers));
311
    list_remove(&(driver->drivers));
323
   
312
   
324
    /* Unregister all its devices */
313
    /* Unregister all its devices */
325
    fibril_mutex_lock(&devices_list_mutex);
314
    fibril_mutex_lock(&devices_list_mutex);
326
    fibril_mutex_lock(&driver->devices_mutex);
315
    fibril_mutex_lock(&driver->devices_mutex);
327
   
316
   
328
    while (!list_empty(&(driver->devices))) {
317
    while (!list_empty(&(driver->devices))) {
329
        devmap_device_t *device = list_get_instance(driver->devices.next,
318
        devmap_device_t *device = list_get_instance(driver->devices.next,
330
            devmap_device_t, driver_devices);
319
            devmap_device_t, driver_devices);
331
        devmap_device_unregister_core(device);
320
        devmap_device_unregister_core(device);
332
    }
321
    }
333
   
322
   
334
    fibril_mutex_unlock(&driver->devices_mutex);
323
    fibril_mutex_unlock(&driver->devices_mutex);
335
    fibril_mutex_unlock(&devices_list_mutex);
324
    fibril_mutex_unlock(&devices_list_mutex);
336
    fibril_mutex_unlock(&drivers_list_mutex);
325
    fibril_mutex_unlock(&drivers_list_mutex);
337
   
326
   
338
    /* free name and driver */
327
    /* free name and driver */
339
    if (driver->name != NULL)
328
    if (driver->name != NULL)
340
        free(driver->name);
329
        free(driver->name);
341
   
330
   
342
    free(driver);
331
    free(driver);
343
   
332
   
344
    return EOK;
333
    return EOK;
345
}
334
}
346
 
335
 
347
 
-
 
348
/** Process pending lookup requests */
-
 
349
static void process_pending_lookup(void)
-
 
350
{
-
 
351
    link_t *cur;
-
 
352
 
-
 
353
loop:
-
 
354
    fibril_mutex_lock(&devices_list_mutex);
-
 
355
    while (!pending_new_dev)
-
 
356
        fibril_condvar_wait(&pending_cv, &devices_list_mutex);
-
 
357
rescan:
-
 
358
    for (cur = pending_req.next; cur != &pending_req; cur = cur->next) {
-
 
359
        pending_req_t *pr = list_get_instance(cur, pending_req_t, link);
-
 
360
       
-
 
361
        const devmap_device_t *dev = devmap_device_find_name(pr->name);
-
 
362
        if (!dev)
-
 
363
            continue;
-
 
364
       
-
 
365
        ipc_answer_1(pr->callid, EOK, dev->handle);
-
 
366
       
-
 
367
        free(pr->name);
-
 
368
        list_remove(cur);
-
 
369
        free(pr);
-
 
370
       
-
 
371
        goto rescan;
-
 
372
    }
-
 
373
    pending_new_dev = false;
-
 
374
    fibril_mutex_unlock(&devices_list_mutex);
-
 
375
    goto loop;
-
 
376
}
-
 
377
 
-
 
378
 
-
 
379
/** Register instance of device
336
/** Register instance of device
380
 *
337
 *
381
 */
338
 */
382
static void devmap_device_register(ipc_callid_t iid, ipc_call_t *icall,
339
static void devmap_device_register(ipc_callid_t iid, ipc_call_t *icall,
383
    devmap_driver_t *driver)
340
    devmap_driver_t *driver)
384
{
341
{
385
    if (driver == NULL) {
342
    if (driver == NULL) {
386
        ipc_answer_0(iid, EREFUSED);
343
        ipc_answer_0(iid, EREFUSED);
387
        return;
344
        return;
388
    }
345
    }
389
   
346
   
390
    /* Create new device entry */
347
    /* Create new device entry */
391
    devmap_device_t *device = (devmap_device_t *) malloc(sizeof(devmap_device_t));
348
    devmap_device_t *device = (devmap_device_t *) malloc(sizeof(devmap_device_t));
392
    if (device == NULL) {
349
    if (device == NULL) {
393
        ipc_answer_0(iid, ENOMEM);
350
        ipc_answer_0(iid, ENOMEM);
394
        return;
351
        return;
395
    }
352
    }
396
   
353
   
397
    /* Get device name */
354
    /* Get device name */
398
    ipc_callid_t callid;
355
    ipc_callid_t callid;
399
    size_t size;
356
    size_t size;
400
    if (!ipc_data_write_receive(&callid, &size)) {
357
    if (!ipc_data_write_receive(&callid, &size)) {
401
        free(device);
358
        free(device);
402
        ipc_answer_0(iid, EREFUSED);
359
        ipc_answer_0(iid, EREFUSED);
403
        return;
360
        return;
404
    }
361
    }
405
   
362
   
406
    if (size > DEVMAP_NAME_MAXLEN) {
363
    if (size > DEVMAP_NAME_MAXLEN) {
407
        free(device);
364
        free(device);
408
        ipc_answer_0(callid, EINVAL);
365
        ipc_answer_0(callid, EINVAL);
409
        ipc_answer_0(iid, EREFUSED);
366
        ipc_answer_0(iid, EREFUSED);
410
        return;
367
        return;
411
    }
368
    }
412
   
369
   
413
    /* +1 for terminating \0 */
370
    /* +1 for terminating \0 */
414
    device->name = (char *) malloc(size + 1);
371
    device->name = (char *) malloc(size + 1);
415
   
372
   
416
    if (device->name == NULL) {
373
    if (device->name == NULL) {
417
        free(device);
374
        free(device);
418
        ipc_answer_0(callid, ENOMEM);
375
        ipc_answer_0(callid, ENOMEM);
419
        ipc_answer_0(iid, EREFUSED);
376
        ipc_answer_0(iid, EREFUSED);
420
        return;
377
        return;
421
    }
378
    }
422
   
379
   
423
    ipc_data_write_finalize(callid, device->name, size);
380
    ipc_data_write_finalize(callid, device->name, size);
424
    device->name[size] = 0;
381
    device->name[size] = 0;
425
   
382
   
426
    list_initialize(&(device->devices));
383
    list_initialize(&(device->devices));
427
    list_initialize(&(device->driver_devices));
384
    list_initialize(&(device->driver_devices));
428
   
385
   
429
    fibril_mutex_lock(&devices_list_mutex);
386
    fibril_mutex_lock(&devices_list_mutex);
430
   
387
   
431
    /* Check that device with such name is not already registered */
388
    /* Check that device with such name is not already registered */
432
    if (NULL != devmap_device_find_name(device->name)) {
389
    if (NULL != devmap_device_find_name(device->name)) {
433
        printf(NAME ": Device '%s' already registered\n", device->name);
390
        printf(NAME ": Device '%s' already registered\n", device->name);
434
        fibril_mutex_unlock(&devices_list_mutex);
391
        fibril_mutex_unlock(&devices_list_mutex);
435
        free(device->name);
392
        free(device->name);
436
        free(device);
393
        free(device);
437
        ipc_answer_0(iid, EEXISTS);
394
        ipc_answer_0(iid, EEXISTS);
438
        return;
395
        return;
439
    }
396
    }
440
   
397
   
441
    /* Get unique device handle */
398
    /* Get unique device handle */
442
    device->handle = devmap_create_handle();
399
    device->handle = devmap_create_handle();
443
   
400
   
444
    device->driver = driver;
401
    device->driver = driver;
445
   
402
   
446
    /* Insert device into list of all devices  */
403
    /* Insert device into list of all devices  */
447
    list_append(&device->devices, &devices_list);
404
    list_append(&device->devices, &devices_list);
448
   
405
   
449
    /* Insert device into list of devices that belog to one driver */
406
    /* Insert device into list of devices that belog to one driver */
450
    fibril_mutex_lock(&device->driver->devices_mutex);
407
    fibril_mutex_lock(&device->driver->devices_mutex);
451
   
408
   
452
    list_append(&device->driver_devices, &device->driver->devices);
409
    list_append(&device->driver_devices, &device->driver->devices);
453
   
410
   
454
    fibril_mutex_unlock(&device->driver->devices_mutex);
411
    fibril_mutex_unlock(&device->driver->devices_mutex);
455
    pending_new_dev = true;
-
 
456
    fibril_condvar_signal(&pending_cv);
412
    fibril_condvar_broadcast(&devices_list_cv);
457
    fibril_mutex_unlock(&devices_list_mutex);
413
    fibril_mutex_unlock(&devices_list_mutex);
458
   
414
   
459
    ipc_answer_1(iid, EOK, device->handle);
415
    ipc_answer_1(iid, EOK, device->handle);
460
}
416
}
461
 
417
 
462
/**
418
/**
463
 *
419
 *
464
 */
420
 */
465
static int devmap_device_unregister(ipc_callid_t iid, ipc_call_t *icall,
421
static int devmap_device_unregister(ipc_callid_t iid, ipc_call_t *icall,
466
    devmap_driver_t *driver)
422
    devmap_driver_t *driver)
467
{
423
{
468
    /* TODO */
424
    /* TODO */
469
    return EOK;
425
    return EOK;
470
}
426
}
471
 
427
 
472
/** Connect client to the device.
428
/** Connect client to the device.
473
 *
429
 *
474
 * Find device driver owning requested device and forward
430
 * Find device driver owning requested device and forward
475
 * the message to it.
431
 * the message to it.
476
 *
432
 *
477
 */
433
 */
478
static void devmap_forward(ipc_callid_t callid, ipc_call_t *call)
434
static void devmap_forward(ipc_callid_t callid, ipc_call_t *call)
479
{
435
{
480
    /*
436
    /*
481
     * Get handle from request
437
     * Get handle from request
482
     */
438
     */
483
    dev_handle_t handle = IPC_GET_ARG2(*call);
439
    dev_handle_t handle = IPC_GET_ARG2(*call);
484
    devmap_device_t *dev = devmap_device_find_handle(handle);
440
    devmap_device_t *dev = devmap_device_find_handle(handle);
485
   
441
   
486
    if ((dev == NULL) || (dev->driver == NULL) || (dev->driver->phone == 0)) {
442
    if ((dev == NULL) || (dev->driver == NULL) || (dev->driver->phone == 0)) {
487
        ipc_answer_0(callid, ENOENT);
443
        ipc_answer_0(callid, ENOENT);
488
        return;
444
        return;
489
    }
445
    }
490
   
446
   
491
    ipc_forward_fast(callid, dev->driver->phone, dev->handle,
447
    ipc_forward_fast(callid, dev->driver->phone, dev->handle,
492
        IPC_GET_ARG3(*call), 0, IPC_FF_NONE);
448
        IPC_GET_ARG3(*call), 0, IPC_FF_NONE);
493
}
449
}
494
 
450
 
495
/** Find handle for device instance identified by name.
451
/** Find handle for device instance identified by name.
496
 *
452
 *
497
 * In answer will be send EOK and device handle in arg1 or a error
453
 * In answer will be send EOK and device handle in arg1 or a error
498
 * code from errno.h.
454
 * code from errno.h.
499
 *
455
 *
500
 */
456
 */
501
static void devmap_get_handle(ipc_callid_t iid, ipc_call_t *icall)
457
static void devmap_get_handle(ipc_callid_t iid, ipc_call_t *icall)
502
{
458
{
503
    /*
459
    /*
504
     * Wait for incoming message with device name (but do not
460
     * Wait for incoming message with device name (but do not
505
     * read the name itself until the buffer is allocated).
461
     * read the name itself until the buffer is allocated).
506
     */
462
     */
507
    ipc_callid_t callid;
463
    ipc_callid_t callid;
508
    size_t size;
464
    size_t size;
509
    if (!ipc_data_write_receive(&callid, &size)) {
465
    if (!ipc_data_write_receive(&callid, &size)) {
510
        ipc_answer_0(callid, EREFUSED);
466
        ipc_answer_0(callid, EREFUSED);
511
        ipc_answer_0(iid, EREFUSED);
467
        ipc_answer_0(iid, EREFUSED);
512
        return;
468
        return;
513
    }
469
    }
514
   
470
   
515
    if ((size < 1) || (size > DEVMAP_NAME_MAXLEN)) {
471
    if ((size < 1) || (size > DEVMAP_NAME_MAXLEN)) {
516
        ipc_answer_0(callid, EINVAL);
472
        ipc_answer_0(callid, EINVAL);
517
        ipc_answer_0(iid, EREFUSED);
473
        ipc_answer_0(iid, EREFUSED);
518
        return;
474
        return;
519
    }
475
    }
520
   
476
   
521
    /*
477
    /*
522
     * Allocate buffer for device name.
478
     * Allocate buffer for device name.
523
     */
479
     */
524
    char *name = (char *) malloc(size + 1);
480
    char *name = (char *) malloc(size + 1);
525
    if (name == NULL) {
481
    if (name == NULL) {
526
        ipc_answer_0(callid, ENOMEM);
482
        ipc_answer_0(callid, ENOMEM);
527
        ipc_answer_0(iid, EREFUSED);
483
        ipc_answer_0(iid, EREFUSED);
528
        return;
484
        return;
529
    }
485
    }
530
   
486
   
531
    /*
487
    /*
532
     * Send confirmation to sender and get data into buffer.
488
     * Send confirmation to sender and get data into buffer.
533
     */
489
     */
534
    ipcarg_t retval = ipc_data_write_finalize(callid, name, size);
490
    ipcarg_t retval = ipc_data_write_finalize(callid, name, size);
535
    if (retval != EOK) {
491
    if (retval != EOK) {
536
        ipc_answer_0(iid, EREFUSED);
492
        ipc_answer_0(iid, EREFUSED);
537
        free(name);
493
        free(name);
538
        return;
494
        return;
539
    }
495
    }
540
    name[size] = '\0';
496
    name[size] = '\0';
541
   
497
   
542
    fibril_mutex_lock(&devices_list_mutex);
498
    fibril_mutex_lock(&devices_list_mutex);
-
 
499
    const devmap_device_t *dev;
-
 
500
recheck:
543
 
501
 
544
    /*
502
    /*
545
     * Find device name in linked list of known devices.
503
     * Find device name in the list of known devices.
546
     */
504
     */
547
    const devmap_device_t *dev = devmap_device_find_name(name);
505
    dev = devmap_device_find_name(name);
548
   
506
   
549
    /*
507
    /*
550
     * Device was not found.
508
     * Device was not found.
551
     */
509
     */
552
    if (dev == NULL) {
510
    if (dev == NULL) {
553
        if (IPC_GET_ARG1(*icall) & IPC_FLAG_BLOCKING) {
511
        if (IPC_GET_ARG1(*icall) & IPC_FLAG_BLOCKING) {
554
            /* Blocking lookup, add to pending list */
512
            /* Blocking lookup */
555
            pending_req_t *pr = (pending_req_t *) malloc(sizeof(pending_req_t));
-
 
556
            if (!pr) {
-
 
557
                fibril_mutex_unlock(&devices_list_mutex);
513
            fibril_condvar_wait(&devices_list_cv,
558
                ipc_answer_0(iid, ENOMEM);
-
 
559
                free(name);
-
 
560
                return;
-
 
561
            }
-
 
562
           
-
 
563
            pr->name = name;
-
 
564
            pr->callid = iid;
-
 
565
            list_append(&pr->link, &pending_req);
-
 
566
            fibril_mutex_unlock(&devices_list_mutex);
514
                &devices_list_mutex);
567
            return;
515
            goto recheck;
568
        }
516
        }
569
       
517
       
570
        ipc_answer_0(iid, ENOENT);
518
        ipc_answer_0(iid, ENOENT);
571
        free(name);
519
        free(name);
572
        fibril_mutex_unlock(&devices_list_mutex);
520
        fibril_mutex_unlock(&devices_list_mutex);
573
        return;
521
        return;
574
    }
522
    }
575
    fibril_mutex_unlock(&devices_list_mutex);
523
    fibril_mutex_unlock(&devices_list_mutex);
576
   
524
   
577
    ipc_answer_1(iid, EOK, dev->handle);
525
    ipc_answer_1(iid, EOK, dev->handle);
578
    free(name);
526
    free(name);
579
}
527
}
580
 
528
 
581
/** Find name of device identified by id and send it to caller.
529
/** Find name of device identified by id and send it to caller.
582
 *
530
 *
583
 */
531
 */
584
static void devmap_get_name(ipc_callid_t iid, ipc_call_t *icall)
532
static void devmap_get_name(ipc_callid_t iid, ipc_call_t *icall)
585
{
533
{
586
    const devmap_device_t *device = devmap_device_find_handle(IPC_GET_ARG1(*icall));
534
    const devmap_device_t *device = devmap_device_find_handle(IPC_GET_ARG1(*icall));
587
   
535
   
588
    /*
536
    /*
589
     * Device not found.
537
     * Device not found.
590
     */
538
     */
591
    if (device == NULL) {
539
    if (device == NULL) {
592
        ipc_answer_0(iid, ENOENT);
540
        ipc_answer_0(iid, ENOENT);
593
        return;
541
        return;
594
    }
542
    }
595
   
543
   
596
    ipc_answer_0(iid, EOK);
544
    ipc_answer_0(iid, EOK);
597
   
545
   
598
    size_t name_size = str_size(device->name);
546
    size_t name_size = str_size(device->name);
599
   
547
   
600
    /* FIXME:
548
    /* FIXME:
601
     * We have no channel from DEVMAP to client, therefore
549
     * We have no channel from DEVMAP to client, therefore
602
     * sending must be initiated by client.
550
     * sending must be initiated by client.
603
     *
551
     *
604
     * int rc = ipc_data_write_send(phone, device->name, name_size);
552
     * int rc = ipc_data_write_send(phone, device->name, name_size);
605
     * if (rc != EOK) {
553
     * if (rc != EOK) {
606
     *     async_wait_for(req, NULL);
554
     *     async_wait_for(req, NULL);
607
     *     return rc;
555
     *     return rc;
608
     * }
556
     * }
609
     */
557
     */
610
   
558
   
611
    /* TODO: send name in response */
559
    /* TODO: send name in response */
612
}
560
}
613
 
561
 
614
static void devmap_get_count(ipc_callid_t iid, ipc_call_t *icall)
562
static void devmap_get_count(ipc_callid_t iid, ipc_call_t *icall)
615
{
563
{
616
    fibril_mutex_lock(&devices_list_mutex);
564
    fibril_mutex_lock(&devices_list_mutex);
617
    ipc_answer_1(iid, EOK, list_count(&devices_list));
565
    ipc_answer_1(iid, EOK, list_count(&devices_list));
618
    fibril_mutex_unlock(&devices_list_mutex);
566
    fibril_mutex_unlock(&devices_list_mutex);
619
}
567
}
620
 
568
 
621
static void devmap_get_devices(ipc_callid_t iid, ipc_call_t *icall)
569
static void devmap_get_devices(ipc_callid_t iid, ipc_call_t *icall)
622
{
570
{
623
    fibril_mutex_lock(&devices_list_mutex);
571
    fibril_mutex_lock(&devices_list_mutex);
624
   
572
   
625
    ipc_callid_t callid;
573
    ipc_callid_t callid;
626
    size_t size;
574
    size_t size;
627
    if (!ipc_data_read_receive(&callid, &size)) {
575
    if (!ipc_data_read_receive(&callid, &size)) {
628
        ipc_answer_0(callid, EREFUSED);
576
        ipc_answer_0(callid, EREFUSED);
629
        ipc_answer_0(iid, EREFUSED);
577
        ipc_answer_0(iid, EREFUSED);
630
        return;
578
        return;
631
    }
579
    }
632
   
580
   
633
    if ((size % sizeof(dev_desc_t)) != 0) {
581
    if ((size % sizeof(dev_desc_t)) != 0) {
634
        ipc_answer_0(callid, EINVAL);
582
        ipc_answer_0(callid, EINVAL);
635
        ipc_answer_0(iid, EREFUSED);
583
        ipc_answer_0(iid, EREFUSED);
636
        return;
584
        return;
637
    }
585
    }
638
   
586
   
639
    size_t count = size / sizeof(dev_desc_t);
587
    size_t count = size / sizeof(dev_desc_t);
640
    dev_desc_t *desc = (dev_desc_t *) malloc(size);
588
    dev_desc_t *desc = (dev_desc_t *) malloc(size);
641
    if (desc == NULL) {
589
    if (desc == NULL) {
642
        ipc_answer_0(callid, ENOMEM);
590
        ipc_answer_0(callid, ENOMEM);
643
        ipc_answer_0(iid, EREFUSED);
591
        ipc_answer_0(iid, EREFUSED);
644
        return;
592
        return;
645
    }
593
    }
646
   
594
   
647
    size_t pos = 0;
595
    size_t pos = 0;
648
    link_t *item = devices_list.next;
596
    link_t *item = devices_list.next;
649
   
597
   
650
    while ((item != &devices_list) && (pos < count)) {
598
    while ((item != &devices_list) && (pos < count)) {
651
        devmap_device_t *device = list_get_instance(item, devmap_device_t, devices);
599
        devmap_device_t *device = list_get_instance(item, devmap_device_t, devices);
652
       
600
       
653
        desc[pos].handle = device->handle;
601
        desc[pos].handle = device->handle;
654
        str_cpy(desc[pos].name, DEVMAP_NAME_MAXLEN, device->name);
602
        str_cpy(desc[pos].name, DEVMAP_NAME_MAXLEN, device->name);
655
        pos++;
603
        pos++;
656
        item = item->next;
604
        item = item->next;
657
    }
605
    }
658
   
606
   
659
    ipcarg_t retval = ipc_data_read_finalize(callid, desc, pos * sizeof(dev_desc_t));
607
    ipcarg_t retval = ipc_data_read_finalize(callid, desc, pos * sizeof(dev_desc_t));
660
    if (retval != EOK) {
608
    if (retval != EOK) {
661
        ipc_answer_0(iid, EREFUSED);
609
        ipc_answer_0(iid, EREFUSED);
662
        free(desc);
610
        free(desc);
663
        return;
611
        return;
664
    }
612
    }
665
   
613
   
666
    free(desc);
614
    free(desc);
667
   
615
   
668
    fibril_mutex_unlock(&devices_list_mutex);
616
    fibril_mutex_unlock(&devices_list_mutex);
669
   
617
   
670
    ipc_answer_1(iid, EOK, pos);
618
    ipc_answer_1(iid, EOK, pos);
671
}
619
}
672
 
620
 
673
/** Initialize device mapper.
621
/** Initialize device mapper.
674
 *
622
 *
675
 *
623
 *
676
 */
624
 */
677
static bool devmap_init(void)
625
static bool devmap_init(void)
678
{
626
{
679
    /* Create NULL device entry */
627
    /* Create NULL device entry */
680
    devmap_device_t *device = (devmap_device_t *) malloc(sizeof(devmap_device_t));
628
    devmap_device_t *device = (devmap_device_t *) malloc(sizeof(devmap_device_t));
681
    if (device == NULL)
629
    if (device == NULL)
682
        return false;
630
        return false;
683
   
631
   
684
    device->name = str_dup("null");
632
    device->name = str_dup("null");
685
    if (device->name == NULL) {
633
    if (device->name == NULL) {
686
        free(device);
634
        free(device);
687
        return false;
635
        return false;
688
    }
636
    }
689
   
637
   
690
    list_initialize(&(device->devices));
638
    list_initialize(&(device->devices));
691
    list_initialize(&(device->driver_devices));
639
    list_initialize(&(device->driver_devices));
692
   
640
   
693
    fibril_mutex_lock(&devices_list_mutex);
641
    fibril_mutex_lock(&devices_list_mutex);
694
   
642
   
695
    /* Get unique device handle */
643
    /* Get unique device handle */
696
    device->handle = devmap_create_handle();
644
    device->handle = devmap_create_handle();
697
    device->driver = NULL;
645
    device->driver = NULL;
698
   
646
   
699
    /* Insert device into list of all devices  */
647
    /* Insert device into list of all devices  */
700
    list_append(&device->devices, &devices_list);
648
    list_append(&device->devices, &devices_list);
701
   
649
   
702
    fibril_mutex_unlock(&devices_list_mutex);
650
    fibril_mutex_unlock(&devices_list_mutex);
703
   
651
   
704
    return true;
652
    return true;
705
}
653
}
706
 
654
 
707
/** Handle connection with device driver.
655
/** Handle connection with device driver.
708
 *
656
 *
709
 */
657
 */
710
static void devmap_connection_driver(ipc_callid_t iid, ipc_call_t *icall)
658
static void devmap_connection_driver(ipc_callid_t iid, ipc_call_t *icall)
711
{
659
{
712
    /* Accept connection */
660
    /* Accept connection */
713
    ipc_answer_0(iid, EOK);
661
    ipc_answer_0(iid, EOK);
714
   
662
   
715
    devmap_driver_t *driver = NULL;
663
    devmap_driver_t *driver = NULL;
716
    devmap_driver_register(&driver);
664
    devmap_driver_register(&driver);
717
   
665
   
718
    if (NULL == driver)
666
    if (NULL == driver)
719
        return;
667
        return;
720
   
668
   
721
    bool cont = true;
669
    bool cont = true;
722
    while (cont) {
670
    while (cont) {
723
        ipc_call_t call;
671
        ipc_call_t call;
724
        ipc_callid_t callid = async_get_call(&call);
672
        ipc_callid_t callid = async_get_call(&call);
725
       
673
       
726
        switch (IPC_GET_METHOD(call)) {
674
        switch (IPC_GET_METHOD(call)) {
727
        case IPC_M_PHONE_HUNGUP:
675
        case IPC_M_PHONE_HUNGUP:
728
            cont = false;
676
            cont = false;
729
            continue;
677
            continue;
730
        case DEVMAP_DRIVER_UNREGISTER:
678
        case DEVMAP_DRIVER_UNREGISTER:
731
            if (NULL == driver)
679
            if (NULL == driver)
732
                ipc_answer_0(callid, ENOENT);
680
                ipc_answer_0(callid, ENOENT);
733
            else
681
            else
734
                ipc_answer_0(callid, EOK);
682
                ipc_answer_0(callid, EOK);
735
            break;
683
            break;
736
        case DEVMAP_DEVICE_REGISTER:
684
        case DEVMAP_DEVICE_REGISTER:
737
            /* Register one instance of device */
685
            /* Register one instance of device */
738
            devmap_device_register(callid, &call, driver);
686
            devmap_device_register(callid, &call, driver);
739
            break;
687
            break;
740
        case DEVMAP_DEVICE_UNREGISTER:
688
        case DEVMAP_DEVICE_UNREGISTER:
741
            /* Remove instance of device identified by handler */
689
            /* Remove instance of device identified by handler */
742
            devmap_device_unregister(callid, &call, driver);
690
            devmap_device_unregister(callid, &call, driver);
743
            break;
691
            break;
744
        case DEVMAP_DEVICE_GET_HANDLE:
692
        case DEVMAP_DEVICE_GET_HANDLE:
745
            devmap_get_handle(callid, &call);
693
            devmap_get_handle(callid, &call);
746
            break;
694
            break;
747
        case DEVMAP_DEVICE_GET_NAME:
695
        case DEVMAP_DEVICE_GET_NAME:
748
            devmap_get_name(callid, &call);
696
            devmap_get_name(callid, &call);
749
            break;
697
            break;
750
        default:
698
        default:
751
            if (!(callid & IPC_CALLID_NOTIFICATION))
699
            if (!(callid & IPC_CALLID_NOTIFICATION))
752
                ipc_answer_0(callid, ENOENT);
700
                ipc_answer_0(callid, ENOENT);
753
        }
701
        }
754
    }
702
    }
755
   
703
   
756
    if (NULL != driver) {
704
    if (NULL != driver) {
757
        /*
705
        /*
758
         * Unregister the device driver and all its devices.
706
         * Unregister the device driver and all its devices.
759
         */
707
         */
760
        devmap_driver_unregister(driver);
708
        devmap_driver_unregister(driver);
761
        driver = NULL;
709
        driver = NULL;
762
    }
710
    }
763
}
711
}
764
 
712
 
765
/** Handle connection with device client.
713
/** Handle connection with device client.
766
 *
714
 *
767
 */
715
 */
768
static void devmap_connection_client(ipc_callid_t iid, ipc_call_t *icall)
716
static void devmap_connection_client(ipc_callid_t iid, ipc_call_t *icall)
769
{
717
{
770
    /* Accept connection */
718
    /* Accept connection */
771
    ipc_answer_0(iid, EOK);
719
    ipc_answer_0(iid, EOK);
772
   
720
   
773
    bool cont = true;
721
    bool cont = true;
774
    while (cont) {
722
    while (cont) {
775
        ipc_call_t call;
723
        ipc_call_t call;
776
        ipc_callid_t callid = async_get_call(&call);
724
        ipc_callid_t callid = async_get_call(&call);
777
       
725
       
778
        switch (IPC_GET_METHOD(call)) {
726
        switch (IPC_GET_METHOD(call)) {
779
        case IPC_M_PHONE_HUNGUP:
727
        case IPC_M_PHONE_HUNGUP:
780
            cont = false;
728
            cont = false;
781
            continue;
729
            continue;
782
        case DEVMAP_DEVICE_GET_HANDLE:
730
        case DEVMAP_DEVICE_GET_HANDLE:
783
            devmap_get_handle(callid, &call);
731
            devmap_get_handle(callid, &call);
784
            break;
732
            break;
785
        case DEVMAP_DEVICE_GET_NAME:
733
        case DEVMAP_DEVICE_GET_NAME:
786
            devmap_get_name(callid, &call);
734
            devmap_get_name(callid, &call);
787
            break;
735
            break;
788
        case DEVMAP_DEVICE_GET_COUNT:
736
        case DEVMAP_DEVICE_GET_COUNT:
789
            devmap_get_count(callid, &call);
737
            devmap_get_count(callid, &call);
790
            break;
738
            break;
791
        case DEVMAP_DEVICE_GET_DEVICES:
739
        case DEVMAP_DEVICE_GET_DEVICES:
792
            devmap_get_devices(callid, &call);
740
            devmap_get_devices(callid, &call);
793
            break;
741
            break;
794
        default:
742
        default:
795
            if (!(callid & IPC_CALLID_NOTIFICATION))
743
            if (!(callid & IPC_CALLID_NOTIFICATION))
796
                ipc_answer_0(callid, ENOENT);
744
                ipc_answer_0(callid, ENOENT);
797
        }
745
        }
798
    }
746
    }
799
}
747
}
800
 
748
 
801
/** Function for handling connections to devmap
749
/** Function for handling connections to devmap
802
 *
750
 *
803
 */
751
 */
804
static void devmap_connection(ipc_callid_t iid, ipc_call_t *icall)
752
static void devmap_connection(ipc_callid_t iid, ipc_call_t *icall)
805
{
753
{
806
    /* Select interface */
754
    /* Select interface */
807
    switch ((ipcarg_t) (IPC_GET_ARG1(*icall))) {
755
    switch ((ipcarg_t) (IPC_GET_ARG1(*icall))) {
808
    case DEVMAP_DRIVER:
756
    case DEVMAP_DRIVER:
809
        devmap_connection_driver(iid, icall);
757
        devmap_connection_driver(iid, icall);
810
        break;
758
        break;
811
    case DEVMAP_CLIENT:
759
    case DEVMAP_CLIENT:
812
        devmap_connection_client(iid, icall);
760
        devmap_connection_client(iid, icall);
813
        break;
761
        break;
814
    case DEVMAP_CONNECT_TO_DEVICE:
762
    case DEVMAP_CONNECT_TO_DEVICE:
815
        /* Connect client to selected device */
763
        /* Connect client to selected device */
816
        devmap_forward(iid, icall);
764
        devmap_forward(iid, icall);
817
        break;
765
        break;
818
    default:
766
    default:
819
        /* No such interface */
767
        /* No such interface */
820
        ipc_answer_0(iid, ENOENT);
768
        ipc_answer_0(iid, ENOENT);
821
    }
769
    }
822
}
770
}
823
 
771
 
824
/**
772
/**
825
 *
773
 *
826
 */
774
 */
827
int main(int argc, char *argv[])
775
int main(int argc, char *argv[])
828
{
776
{
829
    printf(NAME ": HelenOS Device Mapper\n");
777
    printf(NAME ": HelenOS Device Mapper\n");
830
   
778
   
831
    if (!devmap_init()) {
779
    if (!devmap_init()) {
832
        printf(NAME ": Error while initializing service\n");
780
        printf(NAME ": Error while initializing service\n");
833
        return -1;
781
        return -1;
834
    }
782
    }
835
   
783
   
836
    /* Set a handler of incomming connections */
784
    /* Set a handler of incomming connections */
837
    async_set_client_connection(devmap_connection);
785
    async_set_client_connection(devmap_connection);
838
 
786
 
839
    /* Create a fibril for handling pending device lookups */
-
 
840
    fid_t fid = fibril_create(process_pending_lookup, NULL);
-
 
841
    assert(fid);
-
 
842
    fibril_add_ready(fid);
-
 
843
   
-
 
844
    /* Register device mapper at naming service */
787
    /* Register device mapper at naming service */
845
    ipcarg_t phonead;
788
    ipcarg_t phonead;
846
    if (ipc_connect_to_me(PHONE_NS, SERVICE_DEVMAP, 0, 0, &phonead) != 0)
789
    if (ipc_connect_to_me(PHONE_NS, SERVICE_DEVMAP, 0, 0, &phonead) != 0)
847
        return -1;
790
        return -1;
848
   
791
   
849
    printf(NAME ": Accepting connections\n");
792
    printf(NAME ": Accepting connections\n");
850
    async_manager();
793
    async_manager();
851
   
794
   
852
    /* Never reached */
795
    /* Never reached */
853
    return 0;
796
    return 0;
854
}
797
}
855
 
798
 
856
/**
799
/**
857
 * @}
800
 * @}
858
 */
801
 */
859
 
802