Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 3080 → Rev 2678

/trunk/uspace/srv/devmap/devmap.c
44,9 → 44,8
#include <futex.h>
#include <stdlib.h>
#include <string.h>
#include <ipc/devmap.h>
 
#define NAME "devmap"
#include "devmap.h"
 
 
LIST_INITIALIZE(devices_list);
113,8 → 112,10
item = item->next;
}
 
if (item == &devices_list)
if (item == &devices_list) {
printf("DEVMAP: no device named %s.\n", name);
return NULL;
}
 
device = list_get_instance(item, devmap_device_t, devices);
return device;
202,6 → 203,7
* Get driver name
*/
if (!ipc_data_write_receive(&callid, &name_size)) {
printf("Unexpected request.\n");
free(driver);
ipc_answer_0(callid, EREFUSED);
ipc_answer_0(iid, EREFUSED);
209,6 → 211,8
}
 
if (name_size > DEVMAP_NAME_MAXLEN) {
printf("Too logn name: %u: maximum is %u.\n", name_size,
DEVMAP_NAME_MAXLEN);
free(driver);
ipc_answer_0(callid, EINVAL);
ipc_answer_0(iid, EREFUSED);
219,6 → 223,7
* Allocate buffer for device name.
*/
if (NULL == (driver->name = (char *)malloc(name_size + 1))) {
printf("Cannot allocate space for driver name.\n");
free(driver);
ipc_answer_0(callid, ENOMEM);
ipc_answer_0(iid, EREFUSED);
229,6 → 234,7
* Send confirmation to sender and get data into buffer.
*/
if (EOK != ipc_data_write_finalize(callid, driver->name, name_size)) {
printf("Cannot read driver name.\n");
free(driver->name);
free(driver);
ipc_answer_0(iid, EREFUSED);
237,6 → 243,8
 
driver->name[name_size] = 0;
 
printf("Read driver name: '%s'.\n", driver->name);
 
/* Initialize futex for list of devices owned by this driver */
futex_initialize(&(driver->devices_futex), 1);
 
251,6 → 259,8
callid = async_get_call(&call);
 
if (IPC_M_CONNECT_TO_ME != IPC_GET_METHOD(call)) {
printf("DEVMAP: Unexpected method: %u.\n",
IPC_GET_METHOD(call));
ipc_answer_0(callid, ENOTSUP);
free(driver->name);
278,8 → 288,10
futex_up(&drivers_list_futex);
ipc_answer_0(iid, EOK);
printf("Driver registered.\n");
 
*odriver = driver;
return;
}
 
/** Unregister device driver, unregister all its devices and free driver
289,9 → 301,12
{
devmap_device_t *device;
 
if (NULL == driver)
if (NULL == driver) {
printf("Error: driver == NULL.\n");
return EEXISTS;
}
 
printf("Unregister driver '%s'.\n", driver->name);
futex_down(&drivers_list_futex);
 
ipc_hangup(driver->phone);
307,6 → 322,7
while (!list_empty(&(driver->devices))) {
device = list_get_instance(driver->devices.next,
devmap_device_t, driver_devices);
printf("Unregister device '%s'.\n", device->name);
devmap_device_unregister_core(device);
}
321,6 → 337,8
 
free(driver);
 
printf("Driver unregistered.\n");
 
return EOK;
}
 
336,6 → 354,7
devmap_device_t *device;
 
if (NULL == driver) {
printf("Invalid driver registration.\n");
ipc_answer_0(iid, EREFUSED);
return;
}
342,7 → 361,8
/* Create new device entry */
if (NULL ==
(device = (devmap_device_t *) malloc(sizeof(devmap_device_t)))) {
(device = (devmap_device_t *)malloc(sizeof(devmap_device_t)))) {
printf("Cannot allocate new device.\n");
ipc_answer_0(iid, ENOMEM);
return;
}
350,21 → 370,24
/* Get device name */
if (!ipc_data_write_receive(&callid, &size)) {
free(device);
printf("Cannot read device name.\n");
ipc_answer_0(iid, EREFUSED);
return;
}
 
if (size > DEVMAP_NAME_MAXLEN) {
printf("Too long device name: %u.\n", size);
free(device);
ipc_answer_0(callid, EINVAL);
ipc_answer_0(iid, EREFUSED);
return;
}
/* +1 for terminating \0 */
device->name = (char *) malloc(size + 1);
 
/* +1 for terminating \0 */
device->name = (char *)malloc(size + 1);
 
if (NULL == device->name) {
printf("Cannot read device name.\n");
free(device);
ipc_answer_0(callid, ENOMEM);
ipc_answer_0(iid, EREFUSED);
381,7 → 404,7
 
/* Check that device with such name is not already registered */
if (NULL != devmap_device_find_name(device->name)) {
printf(NAME ": Device '%s' already registered\n", device->name);
printf("Device '%s' already registered.\n", device->name);
futex_up(&devices_list_futex);
free(device->name);
free(device);
405,7 → 428,10
futex_up(&device->driver->devices_futex);
futex_up(&devices_list_futex);
 
printf("Device '%s' registered.\n", device->name);
ipc_answer_1(iid, EOK, device->handle);
 
return;
}
 
/**
435,6 → 461,8
dev = devmap_device_find_handle(handle);
 
if (NULL == dev) {
printf("DEVMAP: No registered device with handle %d.\n",
handle);
ipc_answer_0(callid, ENOENT);
return;
}
441,6 → 469,7
 
ipc_forward_fast(callid, dev->driver->phone, (ipcarg_t)(dev->handle),
IPC_GET_ARG3(*call), 0, IPC_FF_NONE);
return;
}
 
/** Find handle for device instance identified by name.
455,6 → 484,7
ipc_callid_t callid;
ipcarg_t retval;
/*
* Wait for incoming message with device name (but do not
* read the name itself until the buffer is allocated).
498,11 → 528,16
* Device was not found.
*/
if (NULL == dev) {
printf("DEVMAP: device %s has not been registered.\n", name);
ipc_answer_0(iid, ENOENT);
return;
}
 
printf("DEVMAP: device %s has handler %d.\n", name, dev->handle);
ipc_answer_1(iid, EOK, dev->handle);
 
return;
}
 
/** Find name of device identified by id and send it to caller.
539,12 → 574,15
}
*/
/* TODO: send name in response */
 
return;
}
 
/** Handle connection with device driver.
*
*/
static void devmap_connection_driver(ipc_callid_t iid, ipc_call_t *icall)
static void
devmap_connection_driver(ipc_callid_t iid, ipc_call_t *icall)
{
ipc_callid_t callid;
ipc_call_t call;
555,8 → 593,10
 
devmap_driver_register(&driver);
 
if (NULL == driver)
if (NULL == driver) {
printf("DEVMAP: driver registration failed.\n");
return;
}
while (cont) {
callid = async_get_call(&call);
563,10 → 603,13
 
switch (IPC_GET_METHOD(call)) {
case IPC_M_PHONE_HUNGUP:
printf("DEVMAP: connection hung up.\n");
cont = false;
continue; /* Exit thread */
case DEVMAP_DRIVER_UNREGISTER:
printf("DEVMAP: unregister driver.\n");
if (NULL == driver) {
printf("DEVMAP: driver was not registered!\n");
ipc_answer_0(callid, ENOENT);
} else {
ipc_answer_0(callid, EOK);
606,7 → 649,8
/** Handle connection with device client.
*
*/
static void devmap_connection_client(ipc_callid_t iid, ipc_call_t *icall)
static void
devmap_connection_client(ipc_callid_t iid, ipc_call_t *icall)
{
ipc_callid_t callid;
ipc_call_t call;
619,6 → 663,7
 
switch (IPC_GET_METHOD(call)) {
case IPC_M_PHONE_HUNGUP:
printf("DEVMAP: connection hung up.\n");
cont = false;
continue; /* Exit thread */
 
641,10 → 686,14
/** Function for handling connections to devmap
*
*/
static void devmap_connection(ipc_callid_t iid, ipc_call_t *icall)
static void
devmap_connection(ipc_callid_t iid, ipc_call_t *icall)
{
/* Select interface */
switch ((ipcarg_t) (IPC_GET_ARG1(*icall))) {
 
printf("DEVMAP: new connection.\n");
 
/* Select interface */
switch ((ipcarg_t)(IPC_GET_ARG1(*icall))) {
case DEVMAP_DRIVER:
devmap_connection_driver(iid, icall);
break;
652,14 → 701,21
devmap_connection_client(iid, icall);
break;
case DEVMAP_CONNECT_TO_DEVICE:
/* Connect client to selected device */
/* Connect client to selected device */
printf("DEVMAP: connect to device %d.\n",
IPC_GET_ARG2(*icall));
devmap_forward(iid, icall);
break;
default:
ipc_answer_0(iid, ENOENT); /* No such interface */
printf("DEVMAP: Unknown interface %u.\n",
(ipcarg_t)(IPC_GET_ARG1(*icall)));
}
 
/* Cleanup */
printf("DEVMAP: connection closed.\n");
return;
}
 
/**
667,16 → 723,16
*/
int main(int argc, char *argv[])
{
printf(NAME ": HelenOS Device Mapper\n");
ipcarg_t phonead;
 
printf("DEVMAP: HelenOS device mapper.\n");
 
if (devmap_init() != 0) {
printf(NAME ": Error while initializing service\n");
printf("Error while initializing DEVMAP service.\n");
return -1;
}
/* Set a handler of incomming connections */
 
/* Set a handler of incomming connections */
async_set_client_connection(devmap_connection);
 
/* Register device mapper at naming service */
683,7 → 739,6
if (ipc_connect_to_me(PHONE_NS, SERVICE_DEVMAP, 0, 0, &phonead) != 0)
return -1;
printf(NAME ": Accepting connections\n");
async_manager();
/* Never reached */
return 0;
692,3 → 747,4
/**
* @}
*/
 
/trunk/uspace/srv/devmap/devmap.h
0,0 → 1,99
/*
* Copyright (c) 2007 Josef Cejka
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup devmap
* @{
*/
 
#ifndef DEVMAP_DEVMAP_H_
#define DEVMAP_DEVMAP_H_
 
#include <ipc/ipc.h>
#include <libadt/list.h>
 
#define DEVMAP_NAME_MAXLEN 512
 
typedef enum {
DEVMAP_DRIVER_REGISTER = IPC_FIRST_USER_METHOD,
DEVMAP_DRIVER_UNREGISTER,
DEVMAP_DEVICE_REGISTER,
DEVMAP_DEVICE_UNREGISTER,
DEVMAP_DEVICE_GET_NAME,
DEVMAP_DEVICE_GET_HANDLE
} devmap_request_t;
 
/** Representation of device driver.
* Each driver is responsible for a set of devices.
*/
typedef struct {
/** Pointers to previous and next drivers in linked list */
link_t drivers;
/** Pointer to the linked list of devices controlled by
* this driver */
link_t devices;
/** Phone asociated with this driver */
ipcarg_t phone;
/** Device driver name */
char *name;
/** Futex for list of devices owned by this driver */
atomic_t devices_futex;
} devmap_driver_t;
 
/** Info about registered device
*
*/
typedef struct {
/** Pointer to the previous and next device in the list of all devices */
link_t devices;
/** Pointer to the previous and next device in the list of devices
owned by one driver */
link_t driver_devices;
/** Unique device identifier */
int handle;
/** Device name */
char *name;
/** Device driver handling this device */
devmap_driver_t *driver;
} devmap_device_t;
 
/** Interface provided by devmap.
* Every process that connects to devmap must ask one of following
* interfaces otherwise connection will be refused.
*/
typedef enum {
/** Connect as device driver */
DEVMAP_DRIVER = 1,
/** Connect as client */
DEVMAP_CLIENT,
/** Create new connection to instance of device that
* is specified by second argument of call. */
DEVMAP_CONNECT_TO_DEVICE
} devmap_interface_t;
 
#endif