Exemplo n.º 1
0
int hal_release(const char *comp_name)
{
    CHECK_HALDATA();
    CHECK_STRLEN(comp_name, HAL_NAME_LEN);
    {
	hal_comp_t *comp __attribute__((cleanup(halpr_autorelease_mutex)));

	rtapi_mutex_get(&(hal_data->mutex));
	comp = halpr_find_comp_by_name(comp_name);

	if (comp == NULL) {
	    HALERR("no such component '%s'", comp_name);
	    return -EINVAL;
	}
	if (comp->type != TYPE_REMOTE) {
	    HALERR("component '%s' not a remote component (%d)",
		   comp_name, comp->type);
	    return -EINVAL;
	}
	if (comp->pid == 0) {
	    HALERR("component '%s': component already disowned",
			    comp_name);
	    return -EINVAL;
	}

	if (comp->pid != getpid()) {
	    HALERR("component '%s': component owned by pid %d",
			    comp_name, comp->pid);
	    // return -EINVAL;
	}
	comp->pid = 0;
    }
    return 0;
}
Exemplo n.º 2
0
int hal_unbind(const char *comp_name)
{
    CHECK_HALDATA();
    CHECK_STRLEN(comp_name, HAL_NAME_LEN);
    {
	hal_comp_t *comp __attribute__((cleanup(halpr_autorelease_mutex)));

	rtapi_mutex_get(&(hal_data->mutex));

	comp = halpr_find_comp_by_name(comp_name);
	if (comp == NULL) {
	    HALERR("no such component '%s'", comp_name);
	    return -EINVAL;
	}
	if (comp->type != TYPE_REMOTE) {
	    HALERR("component '%s' not a remote component (%d)",
		   comp_name, comp->type);
	    return -EINVAL;
	}
	if (comp->state != COMP_BOUND) {
	    HALERR("component '%s': state not bound (%d)",
		   comp_name, comp->state);
	    return -EINVAL;
	}
	comp->state = COMP_UNBOUND;
	comp->last_unbound = (long int) time(NULL);
    }
    return 0;
}
Exemplo n.º 3
0
int rtapi_exit(int module_id)
{
    module_data *module;
    int n;

    if (rtapi_data == NULL) {
	rtapi_print_msg(RTAPI_MSG_ERR,
	    "RTAPI: ERROR: exit called before init\n");
	return -EINVAL;
    }
    rtapi_print_msg(RTAPI_MSG_DBG, "RTAPI: module %02d exiting\n", module_id);
    /* validate module ID */
    if ((module_id < 1) || (module_id > RTAPI_MAX_MODULES)) {
	rtapi_print_msg(RTAPI_MSG_ERR, "RTAPI: ERROR: bad module id\n");
	return -EINVAL;
    }
    /* get mutex */
    rtapi_mutex_get(&(rtapi_data->mutex));
    /* point to the module's data */
    module = &(module_array[module_id]);
    /* check module status */
    if (module->state != USERSPACE) {
	rtapi_print_msg(RTAPI_MSG_ERR,
	    "RTAPI: ERROR: not a userspace module\n");
	rtapi_mutex_give(&(rtapi_data->mutex));
	return -EINVAL;
    }
    /* clean up any mess left behind by the module */
    for (n = 1; n <= RTAPI_MAX_SHMEMS; n++) {
	if (test_bit(module_id, shmem_array[n].bitmap)) {
	    fprintf(stderr,
		"ULAPI: WARNING: module '%s' failed to delete shmem %02d\n",
		module->name, n);
	    shmem_delete(n, module_id);
	}
    }
    for (n = 1; n <= RTAPI_MAX_FIFOS; n++) {
	if ((fifo_array[n].reader == module_id) ||
	    (fifo_array[n].writer == module_id)) {
	    fprintf(stderr,
		"ULAPI: WARNING: module '%s' failed to delete fifo %02d\n",
		module->name, n);
	    fifo_delete(n, module_id);
	}
    }
    /* update module data */
    rtapi_print_msg(RTAPI_MSG_DBG, "RTAPI: module %02d exited, name = '%s'\n",
	module_id, module->name);
    module->state = NO_MODULE;
    module->name[0] = '\0';
    rtapi_data->ul_module_count--;
    rtapi_mutex_give(&(rtapi_data->mutex));
    nummods--;
    if(nummods == 0)
    {
	rtai_free(RTAPI_KEY, rtapi_data);
	rtapi_data = 0;
    }
    return 0;
}
Exemplo n.º 4
0
int hal_set_constructor(int comp_id, constructor make) {
    int next;
    hal_comp_t *comp  __attribute__((cleanup(halpr_autorelease_mutex)));

    rtapi_mutex_get(&(hal_data->mutex));

    /* search component list for 'comp_id' */
    next = hal_data->comp_list_ptr;
    if (next == 0) {
	/* list is empty - should never happen, but... */
	hal_print_msg(RTAPI_MSG_ERR,
	    "HAL: ERROR: component %d not found\n", comp_id);
	return -EINVAL;
    }

    comp = SHMPTR(next);
    while (comp->comp_id != comp_id) {
	/* not a match, try the next one */
	next = comp->next_ptr;
	if (next == 0) {
	    /* reached end of list without finding component */
	    hal_print_msg(RTAPI_MSG_ERR,
		"HAL: ERROR: component %d not found\n", comp_id);
	    return -EINVAL;
	}
	comp = SHMPTR(next);
    }
    comp->make = make;
    return 0;
}
Exemplo n.º 5
0
int hal_bind(const char *comp_name)
{
    if (hal_data == 0) {
	hal_print_msg(RTAPI_MSG_ERR,
			"HAL: ERROR: hal_bind called before hal_init\n");
	return -EINVAL;
    }
    {
	hal_comp_t *comp __attribute__((cleanup(halpr_autorelease_mutex)));

	rtapi_mutex_get(&(hal_data->mutex));
	comp = halpr_find_comp_by_name(comp_name);

	if (comp == NULL) {
	    hal_print_msg(RTAPI_MSG_ERR,
			    "HAL: hal_bind(): no such component '%s'\n", comp_name);
	    return -EINVAL;
	}
	if (comp->type != TYPE_REMOTE) {
	    hal_print_msg(RTAPI_MSG_ERR,
			    "HAL: hal_bind(%s): not a remote componet (%d)\n",
			    comp_name, comp->type);
	    return -EINVAL;
	}
	if (comp->state != COMP_UNBOUND) {
	    hal_print_msg(RTAPI_MSG_ERR,
			    "HAL: hal_bind(%s): state not unbound (%d)\n",
			    comp_name, comp->state);
	    return -EINVAL;
	}
	comp->state = COMP_BOUND;
	comp->last_bound = (long int) time(NULL);; // XXX ugly
    }
    return 0;
}
Exemplo n.º 6
0
int hal_ready(int comp_id) {
    int next;
    hal_comp_t *comp  __attribute__((cleanup(halpr_autorelease_mutex)));

    rtapi_mutex_get(&(hal_data->mutex));

    /* search component list for 'comp_id' */
    next = hal_data->comp_list_ptr;
    if (next == 0) {
	/* list is empty - should never happen, but... */
	HALERR("BUG: no components defined - %d", comp_id);
	return -EINVAL;
    }

    comp = SHMPTR(next);
    while (comp->comp_id != comp_id) {
	/* not a match, try the next one */
	next = comp->next_ptr;
	if (next == 0) {
	    /* reached end of list without finding component */
	    HALERR("component %d not found", comp_id);
	    return -EINVAL;
	}
	comp = SHMPTR(next);
    }
    if(comp->state > COMP_INITIALIZING) {
	HALERR("component '%s' id %d already ready (state %d)",
	       comp->name, comp->comp_id, comp->state);
        return -EINVAL;
    }
    comp->state = (comp->type == TYPE_REMOTE ?  COMP_UNBOUND : COMP_READY);
    return 0;
}
Exemplo n.º 7
0
int hal_ring_detach(const char *name, ringbuffer_t *rbptr)
{

    CHECK_HALDATA();
    CHECK_STRLEN(name, HAL_NAME_LEN);
    CHECK_LOCK(HAL_LOCK_CONFIG);

    if ((rbptr == NULL) || (rbptr->magic != RINGBUFFER_MAGIC)) {
	HALERR("ring '%s': invalid ringbuffer", name);
	return -EINVAL;
    }

    // no mutex(es) held up to here
    {
	int retval __attribute__((cleanup(halpr_autorelease_mutex)));
	rtapi_mutex_get(&(hal_data->mutex));

	ringheader_t *rhptr = rbptr->header;
	rhptr->refcount--;
	rbptr->magic = 0;  // invalidate FIXME

	// unlocking happens automatically on scope exit
    }
    return 0;
}
Exemplo n.º 8
0
int hal_del_funct_from_thread(const char *funct_name, const char *thread_name)
{
    hal_funct_t *funct;
    hal_list_t *list_root, *list_entry;
    hal_funct_entry_t *funct_entry;

    CHECK_HALDATA();
    CHECK_LOCK(HAL_LOCK_CONFIG);
    CHECK_STR(funct_name);
    CHECK_STR(thread_name);

    HALDBG("removing function '%s' from thread '%s'", funct_name, thread_name);
    {
	hal_thread_t *thread __attribute__((cleanup(halpr_autorelease_mutex)));

	/* get mutex before accessing data structures */
	rtapi_mutex_get(&(hal_data->mutex));

	/* search function list for the function */
	funct = halpr_find_funct_by_name(funct_name);
	if (funct == 0) {
	    HALERR("function '%s' not found", funct_name);
	    return -EINVAL;
	}
	/* found the function, is it in use? */
	if (funct->users == 0) {
	    HALERR("function '%s' is not in use", funct_name);
	    return -EINVAL;
	}
	/* search thread list for thread_name */
	thread = halpr_find_thread_by_name(thread_name);
	if (thread == 0) {
	    /* thread not found */
	    HALERR("thread '%s' not found", thread_name);
	    return -EINVAL;
	}
	/* ok, we have thread and function, does thread use funct? */
	list_root = &(thread->funct_list);
	list_entry = list_next(list_root);
	while (1) {
	    if (list_entry == list_root) {
		/* reached end of list, funct not found */
		HALERR("thread '%s' doesn't use %s",
		       thread_name, funct_name);
		return -EINVAL;
	    }
	    funct_entry = (hal_funct_entry_t *) list_entry;
	    if (SHMPTR(funct_entry->funct_ptr) == funct) {
		/* this funct entry points to our funct, unlink */
		list_remove_entry(list_entry);
		/* and delete it */
		free_funct_entry_struct(funct_entry);
		/* done */
		return 0;
	    }
	    /* try next one */
	    list_entry = list_next(list_entry);
	}
    }
}
Exemplo n.º 9
0
int _rtapi_task_delete(int task_id) {
    task_data *task;
    int retval = 0;

    if(task_id < 0 || task_id >= RTAPI_MAX_TASKS) return -EINVAL;

    task = &(task_array[task_id]);
    /* validate task handle */
    if (task->magic != TASK_MAGIC)	// nothing to delete
	return -EINVAL;

    if (task->state != DELETE_LOCKED)	// we don't already hold mutex
	rtapi_mutex_get(&(rtapi_data->mutex));

#ifdef MODULE
    if ((task->state == PERIODIC) || (task->state == FREERUN)) {
	/* task is running, need to stop it */
	rtapi_print_msg(RTAPI_MSG_WARN,
	    "RTAPI: WARNING: tried to delete task %02d while running\n",
	    task_id);
	_rtapi_task_pause(task_id);
    }
    /* get rid of it */
    rt_task_delete(ostask_array[task_id]);
    /* free kernel memory */
    kfree(ostask_array[task_id]);
    /* update data */
    task->prio = 0;
    task->owner = 0;
    task->taskcode = NULL;
    ostask_array[task_id] = NULL;
    rtapi_data->task_count--;
    /* if no more tasks, stop the timer */
    if (rtapi_data->task_count == 0) {
	if (rtapi_data->timer_running != 0) {
#  ifdef HAVE_RTAPI_MODULE_TIMER_STOP
	    _rtapi_module_timer_stop();
#  endif
	    rtapi_data->timer_period = 0;
	    max_delay = DEFAULT_MAX_DELAY;
	    rtapi_data->timer_running = 0;
	}
    }
#endif /* MODULE */

#ifdef HAVE_RTAPI_TASK_DELETE_HOOK
    retval = _rtapi_task_delete_hook(task,task_id);
#endif

    if (task->state != DELETE_LOCKED)	// we don't already hold mutex
	rtapi_mutex_give(&(rtapi_data->mutex));
    task->state = EMPTY;
    task->magic = 0;

    rtapi_print_msg(RTAPI_MSG_DBG, "rt_task_delete %d \"%s\"\n", task_id, 
		    task->name );

    return retval;
}
Exemplo n.º 10
0
// hal mutex scope-locked version of halpr_find_pin_by_name()
hal_pin_t *
hal_find_pin_by_name(const char *name)
{
    hal_pin_t *p __attribute__((cleanup(halpr_autorelease_mutex)));
    rtapi_mutex_get(&(hal_data->mutex));
    p = halpr_find_pin_by_name(name);
    return p;
}
Exemplo n.º 11
0
int _rtapi_exit(int module_id) {
    int retval;

    rtapi_mutex_get(&(rtapi_data->mutex));
    retval = module_delete(module_id);
    rtapi_mutex_give(&(rtapi_data->mutex));
    return retval;
}
Exemplo n.º 12
0
int rtapi_fifo_delete(int fifo_id, int module_id)
{
    int retval;

    rtapi_mutex_get(&(rtapi_data->mutex));
    retval = fifo_delete(fifo_id, module_id);
    rtapi_mutex_give(&(rtapi_data->mutex));
    return retval;
}
Exemplo n.º 13
0
int rtapi_shmem_delete(int shmem_id, int module_id)
{
    int retval;

    rtapi_mutex_get(&(rtapi_data->mutex));
    retval = shmem_delete(shmem_id, module_id);
    rtapi_mutex_give(&(rtapi_data->mutex));
    return retval;
}
Exemplo n.º 14
0
char *hal_comp_name(int comp_id)
{
    hal_comp_t *comp;
    char *result = NULL;
    rtapi_mutex_get(&(hal_data->mutex));
    comp = halpr_find_comp_by_id(comp_id);
    if(comp) result = comp->name;
    rtapi_mutex_give(&(hal_data->mutex));
    return result;
}
Exemplo n.º 15
0
int
hal_comp_state_by_name(const char *name)
{
    hal_comp_t *comp __attribute__((cleanup(halpr_autorelease_mutex)));
    rtapi_mutex_get(&(hal_data->mutex));

    comp = halpr_find_comp_by_name(name);
    if (comp == NULL)
	return -ENOENT;
    return comp->state;
}
Exemplo n.º 16
0
int hal_call_usrfunct(const char *name, const int argc, const char **argv, int *ureturn)
{
    hal_funct_t *funct;

    CHECK_HALDATA();
    CHECK_STR(name);

    if (argc && (argv == NULL)) {
	HALERR("funct '%s': argc=%d but argv is NULL", name, argc);
	return -EINVAL;
    }

    {
	int i __attribute__((cleanup(halpr_autorelease_mutex)));
	rtapi_mutex_get(&(hal_data->mutex));

	funct = halpr_find_funct_by_name(name);
	if (funct == NULL) {
	    HALERR("funct '%s' not found", name);
	    return -ENOENT;
	}

	if (funct->type != FS_USERLAND) {
	    HALERR("funct '%s': invalid type %d", name, funct->type);
	    return -ENOENT;
	}

	// argv sanity check - we dont want to fail this, esp in kernel land
	for (i = 0; i < argc; i++) {
	    if (argv[i] == NULL) {
		HALERR("funct '%s': argc=%d but argv[%d] is NULL",
		       name, i, i);
		return -EINVAL;
	    }
	}
    }
    // call the function with rtapi_mutex unlocked
    long long int now = rtapi_get_clocks();

    hal_funct_args_t fa = {
	.thread_start_time = now,
	.start_time = now,
	.thread = NULL,
	.funct = funct,
	.argc = argc,
	.argv = argv,
    };
    int retval = funct->funct.u(&fa);
    if (ureturn)
	*ureturn = retval;
    return 0;
}
Exemplo n.º 17
0
int _rtapi_exit(int module_id) {
    module_data *module;
    int n;

    if (rtapi_data == NULL) {
	rtapi_print_msg(RTAPI_MSG_ERR,
			"RTAPI:%d ERROR: exit called before init\n",
			rtapi_instance);
	return -EINVAL;
    }
    rtapi_print_msg(RTAPI_MSG_DBG, "RTAPI:%d module %02d exiting\n",
		    rtapi_instance,module_id);
    /* validate module ID */
    if ((module_id < 1) || (module_id > RTAPI_MAX_MODULES)) {
	rtapi_print_msg(RTAPI_MSG_ERR, "RTAPI:%d ERROR: bad module id\n",
			rtapi_instance);
	return -EINVAL;
    }
    /* get mutex */
    rtapi_mutex_get(&(rtapi_data->mutex));
    /* point to the module's data */
    module = &(module_array[module_id]);
    /* check module status */
    if (module->state != USERSPACE) {
	rtapi_print_msg(RTAPI_MSG_ERR,
			"RTAPI:%d ERROR: not a userspace module\n",
			rtapi_instance);
	rtapi_mutex_give(&(rtapi_data->mutex));
	return -EINVAL;
    }
    /* clean up any mess left behind by the module */
    for (n = 1; n <= RTAPI_MAX_SHMEMS; n++) {
	if (rtapi_test_bit(module_id, shmem_array[n].bitmap)) {
	    rtapi_print_msg(RTAPI_MSG_WARN,
			    "ULAPI:%d WARNING: module '%s' failed to delete "
			    "shmem %02d\n", rtapi_instance,module->name, n);
	    // mark block as ready for delete, lock already held
	    shmem_array[n].magic = SHMEM_MAGIC_DEL_LOCKED;
	    _rtapi_shmem_delete(n, module_id);
	}
    }
    /* update module data */
    rtapi_print_msg(RTAPI_MSG_DBG, "RTAPI:%d module %02d exited, name = '%s'\n",
		    rtapi_instance, module_id, module->name);
    module->state = NO_MODULE;
    module->name[0] = '\0';
    rtapi_data->ul_module_count--;
    rtapi_mutex_give(&(rtapi_data->mutex));
    return 0;
}
Exemplo n.º 18
0
int _rtapi_exit(int module_id) {
    module_id -= MODULE_OFFSET;

    if (module_id < 0 || module_id >= RTAPI_MAX_MODULES)
	return -1;
    /* Remove the module from the module_array. */
    rtapi_mutex_get(&(rtapi_data->mutex));
    module_array[module_id].state = NO_MODULE;
    rtapi_print_msg(RTAPI_MSG_DBG,
		    "rtapi_exit: freed module slot %d, was %s\n",
		    module_id, module_array[module_id].name);
    rtapi_mutex_give(&(rtapi_data->mutex));

    return 0;
}
Exemplo n.º 19
0
int hal_acquire(const char *comp_name, int pid)
{
    if (hal_data == 0) {
	hal_print_msg(RTAPI_MSG_ERR,
			"HAL: ERROR: hal_acquire called before hal_init\n");
	return -EINVAL;
    }
    {
	hal_comp_t *comp __attribute__((cleanup(halpr_autorelease_mutex)));

	rtapi_mutex_get(&(hal_data->mutex));
	comp = halpr_find_comp_by_name(comp_name);

	if (comp == NULL) {
	    hal_print_msg(RTAPI_MSG_ERR,
			    "HAL: hal_acquire(): no such component '%s'\n",
			    comp_name);
	    return -EINVAL;
	}
	if (comp->type != TYPE_REMOTE) {
	    hal_print_msg(RTAPI_MSG_ERR,
			    "HAL: hal_acquire(%s): not a remote component (%d)\n",
			    comp_name, comp->type);
	    return -EINVAL;
	}
	if (comp->state == COMP_BOUND) {
	    hal_print_msg(RTAPI_MSG_ERR,
			    "HAL: hal_acquire(%s): cant reown a bound component (%d)\n",
			    comp_name, comp->state);
	    return -EINVAL;
	}
	// let a comp be 'adopted away' from the RT environment
	// this is a tad hacky, should separate owner pid from RT/user distinction
	if ((comp->pid !=0) &&
	    (comp->pid != global_data->rtapi_app_pid))

	    {
		hal_print_msg(RTAPI_MSG_ERR,
				"HAL: hal_acquire(%s): component already owned by pid %d\n",
				comp_name, comp->pid);
		return -EINVAL;
	    }
	comp->pid = pid;
	return comp->comp_id;
    }
}
Exemplo n.º 20
0
void rtapi_app_exit(void)
{
    int retval;

    hal_print_msg(RTAPI_MSG_DBG,
		    "HAL_LIB:%d removing RT support\n",rtapi_instance);
    hal_proc_clean();

    {
	hal_thread_t *thread __attribute__((cleanup(halpr_autorelease_mutex)));

	/* grab mutex before manipulating list */
	rtapi_mutex_get(&(hal_data->mutex));
	/* must remove all threads before unloading this module */
	while (hal_data->thread_list_ptr != 0) {
	    /* point to a thread */
	    thread = SHMPTR(hal_data->thread_list_ptr);
	    /* unlink from list */
	    hal_data->thread_list_ptr = thread->next_ptr;
	    /* and delete it */
	    free_thread_struct(thread);
	}
    }

    /* release RTAPI resources */
    retval = rtapi_shmem_delete(lib_mem_id, lib_module_id);
    if (retval) {
	hal_print_msg(RTAPI_MSG_ERR,
			"HAL_LIB:%d rtapi_shmem_delete(%d,%d) failed: %d\n",
			rtapi_instance, lib_mem_id, lib_module_id, retval);
    }

    retval = rtapi_exit(lib_module_id);
    if (retval) {
	hal_print_msg(RTAPI_MSG_ERR,
			"HAL_LIB:%d rtapi_exit(%d) failed: %d\n",
			rtapi_instance, lib_module_id, retval);
    }
    /* done */
    hal_print_msg(RTAPI_MSG_DBG,
		    "HAL_LIB:%d RT support removed successfully\n",
		    rtapi_instance);
}
Exemplo n.º 21
0
int hal_inst_delete(const char *name)
{
    CHECK_HALDATA();
    CHECK_STR(name);

    {
	hal_inst_t *inst  __attribute__((cleanup(halpr_autorelease_mutex)));
	rtapi_mutex_get(&(hal_data->mutex));

	// inst must exist
	if ((inst = halpr_find_inst_by_name(name)) == NULL) {
	    HALERR("instance '%s' does not exist", name);
	    return -ENOENT;
	}
	// this does most of the heavy lifting
	free_inst_struct(inst);
    }
    return 0;
}
Exemplo n.º 22
0
int hal_release(const char *comp_name)
{
    if (hal_data == 0) {
	hal_print_msg(RTAPI_MSG_ERR,
			"HAL: ERROR: hal_release called before hal_init\n");
	return -EINVAL;
    }
    {
	hal_comp_t *comp __attribute__((cleanup(halpr_autorelease_mutex)));

	rtapi_mutex_get(&(hal_data->mutex));
	comp = halpr_find_comp_by_name(comp_name);

	if (comp == NULL) {
	    hal_print_msg(RTAPI_MSG_ERR,
			    "HAL: hal_release(): no such component '%s'\n",
			    comp_name);
	    return -EINVAL;
	}
	if (comp->type != TYPE_REMOTE) {
	    hal_print_msg(RTAPI_MSG_ERR,
			    "HAL: hal_release(%s): not a remote componet (%d)\n",
			    comp_name, comp->type);
	    return -EINVAL;
	}
	if (comp->pid == 0) {
	    hal_print_msg(RTAPI_MSG_ERR,
			    "HAL: hal_release(%s): component already disowned\n",
			    comp_name);
	    return -EINVAL;
	}

	if (comp->pid != getpid()) {
	    hal_print_msg(RTAPI_MSG_WARN,
			    "HAL: hal_release(%s): component owned by pid %d\n",
			    comp_name, comp->pid);
	    // return -EINVAL;
	}
	comp->pid = 0;
    }
    return 0;
}
Exemplo n.º 23
0
// part of public API
void *hal_malloc(long int size)
{
    void *retval;

    if (hal_data == 0) {
        HALERR("hal_malloc called before init");
        return 0;
    }
    /* get the mutex */
    rtapi_mutex_get(&(hal_data->mutex));
    /* allocate memory */
    retval = shmalloc_up(size);
    /* release the mutex */
    rtapi_mutex_give(&(hal_data->mutex));
    /* check return value */
    if (retval == 0) {
        HALDBG("hal_malloc() can't allocate %ld bytes", size);
    }
    return retval;
}
Exemplo n.º 24
0
int _rtapi_shmem_delete_inst(int handle, int instance, int module_id) {
    shmem_data *shmem;
    int retval = 0;

    if(handle < 1 || handle >= RTAPI_MAX_SHMEMS)
	return -EINVAL;

    rtapi_mutex_get(&(rtapi_data->mutex));
    shmem = &shmem_array[handle];

    /* validate shmem handle */
    if (shmem->magic != SHMEM_MAGIC) {
	rtapi_mutex_give(&(rtapi_data->mutex));
	return -EINVAL;
    }

    shmem->count --;
    if(shmem->count) {
	rtapi_mutex_give(&(rtapi_data->mutex));
	rtapi_print_msg(RTAPI_MSG_DBG,
			"rtapi_shmem_delete: handle=%d module=%d key=0x%x:  "
			"%d remaining users\n",
			handle, module_id, shmem->key, shmem->count);
	return 0;
    }

    retval = shm_common_detach(shmem->size, shmem->mem);
    if (retval < 0) {
	rtapi_print_msg(RTAPI_MSG_ERR,
			"RTAPI:%d ERROR: munmap(0x%8.8x) failed: %s\n",
			instance, shmem->key, strerror(-retval));
    }

    // XXX: probably shmem->mem should be set to NULL here to avoid
    // references to already unmapped segments (and find them early)

    /* free the shmem structure */
    shmem->magic = 0;
    rtapi_mutex_give(&(rtapi_data->mutex));
    return retval;
}
Exemplo n.º 25
0
int _rtapi_init(const char *modname) {
    int n, module_id = -ENOMEM;
    module_data *module;

    /* say hello */
    rtapi_print_msg(RTAPI_MSG_DBG, "RTAPI: initing module %s\n", modname);

    /* get the mutex */
    rtapi_mutex_get(&(rtapi_data->mutex));
    /* find empty spot in module array */
    n = 1;
    while ((n <= RTAPI_MAX_MODULES) && (module_array[n].state != NO_MODULE)) {
	n++;
    }
    if (n > RTAPI_MAX_MODULES) {
	/* no room */
	rtapi_mutex_give(&(rtapi_data->mutex));
	rtapi_print_msg(RTAPI_MSG_ERR, "RTAPI: ERROR: reached module limit %d\n",
			n);
	return -EMFILE;
    }
    /* we have space for the module */
    module_id = n + MODULE_OFFSET;
    module = &(module_array[n]);
    /* update module data */
    module->state = REALTIME;
    if (modname != NULL) {
	/* use name supplied by caller, truncating if needed */
	rtapi_snprintf(module->name, RTAPI_NAME_LEN, "%s", modname);
    } else {
	/* make up a name */
	rtapi_snprintf(module->name, RTAPI_NAME_LEN, "ULMOD%03d", module_id);
    }
    rtapi_data->ul_module_count++;
    rtapi_print_msg(RTAPI_MSG_DBG, "RTAPI: module '%s' loaded, ID: %d\n",
	module->name, module_id);
    rtapi_mutex_give(&(rtapi_data->mutex));
    return module_id;
}
Exemplo n.º 26
0
int hal_acquire(const char *comp_name, int pid)
{
    CHECK_HALDATA();
    CHECK_STRLEN(comp_name, HAL_NAME_LEN);
    {
	hal_comp_t *comp __attribute__((cleanup(halpr_autorelease_mutex)));

	rtapi_mutex_get(&(hal_data->mutex));
	comp = halpr_find_comp_by_name(comp_name);

	if (comp == NULL) {
	    HALERR("no such component '%s'", comp_name);
	    return -EINVAL;
	}
	if (comp->type != TYPE_REMOTE) {
	    HALERR("component '%s' not a remote component (%d)",
		   comp_name, comp->type);
	    return -EINVAL;
	}
	if (comp->state == COMP_BOUND) {
	    HALERR("component '%s': cant reown a bound component (%d)",
		   comp_name, comp->state);
	    return -EINVAL;
	}
	// let a comp be 'adopted away' from the RT environment
	// this is a tad hacky, should separate owner pid from RT/user distinction
	if ((comp->pid !=0) &&
	    (comp->pid != global_data->rtapi_app_pid))

	    {
		HALERR("component '%s': already owned by pid %d",
		       comp_name, comp->pid);
		return -EINVAL;
	    }
	comp->pid = pid;
	return comp->comp_id;
    }
}
Exemplo n.º 27
0
int hal_xinit(const int type,
	      const int userarg1,
	      const int userarg2,
	      const hal_constructor_t ctor,
	      const hal_destructor_t dtor,
	      const char *name)
{
    int comp_id, retval;

    rtapi_set_logtag("hal_lib");
    CHECK_STRLEN(name, HAL_NAME_LEN);

    // sanity: these must have been inited before by the
    // respective rtapi.so/.ko module
    CHECK_NULL(rtapi_switch);

    if ((dtor != NULL) && (ctor == NULL)) {
	HALERR("component '%s': NULL constructor doesnt make"
	       " sense with non-NULL destructor", name);
	return -EINVAL;
    }

    // RTAPI initialisation already done
    HALDBG("initializing component '%s' type=%d arg1=%d arg2=%d/0x%x",
	   name, type, userarg1, userarg2, userarg2);

    if ((lib_module_id < 0) && (type != TYPE_HALLIB)) {
	// if hal_lib not inited yet, do so now - recurse
#ifdef RTAPI
	retval = hal_xinit(TYPE_HALLIB, 0, 0, NULL, NULL, "hal_lib");
#else
	retval = hal_xinitf(TYPE_HALLIB, 0, 0, NULL, NULL, "hal_lib%ld",
			    (long) getpid());
#endif
	if (retval < 0)
	    return retval;
    }

    // tag message origin field since ulapi autoload re-tagged them temporarily
    rtapi_set_logtag("hal_lib");

    /* copy name to local vars, truncating if needed */
    char rtapi_name[RTAPI_NAME_LEN + 1];
    char hal_name[HAL_NAME_LEN + 1];

    rtapi_snprintf(hal_name, sizeof(hal_name), "%s", name);
    rtapi_snprintf(rtapi_name, RTAPI_NAME_LEN, "HAL_%s", hal_name);

    /* do RTAPI init */
    comp_id = rtapi_init(rtapi_name);
    if (comp_id < 0) {
	HALERR("rtapi init(%s) failed", rtapi_name);
	return -EINVAL;
    }

    // recursing? init HAL shm
    if ((lib_module_id < 0) && (type == TYPE_HALLIB)) {
	// recursion case, we're initing hal_lib

	// get HAL shared memory from RTAPI
	int shm_id = rtapi_shmem_new(HAL_KEY,
				     comp_id,
				     global_data->hal_size);
	if (shm_id < 0) {
	    HALERR("hal_lib:%d failed to allocate HAL shm %x, rc=%d",
		   comp_id, HAL_KEY, shm_id);
	    rtapi_exit(comp_id);
	    return -EINVAL;
	}
	// retrieve address of HAL shared memory segment
	void *mem;
	retval = rtapi_shmem_getptr(shm_id, &mem, 0);
	if (retval < 0) {
	    HALERR("hal_lib:%d failed to acquire HAL shm %x, id=%d rc=%d",
		   comp_id, HAL_KEY, shm_id, retval);
	    rtapi_exit(comp_id);
	    return -EINVAL;
	}
	// set up internal pointers to shared mem and data structure
	hal_shmem_base = (char *) mem;
	hal_data = (hal_data_t *) mem;

#ifdef RTAPI
	// only on RTAPI hal_lib initialization:
	// initialize up the HAL shm segment
	retval = init_hal_data();
	if (retval) {
	    HALERR("could not init HAL shared memory rc=%d", retval);
	    rtapi_exit(lib_module_id);
	    lib_module_id = -1;
	    return -EINVAL;
	}
	retval = hal_proc_init();
	if (retval) {
	    HALERR("could not init /proc files");
	    rtapi_exit(lib_module_id);
	    lib_module_id = -1;
	    return -EINVAL;
	}
#endif
	// record hal_lib comp_id
	lib_module_id = comp_id;
	// and the HAL shm segmed id
	lib_mem_id = shm_id;

    }
    // global_data MUST be at hand now:
    HAL_ASSERT(global_data != NULL);

    // paranoia
    HAL_ASSERT(hal_shmem_base != NULL);
    HAL_ASSERT(hal_data != NULL);
    HAL_ASSERT(lib_module_id > -1);
    HAL_ASSERT(lib_mem_id > -1);
    if (lib_module_id < 0) {
	HALERR("giving up");
	return -EINVAL;
    }

    {
	hal_comp_t *comp  __attribute__((cleanup(halpr_autorelease_mutex)));

	/* get mutex before manipulating the shared data */
	rtapi_mutex_get(&(hal_data->mutex));
	/* make sure name is unique in the system */
	if (halpr_find_comp_by_name(hal_name) != 0) {
	    /* a component with this name already exists */
	    HALERR("duplicate component name '%s'", hal_name);
	    rtapi_exit(comp_id);
	    return -EINVAL;
	}
	/* allocate a new component structure */
	comp = halpr_alloc_comp_struct();
	if (comp == 0) {
	    HALERR("insufficient memory for component '%s'", hal_name);
	    rtapi_exit(comp_id);
	    return -ENOMEM;
	}

	/* initialize the comp structure */
	comp->userarg1 = userarg1;
	comp->userarg2 = userarg2;
	comp->comp_id = comp_id;
	comp->type = type;
	comp->ctor = ctor;
	comp->dtor = dtor;
#ifdef RTAPI
	comp->pid = 0;
#else /* ULAPI */
	// a remote component starts out disowned
	comp->pid = comp->type == TYPE_REMOTE ? 0 : getpid();
#endif
	comp->state = COMP_INITIALIZING;
	comp->last_update = 0;
	comp->last_bound = 0;
	comp->last_unbound = 0;
	comp->shmem_base = hal_shmem_base;
	comp->insmod_args = 0;
	rtapi_snprintf(comp->name, sizeof(comp->name), "%s", hal_name);
	/* insert new structure at head of list */
	comp->next_ptr = hal_data->comp_list_ptr;
	hal_data->comp_list_ptr = SHMOFF(comp);

    }
    // scope exited - mutex released

    // finish hal_lib initialisation
    // in ULAPI this will happen after the recursion on hal_lib%d unwinds

    if (type == TYPE_HALLIB) {
#ifdef RTAPI
	// only on RTAPI hal_lib initialization:
	// export the instantiation support userfuncts
	hal_export_xfunct_args_t ni = {
	    .type = FS_USERLAND,
	    .funct.u = create_instance,
	    .arg = NULL,
	    .owner_id = lib_module_id
	};
	if ((retval = hal_export_xfunctf( &ni, "newinst")) < 0)
	    return retval;

	hal_export_xfunct_args_t di = {
	    .type = FS_USERLAND,
	    .funct.u = delete_instance,
	    .arg = NULL,
	    .owner_id = lib_module_id
	};
	if ((retval = hal_export_xfunctf( &di, "delinst")) < 0)
	    return retval;
#endif
	retval = hal_ready(lib_module_id);
	if (retval)
	    HALERR("hal_ready(%d) failed rc=%d", lib_module_id, retval);
	else
	    HALDBG("%s initialization complete", hal_name);
	return retval;
    }

    HALDBG("%s component '%s' id=%d initialized%s",
	   (ctor != NULL) ? "instantiable" : "legacy",
	   hal_name, comp_id,
	   (dtor != NULL) ? ", has destructor" : "");
    return comp_id;
}


