Subversion Repositories HelenOS

Rev

Rev 4581 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

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