Subversion Repositories HelenOS

Rev

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

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