int hal_exit(int comp_id)
{
    int *prev, next, comptype;
    char name[HAL_NAME_LEN + 1];

    CHECK_HALDATA();

    HALDBG("removing component %d", comp_id);

    {
	hal_comp_t *comp  __attribute__((cleanup(halpr_autorelease_mutex)));

	/* grab mutex before manipulating list */
	rtapi_mutex_get(&(hal_data->mutex));
	/* search component list for 'comp_id' */
	prev = &(hal_data->comp_list_ptr);
	next = *prev;
	if (next == 0) {
	    /* list is empty - should never happen, but... */
	    HALERR("no components defined");
	    return -EINVAL;
	}
	comp = SHMPTR(next);
	while (comp->comp_id != comp_id) {
	    /* not a match, try the next one */
	    prev = &(comp->next_ptr);
	    next = *prev;
	    if (next == 0) {
		/* reached end of list without finding component */
		HALERR("no such component with id %d", comp_id);
		return -EINVAL;
	    }
	    comp = SHMPTR(next);
	}

	// record type, since we're about to zap the comp in free_comp_struct()
	comptype = comp->type;

	/* save component name for later */
	rtapi_snprintf(name, sizeof(name), "%s", comp->name);
	/* get rid of the component */
	free_comp_struct(comp);

	// unlink the comp only now as free_comp_struct() must
	// determine ownership of pins/params/functs and this
	// requires access to the current comp, too
	// since this is all under lock it should not matter
	*prev = comp->next_ptr;

	// add it to free list
	comp->next_ptr = hal_data->comp_free_ptr;
	hal_data->comp_free_ptr = SHMOFF(comp);

	// scope exit - mutex released
    }

    // if unloading the hal_lib component, destroy HAL shm
    if (comptype == TYPE_HALLIB) {
	int retval;

	/* release RTAPI resources */
	retval = rtapi_shmem_delete(lib_mem_id, comp_id);
	if (retval) {
	    HALERR("rtapi_shmem_delete(%d,%d) failed: %d",
		   lib_mem_id, comp_id, retval);
	}
	// HAL shm is history, take note ASAP
	lib_mem_id = -1;
	hal_shmem_base = NULL;
	hal_data = NULL;;

	retval = rtapi_exit(comp_id);
	if (retval) {
	    HALERR("rtapi_exit(%d) failed: %d",
		   lib_module_id, retval);
	}
	// the hal_lib RTAPI module is history, too
	// in theory we'd be back to square 1
	lib_module_id = -1;

    } else {
	// the standard case
	rtapi_exit(comp_id);
    }

    //HALDBG("component '%s' id=%d removed", name, comp_id);
    return 0;
}
Exemplo n.º 28
0
int _rtapi_task_new(const rtapi_task_args_t *args) {
    int task_id;
    int __attribute__((__unused__)) retval = 0;
    task_data *task;

    /* get the mutex */
    rtapi_mutex_get(&(rtapi_data->mutex));

#ifdef MODULE
    /* validate owner */
    if ((args->owner < 1) || (args->owner > RTAPI_MAX_MODULES)) {
	rtapi_mutex_give(&(rtapi_data->mutex));
	return -EINVAL;
    }
    if (module_array[args->owner].state != REALTIME) {
	rtapi_mutex_give(&(rtapi_data->mutex));
	return -EINVAL;
    }
    if ((args->flags & (TF_NONRT|TF_NOWAIT)) != 0) {
	rtapi_print_msg(RTAPI_MSG_ERR,
			"task '%s' : nowait/posix flags not supported with kthreads\n",
			args->name);
	rtapi_mutex_give(&(rtapi_data->mutex));
	return -EINVAL;
    }
#endif

    /* find an empty entry in the task array */
    task_id = 1; // tasks start at one!
    // go through task_array until an empty task slot is found
    while ((task_id < RTAPI_MAX_TASKS) &&
	   (task_array[task_id].magic == TASK_MAGIC))
	task_id++;
    // if task_array is full, release lock and return error
    if (task_id == RTAPI_MAX_TASKS) {
	rtapi_mutex_give(&(rtapi_data->mutex));
	return -ENOMEM;
    }
    task = &(task_array[task_id]);

    // if requested priority is invalid, release lock and return error

    if (PRIO_LT(args->prio,_rtapi_prio_lowest()) ||
	PRIO_GT(args->prio,_rtapi_prio_highest())) {
	rtapi_print_msg(RTAPI_MSG_ERR,
			"New task  %d  '%s:%d': invalid priority %d "
			"(highest=%d lowest=%d)\n",
			task_id, args->name, rtapi_instance, args->prio,
			_rtapi_prio_highest(),
			_rtapi_prio_lowest());
	rtapi_mutex_give(&(rtapi_data->mutex));
	return -EINVAL;
    }

    if ((args->flags & (TF_NOWAIT|TF_NONRT)) == TF_NOWAIT) {
	rtapi_print_msg(RTAPI_MSG_ERR,"task '%s' : nowait flag invalid for RT thread\n",
			args->name);
	rtapi_mutex_give(&(rtapi_data->mutex));
	return -EINVAL;
    }

    // task slot found; reserve it and release lock
    rtapi_print_msg(RTAPI_MSG_DBG,
		    "Creating new task %d  '%s:%d': "
		    "req prio %d (highest=%d lowest=%d) stack=%lu fp=%d flags=%d\n",
		    task_id, args->name, rtapi_instance, args->prio,
		    _rtapi_prio_highest(),
		    _rtapi_prio_lowest(),
		    args->stacksize, args->uses_fp, args->flags);
    task->magic = TASK_MAGIC;

    /* fill out task structure */
    task->owner = args->owner;
    task->arg = args->arg;
    task->stacksize = (args->stacksize < MIN_STACKSIZE) ? MIN_STACKSIZE : args->stacksize;
    task->taskcode = args->taskcode;
    task->prio = args->prio;
    task->flags = args->flags;
    task->uses_fp = args->uses_fp;
    task->cpu = args->cpu_id > -1 ? args->cpu_id : rtapi_data->rt_cpu;

    rtapi_print_msg(RTAPI_MSG_DBG, "Task CPU:  %d\n", task->cpu);

    rtapi_snprintf(task->name, sizeof(task->name), 
	     "%s:%d", args->name, rtapi_instance);
    task->name[sizeof(task->name) - 1] = '\0';

#ifdef MODULE
    /* get space for the OS's task data - this is around 900 bytes, */
    /* so we don't want to statically allocate it for unused tasks. */
    ostask_array[task_id] = kmalloc(sizeof(RT_TASK), GFP_USER);
    if (ostask_array[task_id] == NULL) {
	rtapi_mutex_give(&(rtapi_data->mutex));
	return -ENOMEM;
    }

#ifdef HAVE_RTAPI_TASK_NEW_HOOK
    /* kernel threads: rtapi_task_new_hook() should call OS to
       initialize the task - use predetermined or explicitly assigned
       CPU */
    retval = _rtapi_task_new_hook(task, task_id);

    if (retval) {
	rtapi_print_msg(RTAPI_MSG_ERR,
			"rt_task_create failed, rc = %d\n", retval );

	/* couldn't create task, free task data memory */
	kfree(ostask_array[task_id]);
	rtapi_mutex_give(&(rtapi_data->mutex));
	if (retval == ENOMEM) {
	    /* not enough space for stack */
	    return -ENOMEM;
	}
	/* unknown error */
	return -EINVAL;
    }
#endif

    /* the task has been created, update data */
    task->state = PAUSED;
    retval = task_id;
#else  /* userland thread */
    /* userland threads: rtapi_task_new_hook() should perform any
       thread system-specific tasks, and return task_id or an error
       code back to the caller (how do we know the diff between an
       error and a task_id???).  */
    task->state = USERLAND;	// userland threads don't track this

#  ifdef HAVE_RTAPI_TASK_NEW_HOOK
    retval = _rtapi_task_new_hook(task,task_id);
#  else
    retval = task_id;
#  endif
#endif  /* userland thread */

    rtapi_data->task_count++;

    rtapi_mutex_give(&(rtapi_data->mutex));

    /* announce the birth of a brand new baby task */
    rtapi_print_msg(RTAPI_MSG_DBG,
	"RTAPI: task %02d installed by module %02d, priority %d, code: %p\n",
	task_id, task->owner, task->prio, args->taskcode);

    return task_id;
}
Exemplo n.º 29
0
int hal_init_mode(const char *name, int type, int userarg1, int userarg2)
{
    int comp_id;
    char rtapi_name[RTAPI_NAME_LEN + 1];
    char hal_name[HAL_NAME_LEN + 1];

    // tag message origin field
    rtapi_set_logtag("hal_lib");

    if (name == 0) {
	hal_print_msg(RTAPI_MSG_ERR, "HAL: ERROR: no component name\n");
	return -EINVAL;
    }
    if (strlen(name) > HAL_NAME_LEN) {
	hal_print_msg(RTAPI_MSG_ERR,
			"HAL: ERROR: component name '%s' is too long\n", name);
	return -EINVAL;
    }
    // rtapi initialisation already done
    // since this happens through the constructor
    hal_print_msg(RTAPI_MSG_DBG,
		    "HAL: initializing component '%s' type=%d arg1=%d arg2=%d/0x%x\n",
		    name, type, userarg1, userarg2, userarg2);
    /* copy name to local vars, truncating if needed */
    rtapi_snprintf(rtapi_name, RTAPI_NAME_LEN, "HAL_%s", name);
    rtapi_snprintf(hal_name, sizeof(hal_name), "%s", name);

    /* do RTAPI init */
    comp_id = rtapi_init(rtapi_name);
    if (comp_id < 0) {
	hal_print_msg(RTAPI_MSG_ERR, "HAL: ERROR: rtapi init failed\n");
	return -EINVAL;
    }
    // tag message origin field since ulapi autoload re-tagged them
    rtapi_set_logtag("hal_lib");
#ifdef ULAPI
    hal_rtapi_attach();
#endif
    {
	hal_comp_t *comp  __attribute__((cleanup(halpr_autorelease_mutex)));

	/* get mutex before manipulating the shared data */
	rtapi_mutex_get(&(hal_data->mutex));
	/* make sure name is unique in the system */
	if (halpr_find_comp_by_name(hal_name) != 0) {
	    /* a component with this name already exists */
	    hal_print_msg(RTAPI_MSG_ERR,
			    "HAL: ERROR: duplicate component name '%s'\n", hal_name);
	    rtapi_exit(comp_id);
	    return -EINVAL;
	}
	/* allocate a new component structure */
	comp = halpr_alloc_comp_struct();
	if (comp == 0) {
	    /* couldn't allocate structure */
	    hal_print_msg(RTAPI_MSG_ERR,
			    "HAL: ERROR: insufficient memory for component '%s'\n", hal_name);
	    rtapi_exit(comp_id);
	    return -ENOMEM;
	}

	/* initialize the comp structure */
	comp->userarg1 = userarg1;
	comp->userarg2 = userarg2;
	comp->comp_id = comp_id;
	comp->type = type;
#ifdef RTAPI
	comp->pid = 0;   //FIXME revisit this
#else /* ULAPI */
	// a remote component starts out disowned
	comp->pid = comp->type == TYPE_REMOTE ? 0 : getpid(); //FIXME revisit this
#endif
	comp->state = COMP_INITIALIZING;
	comp->last_update = 0;
	comp->last_bound = 0;
	comp->last_unbound = 0;
	comp->shmem_base = hal_shmem_base;
	comp->insmod_args = 0;
	rtapi_snprintf(comp->name, sizeof(comp->name), "%s", hal_name);
	/* insert new structure at head of list */
	comp->next_ptr = hal_data->comp_list_ptr;
	hal_data->comp_list_ptr = SHMOFF(comp);

    }
    // scope exited - mutex released
    /* done */
    hal_print_msg(RTAPI_MSG_DBG,
		    "HAL: component '%s' initialized, ID = %02d\n", hal_name, comp_id);
    return comp_id;
}
Exemplo n.º 30
0
static gboolean dialog_select_source(int chan_num)
{
    scope_vert_t *vert;
    scope_chan_t *chan;
    dialog_generic_t dialog;
    gchar *title, msg[BUFLEN];
    int next, n, initial_page, row, initial_row, max_row;
    gchar *tab_label_text[3], *name;
    GtkWidget *hbox, *label, *notebk, *button;
    GtkAdjustment *adj;
    hal_pin_t *pin;
    hal_sig_t *sig;
    hal_param_t *param;

    vert = &(ctrl_usr->vert);
    chan = &(ctrl_usr->chan[chan_num - 1]);
    title = _("Select Channel Source");
    snprintf(msg, BUFLEN - 1, _("Select a pin, signal, or parameter\n"
	"as the source for channel %d."), chan_num);
    /* create dialog window, disable resizing */
    dialog.retval = 0;
    dialog.window = gtk_dialog_new();
    dialog.app_data = &chan_num;
    /* set initial height of window */
    gtk_widget_set_usize(GTK_WIDGET(dialog.window), -2, 300);
    /* allow user to grow but not shrink the window */
    gtk_window_set_policy(GTK_WINDOW(dialog.window), FALSE, TRUE, FALSE);
    /* window should appear in center of screen */
    gtk_window_set_position(GTK_WINDOW(dialog.window), GTK_WIN_POS_CENTER);
    /* set title */
    gtk_window_set_title(GTK_WINDOW(dialog.window), title);
    /* display message */
    label = gtk_label_new(msg);
    gtk_misc_set_padding(GTK_MISC(label), 15, 5);
    gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog.window)->vbox), label, FALSE,
	TRUE, 0);

    /* a separator */
    gtk_hseparator_new_in_box(GTK_DIALOG(dialog.window)->vbox, 0);

    /* create a notebook to hold pin, signal, and parameter lists */
    notebk = gtk_notebook_new();
    /* add the notebook to the dialog */
    gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog.window)->vbox), notebk, TRUE,
	TRUE, 0);
    /* set overall notebook parameters */
    gtk_notebook_set_homogeneous_tabs(GTK_NOTEBOOK(notebk), TRUE);
    gtk_signal_connect(GTK_OBJECT(notebk), "switch-page", GTK_SIGNAL_FUNC(change_page), &dialog);
    /* text for tab labels */
    tab_label_text[0] = _("Pins");
    tab_label_text[1] = _("Signals");
    tab_label_text[2] = _("Parameters");
    /* loop to create three identical tabs */
    for (n = 0; n < 3; n++) {
	/* Create a scrolled window to display the list */
	vert->windows[n] = gtk_scrolled_window_new(NULL, NULL);
	vert->adjs[n] = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(vert->windows[n]));
	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(vert->windows[n]),
	    GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
	gtk_widget_show(vert->windows[n]);
	/* create a list to hold the data */
	vert->lists[n] = gtk_clist_new(1);
	/* set up a callback for when the user selects a line */
	gtk_signal_connect(GTK_OBJECT(vert->lists[n]), "select_row",
	    GTK_SIGNAL_FUNC(selection_made), &dialog);
	gtk_signal_connect(GTK_OBJECT(vert->lists[n]), "key-press-event",
	    GTK_SIGNAL_FUNC(search_for_entry), &dialog);
	/* It isn't necessary to shadow the border, but it looks nice :) */
	gtk_clist_set_shadow_type(GTK_CLIST(vert->lists[n]), GTK_SHADOW_OUT);
	/* set list for single selection only */
	gtk_clist_set_selection_mode(GTK_CLIST(vert->lists[n]),
	    GTK_SELECTION_BROWSE);
	/* put the list into the scrolled window */
	gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW
	    (vert->windows[n]), vert->lists[n]);
	/* another way to do it - not sure which is better
	gtk_container_add(GTK_CONTAINER(vert->windows[n]), vert->lists[n]); */
	gtk_widget_show(vert->lists[n]);
	/* create a box for the tab label */
	hbox = gtk_hbox_new(TRUE, 0);
	/* create a label for the page */
	gtk_label_new_in_box(tab_label_text[n], hbox, TRUE, TRUE, 0);
	gtk_widget_show(hbox);
	/* add page to the notebook */
	gtk_notebook_append_page(GTK_NOTEBOOK(notebk), vert->windows[n], hbox);
	/* set tab attributes */
	gtk_notebook_set_tab_label_packing(GTK_NOTEBOOK(notebk), hbox,
	    TRUE, TRUE, GTK_PACK_START);
    }
    /* determine initial page: pin, signal, or parameter */
    if (( chan->data_source_type >= 0 ) && ( chan->data_source_type <= 2 )) {
	initial_page = chan->data_source_type;
	gtk_notebook_set_page(GTK_NOTEBOOK(notebk), initial_page);
    } else {
	initial_page = -1;
	gtk_notebook_set_page(GTK_NOTEBOOK(notebk), 0);
    }
    gtk_widget_show(notebk);

    /* populate the pin, signal, and parameter lists */
    gtk_clist_clear(GTK_CLIST(vert->lists[0]));
    gtk_clist_clear(GTK_CLIST(vert->lists[1]));
    gtk_clist_clear(GTK_CLIST(vert->lists[2]));
    rtapi_mutex_get(&(hal_data->mutex));
    next = hal_data->pin_list_ptr;
    initial_row = -1;
    max_row = -1;
    while (next != 0) {
	pin = SHMPTR(next);
	name = pin->name;
	row = gtk_clist_append(GTK_CLIST(vert->lists[0]), &name);
	if ( initial_page == 0 ) {
	    if ( strcmp(name, chan->name) == 0 ) {
		initial_row = row;
	    }
	    max_row = row;
	}
	next = pin->next_ptr;
    }
    next = hal_data->sig_list_ptr;
    while (next != 0) {
	sig = SHMPTR(next);
	name = sig->name;
	row = gtk_clist_append(GTK_CLIST(vert->lists[1]), &name);
	if ( initial_page == 1 ) {
	    if ( strcmp(name, chan->name) == 0 ) {
		initial_row = row;
	    }
	    max_row = row;
	}
	next = sig->next_ptr;
    }
    next = hal_data->param_list_ptr;
    while (next != 0) {
	param = SHMPTR(next);
	name = param->name;
	row = gtk_clist_append(GTK_CLIST(vert->lists[2]), &name);
	if ( initial_page == 2 ) {
	    if ( strcmp(name, chan->name) == 0 ) {
		initial_row = row;
	    }
	    max_row = row;
	}
	next = param->next_ptr;
    }
    rtapi_mutex_give(&(hal_data->mutex));
    
    if ( initial_row >= 0 ) {
	/* highlight the currently selected name */
	gtk_clist_select_row(GTK_CLIST(vert->lists[initial_page]), initial_row, -1);
	/* set scrolling window to show the highlighted name */
	/* FIXME - I can't seem to get this to work */
	adj = vert->adjs[initial_page];
	adj->value = adj->lower + (adj->upper - adj->lower)*((double)(initial_row)/(double)(max_row+1));
	gtk_adjustment_value_changed(vert->adjs[initial_page]);
    }
    /* set up a callback function when the window is destroyed */
    gtk_signal_connect(GTK_OBJECT(dialog.window), "destroy",
	GTK_SIGNAL_FUNC(dialog_generic_destroyed), &dialog);
    /* make Cancel button */
    button = gtk_button_new_with_label(_("Cancel"));
    gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog.window)->action_area),
	button, TRUE, TRUE, 4);
    gtk_signal_connect(GTK_OBJECT(button), "clicked",
	GTK_SIGNAL_FUNC(dialog_generic_button2), &dialog);
    /* make window transient and modal */
    gtk_window_set_transient_for(GTK_WINDOW(dialog.window),
	GTK_WINDOW(ctrl_usr->main_win));
    gtk_window_set_modal(GTK_WINDOW(dialog.window), TRUE);
    gtk_widget_show_all(dialog.window);
    gtk_main();
    /* we get here when the user makes a selection, hits Cancel, or closes
       the window */
    vert->lists[0] = NULL;
    vert->lists[1] = NULL;
    vert->lists[2] = NULL;
    if ((dialog.retval == 0) || (dialog.retval == 2)) {
	/* user either closed dialog, or hit cancel */
	return FALSE;
    }
    /* user made a selection */
    channel_changed();
    return TRUE;
}