Subversion Repositories HelenOS

Rev

Rev 4524 | Rev 4570 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

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