Subversion Repositories HelenOS

Rev

Rev 3022 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

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