Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 4667 → Rev 4668

/branches/dd/uspace/srv/devmap/devmap.c
46,7 → 46,8
#include <string.h>
#include <ipc/devmap.h>
 
#define NAME "devmap"
#define NAME "devmap"
#define NULL_DEVICES 256
 
/** Representation of device driver.
*
83,16 → 84,8
devmap_driver_t *driver;
} devmap_device_t;
 
/** Pending lookup structure. */
typedef struct {
link_t link;
char *name; /**< Device name */
ipc_callid_t callid; /**< Call ID waiting for the lookup */
} pending_req_t;
 
LIST_INITIALIZE(devices_list);
LIST_INITIALIZE(drivers_list);
LIST_INITIALIZE(pending_req);
 
/* Locking order:
* drivers_list_mutex
102,10 → 95,13
**/
 
static FIBRIL_MUTEX_INITIALIZE(devices_list_mutex);
static FIBRIL_CONDVAR_INITIALIZE(devices_list_cv);
static FIBRIL_MUTEX_INITIALIZE(drivers_list_mutex);
static FIBRIL_MUTEX_INITIALIZE(create_handle_mutex);
static FIBRIL_MUTEX_INITIALIZE(null_devices_mutex);
 
static dev_handle_t last_handle = 0;
static devmap_device_t *null_devices[NULL_DEVICES];
 
static dev_handle_t devmap_create_handle(void)
{
174,10 → 170,8
}
 
/**
*
* Unregister device and free it. It's assumed that driver's device list is
* already locked.
*
*/
static int devmap_device_unregister_core(devmap_device_t *device)
{
191,10 → 185,8
}
 
/**
*
* Read info about new driver and add it into linked list of registered
* drivers.
*
*/
static void devmap_driver_register(devmap_driver_t **odriver)
{
344,31 → 336,6
return EOK;
}
 
 
/** Process pending lookup requests */
static void process_pending_lookup(void)
{
link_t *cur;
loop:
for (cur = pending_req.next; cur != &pending_req; cur = cur->next) {
pending_req_t *pr = list_get_instance(cur, pending_req_t, link);
const devmap_device_t *dev = devmap_device_find_name(pr->name);
if (!dev)
continue;
ipc_answer_1(pr->callid, EOK, dev->handle);
free(pr->name);
list_remove(cur);
free(pr);
goto loop;
}
}
 
 
/** Register instance of device
*
*/
445,6 → 412,7
list_append(&device->driver_devices, &device->driver->devices);
fibril_mutex_unlock(&device->driver->devices_mutex);
fibril_condvar_broadcast(&devices_list_cv);
fibril_mutex_unlock(&devices_list_mutex);
ipc_answer_1(iid, EOK, device->handle);
530,10 → 498,14
}
name[size] = '\0';
fibril_mutex_lock(&devices_list_mutex);
const devmap_device_t *dev;
recheck:
 
/*
* Find device name in linked list of known devices.
* Find device name in the list of known devices.
*/
const devmap_device_t *dev = devmap_device_find_name(name);
dev = devmap_device_find_name(name);
/*
* Device was not found.
540,24 → 512,18
*/
if (dev == NULL) {
if (IPC_GET_ARG1(*icall) & IPC_FLAG_BLOCKING) {
/* Blocking lookup, add to pending list */
pending_req_t *pr = (pending_req_t *) malloc(sizeof(pending_req_t));
if (!pr) {
ipc_answer_0(iid, ENOMEM);
free(name);
return;
}
pr->name = name;
pr->callid = iid;
list_append(&pr->link, &pending_req);
return;
/* Blocking lookup */
fibril_condvar_wait(&devices_list_cv,
&devices_list_mutex);
goto recheck;
}
ipc_answer_0(iid, ENOENT);
free(name);
fibril_mutex_unlock(&devices_list_mutex);
return;
}
fibril_mutex_unlock(&devices_list_mutex);
ipc_answer_1(iid, EOK, dev->handle);
free(name);
655,21 → 621,43
ipc_answer_1(iid, EOK, pos);
}
 
/** Initialize device mapper.
*
*
*/
static bool devmap_init()
static void devmap_null_create(ipc_callid_t iid, ipc_call_t *icall)
{
fibril_mutex_lock(&null_devices_mutex);
unsigned int i;
bool fnd = false;
for (i = 0; i < NULL_DEVICES; i++) {
if (null_devices[i] == NULL) {
fnd = true;
break;
}
}
if (!fnd) {
fibril_mutex_unlock(&null_devices_mutex);
ipc_answer_0(iid, ENOMEM);
return;
}
/* Create NULL device entry */
devmap_device_t *device = (devmap_device_t *) malloc(sizeof(devmap_device_t));
if (device == NULL)
return false;
if (device == NULL) {
fibril_mutex_unlock(&null_devices_mutex);
ipc_answer_0(iid, ENOMEM);
return;
}
device->name = str_dup("null");
char null[DEVMAP_NAME_MAXLEN];
snprintf(null, DEVMAP_NAME_MAXLEN, "null%u", i);
device->name = str_dup(null);
if (device->name == NULL) {
fibril_mutex_unlock(&null_devices_mutex);
free(device);
return false;
ipc_answer_0(iid, ENOMEM);
return;
}
list_initialize(&(device->devices));
681,11 → 669,50
device->handle = devmap_create_handle();
device->driver = NULL;
/* Insert device into list of all devices */
/* Insert device into list of all devices
and into null devices array */
list_append(&device->devices, &devices_list);
null_devices[i] = device;
fibril_mutex_unlock(&devices_list_mutex);
fibril_mutex_unlock(&null_devices_mutex);
ipc_answer_1(iid, EOK, (ipcarg_t) i);
}
 
static void devmap_null_destroy(ipc_callid_t iid, ipc_call_t *icall)
{
fibril_mutex_lock(&null_devices_mutex);
ipcarg_t i = IPC_GET_ARG1(*icall);
if (null_devices[i] == NULL) {
ipc_answer_0(iid, ENOENT);
return;
}
devmap_device_unregister_core(null_devices[i]);
null_devices[i] = NULL;
fibril_mutex_unlock(&null_devices_mutex);
ipc_answer_0(iid, EOK);
}
 
/** Initialize device mapper.
*
*
*/
static bool devmap_init(void)
{
fibril_mutex_lock(&null_devices_mutex);
unsigned int i;
for (i = 0; i < NULL_DEVICES; i++)
null_devices[i] = NULL;
fibril_mutex_unlock(&null_devices_mutex);
return true;
}
 
738,7 → 765,7
}
}
if (NULL != driver) {
if (driver != NULL) {
/*
* Unregister the device driver and all its devices.
*/
770,6 → 797,12
case DEVMAP_DEVICE_GET_NAME:
devmap_get_name(callid, &call);
break;
case DEVMAP_DEVICE_NULL_CREATE:
devmap_null_create(callid, &call);
break;
case DEVMAP_DEVICE_NULL_DESTROY:
devmap_null_destroy(callid, &call);
break;
case DEVMAP_DEVICE_GET_COUNT:
devmap_get_count(callid, &call);
break;
818,9 → 851,7
return -1;
}
/* Set a handler of incomming connections and
pending operations */
async_set_pending(process_pending_lookup);
/* Set a handler of incomming connections */
async_set_client_connection(devmap_connection);
/* Register device mapper at naming service */